[llvm] r234846 - [LoopUnrollRuntime] Avoid high-cost trip count computation.
Sanjoy Das
sanjoy at playingwithpointers.com
Mon Apr 13 20:20:38 PDT 2015
Author: sanjoy
Date: Mon Apr 13 22:20:38 2015
New Revision: 234846
URL: http://llvm.org/viewvc/llvm-project?rev=234846&view=rev
Log:
[LoopUnrollRuntime] Avoid high-cost trip count computation.
Summary:
Runtime unrolling of loops needs to emit an expression to compute the
loop's runtime trip-count. Avoid runtime unrolling if this computation
will be expensive.
Depends on D8993.
Reviewers: atrick
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D8994
Added:
llvm/trunk/test/Transforms/LoopUnroll/high-cost-trip-count-computation.ll
Modified:
llvm/trunk/include/llvm/Analysis/TargetTransformInfo.h
llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h
llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
llvm/trunk/lib/Transforms/Utils/LoopUnrollRuntime.cpp
llvm/trunk/test/Transforms/LoopUnroll/runtime-loop.ll
llvm/trunk/test/Transforms/LoopUnroll/runtime-loop4.ll
Modified: llvm/trunk/include/llvm/Analysis/TargetTransformInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/TargetTransformInfo.h?rev=234846&r1=234845&r2=234846&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/TargetTransformInfo.h (original)
+++ llvm/trunk/include/llvm/Analysis/TargetTransformInfo.h Mon Apr 13 22:20:38 2015
@@ -261,6 +261,9 @@ public:
/// loop body even when the number of loop iterations is not known at
/// compile time).
bool Runtime;
+ /// Allow emitting expensive instructions (such as divisions) when computing
+ /// the trip count of a loop for runtime unrolling.
+ bool AllowExpensiveTripCount;
};
/// \brief Get target-customized preferences for the generic loop unrolling
Modified: llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h?rev=234846&r1=234845&r2=234846&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h (original)
+++ llvm/trunk/include/llvm/Transforms/Utils/UnrollLoop.h Mon Apr 13 22:20:38 2015
@@ -28,11 +28,13 @@ class MDNode;
class Pass;
bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool AllowRuntime,
- unsigned TripMultiple, LoopInfo *LI, Pass *PP,
- LPPassManager *LPM, AssumptionCache *AC);
+ bool AllowExpensiveTripCount, unsigned TripMultiple,
+ LoopInfo *LI, Pass *PP, LPPassManager *LPM,
+ AssumptionCache *AC);
-bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI,
- LPPassManager* LPM);
+bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count,
+ bool AllowExpensiveTripCount, LoopInfo *LI,
+ LPPassManager *LPM);
MDNode *GetUnrollMetadata(MDNode *LoopID, StringRef Name);
}
Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp?rev=234846&r1=234845&r2=234846&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Mon Apr 13 22:20:38 2015
@@ -165,6 +165,7 @@ namespace {
UP.MaxCount = UINT_MAX;
UP.Partial = CurrentAllowPartial;
UP.Runtime = CurrentRuntime;
+ UP.AllowExpensiveTripCount = false;
TTI.getUnrollingPreferences(L, UP);
}
@@ -886,8 +887,8 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPa
}
// Unroll the loop.
- if (!UnrollLoop(L, Count, TripCount, AllowRuntime, TripMultiple, LI, this,
- &LPM, &AC))
+ if (!UnrollLoop(L, Count, TripCount, AllowRuntime, UP.AllowExpensiveTripCount,
+ TripMultiple, LI, this, &LPM, &AC))
return false;
return true;
Modified: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp?rev=234846&r1=234845&r2=234846&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp Mon Apr 13 22:20:38 2015
@@ -146,6 +146,13 @@ FoldBlockIntoPredecessor(BasicBlock *BB,
/// Similarly, TripMultiple divides the number of times that the LatchBlock may
/// execute without exiting the loop.
///
+/// If AllowRuntime is true then UnrollLoop will consider unrolling loops that
+/// have a runtime (i.e. not compile time constant) trip count. Unrolling these
+/// loops require a unroll "prologue" that runs "RuntimeTripCount % Count"
+/// iterations before branching into the unrolled loop. UnrollLoop will not
+/// runtime-unroll the loop if computing RuntimeTripCount will be expensive and
+/// AllowExpensiveTripCount is false.
+///
/// The LoopInfo Analysis that is passed will be kept consistent.
///
/// If a LoopPassManager is passed in, and the loop is fully removed, it will be
@@ -154,8 +161,9 @@ FoldBlockIntoPredecessor(BasicBlock *BB,
/// This utility preserves LoopInfo. If DominatorTree or ScalarEvolution are
/// available from the Pass it must also preserve those analyses.
bool llvm::UnrollLoop(Loop *L, unsigned Count, unsigned TripCount,
- bool AllowRuntime, unsigned TripMultiple, LoopInfo *LI,
- Pass *PP, LPPassManager *LPM, AssumptionCache *AC) {
+ bool AllowRuntime, bool AllowExpensiveTripCount,
+ unsigned TripMultiple, LoopInfo *LI, Pass *PP,
+ LPPassManager *LPM, AssumptionCache *AC) {
BasicBlock *Preheader = L->getLoopPreheader();
if (!Preheader) {
DEBUG(dbgs() << " Can't unroll; loop preheader-insertion failed.\n");
@@ -218,7 +226,8 @@ bool llvm::UnrollLoop(Loop *L, unsigned
// flag is specified.
bool RuntimeTripCount = (TripCount == 0 && Count > 0 && AllowRuntime);
- if (RuntimeTripCount && !UnrollRuntimeLoopProlog(L, Count, LI, LPM))
+ if (RuntimeTripCount &&
+ !UnrollRuntimeLoopProlog(L, Count, AllowExpensiveTripCount, LI, LPM))
return false;
// Notify ScalarEvolution that the loop will be substantially changed,
Modified: llvm/trunk/lib/Transforms/Utils/LoopUnrollRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnrollRuntime.cpp?rev=234846&r1=234845&r2=234846&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/LoopUnrollRuntime.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/LoopUnrollRuntime.cpp Mon Apr 13 22:20:38 2015
@@ -278,7 +278,8 @@ static void CloneLoopBlocks(Loop *L, Val
/// ...
/// End:
///
-bool llvm::UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI,
+bool llvm::UnrollRuntimeLoopProlog(Loop *L, unsigned Count,
+ bool AllowExpensiveTripCount, LoopInfo *LI,
LPPassManager *LPM) {
// for now, only unroll loops that contain a single exit
if (!L->getExitingBlock())
@@ -312,6 +313,12 @@ bool llvm::UnrollRuntimeLoopProlog(Loop
if (isa<SCEVCouldNotCompute>(TripCountSC))
return false;
+ BasicBlock *Header = L->getHeader();
+ const DataLayout &DL = Header->getModule()->getDataLayout();
+ SCEVExpander Expander(*SE, DL, "loop-unroll");
+ if (!AllowExpensiveTripCount && Expander.isHighCostExpansion(TripCountSC, L))
+ return false;
+
// We only handle cases when the unroll factor is a power of 2.
// Count is the loop unroll factor, the number of extra copies added + 1.
if (!isPowerOf2_32(Count))
@@ -332,18 +339,15 @@ bool llvm::UnrollRuntimeLoopProlog(Loop
auto *DT = DTWP ? &DTWP->getDomTree() : nullptr;
BasicBlock *PH = L->getLoopPreheader();
- BasicBlock *Header = L->getHeader();
BasicBlock *Latch = L->getLoopLatch();
// It helps to splits the original preheader twice, one for the end of the
// prolog code and one for a new loop preheader
BasicBlock *PEnd = SplitEdge(PH, Header, DT, LI);
BasicBlock *NewPH = SplitBlock(PEnd, PEnd->getTerminator(), DT, LI);
BranchInst *PreHeaderBR = cast<BranchInst>(PH->getTerminator());
- const DataLayout &DL = Header->getModule()->getDataLayout();
// Compute the number of extra iterations required, which is:
// extra iterations = run-time trip count % (loop unroll factor + 1)
- SCEVExpander Expander(*SE, DL, "loop-unroll");
Value *TripCount = Expander.expandCodeFor(TripCountSC, TripCountSC->getType(),
PreHeaderBR);
Value *BECount = Expander.expandCodeFor(BECountSC, BECountSC->getType(),
Added: llvm/trunk/test/Transforms/LoopUnroll/high-cost-trip-count-computation.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/high-cost-trip-count-computation.ll?rev=234846&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LoopUnroll/high-cost-trip-count-computation.ll (added)
+++ llvm/trunk/test/Transforms/LoopUnroll/high-cost-trip-count-computation.ll Mon Apr 13 22:20:38 2015
@@ -0,0 +1,27 @@
+; RUN: opt -S -unroll-runtime -loop-unroll < %s | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+
+;; Check that we don't emit expensive instructions to compute trip
+;; counts when unrolling loops.
+
+define i32 @test(i64 %v12, i8* %array, i64* %loc) {
+; CHECK-LABEL: @test(
+; CHECK-NOT: udiv
+entry:
+ %step = load i64, i64* %loc, !range !0
+ br label %loop
+
+loop: ; preds = %entry, %loop
+ %k.015 = phi i64 [ %v15, %loop ], [ %v12, %entry ]
+ %v14 = getelementptr inbounds i8, i8* %array, i64 %k.015
+ store i8 0, i8* %v14
+ %v15 = add nuw nsw i64 %k.015, %step
+ %v16 = icmp slt i64 %v15, 8193
+ br i1 %v16, label %loop, label %loopexit
+
+loopexit: ; preds = %loop
+ ret i32 0
+}
+
+!0 = !{i64 1, i64 100}
Modified: llvm/trunk/test/Transforms/LoopUnroll/runtime-loop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/runtime-loop.ll?rev=234846&r1=234845&r2=234846&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LoopUnroll/runtime-loop.ll (original)
+++ llvm/trunk/test/Transforms/LoopUnroll/runtime-loop.ll Mon Apr 13 22:20:38 2015
@@ -1,5 +1,7 @@
; RUN: opt < %s -S -loop-unroll -unroll-runtime=true | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+
; Tests for unrolling loops with run-time trip counts
; CHECK: %xtraiter = and i32 %n
Modified: llvm/trunk/test/Transforms/LoopUnroll/runtime-loop4.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/runtime-loop4.ll?rev=234846&r1=234845&r2=234846&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LoopUnroll/runtime-loop4.ll (original)
+++ llvm/trunk/test/Transforms/LoopUnroll/runtime-loop4.ll Mon Apr 13 22:20:38 2015
@@ -20,7 +20,8 @@ loop1:
br label %loop2.header
loop2.header:
- br label %loop2
+ %e = icmp uge i32 %iter, 1
+ br i1 %e, label %loop2, label %exit2
loop2:
%iv2 = phi i32 [ 0, %loop2.header ], [ %inc2, %loop2 ]
More information about the llvm-commits
mailing list