[llvm] [X86][GlobalISel] Enable G_BRJT (PR #81811)

RĂ©mi SEGARD via llvm-commits llvm-commits at lists.llvm.org
Sat Feb 17 12:52:02 PST 2024


https://github.com/RemiSEGARD updated https://github.com/llvm/llvm-project/pull/81811

>From 22d9a0f0c99352150010d27bd46927eb08488297 Mon Sep 17 00:00:00 2001
From: Remi SEGARD <remi.segard at epita.fr>
Date: Thu, 15 Feb 2024 01:44:54 +0100
Subject: [PATCH] [X86][GlobalISel] Enable G_BRJT

---
 llvm/include/llvm/Target/GenericOpcodes.td    |   2 +-
 .../Target/GlobalISel/SelectionDAGCompat.td   |   1 +
 .../X86/GISel/X86InstructionSelector.cpp      |  31 +++
 .../lib/Target/X86/GISel/X86LegalizerInfo.cpp |  68 +++++
 llvm/lib/Target/X86/GISel/X86LegalizerInfo.h  |   4 +
 .../X86/GlobalISel/legalize-brindirect.mir    |  55 ++++
 .../CodeGen/X86/GlobalISel/legalize-brjt.mir  | 257 ++++++++++++++++++
 .../X86/GlobalISel/select-jumptable.mir       | 114 ++++++++
 8 files changed, 531 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/X86/GlobalISel/legalize-brindirect.mir
 create mode 100644 llvm/test/CodeGen/X86/GlobalISel/legalize-brjt.mir
 create mode 100644 llvm/test/CodeGen/X86/GlobalISel/select-jumptable.mir

diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index 19197f50d9dff9..c7eef211ae3425 100644
--- a/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/llvm/include/llvm/Target/GenericOpcodes.td
@@ -1374,7 +1374,7 @@ def G_BRCOND : GenericInstruction {
 // Generic indirect branch.
 def G_BRINDIRECT : GenericInstruction {
   let OutOperandList = (outs);
-  let InOperandList = (ins type0:$src1);
+  let InOperandList = (ins ptype0:$src1);
   let hasSideEffects = false;
   let isBranch = true;
   let isTerminator = true;
diff --git a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
index b1f3c500a1b6c5..0349cc2be73714 100644
--- a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
+++ b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
@@ -131,6 +131,7 @@ let IfConvergent = G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS in {
 
 def : GINodeEquiv<G_BR, br>;
 def : GINodeEquiv<G_BRCOND, brcond>;
+def : GINodeEquiv<G_BRINDIRECT, brind>;
 def : GINodeEquiv<G_BSWAP, bswap>;
 def : GINodeEquiv<G_BITREVERSE, bitreverse>;
 def : GINodeEquiv<G_FSHL, fshl>;
diff --git a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
index 26932ba2c8e242..255385c85a7b9c 100644
--- a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
+++ b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
@@ -107,6 +107,8 @@ class X86InstructionSelector : public InstructionSelector {
                      MachineFunction &MF) const;
   bool selectCondBranch(MachineInstr &I, MachineRegisterInfo &MRI,
                         MachineFunction &MF) const;
+  bool selectJumpTable(MachineInstr &I, MachineRegisterInfo &MRI,
+                       MachineFunction &MF) const;
   bool selectTurnIntoCOPY(MachineInstr &I, MachineRegisterInfo &MRI,
                           const unsigned DstReg,
                           const TargetRegisterClass *DstRC,
@@ -421,6 +423,8 @@ bool X86InstructionSelector::select(MachineInstr &I) {
     return selectInsert(I, MRI, MF);
   case TargetOpcode::G_BRCOND:
     return selectCondBranch(I, MRI, MF);
+  case TargetOpcode::G_JUMP_TABLE:
+    return selectJumpTable(I, MRI, MF);
   case TargetOpcode::G_IMPLICIT_DEF:
   case TargetOpcode::G_PHI:
     return selectImplicitDefOrPHI(I, MRI);
@@ -1472,6 +1476,33 @@ bool X86InstructionSelector::selectCondBranch(MachineInstr &I,
   return true;
 }
 
+bool X86InstructionSelector::selectJumpTable(MachineInstr &I,
+                                             MachineRegisterInfo &MRI,
+                                             MachineFunction &MF) const {
+  auto Dst = I.getOperand(0).getReg();
+  auto JTI = I.getOperand(1).getIndex();
+  auto OpCode = STI.is64Bit() ? X86::LEA64r : X86::LEA32r;
+
+  auto *TLI = STI.getTargetLowering();
+
+  MachineInstr &Lea =
+      *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCode), Dst)
+           .addReg(TLI->isJumpTableRelative()
+                       ? (STI.is64Bit() ? X86::RIP : X86::EIP)
+                       : 0)
+           .addImm(1)
+           .addReg(0)
+           .addJumpTableIndex(JTI)
+           .addReg(0)
+           .getInstr();
+
+  constrainSelectedInstRegOperands(Lea, TII, TRI, RBI);
+
+  I.removeFromParent();
+
+  return true;
+}
+
 bool X86InstructionSelector::materializeFP(MachineInstr &I,
                                            MachineRegisterInfo &MRI,
                                            MachineFunction &MF) const {
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
index 27381dff338e2d..72a79f17766b6f 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
@@ -14,10 +14,16 @@
 #include "X86Subtarget.h"
 #include "X86TargetMachine.h"
 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/CodeGen/TargetLowering.h"
 #include "llvm/CodeGen/TargetOpcodes.h"
 #include "llvm/CodeGen/ValueTypes.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Type.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
 
 using namespace llvm;
 using namespace TargetOpcode;
@@ -326,6 +332,10 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
 
   getActionDefinitionsBuilder(G_BRCOND).legalFor({s1});
 
+  getActionDefinitionsBuilder(G_BRINDIRECT).legalFor({p0});
+  getActionDefinitionsBuilder(G_JUMP_TABLE).legalFor({p0});
+  getActionDefinitionsBuilder(G_BRJT).custom();
+
   // pointer handling
   const std::initializer_list<LLT> PtrTypes32 = {s1, s8, s16, s32};
   const std::initializer_list<LLT> PtrTypes64 = {s1, s8, s16, s32, s64};
@@ -549,6 +559,64 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
   verify(*STI.getInstrInfo());
 }
 
+bool X86LegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
+                                      LostDebugLocObserver &LocObserver) const {
+  switch (MI.getOpcode()) {
+  case G_BRJT:
+    return legalizeBrJT(Helper, MI);
+  default:
+    llvm_unreachable("instruction is not in switch");
+  }
+}
+
+bool X86LegalizerInfo::legalizeBrJT(LegalizerHelper &Helper,
+                                    MachineInstr &MI) const {
+  MachineIRBuilder &MIB = Helper.MIRBuilder;
+  MachineFunction &MF = *MI.getMF();
+  MachineRegisterInfo &MRI = *MIB.getMRI();
+  const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
+
+  unsigned EntrySize = MJTI->getEntrySize(MF.getDataLayout());
+
+  auto PtrReg = MI.getOperand(0).getReg();
+  auto PtrTy = MRI.getType(PtrReg);
+  auto IdxReg = MI.getOperand(2).getReg();
+  auto IdxTy = MRI.getType(IdxReg);
+
+  MachineMemOperand *MMO = MF.getMachineMemOperand(
+      MachinePointerInfo::getJumpTable(MF), MachineMemOperand::MOLoad,
+      PtrTy.getSizeInBytes(), Align(EntrySize));
+
+  auto ShiftAmt = MIB.buildConstant(IdxTy, Log2_32(PtrTy.getSizeInBytes()));
+  auto Shift = MIB.buildShl(IdxTy, IdxReg, ShiftAmt);
+  auto Target =
+      MIB.buildPtrAdd(PtrTy, PtrReg, Shift->getOperand(0).getReg()).getReg(0);
+
+  switch (MJTI->getEntryKind()) {
+  default:
+    return false;
+  case MachineJumpTableInfo::EK_BlockAddress: {
+    Target = MIB.buildLoad(PtrTy, Target, *MMO).getReg(0);
+    break;
+  }
+  case MachineJumpTableInfo::EK_LabelDifference64:
+    assert(Subtarget.is64Bit());
+    [[fallthrough]];
+  case MachineJumpTableInfo::EK_LabelDifference32:
+    auto Load = MIB.buildLoadInstr(
+        TargetOpcode::G_LOAD, LLT::scalar(PtrTy.getSizeInBits()), Target, *MMO);
+    Load = MIB.buildSExtOrTrunc(IdxTy, Load);
+    Target = MIB.buildPtrAdd(PtrTy, PtrReg, Load).getReg(0);
+    break;
+  }
+
+  MIB.buildBrIndirect(Target);
+
+  MI.removeFromParent();
+
+  return true;
+}
+
 bool X86LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
                                          MachineInstr &MI) const {
   return true;
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
index 12134f7b00f1cf..d6ec06ff0c9fc1 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
@@ -30,6 +30,10 @@ class X86LegalizerInfo : public LegalizerInfo {
 public:
   X86LegalizerInfo(const X86Subtarget &STI, const X86TargetMachine &TM);
 
+  bool legalizeBrJT(LegalizerHelper &Helper, MachineInstr &MI) const;
+
+  bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
+                      LostDebugLocObserver &LocObserver) const override;
   bool legalizeIntrinsic(LegalizerHelper &Helper,
                          MachineInstr &MI) const override;
 };
diff --git a/llvm/test/CodeGen/X86/GlobalISel/legalize-brindirect.mir b/llvm/test/CodeGen/X86/GlobalISel/legalize-brindirect.mir
new file mode 100644
index 00000000000000..c023124dab4290
--- /dev/null
+++ b/llvm/test/CodeGen/X86/GlobalISel/legalize-brindirect.mir
@@ -0,0 +1,55 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4
+# RUN: split-file %s %t
+# RUN: llc -mtriple=x86_64-linux-gnu -run-pass=legalizer %t/x64.mir -o - | FileCheck %t/x64.mir
+# RUN: llc -mtriple=i386-linux-gnu   -run-pass=legalizer %t/x32.mir -o - | FileCheck %t/x32.mir
+
+#--- x64.mir
+---
+name:            test64
+alignment:       16
+legalized:       false
+registers:
+  - { id: 0, class: _, preferred-register: '' }
+  - { id: 1, class: _, preferred-register: '' }
+body:             |
+  bb.1.entry:
+    successors:
+    liveins: $rdi
+
+    ; CHECK-LABEL: name: test64
+    ; CHECK: liveins: $rdi
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $rdi
+    ; CHECK-NEXT: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[COPY]](s64)
+    ; CHECK-NEXT: G_BRINDIRECT [[INTTOPTR]](p0)
+    %0(s64) = COPY $rdi
+    %1(p0) = G_INTTOPTR %0(s64)
+    G_BRINDIRECT %1(p0)
+
+...
+
+#--- x32.mir
+---
+name:            test32
+alignment:       16
+legalized:       false
+registers:
+  - { id: 0, class: _, preferred-register: '' }
+  - { id: 1, class: _, preferred-register: '' }
+body:             |
+  bb.1.entry:
+    successors:
+    liveins: $edi
+
+    ; CHECK-LABEL: name: test32
+    ; CHECK: liveins: $edi
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+    ; CHECK-NEXT: [[INTTOPTR:%[0-9]+]]:_(p0) = G_INTTOPTR [[COPY]](s32)
+    ; CHECK-NEXT: G_BRINDIRECT [[INTTOPTR]](p0)
+    %0(s32) = COPY $edi
+    %1(p0) = G_INTTOPTR %0(s32)
+    G_BRINDIRECT %1(p0)
+
+...
+
diff --git a/llvm/test/CodeGen/X86/GlobalISel/legalize-brjt.mir b/llvm/test/CodeGen/X86/GlobalISel/legalize-brjt.mir
new file mode 100644
index 00000000000000..faea0fe1b14413
--- /dev/null
+++ b/llvm/test/CodeGen/X86/GlobalISel/legalize-brjt.mir
@@ -0,0 +1,257 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4
+# RUN: llc -mtriple=x86_64-linux-gnu -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=X64
+# RUN: llc -mtriple=i386-linux-gnu   -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=X32
+
+---
+name:            test_block_address
+alignment:       16
+legalized:       false
+jumpTable:
+  kind:            block-address
+  entries:
+    - id:              0
+      blocks:          [ '%bb.2', '%bb.3', ]
+body:             |
+  ; X64-LABEL: name: test_block_address
+  ; X64: bb.0.entry:
+  ; X64-NEXT:   successors: %bb.1(0x40000000), %bb.4(0x40000000)
+  ; X64-NEXT:   liveins: $edi
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+  ; X64-NEXT:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+  ; X64-NEXT:   [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+  ; X64-NEXT:   [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[C1]]
+  ; X64-NEXT:   [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(ugt), [[SUB]](s32), [[C]]
+  ; X64-NEXT:   [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[ICMP]](s8)
+  ; X64-NEXT:   G_BRCOND [[TRUNC]](s1), %bb.4
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT: bb.1.entry:
+  ; X64-NEXT:   successors: %bb.2(0x40000000), %bb.3(0x40000000)
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT:   [[JUMP_TABLE:%[0-9]+]]:_(p0) = G_JUMP_TABLE %jump-table.0
+  ; X64-NEXT:   [[C2:%[0-9]+]]:_(s8) = G_CONSTANT i8 3
+  ; X64-NEXT:   [[SHL:%[0-9]+]]:_(s32) = G_SHL [[SUB]], [[C2]](s8)
+  ; X64-NEXT:   [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[JUMP_TABLE]], [[SHL]](s32)
+  ; X64-NEXT:   [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[PTR_ADD]](p0) :: (load (s64) from jump-table)
+  ; X64-NEXT:   G_BRINDIRECT [[LOAD]](p0)
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT: bb.2:
+  ; X64-NEXT:   successors: %bb.5(0x80000000)
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT:   G_BR %bb.5
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT: bb.3:
+  ; X64-NEXT:   successors: %bb.5(0x80000000)
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT:   G_BR %bb.5
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT: bb.4:
+  ; X64-NEXT:   successors: %bb.5(0x80000000)
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT: bb.5:
+  ; X64-NEXT:   $eax = COPY [[COPY]](s32)
+  ; X64-NEXT:   RET 0, implicit $eax
+  ;
+  ; X32-LABEL: name: test_block_address
+  ; X32: bb.0.entry:
+  ; X32-NEXT:   successors: %bb.1(0x40000000), %bb.4(0x40000000)
+  ; X32-NEXT:   liveins: $edi
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+  ; X32-NEXT:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+  ; X32-NEXT:   [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+  ; X32-NEXT:   [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[C1]]
+  ; X32-NEXT:   [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(ugt), [[SUB]](s32), [[C]]
+  ; X32-NEXT:   [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[ICMP]](s8)
+  ; X32-NEXT:   G_BRCOND [[TRUNC]](s1), %bb.4
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT: bb.1.entry:
+  ; X32-NEXT:   successors: %bb.2(0x40000000), %bb.3(0x40000000)
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT:   [[JUMP_TABLE:%[0-9]+]]:_(p0) = G_JUMP_TABLE %jump-table.0
+  ; X32-NEXT:   [[C2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2
+  ; X32-NEXT:   [[SHL:%[0-9]+]]:_(s32) = G_SHL [[SUB]], [[C2]](s8)
+  ; X32-NEXT:   [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[JUMP_TABLE]], [[SHL]](s32)
+  ; X32-NEXT:   [[LOAD:%[0-9]+]]:_(p0) = G_LOAD [[PTR_ADD]](p0) :: (load (s32) from jump-table)
+  ; X32-NEXT:   G_BRINDIRECT [[LOAD]](p0)
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT: bb.2:
+  ; X32-NEXT:   successors: %bb.5(0x80000000)
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT:   G_BR %bb.5
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT: bb.3:
+  ; X32-NEXT:   successors: %bb.5(0x80000000)
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT:   G_BR %bb.5
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT: bb.4:
+  ; X32-NEXT:   successors: %bb.5(0x80000000)
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT: bb.5:
+  ; X32-NEXT:   $eax = COPY [[COPY]](s32)
+  ; X32-NEXT:   RET 0, implicit $eax
+  bb.0.entry:
+    successors: %bb.1(0x40000000), %bb.4(0x40000000)
+    liveins: $edi
+
+    %0:_(s32) = COPY $edi
+    %4:_(s32) = G_CONSTANT i32 4
+    %1:_(s32) = G_CONSTANT i32 0
+    %2:_(s32) = G_SUB %0, %1
+    %5:_(s1) = G_ICMP intpred(ugt), %2(s32), %4
+    G_BRCOND %5(s1), %bb.4
+
+  bb.1.entry:
+    successors: %bb.2(0x1999999a), %bb.3(0x1999999a)
+
+    %6:_(p0) = G_JUMP_TABLE %jump-table.0
+    G_BRJT %6(p0), %jump-table.0, %2(s32)
+
+  bb.2:
+    successors: %bb.5(0x80000000)
+
+    G_BR %bb.5
+
+  bb.3:
+    successors: %bb.5(0x80000000)
+
+    G_BR %bb.5
+
+  bb.4:
+    successors: %bb.5(0x80000000)
+
+  bb.5:
+    $eax = COPY %0(s32)
+    RET 0, implicit $eax
+
+...
+
+---
+name:            test_label_diff32
+alignment:       16
+legalized:       false
+jumpTable:
+  kind:            label-difference32
+  entries:
+    - id:              0
+      blocks:          [ '%bb.2', '%bb.3', ]
+body:             |
+  ; X64-LABEL: name: test_label_diff32
+  ; X64: bb.0.entry:
+  ; X64-NEXT:   successors: %bb.1(0x40000000), %bb.4(0x40000000)
+  ; X64-NEXT:   liveins: $edi
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+  ; X64-NEXT:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+  ; X64-NEXT:   [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+  ; X64-NEXT:   [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[C1]]
+  ; X64-NEXT:   [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(ugt), [[SUB]](s32), [[C]]
+  ; X64-NEXT:   [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[ICMP]](s8)
+  ; X64-NEXT:   G_BRCOND [[TRUNC]](s1), %bb.4
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT: bb.1.entry:
+  ; X64-NEXT:   successors: %bb.2(0x40000000), %bb.3(0x40000000)
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT:   [[JUMP_TABLE:%[0-9]+]]:_(p0) = G_JUMP_TABLE %jump-table.0
+  ; X64-NEXT:   [[C2:%[0-9]+]]:_(s8) = G_CONSTANT i8 3
+  ; X64-NEXT:   [[SHL:%[0-9]+]]:_(s32) = G_SHL [[SUB]], [[C2]](s8)
+  ; X64-NEXT:   [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[JUMP_TABLE]], [[SHL]](s32)
+  ; X64-NEXT:   [[LOAD:%[0-9]+]]:_(s64) = G_LOAD [[PTR_ADD]](p0) :: (load (s64) from jump-table, align 4)
+  ; X64-NEXT:   [[TRUNC1:%[0-9]+]]:_(s32) = G_TRUNC [[LOAD]](s64)
+  ; X64-NEXT:   [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[JUMP_TABLE]], [[TRUNC1]](s32)
+  ; X64-NEXT:   G_BRINDIRECT [[PTR_ADD1]](p0)
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT: bb.2:
+  ; X64-NEXT:   successors: %bb.5(0x80000000)
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT:   G_BR %bb.5
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT: bb.3:
+  ; X64-NEXT:   successors: %bb.5(0x80000000)
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT:   G_BR %bb.5
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT: bb.4:
+  ; X64-NEXT:   successors: %bb.5(0x80000000)
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT: bb.5:
+  ; X64-NEXT:   $eax = COPY [[COPY]](s32)
+  ; X64-NEXT:   RET 0, implicit $eax
+  ;
+  ; X32-LABEL: name: test_label_diff32
+  ; X32: bb.0.entry:
+  ; X32-NEXT:   successors: %bb.1(0x40000000), %bb.4(0x40000000)
+  ; X32-NEXT:   liveins: $edi
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+  ; X32-NEXT:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+  ; X32-NEXT:   [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+  ; X32-NEXT:   [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[C1]]
+  ; X32-NEXT:   [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(ugt), [[SUB]](s32), [[C]]
+  ; X32-NEXT:   [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[ICMP]](s8)
+  ; X32-NEXT:   G_BRCOND [[TRUNC]](s1), %bb.4
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT: bb.1.entry:
+  ; X32-NEXT:   successors: %bb.2(0x40000000), %bb.3(0x40000000)
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT:   [[JUMP_TABLE:%[0-9]+]]:_(p0) = G_JUMP_TABLE %jump-table.0
+  ; X32-NEXT:   [[C2:%[0-9]+]]:_(s8) = G_CONSTANT i8 2
+  ; X32-NEXT:   [[SHL:%[0-9]+]]:_(s32) = G_SHL [[SUB]], [[C2]](s8)
+  ; X32-NEXT:   [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[JUMP_TABLE]], [[SHL]](s32)
+  ; X32-NEXT:   [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[PTR_ADD]](p0) :: (load (s32) from jump-table)
+  ; X32-NEXT:   [[COPY1:%[0-9]+]]:_(s32) = COPY [[LOAD]](s32)
+  ; X32-NEXT:   [[PTR_ADD1:%[0-9]+]]:_(p0) = G_PTR_ADD [[JUMP_TABLE]], [[COPY1]](s32)
+  ; X32-NEXT:   G_BRINDIRECT [[PTR_ADD1]](p0)
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT: bb.2:
+  ; X32-NEXT:   successors: %bb.5(0x80000000)
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT:   G_BR %bb.5
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT: bb.3:
+  ; X32-NEXT:   successors: %bb.5(0x80000000)
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT:   G_BR %bb.5
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT: bb.4:
+  ; X32-NEXT:   successors: %bb.5(0x80000000)
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT: bb.5:
+  ; X32-NEXT:   $eax = COPY [[COPY]](s32)
+  ; X32-NEXT:   RET 0, implicit $eax
+  bb.0.entry:
+    successors: %bb.1(0x40000000), %bb.4(0x40000000)
+    liveins: $edi
+
+    %0:_(s32) = COPY $edi
+    %4:_(s32) = G_CONSTANT i32 4
+    %1:_(s32) = G_CONSTANT i32 0
+    %2:_(s32) = G_SUB %0, %1
+    %5:_(s1) = G_ICMP intpred(ugt), %2(s32), %4
+    G_BRCOND %5(s1), %bb.4
+
+  bb.1.entry:
+    successors: %bb.2(0x1999999a), %bb.3(0x1999999a)
+
+    %6:_(p0) = G_JUMP_TABLE %jump-table.0
+    G_BRJT %6(p0), %jump-table.0, %2(s32)
+
+  bb.2:
+    successors: %bb.5(0x80000000)
+
+    G_BR %bb.5
+
+  bb.3:
+    successors: %bb.5(0x80000000)
+
+    G_BR %bb.5
+
+  bb.4:
+    successors: %bb.5(0x80000000)
+
+  bb.5:
+    $eax = COPY %0(s32)
+    RET 0, implicit $eax
+
+...
diff --git a/llvm/test/CodeGen/X86/GlobalISel/select-jumptable.mir b/llvm/test/CodeGen/X86/GlobalISel/select-jumptable.mir
new file mode 100644
index 00000000000000..53057c2d6c5b93
--- /dev/null
+++ b/llvm/test/CodeGen/X86/GlobalISel/select-jumptable.mir
@@ -0,0 +1,114 @@
+# RUN: split-file %s %t
+# RUN: llc -mtriple=x86_64-linux-gnu -run-pass=instruction-select --relocation-model=static %t/x64.mir -o - | \
+# RUN:     FileCheck %t/x64.mir --check-prefix=X64-STATIC
+# RUN: llc -mtriple=x86_64-linux-gnu -run-pass=instruction-select --relocation-model=pic    %t/x64.mir -o - | \
+# RUN:     FileCheck %t/x64.mir --check-prefix=X64-PIC
+# RUN: llc -mtriple=i386-linux-gnu -run-pass=instruction-select --relocation-model=static %t/x32.mir -o - | \
+# RUN:     FileCheck %t/x32.mir --check-prefix=X32-STATIC
+# RUN: llc -mtriple=i386-linux-gnu -run-pass=instruction-select --relocation-model=pic    %t/x32.mir -o - | \
+# RUN:     FileCheck %t/x32.mir --check-prefix=X32-PIC
+
+#--- x64.mir
+---
+name:            test64
+alignment:       16
+exposesReturnsTwice: false
+legalized:       true
+regBankSelected: true
+selected:        false
+registers:
+  - { id: 0, class: gpr, preferred-register: '' }
+jumpTable:
+  kind:            block-address
+  entries:
+    - id:              0
+      blocks:          [ '%bb.1', '%bb.2' ]
+body:             |
+  ; X64-STATIC-LABEL: name: test64
+  ; X64-STATIC: bb.0.entry:
+  ; X64-STATIC-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; X64-STATIC-NEXT: {{  $}}
+  ; X64-STATIC-NEXT:   [[LEA64r:%[0-9]+]]:gr64 = LEA64r $noreg, 1, $noreg, %jump-table.0, $noreg
+  ; X64-STATIC-NEXT:   $rax = COPY [[LEA64r]]
+  ; X64-STATIC-NEXT:   RET 0, implicit $rax
+  ;
+  ; X64-PIC-LABEL: name: test64
+  ; X64-PIC: bb.0.entry:
+  ; X64-PIC-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; X64-PIC-NEXT: {{  $}}
+  ; X64-PIC-NEXT:   [[LEA64r:%[0-9]+]]:gr64 = LEA64r $rip, 1, $noreg, %jump-table.0, $noreg
+  ; X64-PIC-NEXT:   $rax = COPY [[LEA64r]]
+  ; X64-PIC-NEXT:   RET 0, implicit $rax
+  bb.0.entry:
+    successors: %bb.1(0x40000000), %bb.2(0x40000000)
+
+    %0:gpr(p0) = G_JUMP_TABLE %jump-table.0
+    $rax = COPY %0(p0)
+    RET 0, implicit $rax
+
+  bb.1:
+    successors: %bb.4(0x80000000)
+
+    G_BR %bb.4
+
+  bb.2:
+    successors: %bb.4(0x80000000)
+
+    G_BR %bb.4
+
+  bb.4:
+    RET 0, implicit $rax
+
+...
+#--- x32.mir
+---
+name:            test32
+alignment:       16
+exposesReturnsTwice: false
+legalized:       true
+regBankSelected: true
+selected:        false
+registers:
+  - { id: 0, class: gpr, preferred-register: '' }
+jumpTable:
+  kind:            block-address
+  entries:
+    - id:              0
+      blocks:          [ '%bb.1', '%bb.2' ]
+body:             |
+  ; X32-STATIC-LABEL: name: test32
+  ; X32-STATIC: bb.0.entry:
+  ; X32-STATIC-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; X32-STATIC-NEXT: {{  $}}
+  ; X32-STATIC-NEXT:   [[LEA32r:%[0-9]+]]:gr32 = LEA32r $noreg, 1, $noreg, %jump-table.0, $noreg
+  ; X32-STATIC-NEXT:   $eax = COPY [[LEA32r]]
+  ; X32-STATIC-NEXT:   RET 0, implicit $eax
+  ;
+  ; X32-PIC-LABEL: name: test32
+  ; X32-PIC: bb.0.entry:
+  ; X32-PIC-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; X32-PIC-NEXT: {{  $}}
+  ; X32-PIC-NEXT:   [[LEA32r:%[0-9]+]]:gr32 = LEA32r $eip, 1, $noreg, %jump-table.0, $noreg
+  ; X32-PIC-NEXT:   $eax = COPY [[LEA32r]]
+  ; X32-PIC-NEXT:   RET 0, implicit $eax
+  bb.0.entry:
+    successors: %bb.1(0x40000000), %bb.2(0x40000000)
+
+    %0:gpr(p0) = G_JUMP_TABLE %jump-table.0
+    $eax = COPY %0(p0)
+    RET 0, implicit $eax
+
+  bb.1:
+    successors: %bb.4(0x80000000)
+
+    G_BR %bb.4
+
+  bb.2:
+    successors: %bb.4(0x80000000)
+
+    G_BR %bb.4
+
+  bb.4:
+    RET 0, implicit $eax
+
+...



More information about the llvm-commits mailing list