Improve Thumb-2 jump table support.

llvm-svn: 74549
This commit is contained in:
David Goodwin 2009-06-30 19:50:22 +00:00
parent 50475de6af
commit 28d6d87244
5 changed files with 63 additions and 14 deletions

View File

@ -1155,16 +1155,17 @@ void Emitter<CodeEmitter>::emitMiscBranchInstruction(const MachineInstr &MI) {
const TargetInstrDesc &TID = MI.getDesc(); const TargetInstrDesc &TID = MI.getDesc();
// Handle jump tables. // Handle jump tables.
if (TID.Opcode == ARM::BR_JTr || TID.Opcode == ARM::BR_JTadd) { if (TID.Opcode == ARM::BR_JTr || TID.Opcode == ARM::BR_JTadd ||
TID.Opcode == ARM::t2BR_JTr || TID.Opcode == ARM::t2BR_JTadd) {
// First emit a ldr pc, [] instruction. // First emit a ldr pc, [] instruction.
emitDataProcessingInstruction(MI, ARM::PC); emitDataProcessingInstruction(MI, ARM::PC);
// Then emit the inline jump table. // Then emit the inline jump table.
unsigned JTIndex = (TID.Opcode == ARM::BR_JTr) unsigned JTIndex = (TID.Opcode == ARM::BR_JTr || TID.Opcode == ARM::t2BR_JTr)
? MI.getOperand(1).getIndex() : MI.getOperand(2).getIndex(); ? MI.getOperand(1).getIndex() : MI.getOperand(2).getIndex();
emitInlineJumpTable(JTIndex); emitInlineJumpTable(JTIndex);
return; return;
} else if (TID.Opcode == ARM::BR_JTm) { } else if (TID.Opcode == ARM::BR_JTm || TID.Opcode == ARM::t2BR_JTm) {
// First emit a ldr pc, [] instruction. // First emit a ldr pc, [] instruction.
emitLoadStoreInstruction(MI, ARM::PC); emitLoadStoreInstruction(MI, ARM::PC);

View File

@ -379,6 +379,8 @@ void ARMConstantIslands::InitialFunctionScan(MachineFunction &Fn,
switch (Opc) { switch (Opc) {
case ARM::tBR_JTr: case ARM::tBR_JTr:
case ARM::t2BR_JTr: case ARM::t2BR_JTr:
case ARM::t2BR_JTm:
case ARM::t2BR_JTadd:
// A Thumb table jump may involve padding; for the offsets to // A Thumb table jump may involve padding; for the offsets to
// be right, functions containing these must be 4-byte aligned. // be right, functions containing these must be 4-byte aligned.
AFI->setAlign(2U); AFI->setAlign(2U);
@ -766,7 +768,9 @@ void ARMConstantIslands::AdjustBBOffsetsAfter(MachineBasicBlock *BB,
// following unconditional branches are removed by AnalyzeBranch. // following unconditional branches are removed by AnalyzeBranch.
MachineInstr *ThumbJTMI = NULL; MachineInstr *ThumbJTMI = NULL;
if ((prior(MBB->end())->getOpcode() == ARM::tBR_JTr) if ((prior(MBB->end())->getOpcode() == ARM::tBR_JTr)
|| (prior(MBB->end())->getOpcode() == ARM::t2BR_JTr)) || (prior(MBB->end())->getOpcode() == ARM::t2BR_JTr)
|| (prior(MBB->end())->getOpcode() == ARM::t2BR_JTm)
|| (prior(MBB->end())->getOpcode() == ARM::t2BR_JTadd))
ThumbJTMI = prior(MBB->end()); ThumbJTMI = prior(MBB->end());
if (ThumbJTMI) { if (ThumbJTMI) {
unsigned newMIOffset = GetOffsetOf(ThumbJTMI); unsigned newMIOffset = GetOffsetOf(ThumbJTMI);

View File

@ -401,7 +401,8 @@ bool
// correctness of Thumb constant islands. // correctness of Thumb constant islands.
if ((SecondLastOpc == ARM::BR_JTr || SecondLastOpc==ARM::BR_JTm || if ((SecondLastOpc == ARM::BR_JTr || SecondLastOpc==ARM::BR_JTm ||
SecondLastOpc == ARM::BR_JTadd || SecondLastOpc==ARM::tBR_JTr || SecondLastOpc == ARM::BR_JTadd || SecondLastOpc==ARM::tBR_JTr ||
SecondLastOpc==ARM::t2BR_JTr) && SecondLastOpc == ARM::t2BR_JTr || SecondLastOpc==ARM::t2BR_JTm ||
SecondLastOpc == ARM::t2BR_JTadd) &&
(LastOpc == ARM::B || LastOpc == ARM::tB || LastOpc == ARM::t2B)) { (LastOpc == ARM::B || LastOpc == ARM::tB || LastOpc == ARM::t2B)) {
I = LastInst; I = LastInst;
if (AllowModify) if (AllowModify)
@ -708,7 +709,9 @@ ARMBaseInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
case ARM::tBR_JTr: case ARM::tBR_JTr:
case ARM::t2BR_JTr: case ARM::t2BR_JTr:
case ARM::BR_JTr: // Jumptable branch. case ARM::BR_JTr: // Jumptable branch.
case ARM::t2BR_JTm:
case ARM::BR_JTm: // Jumptable branch through mem. case ARM::BR_JTm: // Jumptable branch through mem.
case ARM::t2BR_JTadd:
case ARM::BR_JTadd: // Jumptable branch add to pc. case ARM::BR_JTadd: // Jumptable branch add to pc.
return true; return true;
default: return false; default: return false;
@ -846,8 +849,10 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
case ARM::BR_JTr: case ARM::BR_JTr:
case ARM::BR_JTm: case ARM::BR_JTm:
case ARM::BR_JTadd: case ARM::BR_JTadd:
case ARM::tBR_JTr: case ARM::t2BR_JTr:
case ARM::t2BR_JTr: { case ARM::t2BR_JTm:
case ARM::t2BR_JTadd:
case ARM::tBR_JTr: {
// These are jumptable branches, i.e. a branch followed by an inlined // These are jumptable branches, i.e. a branch followed by an inlined
// jumptable. The size is 4 + 4 * number of entries. // jumptable. The size is 4 + 4 * number of entries.
unsigned NumOps = TID.getNumOperands(); unsigned NumOps = TID.getNumOperands();
@ -865,8 +870,7 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
// bytes, we can use 16-bit entries instead. Then there won't be an // bytes, we can use 16-bit entries instead. Then there won't be an
// alignment issue. // alignment issue.
return getNumJTEntries(JT, JTI) * 4 + return getNumJTEntries(JT, JTI) * 4 +
((MI->getOpcode()==ARM::tBR_JTr || ((MI->getOpcode()==ARM::tBR_JTr) ? 2 : 4);
MI->getOpcode()==ARM::t2BR_JTr) ? 2 : 4);
} }
default: default:
// Otherwise, pseudo-instruction sizes are zero. // Otherwise, pseudo-instruction sizes are zero.

View File

@ -698,11 +698,25 @@ def t2B : T2XI<(outs), (ins brtarget:$target),
"b $target", "b $target",
[(br bb:$target)]>; [(br bb:$target)]>;
def t2BR_JTr : T2JTI<(outs), let isNotDuplicable = 1, isIndirectBranch = 1 in {
(ins tGPR:$target, jtblock_operand:$jt, i32imm:$id), def t2BR_JTr : T2JTI<(outs), (ins GPR:$target, jtblock_operand:$jt, i32imm:$id),
"cpy pc, $target \n\t.align\t2\n$jt", "mov pc, $target \n$jt",
[(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>; [(ARMbrjt GPR:$target, tjumptable:$jt, imm:$id)]>;
}
def t2BR_JTm :
T2JTI<(outs),
(ins t2addrmode_so_reg:$target, jtblock_operand:$jt, i32imm:$id),
"ldr pc, $target \n$jt",
[(ARMbrjt (i32 (load t2addrmode_so_reg:$target)), tjumptable:$jt,
imm:$id)]>;
def t2BR_JTadd :
T2JTI<(outs),
(ins GPR:$target, GPR:$idx, jtblock_operand:$jt, i32imm:$id),
"add pc, $target, $idx \n$jt",
[(ARMbrjt (add GPR:$target, GPR:$idx), tjumptable:$jt, imm:$id)]>;
} // isNotDuplicate, isIndirectBranch
} // isBranch, isTerminator, isBarrier
// FIXME: should be able to write a pattern for ARMBrcond, but can't use // FIXME: should be able to write a pattern for ARMBrcond, but can't use
// a two-value operand where a dag node expects two operands. :( // a two-value operand where a dag node expects two operands. :(

View File

@ -0,0 +1,26 @@
; RUN: llvm-as < %s | llc -march=thumb -mattr=+thumb2 | grep {ldr\\W*pc,} | count 1
define i32 @foo(i32 %a) nounwind {
entry:
switch i32 %a, label %bb4 [
i32 1, label %bb5
i32 2, label %bb1
i32 3, label %bb2
i32 5, label %bb3
]
bb1: ; preds = %entry
ret i32 1
bb2: ; preds = %entry
ret i32 1234
bb3: ; preds = %entry
ret i32 3456
bb4: ; preds = %entry
ret i32 0
bb5: ; preds = %entry
ret i32 12
}