2014-07-22 02:08:34 +08:00
|
|
|
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s | FileCheck %s
|
|
|
|
|
[Clang] Add llvm.loop.unroll.disable to loops with -fno-unroll-loops.
Currently Clang does not respect -fno-unroll-loops during LTO. During
D76916 it was suggested to respect -fno-unroll-loops on a TU basis.
This patch uses the existing llvm.loop.unroll.disable metadata to
disable loop unrolling explicitly for each loop in the TU if
unrolling is disabled. This should ensure that loops from TUs compiled
with -fno-unroll-loops are skipped by the unroller during LTO.
This also means that if a loop from a TU with -fno-unroll-loops
gets inlined into a TU without this option, the loop won't be
unrolled.
Due to the fact that some transforms might drop loop metadata, there
potentially are cases in which we still unroll loops from TUs with
-fno-unroll-loops. I think we should fix those issues rather than
introducing a function attribute to disable loop unrolling during LTO.
Improving the metadata handling will benefit other use cases, like
various loop pragmas, too. And it is an improvement to clang completely
ignoring -fno-unroll-loops during LTO.
If that direction looks good, we can use a similar approach to also
respect -fno-vectorize during LTO, at least for LoopVectorize.
In the future, this might also allow us to remove the UnrollLoops option
LLVM's PassManagerBuilder.
Reviewers: Meinersbur, hfinkel, dexonsmith, tejohnson
Reviewed By: Meinersbur, tejohnson
Differential Revision: https://reviews.llvm.org/D77058
2020-04-07 20:43:48 +08:00
|
|
|
// Check that passing -fno-unroll-loops does not impact the decision made using pragmas.
|
|
|
|
// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - -O1 -disable-llvm-optzns -fno-unroll-loops %s | FileCheck %s
|
|
|
|
|
2014-07-22 02:08:34 +08:00
|
|
|
// 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) {
|
2015-07-28 04:10:20 +08:00
|
|
|
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]]
|
2014-07-22 02:08:34 +08:00
|
|
|
List[i] = i * 2;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify do loop is recognized after multi-option pragma clang loop directive.
|
|
|
|
void do_test(int *List, int Length) {
|
2015-07-28 04:10:20 +08:00
|
|
|
// CHECK: define {{.*}} @_Z7do_test
|
2014-07-22 02:08:34 +08:00
|
|
|
int i = 0;
|
|
|
|
|
2014-07-25 02:09:38 +08:00
|
|
|
#pragma nounroll
|
2014-07-22 02:08:34 +08:00
|
|
|
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) {
|
2015-07-28 04:10:20 +08:00
|
|
|
// CHECK: define {{.*}} @_Z8for_test
|
2014-07-22 02:08:34 +08:00
|
|
|
#pragma unroll 8
|
|
|
|
for (int i = 0; i < Length; i++) {
|
2015-07-28 04:10:20 +08:00
|
|
|
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_3:.*]]
|
2014-07-22 02:08:34 +08:00
|
|
|
List[i] = i * 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify c++11 for range loop is recognized after unroll pragma.
|
|
|
|
void for_range_test() {
|
2015-07-28 04:10:20 +08:00
|
|
|
// CHECK: define {{.*}} @_Z14for_range_test
|
2014-07-22 02:08:34 +08:00
|
|
|
double List[100];
|
|
|
|
|
|
|
|
#pragma unroll(4)
|
|
|
|
for (int i : List) {
|
2015-07-28 04:10:20 +08:00
|
|
|
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_4:.*]]
|
2014-07-22 02:08:34 +08:00
|
|
|
List[i] = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define UNROLLCOUNT 8
|
|
|
|
|
|
|
|
// Verify defines are correctly resolved in unroll pragmas.
|
|
|
|
void for_define_test(int *List, int Length, int Value) {
|
2015-07-28 04:10:20 +08:00
|
|
|
// CHECK: define {{.*}} @_Z15for_define_test
|
2014-07-22 02:08:34 +08:00
|
|
|
#pragma unroll(UNROLLCOUNT)
|
|
|
|
for (int i = 0; i < Length; i++) {
|
2015-07-28 04:10:20 +08:00
|
|
|
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_5:.*]]
|
2014-07-22 02:08:34 +08:00
|
|
|
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) {
|
2015-07-28 04:10:20 +08:00
|
|
|
// CHECK: define {{.*}} @_Z13template_test
|
2014-07-22 02:08:34 +08:00
|
|
|
#pragma unroll 8
|
|
|
|
for (int i = 0; i < Length; i++) {
|
2015-07-28 04:10:20 +08:00
|
|
|
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_6:.*]]
|
2014-07-22 02:08:34 +08:00
|
|
|
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) {
|
2015-07-28 04:10:20 +08:00
|
|
|
// CHECK: define {{.*}} @_Z24for_template_define_test
|
|
|
|
|
2014-07-22 02:08:34 +08:00
|
|
|
#pragma unroll(UNROLLCOUNT)
|
|
|
|
for (int i = 0; i < Length; i++) {
|
2015-07-28 04:10:20 +08:00
|
|
|
// CHECK: br label {{.*}}, !llvm.loop ![[LOOP_7:.*]]
|
2014-07-22 02:08:34 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2015-08-11 01:29:39 +08:00
|
|
|
// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNROLL_ENABLE:.*]]}
|
|
|
|
// CHECK: ![[UNROLL_ENABLE]] = !{!"llvm.loop.unroll.enable"}
|
2015-01-09 06:39:28 +08:00
|
|
|
// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[UNROLL_DISABLE:.*]]}
|
2014-12-16 03:10:08 +08:00
|
|
|
// CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"}
|
2015-01-09 06:39:28 +08:00
|
|
|
// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNROLL_8:.*]]}
|
2014-12-16 03:10:08 +08:00
|
|
|
// CHECK: ![[UNROLL_8]] = !{!"llvm.loop.unroll.count", i32 8}
|
2015-01-09 06:39:28 +08:00
|
|
|
// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[UNROLL_4:.*]]}
|
2014-12-16 03:10:08 +08:00
|
|
|
// CHECK: ![[UNROLL_4]] = !{!"llvm.loop.unroll.count", i32 4}
|
2015-01-09 06:39:28 +08:00
|
|
|
// CHECK: ![[LOOP_5]] = distinct !{![[LOOP_5]], ![[UNROLL_8:.*]]}
|
|
|
|
// CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], ![[UNROLL_8:.*]]}
|
|
|
|
// CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[UNROLL_8:.*]]}
|