20 changes: 19 additions & 1 deletion llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SELECT_CC, MVT::f16, Custom);
setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);
setOperationAction(ISD::BR_JT, MVT::Other, Expand);
setOperationAction(ISD::BR_JT, MVT::Other, Custom);
setOperationAction(ISD::JumpTable, MVT::i64, Custom);

setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom);
Expand Down Expand Up @@ -2825,6 +2825,8 @@ SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
return LowerSELECT_CC(Op, DAG);
case ISD::JumpTable:
return LowerJumpTable(Op, DAG);
case ISD::BR_JT:
return LowerBR_JT(Op, DAG);
case ISD::ConstantPool:
return LowerConstantPool(Op, DAG);
case ISD::BlockAddress:
Expand Down Expand Up @@ -4902,6 +4904,22 @@ SDValue AArch64TargetLowering::LowerJumpTable(SDValue Op,
return getAddr(JT, DAG);
}

SDValue AArch64TargetLowering::LowerBR_JT(SDValue Op,
SelectionDAG &DAG) const {
// Jump table entries as PC relative offsets. No additional tweaking
// is necessary here. Just get the address of the jump table.
SDLoc DL(Op);
SDValue JT = Op.getOperand(1);
SDValue Entry = Op.getOperand(2);
int JTI = cast<JumpTableSDNode>(JT.getNode())->getIndex();

SDNode *Dest =
DAG.getMachineNode(AArch64::JumpTableDest32, DL, MVT::i64, MVT::i64, JT,
Entry, DAG.getTargetJumpTable(JTI, MVT::i32));
return DAG.getNode(ISD::BRIND, DL, MVT::Other, Op.getOperand(0),
SDValue(Dest, 0));
}

SDValue AArch64TargetLowering::LowerConstantPool(SDValue Op,
SelectionDAG &DAG) const {
ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/AArch64/AArch64ISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,7 @@ class AArch64TargetLowering : public TargetLowering {
SDValue TVal, SDValue FVal, const SDLoc &dl,
SelectionDAG &DAG) const;
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerAAPCS_VASTART(SDValue Op, SelectionDAG &DAG) const;
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,14 @@ unsigned AArch64InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
// This gets lowered to an instruction sequence which takes 16 bytes
NumBytes = 16;
break;
case AArch64::JumpTableDest32:
case AArch64::JumpTableDest16:
case AArch64::JumpTableDest8:
NumBytes = 12;
break;
case AArch64::SPACE:
NumBytes = MI.getOperand(1).getImm();
break;
}

return NumBytes;
Expand Down
24 changes: 24 additions & 0 deletions llvm/lib/Target/AArch64/AArch64InstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,30 @@ def : Pat<(AArch64LOADgot texternalsym:$addr),
def : Pat<(AArch64LOADgot tconstpool:$addr),
(LOADgot tconstpool:$addr)>;

// 32-bit jump table destination is actually only 2 instructions since we can
// use the table itself as a PC-relative base. But optimization occurs after
// branch relaxation so be pessimistic.
let Size = 12, Constraints = "@earlyclobber $dst,@earlyclobber $scratch" in {
def JumpTableDest32 : Pseudo<(outs GPR64:$dst, GPR64sp:$scratch),
(ins GPR64:$table, GPR64:$entry, i32imm:$jti), []>,
Sched<[]>;
def JumpTableDest16 : Pseudo<(outs GPR64:$dst, GPR64sp:$scratch),
(ins GPR64:$table, GPR64:$entry, i32imm:$jti), []>,
Sched<[]>;
def JumpTableDest8 : Pseudo<(outs GPR64:$dst, GPR64sp:$scratch),
(ins GPR64:$table, GPR64:$entry, i32imm:$jti), []>,
Sched<[]>;
}

// Space-consuming pseudo to aid testing of placement and reachability
// algorithms. Immediate operand is the number of bytes this "instruction"
// occupies; register operands can be used to enforce dependency and constrain
// the scheduler.
let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
def SPACE : Pseudo<(outs GPR64:$Rd), (ins i32imm:$size, GPR64:$Rn),
[(set GPR64:$Rd, (int_aarch64_space imm:$size, GPR64:$Rn))]>,
Sched<[]>;

//===----------------------------------------------------------------------===//
// System instructions.
//===----------------------------------------------------------------------===//
Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,19 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
unsigned getVarArgsFPRSize() const { return VarArgsFPRSize; }
void setVarArgsFPRSize(unsigned Size) { VarArgsFPRSize = Size; }

unsigned getJumpTableEntrySize(int Idx) const {
auto It = JumpTableEntryInfo.find(Idx);
if (It != JumpTableEntryInfo.end())
return It->second.first;
return 4;
}
MCSymbol *getJumpTableEntryPCRelSymbol(int Idx) const {
return JumpTableEntryInfo.find(Idx)->second.second;
}
void setJumpTableEntryInfo(int Idx, unsigned Size, MCSymbol *PCRelSym) {
JumpTableEntryInfo[Idx] = std::make_pair(Size, PCRelSym);
}

using SetOfInstructions = SmallPtrSet<const MachineInstr *, 16>;

const SetOfInstructions &getLOHRelated() const { return LOHRelated; }
Expand Down Expand Up @@ -200,6 +213,8 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
// Hold the lists of LOHs.
MILOHContainer LOHContainerSet;
SetOfInstructions LOHRelated;

DenseMap<int, std::pair<unsigned, MCSymbol *>> JumpTableEntryInfo;
};

} // end namespace llvm
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/AArch64/AArch64Subtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
bool HasFuseLiterals = false;
bool DisableLatencySchedHeuristic = false;
bool UseRSqrt = false;
bool Force32BitJumpTables = false;
uint8_t MaxInterleaveFactor = 2;
uint8_t VectorInsertExtractBaseCost = 3;
uint16_t CacheLineSize = 0;
Expand Down Expand Up @@ -292,6 +293,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
}

bool useRSqrt() const { return UseRSqrt; }
bool force32BitJumpTables() const { return Force32BitJumpTables; }
unsigned getMaxInterleaveFactor() const { return MaxInterleaveFactor; }
unsigned getVectorInsertExtractBaseCost() const {
return VectorInsertExtractBaseCost;
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ static cl::opt<bool>
BranchRelaxation("aarch64-enable-branch-relax", cl::Hidden, cl::init(true),
cl::desc("Relax out of range conditional branches"));

static cl::opt<bool> EnableCompressJumpTables(
"aarch64-enable-compress-jump-tables", cl::Hidden, cl::init(true),
cl::desc("Use smallest entry possible for jump tables"));

// FIXME: Unify control over GlobalMerge.
static cl::opt<cl::boolOrDefault>
EnableGlobalMerge("aarch64-enable-global-merge", cl::Hidden,
Expand Down Expand Up @@ -158,6 +162,7 @@ extern "C" void LLVMInitializeAArch64Target() {
initializeAArch64AdvSIMDScalarPass(*PR);
initializeAArch64BranchTargetsPass(*PR);
initializeAArch64CollectLOHPass(*PR);
initializeAArch64CompressJumpTablesPass(*PR);
initializeAArch64ConditionalComparesPass(*PR);
initializeAArch64ConditionOptimizerPass(*PR);
initializeAArch64DeadRegisterDefinitionsPass(*PR);
Expand Down Expand Up @@ -546,6 +551,9 @@ void AArch64PassConfig::addPreEmitPass() {
if (EnableBranchTargets)
addPass(createAArch64BranchTargetsPass());

if (TM->getOptLevel() != CodeGenOpt::None && EnableCompressJumpTables)
addPass(createAArch64CompressJumpTablesPass());

if (TM->getOptLevel() != CodeGenOpt::None && EnableCollectLOH &&
TM->getTargetTriple().isOSBinFormatMachO())
addPass(createAArch64CollectLOHPass());
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/AArch64/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ add_llvm_target(AArch64CodeGen
AArch64FastISel.cpp
AArch64A53Fix835769.cpp
AArch64FrameLowering.cpp
AArch64CompressJumpTables.cpp
AArch64ConditionOptimizer.cpp
AArch64RedundantCopyElimination.cpp
AArch64ISelDAGToDAG.cpp
Expand Down
1 change: 1 addition & 0 deletions llvm/test/CodeGen/AArch64/O3-pipeline.ll
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@
; CHECK-NEXT: Branch Probability Basic Block Placement
; CHECK-NEXT: Branch relaxation pass
; CHECK-NEXT: AArch64 Branch Targets
; CHECK-NEXT: AArch64 Compress Jump Tables
; CHECK-NEXT: Contiguously Lay Out Funclets
; CHECK-NEXT: StackMap Liveness Analysis
; CHECK-NEXT: Live DEBUG_VALUE analysis
Expand Down
111 changes: 111 additions & 0 deletions llvm/test/CodeGen/AArch64/jump-table-compress.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# RUN: llc -mtriple=aarch64-linux-gnu %s -run-pass=aarch64-jump-tables -o - | FileCheck %s
--- |
define i32 @test_jumptable(i32 %in) {
unreachable
}

...
---
name: test_jumptable
alignment: 2
exposesReturnsTwice: false
legalized: false
regBankSelected: false
selected: false
tracksRegLiveness: true
liveins:
- { reg: '$w0' }
frameInfo:
isFrameAddressTaken: false
isReturnAddressTaken: false
hasStackMap: false
hasPatchPoint: false
stackSize: 0
offsetAdjustment: 0
maxAlignment: 0
adjustsStack: false
hasCalls: false
maxCallFrameSize: 0
hasOpaqueSPAdjustment: false
hasVAStart: false
hasMustTailInVarArgFunc: false
jumpTable:
kind: block-address
entries:
- id: 0
blocks: [ '%bb.2', '%bb.3' ]
- id: 1
blocks: [ '%bb.4', '%bb.5' ]
- id: 2
blocks: [ '%bb.7' ]
- id: 3
blocks: [ '%bb.9' ]
- id: 4
blocks: [ '%bb.9' ]
- id: 5
blocks: [ '%bb.11' ]
body: |
bb.0 (%ir-block.0):
bb.1 (%ir-block.0):
; CHECK-LABEL: body:
; CHECK-LABEL: bb.1
; CHECK: JumpTableDest8
liveins: $x8
early-clobber $x10, dead early-clobber $x11 = JumpTableDest32 undef killed $x9, undef killed $x8, %jump-table.0
BR killed $x10
bb.2:
; Last destination is 4 * 255 = 1020 bytes after first. Byte is OK.
dead $xzr = SPACE 1020, undef $xzr
bb.3:
; CHECK-LABEL: bb.3
; CHECK: JumpTableDest16
early-clobber $x10, dead early-clobber $x11 = JumpTableDest32 undef killed $x9, undef killed $x8, %jump-table.1
BR killed $x10
bb.4:
; Last destination is 4 * 256 = 1024 bytes after first. Half needed.
dead $xzr = SPACE 1024, undef $xzr
bb.5:
; CHECK-LABEL: bb.5
; CHECK: JumpTableDest8
early-clobber $x10, dead early-clobber $x11 = JumpTableDest32 undef killed $x9, undef killed $x8, %jump-table.2
BR killed $x10
bb.6:
; First destination is (2^20 - 4) after reference. Just reachable by ADR so can use compressed table.
dead $xzr = SPACE 1048556, undef $xzr
bb.7:
; CHECK-LABEL: bb.7
; CHECK: JumpTableDest32
early-clobber $x10, dead early-clobber $x11 = JumpTableDest32 undef killed $x9, undef killed $x8, %jump-table.3
BR killed $x10
bb.8:
; First destination is 2^20 after reference. Compressed table cannot reach it.
dead $xzr = SPACE 1048560, undef $xzr
bb.9:
; First destination is 2^20 before reference. Just within reach of ADR.
dead $xzr = SPACE 1048576, undef $xzr
bb.10:
; CHECK-LABEL: bb.10
; CHECK: JumpTableDest8
early-clobber $x10, dead early-clobber $x11 = JumpTableDest32 undef killed $x9, undef killed $x8, %jump-table.4
BR killed $x10
bb.11:
; First destination is 2^20 before reference. Just within reach of ADR.
dead $xzr = SPACE 1048580, undef $xzr
bb.12:
; CHECK-LABEL: bb.12
; CHECK: JumpTableDest32
early-clobber $x10, dead early-clobber $x11 = JumpTableDest32 undef killed $x9, undef killed $x8, %jump-table.5
BR killed $x10
...
67 changes: 67 additions & 0 deletions llvm/test/CodeGen/AArch64/jump-table-exynos.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
; RUN: llc -o - %s -mtriple=aarch64-none-linux-gnu -mattr=+force-32bit-jump-tables -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s
; RUN: llc -o - %s -mtriple=aarch64-none-linux-gnu -mcpu=exynos-m1 -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s
; RUN: llc -o - %s -mtriple=aarch64-none-linux-gnu -mcpu=exynos-m2 -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s
; RUN: llc -o - %s -mtriple=aarch64-none-linux-gnu -mcpu=exynos-m3 -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s

; Exynos doesn't want jump tables to be compressed for now.

define i32 @test_jumptable(i32 %in) {
switch i32 %in, label %def [
i32 0, label %lbl1
i32 1, label %lbl2
i32 2, label %lbl3
i32 4, label %lbl4
]
; CHECK-LABEL: test_jumptable:
; CHECK-NOT: ldrb

def:
ret i32 0

lbl1:
ret i32 1

lbl2:
ret i32 2

lbl3:
ret i32 4

lbl4:
ret i32 8

}

define i32 @test_jumptable_minsize(i32 %in) minsize {
switch i32 %in, label %def [
i32 0, label %lbl1
i32 1, label %lbl2
i32 2, label %lbl3
i32 4, label %lbl4
]
; CHECK-LABEL: test_jumptable_minsize:
; CHECK: adrp [[JTPAGE:x[0-9]+]], .LJTI1_0
; CHECK: add x[[JT:[0-9]+]], [[JTPAGE]], {{#?}}:lo12:.LJTI1_0
; CHECK: adr [[PCBASE:x[0-9]+]], [[JTBASE:.LBB[0-9]+_[0-9]+]]
; CHECK: ldrb w[[OFFSET:[0-9]+]], [x[[JT]], {{x[0-9]+}}]
; CHECK: add [[DEST:x[0-9]+]], [[PCBASE]], x[[OFFSET]], lsl #2
; CHECK: br [[DEST]]



def:
ret i32 0

lbl1:
ret i32 1

lbl2:
ret i32 2

lbl3:
ret i32 4

lbl4:
ret i32 8

}
156 changes: 121 additions & 35 deletions llvm/test/CodeGen/AArch64/jump-table.ll
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
; RUN: llc -verify-machineinstrs -o - %s -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s
; RUN: llc -code-model=large -verify-machineinstrs -o - %s -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck --check-prefix=CHECK-LARGE %s
; RUN: llc -mtriple=aarch64-none-linux-gnu -verify-machineinstrs -relocation-model=pic -aarch64-enable-atomic-cfg-tidy=0 -o - %s | FileCheck --check-prefix=CHECK-PIC %s
; RUN: llc -code-model=tiny -verify-machineinstrs -o - %s -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck --check-prefix=CHECK-TINY %s
; RUN: llc -no-integrated-as -verify-machineinstrs -o - %s -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s
; RUN: llc -no-integrated-as -code-model=large -verify-machineinstrs -o - %s -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck --check-prefix=CHECK-LARGE %s
; RUN: llc -no-integrated-as -mtriple=aarch64-none-linux-gnu -verify-machineinstrs -relocation-model=pic -aarch64-enable-atomic-cfg-tidy=0 -o - %s | FileCheck --check-prefix=CHECK-PIC %s
; RUN: llc -no-integrated-as -code-model=tiny -verify-machineinstrs -o - %s -mtriple=aarch64-none-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 | FileCheck --check-prefix=CHECK-TINY %s

define i32 @test_jumptable(i32 %in) {
; CHECK: test_jumptable
Expand All @@ -12,27 +12,45 @@ define i32 @test_jumptable(i32 %in) {
i32 2, label %lbl3
i32 4, label %lbl4
]
; CHECK: adrp [[JTPAGE:x[0-9]+]], .LJTI0_0
; CHECK: add x[[JT:[0-9]+]], [[JTPAGE]], {{#?}}:lo12:.LJTI0_0
; CHECK: ldr [[DEST:x[0-9]+]], [x[[JT]], {{x[0-9]+}}, lsl #3]
; CHECK: br [[DEST]]

; CHECK-LARGE: movz x[[JTADDR:[0-9]+]], #:abs_g0_nc:.LJTI0_0
; CHECK-LARGE: movk x[[JTADDR]], #:abs_g1_nc:.LJTI0_0
; CHECK-LARGE: movk x[[JTADDR]], #:abs_g2_nc:.LJTI0_0
; CHECK-LARGE: movk x[[JTADDR]], #:abs_g3:.LJTI0_0
; CHECK-LARGE: ldr [[DEST:x[0-9]+]], [x[[JTADDR]], {{x[0-9]+}}, lsl #3]
; CHECK-LARGE: br [[DEST]]

; CHECK-PIC: adrp [[JTPAGE:x[0-9]+]], .LJTI0_0
; CHECK-PIC: add x[[JT:[0-9]+]], [[JTPAGE]], {{#?}}:lo12:.LJTI0_0
; CHECK-PIC: ldrsw [[DEST:x[0-9]+]], [x[[JT]], {{x[0-9]+}}, lsl #2]
; CHECK-PIC: add [[TABLE:x[0-9]+]], [[DEST]], x[[JT]]
; CHECK-PIC: br [[TABLE]]

; CHECK-TINY: adr x[[JT:[0-9]+]], .LJTI0_0
; CHECK-TINY: ldr [[DEST:x[0-9]+]], [x[[JT]], {{x[0-9]+}}, lsl #3]
; CHECK-TINY: br [[DEST]]
; CHECK-LABEL: test_jumptable:
; CHECK: adrp [[JTPAGE:x[0-9]+]], .LJTI0_0
; CHECK: add x[[JT:[0-9]+]], [[JTPAGE]], {{#?}}:lo12:.LJTI0_0
; CHECK: adr [[PCBASE:x[0-9]+]], [[JTBASE:.LBB[0-9]+_[0-9]+]]
; CHECK: ldrb w[[OFFSET:[0-9]+]], [x[[JT]], {{x[0-9]+}}]
; CHECK: add [[DEST:x[0-9]+]], [[PCBASE]], x[[OFFSET]], lsl #2
; CHECK: br [[DEST]]

; CHECK-LARGE: movz x[[JTADDR:[0-9]+]], #:abs_g0_nc:.LJTI0_0
; CHECK-LARGE: movk x[[JTADDR]], #:abs_g1_nc:.LJTI0_0
; CHECK-LARGE: movk x[[JTADDR]], #:abs_g2_nc:.LJTI0_0
; CHECK-LARGE: movk x[[JTADDR]], #:abs_g3:.LJTI0_0
; CHECK-LARGE: adr [[PCBASE:x[0-9]+]], [[JTBASE:.LBB[0-9]+_[0-9]+]]
; CHECK-LARGE: ldrb w[[OFFSET:[0-9]+]], [x[[JTADDR]], {{x[0-9]+}}]
; CHECK-LARGE: add [[DEST:x[0-9]+]], [[PCBASE]], x[[OFFSET]], lsl #2
; CHECK-LARGE: br [[DEST]]

; CHECK-PIC-LABEL: test_jumptable:
; CHECK-PIC: adrp [[JTPAGE:x[0-9]+]], .LJTI0_0
; CHECK-PIC: add x[[JT:[0-9]+]], [[JTPAGE]], {{#?}}:lo12:.LJTI0_0
; CHECK-PIC: adr [[PCBASE:x[0-9]+]], [[JTBASE:.LBB[0-9]+_[0-9]+]]
; CHECK-PIC: ldrb w[[OFFSET:[0-9]+]], [x[[JT]], {{x[0-9]+}}]
; CHECK-PIC: add [[DEST:x[0-9]+]], [[PCBASE]], x[[OFFSET]], lsl #2
; CHECK-PIC: br [[DEST]]

; CHECK-IOS: adrp [[JTPAGE:x[0-9]+]], LJTI0_0@PAGE
; CHECK-IOS: add x[[JT:[0-9]+]], [[JTPAGE]], LJTI0_0@PAGEOFF
; CHECK-IOS: adr [[PCBASE:x[0-9]+]], [[JTBASE:LBB[0-9]+_[0-9]+]]
; CHECK-IOS: ldrb w[[OFFSET:[0-9]+]], [x[[JT]], {{x[0-9]+}}]
; CHECK-IOS: add [[DEST:x[0-9]+]], [[PCBASE]], x[[OFFSET]], lsl #2
; CHECK-IOS: br [[DEST]]

; CHECK-TINY-LABEL: test_jumptable:
; CHECK-TINY: adr x[[JT:[0-9]+]], .LJTI0_0
; CHECK-TINY: adr [[PCBASE:x[0-9]+]], [[JTBASE:.LBB[0-9]+_[0-9]+]]
; CHECK-TINY: ldrb w[[OFFSET:[0-9]+]], [x[[JT]], {{x[0-9]+}}]
; CHECK-TINY: add [[DEST:x[0-9]+]], [[PCBASE]], x[[OFFSET]], lsl #2
; CHECK-TINY: br [[DEST]]


def:
ret i32 0
Expand All @@ -54,18 +72,86 @@ lbl4:
; CHECK: .rodata

; CHECK: .LJTI0_0:
; CHECK-NEXT: .xword
; CHECK-NEXT: .xword
; CHECK-NEXT: .xword
; CHECK-NEXT: .xword
; CHECK-NEXT: .xword
; CHECK-NEXT: .byte ([[JTBASE]]-[[JTBASE]])>>2
; CHECK-NEXT: .byte (.LBB{{.*}}-[[JTBASE]])>>2
; CHECK-NEXT: .byte (.LBB{{.*}}-[[JTBASE]])>>2
; CHECK-NEXT: .byte (.LBB{{.*}}-[[JTBASE]])>>2
; CHECK-NEXT: .byte (.LBB{{.*}}-[[JTBASE]])>>2

define i32 @test_jumptable16(i32 %in) {

switch i32 %in, label %def [
i32 0, label %lbl1
i32 1, label %lbl2
i32 2, label %lbl3
i32 4, label %lbl4
]
; CHECK-LABEL: test_jumptable16:
; CHECK: adrp [[JTPAGE:x[0-9]+]], .LJTI1_0
; CHECK: add x[[JT:[0-9]+]], [[JTPAGE]], {{#?}}:lo12:.LJTI1_0
; CHECK: adr [[PCBASE:x[0-9]+]], [[JTBASE:.LBB[0-9]+_[0-9]+]]
; CHECK: ldrh w[[OFFSET:[0-9]+]], [x[[JT]], {{x[0-9]+}}, lsl #1]
; CHECK: add [[DEST:x[0-9]+]], [[PCBASE]], x[[OFFSET]], lsl #2
; CHECK: br [[DEST]]

def:
ret i32 0

lbl1:
ret i32 1

lbl2:
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
call void asm sideeffect "1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16", ""()
ret i32 2

lbl3:
ret i32 4

lbl4:
ret i32 8

}

; CHECK: .rodata
; CHECK: .p2align 1
; CHECK: .LJTI1_0:
; CHECK-NEXT: .hword ([[JTBASE]]-[[JTBASE]])>>2
; CHECK-NEXT: .hword (.LBB{{.*}}-[[JTBASE]])>>2
; CHECK-NEXT: .hword (.LBB{{.*}}-[[JTBASE]])>>2
; CHECK-NEXT: .hword (.LBB{{.*}}-[[JTBASE]])>>2
; CHECK-NEXT: .hword (.LBB{{.*}}-[[JTBASE]])>>2

; CHECK-PIC-NOT: .data_region
; CHECK-PIC-NOT: .LJTI0_0
; CHECK-PIC: .LJTI0_0:
; CHECK-PIC-NEXT: .word .LBB{{.*}}-.LJTI0_0
; CHECK-PIC-NEXT: .word .LBB{{.*}}-.LJTI0_0
; CHECK-PIC-NEXT: .word .LBB{{.*}}-.LJTI0_0
; CHECK-PIC-NEXT: .word .LBB{{.*}}-.LJTI0_0
; CHECK-PIC-NEXT: .word .LBB{{.*}}-.LJTI0_0
; CHECK-PIC-NEXT: .byte ([[JTBASE]]-[[JTBASE]])>>2
; CHECK-PIC-NEXT: .byte (.LBB{{.*}}-[[JTBASE]])>>2
; CHECK-PIC-NEXT: .byte (.LBB{{.*}}-[[JTBASE]])>>2
; CHECK-PIC-NEXT: .byte (.LBB{{.*}}-[[JTBASE]])>>2
; CHECK-PIC-NEXT: .byte (.LBB{{.*}}-[[JTBASE]])>>2
; CHECK-PIC-NOT: .end_data_region

; CHECK-IOS: .section __TEXT,__const
; CHECK-IOS-NOT: .data_region
; CHECK-IOS: LJTI0_0:
; CHECK-IOS-NEXT: .byte ([[JTBASE]]-[[JTBASE]])>>2
; CHECK-IOS-NEXT: .byte (LBB{{.*}}-[[JTBASE]])>>2
; CHECK-IOS-NEXT: .byte (LBB{{.*}}-[[JTBASE]])>>2
; CHECK-IOS-NEXT: .byte (LBB{{.*}}-[[JTBASE]])>>2
; CHECK-IOS-NEXT: .byte (LBB{{.*}}-[[JTBASE]])>>2
; CHECK-IOS-NOT: .end_data_region
6 changes: 3 additions & 3 deletions llvm/test/CodeGen/AArch64/min-jump-table.ll
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ entry:
; CHECK0-NEXT: Jump Tables:
; CHECK0-NEXT: %jump-table.0:
; CHECK0-NOT: %jump-table.1:
; CHECK4-NOT: Jump Tables:
; CHECK8-NOT: Jump Tables:
; CHECK4-NOT: {{^}}Jump Tables:
; CHECK8-NOT: {{^}}Jump Tables:

bb1: tail call void @ext(i32 0) br label %return
bb2: tail call void @ext(i32 2) br label %return
Expand All @@ -38,7 +38,7 @@ entry:
; CHECK4-NEXT: Jump Tables:
; CHECK4-NEXT: %jump-table.0:
; CHECK4-NOT: %jump-table.1:
; CHECK8-NOT: Jump Tables:
; CHECK8-NOT: {{^}}Jump Tables:

bb1: tail call void @ext(i32 0) br label %return
bb2: tail call void @ext(i32 2) br label %return
Expand Down