From 4fb0e0114f626c6a492738f609744eab5d331310 Mon Sep 17 00:00:00 2001 From: John Brawn Date: Thu, 1 Jun 2023 17:04:39 +0100 Subject: [PATCH] [ARM] Generate out-of-line jump tables for XO without 32-bit branch When we only have a 16-bit pc-relative branch instruction we generate a table of address for a jump table. Currently this is placed inline, but this won't work with execute-only memory. In this case generate the jump table out-of-line. Differential Revision: https://reviews.llvm.org/D153774 --- llvm/lib/Target/ARM/ARMConstantIslandPass.cpp | 15 +++++++++++++-- llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp | 21 +++++++++++++++++++++ llvm/lib/Target/ARM/ARMISelLowering.cpp | 5 +++++ llvm/test/CodeGen/ARM/execute-only.ll | 21 +++++++++++++++++++++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp index 590612e..a6682f0 100644 --- a/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp +++ b/llvm/lib/Target/ARM/ARMConstantIslandPass.cpp @@ -605,6 +605,10 @@ void ARMConstantIslands::doInitialJumpTablePlacement( 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 @@ initializeFunctionInfo(const std::vector &CPEMIs) { // 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 @@ initializeFunctionInfo(const std::vector &CPEMIs) { 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 @@ initializeFunctionInfo(const std::vector &CPEMIs) { // 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. diff --git a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp index bf75e22..f628a72 100644 --- a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/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 @@ void ARMExpandPseudo::ExpandTMOV32BitImm(MachineBasicBlock &MBB, 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 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, 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) diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 6bffbc0..a12fd78 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -3484,6 +3484,11 @@ SDValue ARMTargetLowering::LowerConstantPool(SDValue Op, } 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; } diff --git a/llvm/test/CodeGen/ARM/execute-only.ll b/llvm/test/CodeGen/ARM/execute-only.ll index 1123efb..304b855 100644 --- a/llvm/test/CodeGen/ARM/execute-only.ll +++ b/llvm/test/CodeGen/ARM/execute-only.ll @@ -45,6 +45,27 @@ define i32 @jump_table(i32 %c, i32 %a, i32 %b) #0 { ; 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 -- 2.7.4