Index: include/llvm/CodeGen/MIRYamlMapping.h =================================================================== --- include/llvm/CodeGen/MIRYamlMapping.h +++ include/llvm/CodeGen/MIRYamlMapping.h @@ -129,6 +129,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); } Index: include/llvm/CodeGen/MachineJumpTableInfo.h =================================================================== --- include/llvm/CodeGen/MachineJumpTableInfo.h +++ include/llvm/CodeGen/MachineJumpTableInfo.h @@ -67,6 +67,15 @@ /// .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.: + /// .word LBB123 - LJTI1_2 + /// If the .set directive is supported, this is emitted as: + /// .set L4_5_set_123, LBB123 - LJTI1_2 + /// .word L4_5_set_123 + 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, Index: lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1538,7 +1538,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. @@ -1559,9 +1560,10 @@ // If this jump table was deleted, ignore it. if (JTBBs.empty()) continue; - // For the EK_LabelDifference32 entry, if using .set avoids a relocation, + // For the EK_LabelDifference(32|64) entry, if using .set avoids a relocation, /// emit a .set directive for each unique entry. - if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 && + if ((MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 || + MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference64) && MAI->doesSetDirectiveSuppressReloc()) { SmallPtrSet EmittedSets; const TargetLowering *TLI = MF->getSubtarget().getTargetLowering(); @@ -1635,9 +1637,11 @@ return; } + + case MachineJumpTableInfo::EK_LabelDifference64: case MachineJumpTableInfo::EK_LabelDifference32: { // 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. + // table. This is used for PIC jump tables where gprel32 or gprel64 is not supported. // e.g.: // .word LBB123 - LJTI1_2 // If the .set directive avoids relocations, this is emitted as: Index: lib/CodeGen/MachineFunction.cpp =================================================================== --- lib/CodeGen/MachineFunction.cpp +++ lib/CodeGen/MachineFunction.cpp @@ -765,6 +765,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: @@ -785,6 +786,7 @@ case MachineJumpTableInfo::EK_BlockAddress: return TD.getPointerABIAlignment(); case MachineJumpTableInfo::EK_GPRel64BlockAddress: + case MachineJumpTableInfo::EK_LabelDifference64: return TD.getABIIntegerTypeAlignment(64); case MachineJumpTableInfo::EK_GPRel32BlockAddress: case MachineJumpTableInfo::EK_LabelDifference32: Index: lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -288,12 +288,22 @@ if (!isPositionIndependent()) return MachineJumpTableInfo::EK_BlockAddress; - // In PIC mode, if the target supports a GPRel32 directive, use it. - if (getTargetMachine().getMCAsmInfo()->getGPRel32Directive() != nullptr) - return MachineJumpTableInfo::EK_GPRel32BlockAddress; + const auto &TM = getTargetMachine(); + if (TM.getPointerSize() == 8 && TM.getCodeModel() == CodeModel::Large) { + // In PIC mode, if the target supports a GPRel64 directive, use it. + if (TM.getMCAsmInfo()->getGPRel64Directive() != nullptr) + return MachineJumpTableInfo::EK_GPRel64BlockAddress; + + // Otherwise, use a label difference. + return MachineJumpTableInfo::EK_LabelDifference64; + } else { + // In PIC mode, if the target supports a GPRel32 directive, use it. + if (TM.getMCAsmInfo()->getGPRel32Directive() != nullptr) + return MachineJumpTableInfo::EK_GPRel32BlockAddress; - // Otherwise, use a label difference. - return MachineJumpTableInfo::EK_LabelDifference32; + // Otherwise, use a label difference. + return MachineJumpTableInfo::EK_LabelDifference32; + } } SDValue TargetLowering::getPICJumpTableRelocBase(SDValue Table, Index: test/CodeGen/AArch64/jumptable-large.ll =================================================================== --- /dev/null +++ test/CodeGen/AArch64/jumptable-large.ll @@ -0,0 +1,51 @@ +; RUN: llc -O0 -relocation-model=pic -code-model=small -march=aarch64 %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-SMALL %s +; RUN: llc -O0 -relocation-model=pic -code-model=large -march=aarch64 %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-LARGE %s + +define double @f(i64) { +top: + switch i64 %0, label %L19 [ + i64 0, label %if + i64 1, label %if1 + i64 2, label %if2 + i64 3, label %if3 + ] + +if: ; preds = %top + %1 = call double @g1(double -1.000000e+00) + ret double %1 + +if1: ; preds = %top + %2 = call double @g2(double 1.000000e+00) + ret double %2 + +if2: ; preds = %top + %3 = call double @g3(double 1.000000e+00) + ret double %3 + +if3: ; preds = %top + %4 = call double @g4(double 1.000000e+00) + ret double %4 + +L19: ; preds = %top + %5 = call double @g5(double 1.000000e+00) + ret double %5 +; CHECK-LABEL: .LJTI0_0: +; CHECK-LARGE-NEXT: .xword .LBB{{.*}}-.LJTI0_0 +; CHECK-LARGE-NEXT: .xword .LBB{{.*}}-.LJTI0_0 +; CHECK-LARGE-NEXT: .xword .LBB{{.*}}-.LJTI0_0 +; CHECK-LARGE-NEXT: .xword .LBB{{.*}}-.LJTI0_0 +; CHECK-SMALL-NEXT: .word .LBB{{.*}}-.LJTI0_0 +; CHECK-SMALL-NEXT: .word .LBB{{.*}}-.LJTI0_0 +; CHECK-SMALL-NEXT: .word .LBB{{.*}}-.LJTI0_0 +; CHECK-SMALL-NEXT: .word .LBB{{.*}}-.LJTI0_0 +} + +declare double @g1(double) + +declare double @g2(double) + +declare double @g3(double) + +declare double @g4(double) + +declare double @g5(double) Index: test/CodeGen/PowerPC/jumptable-large.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/jumptable-large.ll @@ -0,0 +1,51 @@ +; RUN: llc -O0 -relocation-model=pic -code-model=small -march=ppc64 %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-SMALL %s +; RUN: llc -O0 -relocation-model=pic -code-model=large -march=ppc64 %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-LARGE %s + +define double @f(i64) { +top: + switch i64 %0, label %L19 [ + i64 0, label %if + i64 1, label %if1 + i64 2, label %if2 + i64 3, label %if3 + ] + +if: ; preds = %top + %1 = call double @g1(double -1.000000e+00) + ret double %1 + +if1: ; preds = %top + %2 = call double @g2(double 1.000000e+00) + ret double %2 + +if2: ; preds = %top + %3 = call double @g3(double 1.000000e+00) + ret double %3 + +if3: ; preds = %top + %4 = call double @g4(double 1.000000e+00) + ret double %4 + +L19: ; preds = %top + %5 = call double @g5(double 1.000000e+00) + ret double %5 +; CHECK-LABEL: .LJTI0_0: +; CHECK-LARGE-NEXT: .long .LBB{{.*}}-.L0$pb +; CHECK-LARGE-NEXT: .long .LBB{{.*}}-.L0$pb +; CHECK-LARGE-NEXT: .long .LBB{{.*}}-.L0$pb +; CHECK-LARGE-NEXT: .long .LBB{{.*}}-.L0$pb +; CHECK-SMALL-NEXT: .long .LBB{{.*}}-.LJTI0_0 +; CHECK-SMALL-NEXT: .long .LBB{{.*}}-.LJTI0_0 +; CHECK-SMALL-NEXT: .long .LBB{{.*}}-.LJTI0_0 +; CHECK-SMALL-NEXT: .long .LBB{{.*}}-.LJTI0_0 +} + +declare double @g1(double) + +declare double @g2(double) + +declare double @g3(double) + +declare double @g4(double) + +declare double @g5(double) Index: test/CodeGen/X86/jumptable-large.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/jumptable-large.ll @@ -0,0 +1,51 @@ +; RUN: llc -O0 -relocation-model=pic -code-model=small -march=x86-64 %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-SMALL %s +; RUN: llc -O0 -relocation-model=pic -code-model=large -march=x86-64 %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CHECK-LARGE %s + +define double @f(i64) { +top: + switch i64 %0, label %L19 [ + i64 0, label %if + i64 1, label %if1 + i64 2, label %if2 + i64 3, label %if3 + ] + +if: ; preds = %top + %1 = call double @g1(double -1.000000e+00) + ret double %1 + +if1: ; preds = %top + %2 = call double @g2(double 1.000000e+00) + ret double %2 + +if2: ; preds = %top + %3 = call double @g3(double 1.000000e+00) + ret double %3 + +if3: ; preds = %top + %4 = call double @g4(double 1.000000e+00) + ret double %4 + +L19: ; preds = %top + %5 = call double @g5(double 1.000000e+00) + ret double %5 +; CHECK-LABEL: .LJTI0_0: +; CHECK-LARGE-NEXT: .quad .LBB{{.*}}-.LJTI0_0 +; CHECK-LARGE-NEXT: .quad .LBB{{.*}}-.LJTI0_0 +; CHECK-LARGE-NEXT: .quad .LBB{{.*}}-.LJTI0_0 +; CHECK-LARGE-NEXT: .quad .LBB{{.*}}-.LJTI0_0 +; CHECK-SMALL-NEXT: .long .LBB{{.*}}-.LJTI0_0 +; CHECK-SMALL-NEXT: .long .LBB{{.*}}-.LJTI0_0 +; CHECK-SMALL-NEXT: .long .LBB{{.*}}-.LJTI0_0 +; CHECK-SMALL-NEXT: .long .LBB{{.*}}-.LJTI0_0 +} + +declare double @g1(double) + +declare double @g2(double) + +declare double @g3(double) + +declare double @g4(double) + +declare double @g5(double)