mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-19 11:35:51 -04:00

This change adds the new unroll metadata "llvm.loop.unroll.enable" which directs the optimizer to unroll a loop fully if the trip count is known at compile time, and unroll partially if the trip count is not known at compile time. This differs from "llvm.loop.unroll.full" which explicitly does not unroll a loop if the trip count is not known at compile time With this change "#pragma unroll" generates "llvm.loop.unroll.enable" rather than "llvm.loop.unroll.full" metadata. This changes the semantics of "#pragma unroll" slightly to mean "unroll aggressively (fully or partially)" rather than "unroll fully or not at all". The motivating example for this change was some internal code with a loop marked with "#pragma unroll" which only sometimes had a compile-time trip count depending on template magic. When the trip count was a compile-time constant, everything works as expected and the loop is fully unrolled. However, when the trip count was not a compile-time constant the "#pragma unroll" explicitly disabled unrolling of the loop(!). Removing "#pragma unroll" caused the loop to be unrolled partially which was desirable from a performance perspective. llvm-svn: 244467
107 lines
3.2 KiB
C++
107 lines
3.2 KiB
C++
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s
|
|
|
|
// Verify while loop is recognized after unroll pragma.
|
|
void while_test(int *List, int Length) {
|
|
// CHECK: define {{.*}} @_Z10while_test
|
|
int i = 0;
|
|
|
|
#pragma unroll
|
|
while (i < Length) {
|
|
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]]
|
|
List[i] = i * 2;
|
|
i++;
|
|
}
|
|
}
|
|
|
|
// Verify do loop is recognized after multi-option pragma clang loop directive.
|
|
void do_test(int *List, int Length) {
|
|
// CHECK: define {{.*}} @_Z7do_test
|
|
int i = 0;
|
|
|
|
#pragma nounroll
|
|
do {
|
|
// CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_2:.*]]
|
|
List[i] = i * 2;
|
|
i++;
|
|
} while (i < Length);
|
|
}
|
|
|
|
// Verify for loop is recognized after unroll pragma.
|
|
void for_test(int *List, int Length) {
|
|
// CHECK: define {{.*}} @_Z8for_test
|
|
#pragma unroll 8
|
|
for (int i = 0; i < Length; i++) {
|
|
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_3:.*]]
|
|
List[i] = i * 2;
|
|
}
|
|
}
|
|
|
|
// Verify c++11 for range loop is recognized after unroll pragma.
|
|
void for_range_test() {
|
|
// CHECK: define {{.*}} @_Z14for_range_test
|
|
double List[100];
|
|
|
|
#pragma unroll(4)
|
|
for (int i : List) {
|
|
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_4:.*]]
|
|
List[i] = i;
|
|
}
|
|
}
|
|
|
|
#define UNROLLCOUNT 8
|
|
|
|
// Verify defines are correctly resolved in unroll pragmas.
|
|
void for_define_test(int *List, int Length, int Value) {
|
|
// CHECK: define {{.*}} @_Z15for_define_test
|
|
#pragma unroll(UNROLLCOUNT)
|
|
for (int i = 0; i < Length; i++) {
|
|
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_5:.*]]
|
|
List[i] = i * Value;
|
|
}
|
|
}
|
|
|
|
// Verify metadata is generated when template is used.
|
|
template <typename A>
|
|
void for_template_test(A *List, int Length, A Value) {
|
|
// CHECK: define {{.*}} @_Z13template_test
|
|
#pragma unroll 8
|
|
for (int i = 0; i < Length; i++) {
|
|
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_6:.*]]
|
|
List[i] = i * Value;
|
|
}
|
|
}
|
|
|
|
// Verify define is resolved correctly when template is used.
|
|
template <typename A>
|
|
void for_template_define_test(A *List, int Length, A Value) {
|
|
// CHECK: define {{.*}} @_Z24for_template_define_test
|
|
|
|
#pragma unroll(UNROLLCOUNT)
|
|
for (int i = 0; i < Length; i++) {
|
|
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_7:.*]]
|
|
List[i] = i * Value;
|
|
}
|
|
}
|
|
|
|
#undef UNROLLCOUNT
|
|
|
|
// Use templates defined above. Test verifies metadata is generated correctly.
|
|
void template_test(double *List, int Length) {
|
|
double Value = 10;
|
|
|
|
for_template_test<double>(List, Length, Value);
|
|
for_template_define_test<double>(List, Length, Value);
|
|
}
|
|
|
|
// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNROLL_ENABLE:.*]]}
|
|
// CHECK: ![[UNROLL_ENABLE]] = !{!"llvm.loop.unroll.enable"}
|
|
// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[UNROLL_DISABLE:.*]]}
|
|
// CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"}
|
|
// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNROLL_8:.*]]}
|
|
// CHECK: ![[UNROLL_8]] = !{!"llvm.loop.unroll.count", i32 8}
|
|
// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[UNROLL_4:.*]]}
|
|
// CHECK: ![[UNROLL_4]] = !{!"llvm.loop.unroll.count", i32 4}
|
|
// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[UNROLL_8:.*]]}
|
|
// CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[UNROLL_8:.*]]}
|
|
// CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[UNROLL_8:.*]]}
|