diff --git a/lib/CodeGen/MachineSink.cpp b/lib/CodeGen/MachineSink.cpp index 468bd01548c..0e18fa742f5 100644 --- a/lib/CodeGen/MachineSink.cpp +++ b/lib/CodeGen/MachineSink.cpp @@ -111,20 +111,29 @@ bool MachineSinking::runOnMachineFunction(MachineFunction &MF) { } bool MachineSinking::ProcessBlock(MachineBasicBlock &MBB) { - bool MadeChange = false; - // Can't sink anything out of a block that has less than two successors. - if (MBB.succ_size() <= 1) return false; - + if (MBB.succ_size() <= 1 || MBB.empty()) return false; + + bool MadeChange = false; + // Walk the basic block bottom-up. Remember if we saw a store. - bool SawStore = false; - for (MachineBasicBlock::iterator I = MBB.end(); I != MBB.begin(); ){ - MachineBasicBlock::iterator LastIt = I; - if (SinkInstruction(--I, SawStore)) { - I = LastIt; - ++NumSunk; - } - } + MachineBasicBlock::iterator I = MBB.end(); + --I; + bool ProcessedBegin, SawStore = false; + do { + MachineInstr *MI = I; // The instruction to sink. + + // Predecrement I (if it's not begin) so that it isn't invalidated by + // sinking. + ProcessedBegin = I == MBB.begin(); + if (!ProcessedBegin) + --I; + + if (SinkInstruction(MI, SawStore)) + ++NumSunk, MadeChange = true; + + // If we just processed the first instruction in the block, we're done. + } while (!ProcessedBegin); return MadeChange; } @@ -218,6 +227,11 @@ bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) { if (SuccToSinkTo->isLandingPad()) return false; + // If is not possible to sink an instruction into its own block. This can + // happen with loops. + if (MI->getParent() == SuccToSinkTo) + return false; + DEBUG(cerr << "Sink instr " << *MI); DEBUG(cerr << "to block " << *SuccToSinkTo); diff --git a/test/CodeGen/Generic/2009-04-10-SinkCrash.ll b/test/CodeGen/Generic/2009-04-10-SinkCrash.ll new file mode 100644 index 00000000000..3637a06c217 --- /dev/null +++ b/test/CodeGen/Generic/2009-04-10-SinkCrash.ll @@ -0,0 +1,16 @@ +; RUN: llvm-as < %s | llc + +define void @QRiterate(i32 %p.1, double %tmp.212) nounwind { +entry: + br i1 false, label %shortcirc_next.1, label %exit.1.critedge + +shortcirc_next.1: ; preds = %shortcirc_next.1, %entry + %tmp.213 = fcmp une double %tmp.212, 0.000000e+00 ; [#uses=1] + br i1 %tmp.213, label %shortcirc_next.1, label %exit.1 + +exit.1.critedge: ; preds = %entry + ret void + +exit.1: ; preds = %shortcirc_next.1 + ret void +}