From c9a59b5960088f48c3be234bcc4c79a1ed915d73 Mon Sep 17 00:00:00 2001 From: David Goodwin Date: Tue, 30 Jun 2009 19:50:22 +0000 Subject: [PATCH] Improve Thumb-2 jump table support. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74549 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMCodeEmitter.cpp | 7 ++++--- lib/Target/ARM/ARMConstantIslandPass.cpp | 6 +++++- lib/Target/ARM/ARMInstrInfo.cpp | 14 ++++++++----- lib/Target/ARM/ARMInstrThumb2.td | 24 +++++++++++++++++----- test/CodeGen/Thumb2/thumb2-jumptbl.ll | 26 ++++++++++++++++++++++++ 5 files changed, 63 insertions(+), 14 deletions(-) create mode 100644 test/CodeGen/Thumb2/thumb2-jumptbl.ll diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index 8424c2eaed1..f29576148b3 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -1155,16 +1155,17 @@ void Emitter::emitMiscBranchInstruction(const MachineInstr &MI) { const TargetInstrDesc &TID = MI.getDesc(); // 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. emitDataProcessingInstruction(MI, ARM::PC); // 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(); emitInlineJumpTable(JTIndex); 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. emitLoadStoreInstruction(MI, ARM::PC); diff --git a/lib/Target/ARM/ARMConstantIslandPass.cpp b/lib/Target/ARM/ARMConstantIslandPass.cpp index 50badfffecd..19c311c4f28 100644 --- a/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -379,6 +379,8 @@ void ARMConstantIslands::InitialFunctionScan(MachineFunction &Fn, switch (Opc) { case ARM::tBR_JTr: case ARM::t2BR_JTr: + case ARM::t2BR_JTm: + case ARM::t2BR_JTadd: // A Thumb table jump may involve padding; for the offsets to // be right, functions containing these must be 4-byte aligned. AFI->setAlign(2U); @@ -766,7 +768,9 @@ void ARMConstantIslands::AdjustBBOffsetsAfter(MachineBasicBlock *BB, // following unconditional branches are removed by AnalyzeBranch. MachineInstr *ThumbJTMI = NULL; 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()); if (ThumbJTMI) { unsigned newMIOffset = GetOffsetOf(ThumbJTMI); diff --git a/lib/Target/ARM/ARMInstrInfo.cpp b/lib/Target/ARM/ARMInstrInfo.cpp index 5941b1eddb3..35ebb7eec86 100644 --- a/lib/Target/ARM/ARMInstrInfo.cpp +++ b/lib/Target/ARM/ARMInstrInfo.cpp @@ -401,7 +401,8 @@ bool // correctness of Thumb constant islands. if ((SecondLastOpc == ARM::BR_JTr || SecondLastOpc==ARM::BR_JTm || 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)) { I = LastInst; if (AllowModify) @@ -708,7 +709,9 @@ ARMBaseInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const { case ARM::tBR_JTr: case ARM::t2BR_JTr: case ARM::BR_JTr: // Jumptable branch. + case ARM::t2BR_JTm: case ARM::BR_JTm: // Jumptable branch through mem. + case ARM::t2BR_JTadd: case ARM::BR_JTadd: // Jumptable branch add to pc. return true; default: return false; @@ -846,8 +849,10 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { case ARM::BR_JTr: case ARM::BR_JTm: 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 // jumptable. The size is 4 + 4 * number of entries. 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 // alignment issue. return getNumJTEntries(JT, JTI) * 4 + - ((MI->getOpcode()==ARM::tBR_JTr || - MI->getOpcode()==ARM::t2BR_JTr) ? 2 : 4); + ((MI->getOpcode()==ARM::tBR_JTr) ? 2 : 4); } default: // Otherwise, pseudo-instruction sizes are zero. diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index b6d54f00230..8479154319f 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -698,11 +698,25 @@ def t2B : T2XI<(outs), (ins brtarget:$target), "b $target", [(br bb:$target)]>; -def t2BR_JTr : T2JTI<(outs), - (ins tGPR:$target, jtblock_operand:$jt, i32imm:$id), - "cpy pc, $target \n\t.align\t2\n$jt", - [(ARMbrjt tGPR:$target, tjumptable:$jt, imm:$id)]>; -} +let isNotDuplicable = 1, isIndirectBranch = 1 in { +def t2BR_JTr : T2JTI<(outs), (ins GPR:$target, jtblock_operand:$jt, i32imm:$id), + "mov pc, $target \n$jt", + [(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 // a two-value operand where a dag node expects two operands. :( diff --git a/test/CodeGen/Thumb2/thumb2-jumptbl.ll b/test/CodeGen/Thumb2/thumb2-jumptbl.ll new file mode 100644 index 00000000000..512c669b7d4 --- /dev/null +++ b/test/CodeGen/Thumb2/thumb2-jumptbl.ll @@ -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 +} -- 2.34.1