diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp index 13b812ca1ae..1b936312c0a 100644 --- a/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -740,14 +740,11 @@ void ARMConstantIslands::AdjustBBOffsetsAfter(MachineBasicBlock *BB, delta -= 2; } } - // Thumb jump tables require padding. They can be at the end, or - // followed by an unconditional branch. + // Thumb jump tables require padding. They should be at the end; + // following unconditional branches are removed by AnalyzeBranch. MachineInstr *ThumbJTMI = NULL; if (prior(MBB->end())->getOpcode() == ARM::tBR_JTr) ThumbJTMI = prior(MBB->end()); - else if (prior(MBB->end()) != MBB->begin() && - prior(prior(MBB->end()))->getOpcode() == ARM::tBR_JTr) - ThumbJTMI = prior(prior(MBB->end())); if (ThumbJTMI) { unsigned newMIOffset = GetOffsetOf(ThumbJTMI); unsigned oldMIOffset = newMIOffset - delta; diff --git a/lib/Target/ARM/ARMInstrInfo.cpp b/lib/Target/ARM/ARMInstrInfo.cpp index f4b4dbe2e3a..b404ec078e5 100644 --- a/lib/Target/ARM/ARMInstrInfo.cpp +++ b/lib/Target/ARM/ARMInstrInfo.cpp @@ -350,8 +350,8 @@ bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB, return false; } - // If the block ends with two B's or tB's, handle it. The second one is not - // executed, so remove it. + // If the block ends with two unconditional branches, handle it. The second + // one is not executed, so remove it. if ((SecondLastOpc == ARM::B || SecondLastOpc==ARM::tB) && (LastOpc == ARM::B || LastOpc == ARM::tB)) { TBB = SecondLastInst->getOperand(0).getMachineBasicBlock(); @@ -360,6 +360,17 @@ bool ARMInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB, return false; } + // Likewise if it ends with a branch table followed by an unconditional branch. + // The branch folder can create these, and we must get rid of them for + // correctness of Thumb constant islands. + if ((SecondLastOpc == ARM::BR_JTr || SecondLastOpc==ARM::BR_JTm || + SecondLastOpc == ARM::BR_JTadd || SecondLastOpc==ARM::tBR_JTr) && + (LastOpc == ARM::B || LastOpc == ARM::tB)) { + I = LastInst; + I->eraseFromParent(); + return true; + } + // Otherwise, can't handle this. return true; }