From 98b5c16e3bf2f26264925e74f89b8a1d77ea2a1a Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Tue, 29 Jul 2008 13:21:23 +0000 Subject: [PATCH] Add -unroll-allow-partial command line option that enabled the loop unroller to partially unroll a loop when fully unrolling would not fit under the threshold. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch by Mikael Lepistö. llvm-svn: 54160 --- llvm/lib/Transforms/Scalar/LoopUnroll.cpp | 30 +++++++++++++++++++--- llvm/test/Transforms/LoopUnroll/partial.ll | 15 +++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 llvm/test/Transforms/LoopUnroll/partial.ll diff --git a/llvm/lib/Transforms/Scalar/LoopUnroll.cpp b/llvm/lib/Transforms/Scalar/LoopUnroll.cpp index 492db4db0973..386b91c252ca 100644 --- a/llvm/lib/Transforms/Scalar/LoopUnroll.cpp +++ b/llvm/lib/Transforms/Scalar/LoopUnroll.cpp @@ -33,6 +33,11 @@ static cl::opt UnrollCount("unroll-count", cl::init(0), cl::Hidden, cl::desc("Use this unroll count for all loops, for testing purposes")); +static cl::opt +UnrollAllowPartial("unroll-allow-partial", cl::init(false), cl::Hidden, + cl::desc("Allows loops to be partially unrolled until " + "-unroll-threshold loop size is reached.")); + namespace { class VISIBILITY_HIDDEN LoopUnroll : public LoopPass { public: @@ -122,7 +127,8 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) { if (Count == 0) { // Conservative heuristic: if we know the trip count, see if we can // completely unroll (subject to the threshold, checked below); otherwise - // don't unroll. + // try to find greatest modulo of the trip count which is still under + // threshold value. if (TripCount != 0) { Count = TripCount; } else { @@ -136,9 +142,25 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) { DOUT << " Loop Size = " << LoopSize << "\n"; uint64_t Size = (uint64_t)LoopSize*Count; if (TripCount != 1 && Size > UnrollThreshold) { - DOUT << " TOO LARGE TO UNROLL: " - << Size << ">" << UnrollThreshold << "\n"; - return false; + DOUT << " Too large to fully unroll with count: " << Count + << " because size: " << Size << ">" << UnrollThreshold << "\n"; + if (UnrollAllowPartial) { + // Reduce unroll count to be modulo of TripCount for partial unrolling + Count = UnrollThreshold / LoopSize; + while (Count != 0 && TripCount%Count != 0) { + Count--; + } + if (Count < 2) { + DOUT << " could not unroll partially\n"; + return false; + } else { + DOUT << " partially unrolling with count: " << Count << "\n"; + } + } else { + DOUT << " will not try to unroll partially because " + << "-unroll-allow-partial not given\n"; + return false; + } } } diff --git a/llvm/test/Transforms/LoopUnroll/partial.ll b/llvm/test/Transforms/LoopUnroll/partial.ll new file mode 100644 index 000000000000..26da82b3b2bc --- /dev/null +++ b/llvm/test/Transforms/LoopUnroll/partial.ll @@ -0,0 +1,15 @@ +; RUN: llvm-as < %s | opt -debug -loop-unroll |& grep {will not try to unroll partially because} +; RUN: llvm-as < %s | opt -debug -loop-unroll -unroll-allow-partial |& grep {partially unrolling with count} +; RUN: llvm-as < %s | opt -debug -loop-unroll -unroll-allow-partial -unroll-threshold=3 |& grep {could not unroll partially} + +define i32 @main() { +entry: + br label %no_exit +no_exit: ; preds = %no_exit, %entry + %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %no_exit ] ; [#uses=1] + %indvar.next = add i32 %indvar, 1 ; [#uses=2] + %exitcond = icmp ne i32 %indvar.next, 100 ; [#uses=1] + br i1 %exitcond, label %no_exit, label %loopexit +loopexit: ; preds = %no_exit + ret i32 0 +}