OSDN Git Service

[Reassociate] Avoid iterator invalidation when negating value.
authorChad Rosier <mcrosier@codeaurora.org>
Wed, 17 Aug 2016 14:16:45 +0000 (14:16 +0000)
committerChad Rosier <mcrosier@codeaurora.org>
Wed, 17 Aug 2016 14:16:45 +0000 (14:16 +0000)
Differential Revision: https://reviews.llvm.org/D23464
PR28367

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

lib/Transforms/Scalar/Reassociate.cpp
test/Transforms/Reassociate/invalid-iterator.ll [new file with mode: 0644]

index b930a8f..5b3e7c5 100644 (file)
@@ -842,6 +842,13 @@ static Value *NegateValue(Value *V, Instruction *BI,
     if (TheNeg->getParent()->getParent() != BI->getParent()->getParent())
       continue;
 
+    // Don't move the negate if it's in the block we're currently optimizing as
+    // this may invalidate our iterator.
+    // FIXME: We should find a more robust solution as we're missing local CSE
+    // opportunities because of this constraint.
+    if (TheNeg->getParent() == BI->getParent())
+      continue;
+
     BasicBlock::iterator InsertPt;
     if (Instruction *InstInput = dyn_cast<Instruction>(V)) {
       if (InvokeInst *II = dyn_cast<InvokeInst>(InstInput)) {
@@ -1863,6 +1870,8 @@ void ReassociatePass::RecursivelyEraseDeadInsts(
 /// Zap the given instruction, adding interesting operands to the work list.
 void ReassociatePass::EraseInst(Instruction *I) {
   assert(isInstructionTriviallyDead(I) && "Trivially dead instructions only!");
+  DEBUG(dbgs() << "Erasing dead inst: "; I->dump());
+
   SmallVector<Value*, 8> Ops(I->op_begin(), I->op_end());
   // Erase the dead instruction.
   ValueRankMap.erase(I);
diff --git a/test/Transforms/Reassociate/invalid-iterator.ll b/test/Transforms/Reassociate/invalid-iterator.ll
new file mode 100644 (file)
index 0000000..14211d1
--- /dev/null
@@ -0,0 +1,30 @@
+; RUN: opt < %s -reassociate -die -S | FileCheck %s
+
+; PR28367
+; Check to make sure %sub2 isn't moved from for.body.  Doing so would invalidate
+; the iterator.
+
+; CHECK-LABEL: @fn1
+; CHECK: for.body:
+; CHECK-NEXT:   %sub2 = sub nsw i32 0, %d.0
+; CHECK-NEXT:   store i32 %sub2, i32* %ptr, align 4
+define void @fn1(i32 %a, i1 %c, i32* %ptr)  {
+entry:
+  br label %for.cond
+
+for.cond:
+  %d.0 = phi i32 [ 1, %entry ], [ 2, %for.body ]
+  br i1 %c, label %for.end, label %for.body
+
+for.body:
+  %sub1 = sub i32 %a, %d.0
+  %dead1 = add i32 %sub1, 1
+  %dead2 = mul i32 %dead1, 3
+  %dead3 = mul i32 %dead2, %sub1
+  %sub2 = sub nsw i32 0, %d.0
+  store i32 %sub2, i32* %ptr, align 4
+  br label %for.cond
+
+for.end:
+  ret void
+}