[PATCH] D23464: [PR28367][Reassociation] Avoid iterator invalidation when negating value.

Chad Rosier via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 12 13:47:12 PDT 2016


mcrosier created this revision.
mcrosier added reviewers: aditya_nandakumar, gberry, hans.
mcrosier added a subscriber: llvm-commits.

When trying to negate a value, V, we try to avoid materializing the negated value by scanning the use list of V to see if we already have one.  If we do find a negated version and that version is in the block we're currently optimizing, moving that instruction may invalidate our iterator.

Example:
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
}

The invalidation occurs as follows:
1. Assume we're optimizing %dead3, which is trivially dead.
2. The BB iterator is incremented (now pointing to %sub2) and EraseInst is called to delete %dead3.
3. When the %dead3 instruction is removed its operand %sub1 is added to the RedoInst list.
4. When %sub1 is reoptimized the ShouldBreakUpSubtract() function returns true and the BreakUpSubtract() function is called.  This didn't happen the first time %sub1 was optimized because it had more than one use (i.e., %dead1 and %dead3).
5. The NegateValue() function then hoists the %sub2 (as it is the negated form of %d.0) instruction into the for.cond block invalidating the iterator and causing the assertion.  Without the assert we would dereference an invalid iterator and segfault.

Please take a look,
 Chad

https://reviews.llvm.org/D23464

Files:
  lib/Transforms/Scalar/Reassociate.cpp
  test/Transforms/Reassociate/invalid-iterator.ll

Index: test/Transforms/Reassociate/invalid-iterator.ll
===================================================================
--- /dev/null
+++ test/Transforms/Reassociate/invalid-iterator.ll
@@ -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
+}
Index: lib/Transforms/Scalar/Reassociate.cpp
===================================================================
--- lib/Transforms/Scalar/Reassociate.cpp
+++ lib/Transforms/Scalar/Reassociate.cpp
@@ -842,6 +842,11 @@
     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.
+    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 +1868,8 @@
 /// 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);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D23464.67903.patch
Type: text/x-patch
Size: 2021 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160812/03e8eccf/attachment.bin>


More information about the llvm-commits mailing list