From 0701c5a0744b27a08724adcb584319f4b65d7328 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Sat, 27 Jan 2007 02:29:45 +0000 Subject: [PATCH] Thumb jumptable support. llvm-svn: 33568 --- llvm/lib/Target/ARM/ARMAsmPrinter.cpp | 3 ++- llvm/lib/Target/ARM/ARMConstantIslandPass.cpp | 10 ++++++++- llvm/lib/Target/ARM/ARMInstrThumb.td | 22 ++++++++++++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp index 1fba4e1ebd4c..7e95c9c36adc 100644 --- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp @@ -647,7 +647,8 @@ void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) { << getFunctionNumber() << '_' << JTI << '_' << MO2.getImmedValue(); } else printBasicBlockLabel(MBB, false, false); - O << '\n'; + if (i != e-1) + O << '\n'; } } diff --git a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp index ed88960ffb16..7ce62dacd3cf 100644 --- a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -352,7 +352,8 @@ unsigned ARMConstantIslands::GetInstSize(MachineInstr *MI) const { return MI->getOperand(2).getImm(); case ARM::BR_JTr: case ARM::BR_JTm: - case ARM::BR_JTadd: { + case ARM::BR_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 JTI = MI->getOperand(MI->getNumOperands()-2).getJumpTableIndex(); @@ -360,6 +361,13 @@ unsigned ARMConstantIslands::GetInstSize(MachineInstr *MI) const { MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); const std::vector &JT = MJTI->getJumpTables(); assert(JTI < JT.size()); + // Thumb instructions are 2 byte aligned, but JT entries are 4 byte + // 4 aligned. The assembler / linker may add 2 byte padding just before + // the JT entries. Use + 4 even for tBR_JTr to purposely over-estimate + // the size the jumptable. + // FIXME: If we know the size of the function is less than (1 << 16) *2 + // bytes, we can use 16-bit entries instead. Then there won't be an + // alignment issue. return getNumJTEntries(JT, JTI) * 4 + 4; } default: diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td index 52b8939e24cc..c494be470569 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb.td @@ -56,6 +56,10 @@ class TIt pattern> class TIx2 pattern> : ThumbI; +// BR_JT instructions +class TJTI pattern> + : ThumbI; + def imm_neg_XFORM : SDNodeXFormgetTargetConstant(-(int)N->getValue(), MVT::i32); }]>; @@ -188,9 +192,14 @@ let isCall = 1, noResults = 1, [(ARMcall_nolink GPR:$dst)]>; } -let isBranch = 1, isTerminator = 1, isBarrier = 1 in +let isBranch = 1, isTerminator = 1, isBarrier = 1 in { def tB : TI<(ops brtarget:$dst), "b $dst", [(br bb:$dst)]>; + def tBR_JTr : TJTI<(ops GPR:$dst, jtblock_operand:$jt, i32imm:$id), + "cpy pc, $dst \n\t.align\t2\n$jt", + [(ARMbrjt GPR:$dst, tjumptable:$jt, imm:$id)]>; +} + let isBranch = 1, isTerminator = 1, noResults = 1, isBarrier = 1 in def tBcc : TI<(ops brtarget:$dst, CCOp:$cc), "b$cc $dst", [(ARMbrcond bb:$dst, imm:$cc)]>; @@ -477,6 +486,13 @@ def tLEApcrelCall : TI<(ops GPR:$dst, i32imm:$label), "add $dst, pc, #PCRELV${:uid}")), []>; +def tLEApcrelJT : TI<(ops GPR:$dst, i32imm:$label, i32imm:$id), + !strconcat(!strconcat(".set PCRELV${:uid}, (${label}_${id:no_hash}-(", + "${:private}PCRELL${:uid}+4))\n"), + !strconcat("${:private}PCRELL${:uid}:\n\t", + "add $dst, pc, #PCRELV${:uid}")), + []>; + //===----------------------------------------------------------------------===// // Non-Instruction Patterns // @@ -489,6 +505,10 @@ def : ThumbPat<(ARMWrapperCall tglobaladdr :$dst), def : ThumbPat<(ARMWrapperCall texternalsym:$dst), (tLEApcrelCall texternalsym:$dst)>; +// JumpTable +def : ThumbPat<(ARMWrapperJT tjumptable:$dst, imm:$id), + (tLEApcrelJT tjumptable:$dst, imm:$id)>; + // Direct calls def : ThumbPat<(ARMtcall texternalsym:$func), (tBL texternalsym:$func)>; def : ThumbV5Pat<(ARMcall texternalsym:$func), (tBLXi texternalsym:$func)>;