Index: llvm/lib/Target/ARM/ARMConstantIslandPass.cpp =================================================================== --- llvm/lib/Target/ARM/ARMConstantIslandPass.cpp +++ llvm/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -605,6 +605,10 @@ auto MJTI = MF->getJumpTableInfo(); const std::vector &JT = MJTI->getJumpTables(); + // Only inline jump tables are placed in the function. + if (MJTI->getEntryKind() != MachineJumpTableInfo::EK_Inline) + return; + MachineBasicBlock *LastCorrectlyNumberedBB = nullptr; for (MachineBasicBlock &MBB : *MF) { auto MI = MBB.getLastNonDebugInstr(); @@ -777,6 +781,11 @@ // Compute block offsets and known bits. BBUtils->adjustBBOffsetsAfter(&MF->front()); + // We only care about jump table instructions when jump tables are inline. + MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); + bool InlineJumpTables = + MJTI && MJTI->getEntryKind() == MachineJumpTableInfo::EK_Inline; + // Now go back through the instructions and build up our data structures. for (MachineBasicBlock &MBB : *MF) { // If this block doesn't fall through into the next MBB, then this is @@ -799,7 +808,8 @@ continue; // Ignore other JT branches case ARM::t2BR_JT: case ARM::tBR_JTr: - T2JumpTables.push_back(&I); + if (InlineJumpTables) + T2JumpTables.push_back(&I); continue; // Does not get an entry in ImmBranches case ARM::Bcc: isCond = true; @@ -846,7 +856,8 @@ // Scan the instructions for constant pool operands. for (unsigned op = 0, e = I.getNumOperands(); op != e; ++op) - if (I.getOperand(op).isCPI() || I.getOperand(op).isJTI()) { + if (I.getOperand(op).isCPI() || + (I.getOperand(op).isJTI() && InlineJumpTables)) { // We found one. The addressing mode tells us the max displacement // from the PC that this instruction permits. Index: llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp =================================================================== --- llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -23,6 +23,7 @@ #include "llvm/CodeGen/LivePhysRegs.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/Debug.h" @@ -1041,6 +1042,15 @@ Lower0_7 = Lower0_7.addExternalSymbol(ES, TF | ARMII::MO_LO_0_7); break; } + case MachineOperand::MO_JumpTableIndex: { + unsigned Idx = MO.getIndex(); + unsigned TF = MO.getTargetFlags(); + Upper8_15 = Upper8_15.addJumpTableIndex(Idx, TF | ARMII::MO_HI_8_15); + Upper0_7 = Upper0_7.addJumpTableIndex(Idx, TF | ARMII::MO_HI_0_7); + Lower8_15 = Lower8_15.addJumpTableIndex(Idx, TF | ARMII::MO_LO_8_15); + Lower0_7 = Lower0_7.addJumpTableIndex(Idx, TF | ARMII::MO_LO_0_7); + break; + } default: { const GlobalValue *GV = MO.getGlobal(); unsigned TF = MO.getTargetFlags(); @@ -2764,6 +2774,17 @@ ExpandTMOV32BitImm(MBB, MBBI); return true; + case ARM::tLEApcrelJT: + // Inline jump tables are handled in ARMAsmPrinter. + if (MI.getMF()->getJumpTableInfo()->getEntryKind() == + MachineJumpTableInfo::EK_Inline) + return false; + + // Use a 32-bit immediate move to generate the address of the jump table. + assert(STI->isThumb() && "Non-inline jump tables expected only in thumb"); + ExpandTMOV32BitImm(MBB, MBBI); + return true; + case ARM::SUBS_PC_LR: { MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::SUBri), ARM::PC) Index: llvm/lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- llvm/lib/Target/ARM/ARMISelLowering.cpp +++ llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -3492,6 +3492,11 @@ } unsigned ARMTargetLowering::getJumpTableEncoding() const { + // If we don't have a 32-bit pc-relative branch instruction then the jump + // table consists of block addresses. Usually this is inline, but for + // execute-only it must be placed out-of-line. + if (Subtarget->genExecuteOnly() && !Subtarget->hasV8MBaselineOps()) + return MachineJumpTableInfo::EK_BlockAddress; return MachineJumpTableInfo::EK_Inline; } Index: llvm/test/CodeGen/ARM/execute-only.ll =================================================================== --- llvm/test/CodeGen/ARM/execute-only.ll +++ llvm/test/CodeGen/ARM/execute-only.ll @@ -47,6 +47,27 @@ ; CHECK-NEXT: b.w ; CHECK-NEXT: b.w +; CHECK-T1-LABEL: jump_table: +; CHECK-T1: lsls [[REG_OFFSET:r[0-9]+]], {{r[0-9]+}}, #2 +; CHECK-T1-NEXT: movs [[REG_JT:r[0-9]+]], :upper8_15:.LJTI1_0 +; CHECK-T1-NEXT: lsls [[REG_JT]], [[REG_JT]], #8 +; CHECK-T1-NEXT: adds [[REG_JT]], :upper0_7:.LJTI1_0 +; CHECK-T1-NEXT: lsls [[REG_JT]], [[REG_JT]], #8 +; CHECK-T1-NEXT: adds [[REG_JT]], :lower8_15:.LJTI1_0 +; CHECK-T1-NEXT: lsls [[REG_JT]], [[REG_JT]], #8 +; CHECK-T1-NEXT: adds [[REG_JT]], :lower0_7:.LJTI1_0 +; CHECK-T1-NEXT: ldr [[REG_ENTRY:r[0-9]+]], [[[REG_JT]], [[REG_OFFSET]]] +; CHECK-T1-NEXT: mov pc, [[REG_ENTRY]] +; CHECK-T1: .section .rodata,"a",%progbits +; CHECK-T1-NEXT: .p2align 2, 0x0 +; CHECK-T1-NEXT: .LJTI1_0: +; CHECK-T1-NEXT: .long +; CHECK-T1-NEXT: .long +; CHECK-T1-NEXT: .long +; CHECK-T1-NEXT: .long +; CHECK-T1-NEXT: .long +; CHECK-T1-NEXT: .long + entry: switch i32 %c, label %return [ i32 1, label %sw.bb