diff --git a/clang/test/Misc/loop-opt-setup.c b/clang/test/Misc/loop-opt-setup.c --- a/clang/test/Misc/loop-opt-setup.c +++ b/clang/test/Misc/loop-opt-setup.c @@ -1,5 +1,5 @@ -// RUN: %clang -O1 -fexperimental-new-pass-manager -fno-unroll-loops -S -o - %s -emit-llvm | FileCheck %s -// RUN: %clang -O1 -fno-experimental-new-pass-manager -fno-unroll-loops -S -o - %s -emit-llvm | FileCheck %s +// RUN: %clang -O1 -fexperimental-new-pass-manager -fno-unroll-loops -S -o - %s -emit-llvm | FileCheck %s -check-prefix=CHECK-NEWPM +// RUN: %clang -O1 -fno-experimental-new-pass-manager -fno-unroll-loops -S -o - %s -emit-llvm | FileCheck %s -check-prefix=CHECK-OLDPM extern int a[16]; int b = 0; int foo(void) { @@ -8,5 +8,34 @@ a[i] = b += 2; return b; } +// Check br i1 to make sure that the loop is fully unrolled // CHECK-NOT: br i1 +inline void Helper() { + const int* nodes[5]; + int num_active = 5; + + while (num_active) { +#pragma clang loop unroll(full) + for (int i = 0; i < 5; ++i) { + if (nodes[i]) { + --num_active; + } + } + } +} + +void Run() { + Helper(); +} + +// Check br i1 to make sure the loop is gone, there will still be a label branch for the infinite loop. +// CHECK-NEWPM-NOT: br i1 + +// The old pass manager doesn't remove the loop so check for 5 load i32*. +// CHECK-OLDPM: Helper +// CHECK-OLDPM: load i32* +// CHECK-OLDPM: load i32* +// CHECK-OLDPM: load i32* +// CHECK-OLDPM: load i32* +// CHECK-OLDPM: load i32* diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -496,12 +496,13 @@ LPM2.addPass(LoopDeletionPass()); // Do not enable unrolling in PreLinkThinLTO phase during sample PGO // because it changes IR to makes profile annotation in back compile - // inaccurate. - if ((Phase != ThinLTOPhase::PreLink || !PGOOpt || - PGOOpt->Action != PGOOptions::SampleUse) && - PTO.LoopUnrolling) + // inaccurate. The normal unroller doesn't pay attention to forced full unroll + // attributes so we need to make sure and allow the full unroll pass to pay + // attention to it. + if (Phase != ThinLTOPhase::PreLink || !PGOOpt || + PGOOpt->Action != PGOOptions::SampleUse) LPM2.addPass(LoopFullUnrollPass(Level.getSpeedupLevel(), - /*OnlyWhenForced=*/false, + /*OnlyWhenForced=*/!PTO.LoopUnrolling, PTO.ForgetAllSCEVInLoopUnroll)); for (auto &C : LoopOptimizerEndEPCallbacks)