// Assuming canSinkLastInstruction(Blocks) has returned true, sink the last
// instruction of every block in Blocks to their common successor, commoning
// into one instruction.
-static void sinkLastInstruction(ArrayRef<BasicBlock*> Blocks) {
+static bool sinkLastInstruction(ArrayRef<BasicBlock*> Blocks) {
auto *BBEnd = Blocks[0]->getTerminator()->getSuccessor(0);
// canSinkLastInstruction returning true guarantees that every block has at
for (auto *BB : Blocks)
Insts.push_back(BB->getTerminator()->getPrevNode());
- // We don't need to do any checking here; canSinkLastInstruction should have
- // done it all for us.
+ // The only checking we need to do now is that all users of all instructions
+ // are the same PHI node. canSinkLastInstruction should have checked this but
+ // it is slightly over-aggressive - it gets confused by commutative instructions
+ // so double-check it here.
Instruction *I0 = Insts.front();
+ if (!isa<StoreInst>(I0)) {
+ auto *PNUse = dyn_cast<PHINode>(*I0->user_begin());
+ if (!all_of(Insts, [&PNUse](const Instruction *I) -> bool {
+ auto *U = cast<Instruction>(*I->user_begin());
+ return U == PNUse || U->getParent() == I->getParent();
+ }))
+ return false;
+ }
+
+ // We don't need to do any more checking here; canSinkLastInstruction should
+ // have done it all for us.
SmallVector<Value*, 4> NewOperands;
for (unsigned O = 0, E = I0->getNumOperands(); O != E; ++O) {
// This check is different to that in canSinkLastInstruction. There, we
for (auto *I : Insts)
if (I != I0)
I->eraseFromParent();
+
+ return true;
}
namespace {
LockstepReverseIterator LRI(UnconditionalPreds);
while (LRI.isValid() &&
canSinkInstructions(*LRI, PHIOperands)) {
- DEBUG(dbgs() << "SINK: instruction can be sunk: " << (*LRI)[0] << "\n");
+ DEBUG(dbgs() << "SINK: instruction can be sunk: " << *(*LRI)[0] << "\n");
InstructionsToSink.insert((*LRI).begin(), (*LRI).end());
++ScanIdx;
--LRI;
break;
}
- sinkLastInstruction(UnconditionalPreds);
+ if (!sinkLastInstruction(UnconditionalPreds))
+ return Changed;
NumSinkCommons++;
Changed = true;
}
; CHECK: store
; CHECK: store
+define zeroext i1 @test19(i1 zeroext %flag, i32* %i4, i32* %m, i32* %n) {
+entry:
+ br i1 %flag, label %if.then, label %if.else
+
+if.then:
+ %tmp1 = load i32, i32* %i4
+ %tmp2 = add i32 %tmp1, -1
+ store i32 %tmp2, i32* %i4
+ br label %if.end
+
+if.else:
+ %tmp3 = load i32, i32* %m
+ %tmp4 = load i32, i32* %n
+ %tmp5 = add i32 %tmp3, %tmp4
+ store i32 %tmp5, i32* %i4
+ br label %if.end
+
+if.end:
+ ret i1 true
+}
+
+; No checks for test19 - just ensure it doesn't crash!
+
; CHECK: !0 = !{!1, !1, i64 0}
; CHECK: !1 = !{!"float", !2}
; CHECK: !2 = !{!"an example type tree"}