[llvm] r269213 - [SCEVExpander] Fix a failed cast<> assertion

Sanjoy Das via llvm-commits llvm-commits at lists.llvm.org
Wed May 11 10:41:42 PDT 2016


Author: sanjoy
Date: Wed May 11 12:41:41 2016
New Revision: 269213

URL: http://llvm.org/viewvc/llvm-project?rev=269213&view=rev
Log:
[SCEVExpander] Fix a failed cast<> assertion

SCEVExpander::replaceCongruentIVs assumes the backedge value of an
SCEV-analysable PHI to always be an instruction, when this is not
necessarily true.  For now address this by bailing out of the
optimization if the backedge value of the PHI is a non-Instruction.

Modified:
    llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp
    llvm/trunk/test/Analysis/ScalarEvolution/expander-replace-congruent-ivs.ll

Modified: llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp?rev=269213&r1=269212&r2=269213&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Wed May 11 12:41:41 2016
@@ -1794,51 +1794,55 @@ unsigned SCEVExpander::replaceCongruentI
       continue;
 
     if (BasicBlock *LatchBlock = L->getLoopLatch()) {
-      Instruction *OrigInc =
-        cast<Instruction>(OrigPhiRef->getIncomingValueForBlock(LatchBlock));
+      Instruction *OrigInc = dyn_cast<Instruction>(
+          OrigPhiRef->getIncomingValueForBlock(LatchBlock));
       Instruction *IsomorphicInc =
-        cast<Instruction>(Phi->getIncomingValueForBlock(LatchBlock));
+          dyn_cast<Instruction>(Phi->getIncomingValueForBlock(LatchBlock));
 
-      // If this phi has the same width but is more canonical, replace the
-      // original with it. As part of the "more canonical" determination,
-      // respect a prior decision to use an IV chain.
-      if (OrigPhiRef->getType() == Phi->getType() &&
-          !(ChainedPhis.count(Phi) ||
-            isExpandedAddRecExprPHI(OrigPhiRef, OrigInc, L)) &&
-          (ChainedPhis.count(Phi) ||
-           isExpandedAddRecExprPHI(Phi, IsomorphicInc, L))) {
-        std::swap(OrigPhiRef, Phi);
-        std::swap(OrigInc, IsomorphicInc);
-      }
-      // Replacing the congruent phi is sufficient because acyclic redundancy
-      // elimination, CSE/GVN, should handle the rest. However, once SCEV proves
-      // that a phi is congruent, it's often the head of an IV user cycle that
-      // is isomorphic with the original phi. It's worth eagerly cleaning up the
-      // common case of a single IV increment so that DeleteDeadPHIs can remove
-      // cycles that had postinc uses.
-      const SCEV *TruncExpr = SE.getTruncateOrNoop(SE.getSCEV(OrigInc),
-                                                   IsomorphicInc->getType());
-      if (OrigInc != IsomorphicInc && TruncExpr == SE.getSCEV(IsomorphicInc) &&
-          SE.LI.replacementPreservesLCSSAForm(IsomorphicInc, OrigInc) &&
-          hoistIVInc(OrigInc, IsomorphicInc)) {
-        DEBUG_WITH_TYPE(DebugType,
-                        dbgs() << "INDVARS: Eliminated congruent iv.inc: "
-                               << *IsomorphicInc << '\n');
-        Value *NewInc = OrigInc;
-        if (OrigInc->getType() != IsomorphicInc->getType()) {
-          Instruction *IP = nullptr;
-          if (PHINode *PN = dyn_cast<PHINode>(OrigInc))
-            IP = &*PN->getParent()->getFirstInsertionPt();
-          else
-            IP = OrigInc->getNextNode();
+      if (OrigInc && IsomorphicInc) {
+        // If this phi has the same width but is more canonical, replace the
+        // original with it. As part of the "more canonical" determination,
+        // respect a prior decision to use an IV chain.
+        if (OrigPhiRef->getType() == Phi->getType() &&
+            !(ChainedPhis.count(Phi) ||
+              isExpandedAddRecExprPHI(OrigPhiRef, OrigInc, L)) &&
+            (ChainedPhis.count(Phi) ||
+             isExpandedAddRecExprPHI(Phi, IsomorphicInc, L))) {
+          std::swap(OrigPhiRef, Phi);
+          std::swap(OrigInc, IsomorphicInc);
+        }
+        // Replacing the congruent phi is sufficient because acyclic
+        // redundancy elimination, CSE/GVN, should handle the
+        // rest. However, once SCEV proves that a phi is congruent,
+        // it's often the head of an IV user cycle that is isomorphic
+        // with the original phi. It's worth eagerly cleaning up the
+        // common case of a single IV increment so that DeleteDeadPHIs
+        // can remove cycles that had postinc uses.
+        const SCEV *TruncExpr =
+            SE.getTruncateOrNoop(SE.getSCEV(OrigInc), IsomorphicInc->getType());
+        if (OrigInc != IsomorphicInc &&
+            TruncExpr == SE.getSCEV(IsomorphicInc) &&
+            SE.LI.replacementPreservesLCSSAForm(IsomorphicInc, OrigInc) &&
+            hoistIVInc(OrigInc, IsomorphicInc)) {
+          DEBUG_WITH_TYPE(DebugType,
+                          dbgs() << "INDVARS: Eliminated congruent iv.inc: "
+                                 << *IsomorphicInc << '\n');
+          Value *NewInc = OrigInc;
+          if (OrigInc->getType() != IsomorphicInc->getType()) {
+            Instruction *IP = nullptr;
+            if (PHINode *PN = dyn_cast<PHINode>(OrigInc))
+              IP = &*PN->getParent()->getFirstInsertionPt();
+            else
+              IP = OrigInc->getNextNode();
 
-          IRBuilder<> Builder(IP);
-          Builder.SetCurrentDebugLocation(IsomorphicInc->getDebugLoc());
-          NewInc = Builder.
-            CreateTruncOrBitCast(OrigInc, IsomorphicInc->getType(), IVName);
+            IRBuilder<> Builder(IP);
+            Builder.SetCurrentDebugLocation(IsomorphicInc->getDebugLoc());
+            NewInc = Builder.CreateTruncOrBitCast(
+                OrigInc, IsomorphicInc->getType(), IVName);
+          }
+          IsomorphicInc->replaceAllUsesWith(NewInc);
+          DeadInsts.emplace_back(IsomorphicInc);
         }
-        IsomorphicInc->replaceAllUsesWith(NewInc);
-        DeadInsts.emplace_back(IsomorphicInc);
       }
     }
     DEBUG_WITH_TYPE(DebugType, dbgs() << "INDVARS: Eliminated congruent iv: "

Modified: llvm/trunk/test/Analysis/ScalarEvolution/expander-replace-congruent-ivs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/expander-replace-congruent-ivs.ll?rev=269213&r1=269212&r2=269213&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/ScalarEvolution/expander-replace-congruent-ivs.ll (original)
+++ llvm/trunk/test/Analysis/ScalarEvolution/expander-replace-congruent-ivs.ll Wed May 11 12:41:41 2016
@@ -39,3 +39,73 @@ loop_1:
 leave:
   ret void
 }
+
+
+; @ReplaceArg_0 and @ReplaceArg_1 used to trigger a failed cast<>
+; assertion in SCEVExpander.
+
+define void @ReplaceArg_0(i32 %val) {
+; CHECK-LABEL: @ReplaceArg_0(
+entry:
+  br i1 undef, label %loop_0.cond, label %for.body.us
+
+for.body.us:
+  br label %loop_0.cond
+
+loop_0.cond:
+  br i1 true, label %loop_0.ph, label %loop_1.ph
+
+loop_0.ph:
+  br label %loop_0
+
+loop_1.exit:
+  br label %loop_1.ph
+
+loop_1.ph:
+  %c.lcssa = phi i32 [ 0, %loop_0.cond ], [ %val, %loop_1.exit ]
+  br label %loop_1
+
+loop_0:
+  br i1 undef, label %loop_0, label %loop_1.exit
+
+loop_1:
+  %d.1 = phi i32 [ %c.lcssa, %loop_1 ], [ %val, %loop_1.ph ]
+  %t.1 = phi i32 [ %val, %loop_1 ], [ %c.lcssa, %loop_1.ph ]
+  br i1 undef, label %leave, label %loop_1
+
+leave:
+  ret void
+}
+
+define void @ReplaceArg_1(i32 %val) {
+; CHECK-LABEL: @ReplaceArg_1(
+entry:
+  br i1 undef, label %loop_0.cond, label %for.body.us
+
+for.body.us:
+  br label %loop_0.cond
+
+loop_0.cond:
+  br i1 true, label %loop_0.ph, label %loop_1.ph
+
+loop_0.ph:
+  br label %loop_0
+
+loop_1.exit:
+  br label %loop_1.ph
+
+loop_1.ph:
+  %c.lcssa = phi i32 [ 0, %loop_0.cond ], [ %val, %loop_1.exit ]
+  br label %loop_1
+
+loop_0:
+  br i1 undef, label %loop_0, label %loop_1.exit
+
+loop_1:
+  %t.1 = phi i32 [ %val, %loop_1 ], [ %c.lcssa, %loop_1.ph ]
+  %d.1 = phi i32 [ %c.lcssa, %loop_1 ], [ %val, %loop_1.ph ]
+  br i1 undef, label %leave, label %loop_1
+
+leave:
+  ret void
+}




More information about the llvm-commits mailing list