Don't attempt to simplify an non-affine IV expression if it can't
authorDan Gohman <gohman@apple.com>
Wed, 3 Jun 2009 19:11:31 +0000 (19:11 +0000)
committerDan Gohman <gohman@apple.com>
Wed, 3 Jun 2009 19:11:31 +0000 (19:11 +0000)
be simplified to a loop-invariant value. This fixes PR4315.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72798 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/IndVarSimplify.cpp
test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll [new file with mode: 0644]
test/Transforms/IndVarSimplify/variable-stride-ivs-1.ll [new file with mode: 0644]
test/Transforms/IndVarSimplify/variable-stride-ivs.ll [deleted file]

index ca7aa7bd30db652a05b87c7c3595121f7ebd7b32..af61eae16f802a704434cdfc7da74abdc6724d5e 100644 (file)
@@ -465,17 +465,6 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType,
       // Compute the final addrec to expand into code.
       SCEVHandle AR = IU->getReplacementExpr(*UI);
 
-      // FIXME: It is an extremely bad idea to indvar substitute anything more
-      // complex than affine induction variables.  Doing so will put expensive
-      // polynomial evaluations inside of the loop, and the str reduction pass
-      // currently can only reduce affine polynomials.  For now just disable
-      // indvar subst on anything more complex than an affine addrec, unless
-      // it can be expanded to a trivial value.
-      if (!Stride->isLoopInvariant(L) &&
-          !isa<SCEVConstant>(AR) &&
-          L->contains(User->getParent()))
-        continue;
-
       Value *NewVal = 0;
       if (AR->isLoopInvariant(L)) {
         BasicBlock::iterator I = Rewriter.getInsertionPoint();
@@ -487,6 +476,15 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType,
         Rewriter.setInsertionPoint(I);
         ++NumReplaced;
       } else {
+        // FIXME: It is an extremely bad idea to indvar substitute anything more
+        // complex than affine induction variables.  Doing so will put expensive
+        // polynomial evaluations inside of the loop, and the str reduction pass
+        // currently can only reduce affine polynomials.  For now just disable
+        // indvar subst on anything more complex than an affine addrec, unless
+        // it can be expanded to a trivial value.
+        if (!Stride->isLoopInvariant(L))
+          continue;
+
         const Type *IVTy = Offset->getType();
         const Type *UseTy = Op->getType();
 
@@ -520,7 +518,7 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType,
         // induction variable, still in the canonical induction variable's
         // type, so that all expanded arithmetic is done in the same type.
         SCEVHandle NewAR = SE->getAddRecExpr(SE->getIntegerSCEV(0, LargestType),
-                                           PromotedStride, L);
+                                             PromotedStride, L);
         // Add the PromotedOffset as a separate step, because it may not be
         // loop-invariant.
         NewAR = SE->getAddExpr(NewAR, PromotedOffset);
diff --git a/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll b/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll
new file mode 100644 (file)
index 0000000..759ba8e
--- /dev/null
@@ -0,0 +1,43 @@
+; RUN: llvm-as < %s | opt -indvars -instcombine | llvm-dis | \
+; RUN:   grep {store i32 0}
+; Test that -indvars can reduce variable stride IVs.  If it can reduce variable
+; stride iv's, it will make %iv. and %m.0.0 isomorphic to each other without 
+; cycles, allowing the tmp.21 subtraction to be eliminated.
+; END.
+
+define void @vnum_test8(i32* %data) {
+entry:
+        %tmp.1 = getelementptr i32* %data, i32 3                ; <i32*> [#uses=1]
+        %tmp.2 = load i32* %tmp.1               ; <i32> [#uses=2]
+        %tmp.4 = getelementptr i32* %data, i32 4                ; <i32*> [#uses=1]
+        %tmp.5 = load i32* %tmp.4               ; <i32> [#uses=2]
+        %tmp.8 = getelementptr i32* %data, i32 2                ; <i32*> [#uses=1]
+        %tmp.9 = load i32* %tmp.8               ; <i32> [#uses=3]
+        %tmp.125 = icmp sgt i32 %tmp.2, 0               ; <i1> [#uses=1]
+        br i1 %tmp.125, label %no_exit.preheader, label %return
+
+no_exit.preheader:              ; preds = %entry
+        %tmp.16 = getelementptr i32* %data, i32 %tmp.9          ; <i32*> [#uses=1]
+        br label %no_exit
+
+no_exit:                ; preds = %no_exit, %no_exit.preheader
+        %iv.ui = phi i32 [ 0, %no_exit.preheader ], [ %iv..inc.ui, %no_exit ]           ; <i32> [#uses=1]
+        %iv. = phi i32 [ %tmp.5, %no_exit.preheader ], [ %iv..inc, %no_exit ]           ; <i32> [#uses=2]
+        %m.0.0 = phi i32 [ %tmp.5, %no_exit.preheader ], [ %tmp.24, %no_exit ]          ; <i32> [#uses=2]
+        store i32 2, i32* %tmp.16
+        %tmp.21 = sub i32 %m.0.0, %iv.          ; <i32> [#uses=1]
+        store i32 %tmp.21, i32* %data
+        %tmp.24 = add i32 %m.0.0, %tmp.9                ; <i32> [#uses=1]
+        %iv..inc = add i32 %tmp.9, %iv.         ; <i32> [#uses=1]
+        %iv..inc.ui = add i32 %iv.ui, 1         ; <i32> [#uses=2]
+        %iv..inc1 = bitcast i32 %iv..inc.ui to i32              ; <i32> [#uses=1]
+        %tmp.12 = icmp slt i32 %iv..inc1, %tmp.2                ; <i1> [#uses=1]
+        br i1 %tmp.12, label %no_exit, label %return.loopexit
+
+return.loopexit:                ; preds = %no_exit
+        br label %return
+
+return:         ; preds = %return.loopexit, %entry
+        ret void
+}
+
diff --git a/test/Transforms/IndVarSimplify/variable-stride-ivs-1.ll b/test/Transforms/IndVarSimplify/variable-stride-ivs-1.ll
new file mode 100644 (file)
index 0000000..075e899
--- /dev/null
@@ -0,0 +1,43 @@
+; RUN: llvm-as < %s | opt -indvars
+; PR4315
+
+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-f80:128:128"
+target triple = "x86_64-undermydesk-freebsd8.0"
+       %struct.mbuf = type <{ %struct.mbuf*, i8*, i32, i8, i8, i8, i8 }>
+
+define i32 @crash(%struct.mbuf* %m) nounwind {
+entry:
+       br label %for.cond
+
+for.cond:              ; preds = %if.end, %entry
+       %i.0 = phi i32 [ 0, %entry ], [ %inc, %if.end ]         ; <i32> [#uses=3]
+       %chksum.0 = phi i8 [ 0, %entry ], [ %conv3, %if.end ]           ; <i8> [#uses=3]
+       %cmp = icmp slt i32 %i.0, 1             ; <i1> [#uses=1]
+       br i1 %cmp, label %for.body, label %do.body
+
+for.body:              ; preds = %for.cond
+       br i1 undef, label %if.end, label %do.body
+
+if.end:                ; preds = %for.body
+       %i.02 = trunc i32 %i.0 to i8            ; <i8> [#uses=1]
+       %conv3 = add i8 %chksum.0, %i.02                ; <i8> [#uses=1]
+       %inc = add i32 %i.0, 1          ; <i32> [#uses=1]
+       br label %for.cond
+
+do.body:               ; preds = %do.cond, %for.body, %for.cond
+       %chksum.2 = phi i8 [ undef, %do.cond ], [ %chksum.0, %for.body ], [ %chksum.0, %for.cond ]              ; <i8> [#uses=1]
+       br i1 undef, label %do.cond, label %bb.nph
+
+bb.nph:                ; preds = %do.body
+       br label %while.body
+
+while.body:            ; preds = %while.body, %bb.nph
+       %chksum.13 = phi i8 [ undef, %while.body ], [ %chksum.2, %bb.nph ]              ; <i8> [#uses=0]
+       br i1 undef, label %do.cond, label %while.body
+
+do.cond:               ; preds = %while.body, %do.body
+       br i1 false, label %do.end, label %do.body
+
+do.end:                ; preds = %do.cond
+       ret i32 0
+}
diff --git a/test/Transforms/IndVarSimplify/variable-stride-ivs.ll b/test/Transforms/IndVarSimplify/variable-stride-ivs.ll
deleted file mode 100644 (file)
index 759ba8e..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-; RUN: llvm-as < %s | opt -indvars -instcombine | llvm-dis | \
-; RUN:   grep {store i32 0}
-; Test that -indvars can reduce variable stride IVs.  If it can reduce variable
-; stride iv's, it will make %iv. and %m.0.0 isomorphic to each other without 
-; cycles, allowing the tmp.21 subtraction to be eliminated.
-; END.
-
-define void @vnum_test8(i32* %data) {
-entry:
-        %tmp.1 = getelementptr i32* %data, i32 3                ; <i32*> [#uses=1]
-        %tmp.2 = load i32* %tmp.1               ; <i32> [#uses=2]
-        %tmp.4 = getelementptr i32* %data, i32 4                ; <i32*> [#uses=1]
-        %tmp.5 = load i32* %tmp.4               ; <i32> [#uses=2]
-        %tmp.8 = getelementptr i32* %data, i32 2                ; <i32*> [#uses=1]
-        %tmp.9 = load i32* %tmp.8               ; <i32> [#uses=3]
-        %tmp.125 = icmp sgt i32 %tmp.2, 0               ; <i1> [#uses=1]
-        br i1 %tmp.125, label %no_exit.preheader, label %return
-
-no_exit.preheader:              ; preds = %entry
-        %tmp.16 = getelementptr i32* %data, i32 %tmp.9          ; <i32*> [#uses=1]
-        br label %no_exit
-
-no_exit:                ; preds = %no_exit, %no_exit.preheader
-        %iv.ui = phi i32 [ 0, %no_exit.preheader ], [ %iv..inc.ui, %no_exit ]           ; <i32> [#uses=1]
-        %iv. = phi i32 [ %tmp.5, %no_exit.preheader ], [ %iv..inc, %no_exit ]           ; <i32> [#uses=2]
-        %m.0.0 = phi i32 [ %tmp.5, %no_exit.preheader ], [ %tmp.24, %no_exit ]          ; <i32> [#uses=2]
-        store i32 2, i32* %tmp.16
-        %tmp.21 = sub i32 %m.0.0, %iv.          ; <i32> [#uses=1]
-        store i32 %tmp.21, i32* %data
-        %tmp.24 = add i32 %m.0.0, %tmp.9                ; <i32> [#uses=1]
-        %iv..inc = add i32 %tmp.9, %iv.         ; <i32> [#uses=1]
-        %iv..inc.ui = add i32 %iv.ui, 1         ; <i32> [#uses=2]
-        %iv..inc1 = bitcast i32 %iv..inc.ui to i32              ; <i32> [#uses=1]
-        %tmp.12 = icmp slt i32 %iv..inc1, %tmp.2                ; <i1> [#uses=1]
-        br i1 %tmp.12, label %no_exit, label %return.loopexit
-
-return.loopexit:                ; preds = %no_exit
-        br label %return
-
-return:         ; preds = %return.loopexit, %entry
-        ret void
-}
-