llvm-project/clang/test/AST/ast-dump-pragma-unroll.cpp
yronglin c4c8d08b81
[Clang] Fix incorrect handling of #pragma {GCC} unroll N in dependent context (#90240)
PR https://github.com/llvm/llvm-project/pull/89567 fix the `#pragma
unroll N` crash issue in dependent context, but it's introduce an new
issue:

Since https://github.com/llvm/llvm-project/pull/89567, if `N` is value
dependent, 'option' and 'state' were ` (LoopHintAttr::Unroll,
LoopHintAttr::Enable)`. Therefor, clang's code generator generated
incorrect IR metadata.

For the situation `#pragma {GCC} unroll {0|1}`, before template
instantiation, this PR tweak the 'option' to `LoopHintAttr::UnrollCount`
and 'state' to `LoopHintAttr::Numeric`. During template instantiation
and if unroll count is 0 or 1 this PR tweak 'option' to
`LoopHintAttr::Unroll` and 'state' to `LoopHintAttr::Disable`. We don't
use `LoopHintAttr::UnrollCount` here because it's will emit an redundant
LLVM IR metadata `!{!"llvm.loop.unroll.count", i32 1}` when unroll count
is 1.

---------

Signed-off-by: yronglin <yronglin777@gmail.com>
2024-04-29 22:00:41 +08:00

32 lines
936 B
C++

// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ast-dump %s | FileCheck %s
using size_t = unsigned long long;
// CHECK: LoopHintAttr {{.*}} Implicit unroll UnrollCount Numeric
// CHECK: LoopHintAttr {{.*}} Implicit unroll UnrollCount Numeric
// CHECK: LoopHintAttr {{.*}} Implicit unroll Unroll Disable
// CHECK: LoopHintAttr {{.*}} Implicit unroll Unroll Disable
template <bool Flag>
int value_dependent(int n) {
constexpr int N = 100;
auto init = [=]() { return Flag ? n : 0UL; };
auto cond = [=](size_t ix) { return Flag ? ix != 0 : ix < 10; };
auto iter = [=](size_t ix) {
return Flag ? ix & ~(1ULL << __builtin_clzll(ix)) : ix + 1;
};
#pragma unroll Flag ? 1 : N
for (size_t ix = init(); cond(ix); ix = iter(ix)) {
n *= n;
}
#pragma unroll Flag ? 0 : N
for (size_t ix = init(); cond(ix); ix = iter(ix)) {
n *= n;
}
return n;
}
void test_value_dependent(int n) {
value_dependent<true>(n);
}