summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/Scalar/LoopUnroll.cpp30
-rw-r--r--test/Transforms/LoopUnroll/partial.ll15
2 files changed, 41 insertions, 4 deletions
diff --git a/lib/Transforms/Scalar/LoopUnroll.cpp b/lib/Transforms/Scalar/LoopUnroll.cpp
index 492db4db09..386b91c252 100644
--- a/lib/Transforms/Scalar/LoopUnroll.cpp
+++ b/lib/Transforms/Scalar/LoopUnroll.cpp
@@ -33,6 +33,11 @@ static cl::opt<unsigned>
UnrollCount("unroll-count", cl::init(0), cl::Hidden,
cl::desc("Use this unroll count for all loops, for testing purposes"));
+static cl::opt<bool>
+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/test/Transforms/LoopUnroll/partial.ll b/test/Transforms/LoopUnroll/partial.ll
new file mode 100644
index 0000000000..26da82b3b2
--- /dev/null
+++ b/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 ] ; <i32> [#uses=1]
+ %indvar.next = add i32 %indvar, 1 ; <i32> [#uses=2]
+ %exitcond = icmp ne i32 %indvar.next, 100 ; <i1> [#uses=1]
+ br i1 %exitcond, label %no_exit, label %loopexit
+loopexit: ; preds = %no_exit
+ ret i32 0
+}