This patch series provides "#pragma unroll N" and "#pragma unroll" (without the "GCC" qualifier) as aliases for the existing "#pragma GCC unroll N", easing code portability with Clang, NVCC, and IBM XL C/C++:
* "#pragma unroll N" -> "#pragma GCC unroll N" * "#pragma unroll" -> "#pragma GCC unroll <USHRT_MAX - 1>" The no-argument form completely unrolls the loop to match Clang and NVCC, which is a compatibility choice instead of a proposal for how a GCC-native no-argument unroll should behave. In particular, this series does not change "#pragma GCC unroll N", and the no-argument form "#pragma GCC unroll" is deliberately left out, reserving room for future work with different semantics. All compilers listed above support "#pragma unroll N" with the N being the unroll factor applying to loops with compile-time constant trip counts, [1][3][4] only with slightly different limitations: * The upper limit of GCC is (USHRT_MAX - 1). This is decided in the implementation prior to these changes. * Clang skips all limitation regarding size or trip counts. [2] The only limitation left is asserting (AllowRemainder || trip_count % N == 0) [2] * The upper limit of NVCC is (INT_MAX). [3] * The upper limit of IBM XL C/C++ is not documented publicly. They also support "#pragma unroll", [1][3][4] but with some notable behavioural differences: * GCC, if this patch is applied, will only unroll loops completely if (trip_count <= USHRT_MAX - 1), and will otherwise decide on the unroll factor heuristically. * Clang has upper limits guarding [2] * unrolled body size (PragmaUnrollThreshold) * trip counts (PragmaUnrollFullMaxIterations (default 1,000,000)) When exceeded, the loop won't be completely unrolled. * IBM XL C/C++ Compiler will decide on the unroll factor instead of unrolling completely when n is not specified. [5] The compiler ICC mentioned in PR91840 has reached its EOL, and is thus not discussed here. Regarding the (USHRT_MAX - 1) limitation: * It is a pre-existing implementation detail, which currently surfaces only in error messages and code comments. * If applied, this series documents the limit only on the complete-unrolling "#pragma unroll", leaving `#pragma GCC unroll N` and `#pragma unroll N` without it. * I am not certain which level of exposure would be the best balance between utility and maintainability. Guidance on how much to expose here would be appreciated. Future work: "#pragma nounroll" is a natural companion, but it is currently left out of this patch series as not all of the compilers compared above (e.g., NVCC) support it, [3] so its inter-compiler-compatibility rationale is weaker and its semantics need separate consideration. It can follow as a standalone patch. Regtested on x86_64-pc-linux-gnu; no regressions. New tests for the added pragmas pass under both C and C++. [1]: https://clang.llvm.org/docs/AttributeReference.html#pragma-unroll-pragma-nounroll [2]: https://github.com/llvm/llvm-project/blob/afb54cc942d5fccf63f5594a6808f21eb179db6f/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp [3]: https://docs.nvidia.com/cuda/cuda-programming-guide/05-appendices/cpp-language-extensions.html#pragma-unroll [4]: https://www.ibm.com/docs/en/ent-metalc-zos/3.1.0?topic=descriptions-pragma-unroll [5]: https://www.ibm.com/docs/en/SSRZSMX_17.1.3/pdf/user.pdf Yueh-Shun Li (3): testsuite: c-c++-common/unroll-8.c: new test c-family: support #pragma unroll (n) [PR91840] c-family: support complete unrolling with #pragma unroll gcc/c-family/c-pragma.cc | 4 ++ gcc/c-family/c-pragma.h | 1 + gcc/c/c-parser.cc | 21 +++++++-- gcc/cp/parser.cc | 20 +++++++- gcc/doc/extend.texi | 18 ++++++++ .../unroll-1-unqualified-complete.c | 24 ++++++++++ .../unroll-1-unqualified-constant.c | 46 +++++++++++++++++++ .../unroll-4-unqualified-constant.c | 31 +++++++++++++ .../unroll-5-unqualified-constant.c | 35 ++++++++++++++ .../unroll-8-unqualified-complete.c | 29 ++++++++++++ gcc/testsuite/c-c++-common/unroll-8.c | 37 +++++++++++++++ .../pr126323-unroll-unqualified-complete.C | 13 ++++++ .../pr126323-unroll-unqualified-constant.C | 12 +++++ 13 files changed, 285 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/unroll-1-unqualified-complete.c create mode 100644 gcc/testsuite/c-c++-common/unroll-1-unqualified-constant.c create mode 100644 gcc/testsuite/c-c++-common/unroll-4-unqualified-constant.c create mode 100644 gcc/testsuite/c-c++-common/unroll-5-unqualified-constant.c create mode 100644 gcc/testsuite/c-c++-common/unroll-8-unqualified-complete.c create mode 100644 gcc/testsuite/c-c++-common/unroll-8.c create mode 100644 gcc/testsuite/g++.dg/parse/pr126323-unroll-unqualified-complete.C create mode 100644 gcc/testsuite/g++.dg/parse/pr126323-unroll-unqualified-constant.C -- 2.54.0
