LoopVectorizer: When we vectorizer and widen loops we process many elements at once. This is a good thing, except for

small loops. On small loops post-loop that handles scalars (and runs slower) can take more time to execute than the
rest of the loop. This patch disables widening of loops with a small static trip count.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171798 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nadav Rotem 2013-01-07 21:54:51 +00:00
parent 6c1d4972cf
commit 9a6c6a3736
2 changed files with 65 additions and 3 deletions

View File

@ -101,7 +101,13 @@ EnableIfConversion("enable-if-conversion", cl::init(true), cl::Hidden,
cl::desc("Enable if-conversion during vectorization."));
/// We don't vectorize loops with a known constant trip count below this number.
static const unsigned TinyTripCountThreshold = 16;
static const unsigned TinyTripCountVectorThreshold = 16;
/// We don't unroll loops with a known constant trip count below this number.
static const unsigned TinyTripCountUnrollThreshold = 128;
/// We don't unroll loops that are larget than this threshold.
static const unsigned MaxLoopSizeThreshold = 32;
/// When performing a runtime memory check, do not check more than this
/// number of pointers. Notice that the check is quadratic!
@ -2016,7 +2022,7 @@ bool LoopVectorizationLegality::canVectorize() {
// Do not loop-vectorize loops with a tiny trip count.
unsigned TC = SE->getSmallConstantTripCount(TheLoop, Latch);
if (TC > 0u && TC < TinyTripCountThreshold) {
if (TC > 0u && TC < TinyTripCountVectorThreshold) {
DEBUG(dbgs() << "LV: Found a loop with a very small trip count. " <<
"This loop is not worth vectorizing.\n");
return false;
@ -2678,6 +2684,12 @@ LoopVectorizationCostModel::selectUnrollFactor(bool OptForSize,
if (OptForSize)
return 1;
// Do not unroll loops with a relatively small trip count.
unsigned TC = SE->getSmallConstantTripCount(TheLoop,
TheLoop->getLoopLatch());
if (TC > 1 && TC < TinyTripCountUnrollThreshold)
return 1;
unsigned TargetVectorRegisters = TTI.getNumberOfRegisters(true);
DEBUG(dbgs() << "LV: The target has " << TargetVectorRegisters <<
" vector registers\n");
@ -2698,7 +2710,7 @@ LoopVectorizationCostModel::selectUnrollFactor(bool OptForSize,
// We don't want to unroll the loops to the point where they do not fit into
// the decoded cache. Assume that we only allow 32 IR instructions.
UF = std::min(UF, (32 / R.NumInstructions));
UF = std::min(UF, (MaxLoopSizeThreshold / R.NumInstructions));
// Clamp the unroll factor ranges to reasonable factors.
if (UF > MaxUnrollSize)

View File

@ -0,0 +1,50 @@
; RUN: opt < %s -loop-vectorize -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx2 -force-vector-width=4 -force-vector-unroll=0 -dce -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"
target triple = "x86_64-apple-macosx10.8.0"
;CHECK: @foo
;CHECK: load <4 x i32>
;CHECK-NOT: load <4 x i32>
;CHECK: store <4 x i32>
;CHECK-NOT: store <4 x i32>
;CHECK: ret
define i32 @foo(i32* nocapture %A) nounwind uwtable ssp {
br label %1
; <label>:1 ; preds = %1, %0
%indvars.iv = phi i64 [ 0, %0 ], [ %indvars.iv.next, %1 ]
%2 = getelementptr inbounds i32* %A, i64 %indvars.iv
%3 = load i32* %2, align 4
%4 = add nsw i32 %3, 6
store i32 %4, i32* %2, align 4
%indvars.iv.next = add i64 %indvars.iv, 1
%lftr.wideiv = trunc i64 %indvars.iv.next to i32
%exitcond = icmp eq i32 %lftr.wideiv, 100
br i1 %exitcond, label %5, label %1
; <label>:5 ; preds = %1
ret i32 undef
}
;CHECK: @bar
;CHECK: store <4 x i32>
;CHECK: store <4 x i32>
;CHECK: ret
define i32 @bar(i32* nocapture %A, i32 %n) nounwind uwtable ssp {
%1 = icmp sgt i32 %n, 0
br i1 %1, label %.lr.ph, label %._crit_edge
.lr.ph: ; preds = %0, %.lr.ph
%indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %0 ]
%2 = getelementptr inbounds i32* %A, i64 %indvars.iv
%3 = load i32* %2, align 4
%4 = add nsw i32 %3, 6
store i32 %4, i32* %2, align 4
%indvars.iv.next = add i64 %indvars.iv, 1
%lftr.wideiv = trunc i64 %indvars.iv.next to i32
%exitcond = icmp eq i32 %lftr.wideiv, %n
br i1 %exitcond, label %._crit_edge, label %.lr.ph
._crit_edge: ; preds = %.lr.ph, %0
ret i32 undef
}