diff --git a/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/llvm/include/llvm/CodeGen/MIRYamlMapping.h --- a/llvm/include/llvm/CodeGen/MIRYamlMapping.h +++ b/llvm/include/llvm/CodeGen/MIRYamlMapping.h @@ -137,6 +137,8 @@ MachineJumpTableInfo::EK_GPRel32BlockAddress); IO.enumCase(EntryKind, "label-difference32", MachineJumpTableInfo::EK_LabelDifference32); + IO.enumCase(EntryKind, "label-difference64", + MachineJumpTableInfo::EK_LabelDifference64); IO.enumCase(EntryKind, "inline", MachineJumpTableInfo::EK_Inline); IO.enumCase(EntryKind, "custom32", MachineJumpTableInfo::EK_Custom32); } diff --git a/llvm/include/llvm/CodeGen/MachineJumpTableInfo.h b/llvm/include/llvm/CodeGen/MachineJumpTableInfo.h --- a/llvm/include/llvm/CodeGen/MachineJumpTableInfo.h +++ b/llvm/include/llvm/CodeGen/MachineJumpTableInfo.h @@ -67,6 +67,12 @@ /// .word L4_5_set_123 EK_LabelDifference32, + /// EK_LabelDifference64 - Each entry is the address of the block minus + /// the address of the jump table. This is used for PIC jump tables where + /// gprel64 is not supported. e.g.: + /// .quad LBB123 - LJTI1_2 + EK_LabelDifference64, + /// EK_Inline - Jump table entries are emitted inline at their point of /// use. It is the responsibility of the target to emit the entries. EK_Inline, @@ -75,6 +81,7 @@ /// TargetLowering::LowerCustomJumpTableEntry hook. EK_Custom32 }; + private: JTEntryKind EntryKind; std::vector JumpTables; diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2571,7 +2571,8 @@ const Function &F = MF->getFunction(); const TargetLoweringObjectFile &TLOF = getObjFileLowering(); bool JTInDiffSection = !TLOF.shouldPutJumpTableInFunctionSection( - MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32, + MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 || + MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference64, F); if (JTInDiffSection) { // Drop it in the readonly section. @@ -2669,7 +2670,8 @@ return; } - case MachineJumpTableInfo::EK_LabelDifference32: { + case MachineJumpTableInfo::EK_LabelDifference32: + case MachineJumpTableInfo::EK_LabelDifference64: { // Each entry is the address of the block minus the address of the jump // table. This is used for PIC jump tables where gprel32 is not supported. // e.g.: @@ -2677,7 +2679,8 @@ // If the .set directive avoids relocations, this is emitted as: // .set L4_5_set_123, LBB123 - LJTI1_2 // .word L4_5_set_123 - if (MAI->doesSetDirectiveSuppressReloc()) { + if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 && + MAI->doesSetDirectiveSuppressReloc()) { Value = MCSymbolRefExpr::create(GetJTSetSymbol(UID, MBB->getNumber()), OutContext); break; diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -3545,6 +3545,7 @@ break; case MachineJumpTableInfo::EK_Inline: case MachineJumpTableInfo::EK_LabelDifference32: + case MachineJumpTableInfo::EK_LabelDifference64: // Ask the AsmPrinter. std::tie(Base, BaseOffset, Branch, EntrySize) = Asm->getCodeViewJumpTableInfo(JumpTableIndex, &BranchMI, Branch); diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -1244,6 +1244,7 @@ case MachineJumpTableInfo::EK_BlockAddress: return TD.getPointerSize(); case MachineJumpTableInfo::EK_GPRel64BlockAddress: + case MachineJumpTableInfo::EK_LabelDifference64: return 8; case MachineJumpTableInfo::EK_GPRel32BlockAddress: case MachineJumpTableInfo::EK_LabelDifference32: @@ -1264,6 +1265,7 @@ case MachineJumpTableInfo::EK_BlockAddress: return TD.getPointerABIAlignment(0).value(); case MachineJumpTableInfo::EK_GPRel64BlockAddress: + case MachineJumpTableInfo::EK_LabelDifference64: return TD.getABIIntegerTypeAlignment(64).value(); case MachineJumpTableInfo::EK_GPRel32BlockAddress: case MachineJumpTableInfo::EK_LabelDifference32: diff --git a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp --- a/llvm/lib/Target/X86/X86ISelLoweringCall.cpp +++ b/llvm/lib/Target/X86/X86ISelLoweringCall.cpp @@ -413,6 +413,9 @@ // symbol. if (isPositionIndependent() && Subtarget.isPICStyleGOT()) return MachineJumpTableInfo::EK_Custom32; + if (isPositionIndependent() && + getTargetMachine().getCodeModel() == CodeModel::Large) + return MachineJumpTableInfo::EK_LabelDifference64; // Otherwise, use the normal jump table encoding heuristics. return TargetLowering::getJumpTableEncoding(); @@ -512,7 +515,9 @@ getPICJumpTableRelocBaseExpr(const MachineFunction *MF, unsigned JTI, MCContext &Ctx) const { // X86-64 uses RIP relative addressing based on the jump table label. - if (Subtarget.isPICStyleRIPRel()) + if (Subtarget.isPICStyleRIPRel() || + (Subtarget.is64Bit() && + getTargetMachine().getCodeModel() == CodeModel::Large)) return TargetLowering::getPICJumpTableRelocBaseExpr(MF, JTI, Ctx); // Otherwise, the reference is relative to the PIC base. diff --git a/llvm/test/CodeGen/X86/large-pic-jump-table.ll b/llvm/test/CodeGen/X86/large-pic-jump-table.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/large-pic-jump-table.ll @@ -0,0 +1,39 @@ +; RUN: llc -code-model=large -relocation-model=pic %s -o - | FileCheck %s + +target triple = "x86_64-linux-gnu" + +define i32 @f(i32 %i) { +bb: + switch i32 %i, label %bb4 [ + i32 0, label %bb0 + i32 1, label %bb1 + i32 2, label %bb2 + i32 3, label %bb3 + ] + +bb0: + ret i32 1 + +bb1: + ret i32 100 + +bb2: + ret i32 200 + +bb3: + ret i32 400 + +bb4: + ret i32 300 +} + +; CHECK: movabsq $.LJTI0_0@GOTOFF, [[R1:%r[a-z]{2}]] +; CHECK-NEXT: addq [[R1]], [[R2:%r[a-z]{2}]] +; CHECK-NEXT: addq ([[R2]],[[R3:%r[a-z]{2}]],8), [[R2]] +; CHECK-NEXT: jmpq *[[R2]] + +; CHECK: .LJTI0_0: +; CHECK-NEXT: .quad .LBB0_2-.LJTI0_0 +; CHECK-NEXT: .quad .LBB0_3-.LJTI0_0 +; CHECK-NEXT: .quad .LBB0_4-.LJTI0_0 +; CHECK-NEXT: .quad .LBB0_5-.LJTI0_0