indvars: insert truncate at loop boundary to avoid redundant IVs.
authorAndrew Trick <atrick@apple.com>
Thu, 2 Jan 2014 19:29:38 +0000 (19:29 +0000)
committerAndrew Trick <atrick@apple.com>
Thu, 2 Jan 2014 19:29:38 +0000 (19:29 +0000)
When widening an IV to remove s/zext, we generally try to eliminate
the original narrow IV. However, LCSSA phi nodes outside the loop were
still using the original IV. Clean this up more aggressively to avoid
redundancy in generated code.

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

lib/Transforms/Scalar/IndVarSimplify.cpp
test/Transforms/IndVarSimplify/iv-widen.ll [new file with mode: 0644]

index c291f68bd6343adc545467775103839a61e3c2cf..c992f8c12a62f9ada684c8a7a6e7447ed7daed67 100644 (file)
@@ -897,15 +897,24 @@ const SCEVAddRecExpr *WidenIV::GetWideRecurrence(Instruction *NarrowUse) {
   return AddRec;
 }
 
+/// This IV user cannot be widen. Replace this use of the original narrow IV
+/// with a truncation of the new wide IV to isolate and eliminate the narrow IV.
+static void truncateIVUse(NarrowIVDefUse DU, DominatorTree *DT) {
+  IRBuilder<> Builder(getInsertPointForUses(DU.NarrowUse, DU.NarrowDef, DT));
+  Value *Trunc = Builder.CreateTrunc(DU.WideDef, DU.NarrowDef->getType());
+  DU.NarrowUse->replaceUsesOfWith(DU.NarrowDef, Trunc);
+}
+
 /// WidenIVUse - Determine whether an individual user of the narrow IV can be
 /// widened. If so, return the wide clone of the user.
 Instruction *WidenIV::WidenIVUse(NarrowIVDefUse DU, SCEVExpander &Rewriter) {
 
   // Stop traversing the def-use chain at inner-loop phis or post-loop phis.
   if (isa<PHINode>(DU.NarrowUse) &&
-      LI->getLoopFor(DU.NarrowUse->getParent()) != L)
+      LI->getLoopFor(DU.NarrowUse->getParent()) != L) {
+    truncateIVUse(DU, DT);
     return 0;
-
+  }
   // Our raison d'etre! Eliminate sign and zero extension.
   if (IsSigned ? isa<SExtInst>(DU.NarrowUse) : isa<ZExtInst>(DU.NarrowUse)) {
     Value *NewDef = DU.WideDef;
@@ -953,9 +962,7 @@ Instruction *WidenIV::WidenIVUse(NarrowIVDefUse DU, SCEVExpander &Rewriter) {
     // This user does not evaluate to a recurence after widening, so don't
     // follow it. Instead insert a Trunc to kill off the original use,
     // eventually isolating the original narrow IV so it can be removed.
-    IRBuilder<> Builder(getInsertPointForUses(DU.NarrowUse, DU.NarrowDef, DT));
-    Value *Trunc = Builder.CreateTrunc(DU.WideDef, DU.NarrowDef->getType());
-    DU.NarrowUse->replaceUsesOfWith(DU.NarrowDef, Trunc);
+    truncateIVUse(DU, DT);
     return 0;
   }
   // Assume block terminators cannot evaluate to a recurrence. We can't to
diff --git a/test/Transforms/IndVarSimplify/iv-widen.ll b/test/Transforms/IndVarSimplify/iv-widen.ll
new file mode 100644 (file)
index 0000000..12067ab
--- /dev/null
@@ -0,0 +1,39 @@
+; RUN: opt < %s -indvars -S | FileCheck %s
+
+target triple = "x86_64-apple-darwin"
+
+; CHECK-LABEL: @sloop
+; CHECK-LABEL: B18:
+; Only one phi now.
+; CHECK: phi
+; CHECK-NOT: phi
+; We now get 2 trunc, one for the gep and one for the lcssa phi.
+; CHECK: trunc i64 %indvars.iv to i32
+; CHECK: trunc i64 %indvars.iv to i32
+; CHECK-LABEL: B24:
+define void @sloop(i32* %a) {
+Prologue:
+  br i1 undef, label %B18, label %B6
+
+B18:                                        ; preds = %B24, %Prologue
+  %.02 = phi i32 [ 0, %Prologue ], [ %tmp33, %B24 ]
+  %tmp23 = zext i32 %.02 to i64
+  %tmp33 = add i32 %.02, 1
+  %o = getelementptr i32* %a, i32 %.02
+  %v = load i32* %o
+  %t = icmp eq i32 %v, 0
+  br i1 %t, label %exit24, label %B24
+
+B24:                                        ; preds = %B18
+  %t2 = icmp eq i32 %tmp33, 20
+  br i1 %t2, label %B6, label %B18
+
+B6:                                       ; preds = %Prologue
+  ret void
+
+exit24:                      ; preds = %B18
+  call void @dummy(i32 %.02)
+  unreachable
+}
+
+declare void @dummy(i32)