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

RĂ©mi SEGARD via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 14 17:06:58 PST 2024


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

- Legalizer for **G_BRJT** and **G_JUMP_TABLE**
- Instruction Selection for **G_BRJT**
- The **G_JUMP_TABLE** becomes dead at instruction selection. I am unsure that it needs to be used or what to do with it.

>From 3863c66557d9b8f60b475957dcaa699061e46751 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

---
 .../X86/GISel/X86InstructionSelector.cpp      |  42 ++++++
 .../lib/Target/X86/GISel/X86LegalizerInfo.cpp |   9 ++
 .../CodeGen/X86/GlobalISel/legalize-brjt.mir  |  84 ++++++++++++
 .../CodeGen/X86/GlobalISel/select-brjt.mir    | 126 ++++++++++++++++++
 4 files changed, 261 insertions(+)
 create mode 100644 llvm/test/CodeGen/X86/GlobalISel/legalize-brjt.mir
 create mode 100644 llvm/test/CodeGen/X86/GlobalISel/select-brjt.mir

diff --git a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
index 26932ba2c8e242..9cec11e7fcce6d 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 selectBrJT(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_BRJT:
+    return selectBrJT(I, MRI, MF);
   case TargetOpcode::G_IMPLICIT_DEF:
   case TargetOpcode::G_PHI:
     return selectImplicitDefOrPHI(I, MRI);
@@ -1472,6 +1476,44 @@ bool X86InstructionSelector::selectCondBranch(MachineInstr &I,
   return true;
 }
 
+bool X86InstructionSelector::selectBrJT(MachineInstr &I,
+                                        MachineRegisterInfo &MRI,
+                                        MachineFunction &MF) const {
+  assert((I.getOpcode() == TargetOpcode::G_BRJT) && "unexpected instruction");
+
+  auto Dst = I.getOperand(0).getReg();
+  auto DstTy = MRI.getType(I.getOperand(0).getReg());
+  auto JTI = I.getOperand(1).getIndex();
+  auto Idx = I.getOperand(2).getReg();
+  auto NewDst = MRI.createGenericVirtualRegister(MRI.getType(Dst));
+  auto *MMO = MF.getMachineMemOperand(MachinePointerInfo().getJumpTable(MF),
+                                      MachineMemOperand::MOLoad, DstTy,
+                                      Align(DstTy.getSizeInBytes()));
+
+  auto MovOp = STI.is64Bit() ? X86::MOV64rm : X86::MOV32rm;
+  auto JmpOp = STI.is64Bit() ? X86::JMP64r : X86::JMP32r;
+
+  // TODO: Maybe there is a way to use X86AddressMode
+  auto Mov = BuildMI(I.getParent(), I.getDebugLoc(), TII.get(MovOp))
+                 .addDef(NewDst)
+                 .addReg(0)
+                 .addImm(8)
+                 .addReg(Idx)
+                 .addJumpTableIndex(JTI)
+                 .addReg(0)
+                 .addMemOperand(MMO);
+
+  auto Jmp =
+      BuildMI(I.getParent(), I.getDebugLoc(), TII.get(JmpOp)).addReg(NewDst);
+
+  I.removeFromParent();
+
+  if (!constrainSelectedInstRegOperands(*Mov, TII, TRI, RBI) &&
+      !constrainSelectedInstRegOperands(*Jmp, TII, TRI, RBI))
+    return false;
+  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..a659d9d850f87e 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
@@ -326,6 +326,15 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI,
 
   getActionDefinitionsBuilder(G_BRCOND).legalFor({s1});
 
+  getActionDefinitionsBuilder(G_JUMP_TABLE).legalFor({p0});
+  getActionDefinitionsBuilder(G_BRJT)
+      .legalIf([=](const LegalityQuery &Query) -> bool {
+        return typePairInSet(0, 1, {{p0, s32}})(Query) ||
+               (Is64Bit && typePairInSet(0, 1, {{p0, s64}})(Query));
+      })
+      .widenScalarOrEltToNextPow2(2, 32)
+      .clampScalar(1, s32, sMaxScalar);
+
   // pointer handling
   const std::initializer_list<LLT> PtrTypes32 = {s1, s8, s16, s32};
   const std::initializer_list<LLT> PtrTypes64 = {s1, s8, s16, s32, s64};
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..b4975cd613ebca
--- /dev/null
+++ b/llvm/test/CodeGen/X86/GlobalISel/legalize-brjt.mir
@@ -0,0 +1,84 @@
+# 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=ALL
+# RUN: llc -mtriple=i386-linux-gnu   -run-pass=legalizer %s -o - | FileCheck %s --check-prefix=ALL
+
+---
+name:            test
+alignment:       16
+legalized:       false
+jumpTable:
+  kind:            block-address
+  entries:
+    - id:              0
+      blocks:          [ '%bb.2', '%bb.3', ]
+body:             |
+  ; ALL-LABEL: name: test
+  ; ALL: bb.0.entry:
+  ; ALL-NEXT:   successors: %bb.1(0x40000000), %bb.4(0x40000000)
+  ; ALL-NEXT:   liveins: $edi
+  ; ALL-NEXT: {{  $}}
+  ; ALL-NEXT:   [[COPY:%[0-9]+]]:_(s32) = COPY $edi
+  ; ALL-NEXT:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+  ; ALL-NEXT:   [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+  ; ALL-NEXT:   [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[C1]]
+  ; ALL-NEXT:   [[ICMP:%[0-9]+]]:_(s8) = G_ICMP intpred(ugt), [[SUB]](s32), [[C]]
+  ; ALL-NEXT:   [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[ICMP]](s8)
+  ; ALL-NEXT:   G_BRCOND [[TRUNC]](s1), %bb.4
+  ; ALL-NEXT: {{  $}}
+  ; ALL-NEXT: bb.1.entry:
+  ; ALL-NEXT:   successors: %bb.2(0x40000000), %bb.3(0x40000000)
+  ; ALL-NEXT: {{  $}}
+  ; ALL-NEXT:   [[JUMP_TABLE:%[0-9]+]]:_(p0) = G_JUMP_TABLE %jump-table.0
+  ; ALL-NEXT:   G_BRJT [[JUMP_TABLE]](p0), %jump-table.0, [[SUB]](s32)
+  ; ALL-NEXT: {{  $}}
+  ; ALL-NEXT: bb.2:
+  ; ALL-NEXT:   successors: %bb.5(0x80000000)
+  ; ALL-NEXT: {{  $}}
+  ; ALL-NEXT:   G_BR %bb.5
+  ; ALL-NEXT: {{  $}}
+  ; ALL-NEXT: bb.3:
+  ; ALL-NEXT:   successors: %bb.5(0x80000000)
+  ; ALL-NEXT: {{  $}}
+  ; ALL-NEXT:   G_BR %bb.5
+  ; ALL-NEXT: {{  $}}
+  ; ALL-NEXT: bb.4:
+  ; ALL-NEXT:   successors: %bb.5(0x80000000)
+  ; ALL-NEXT: {{  $}}
+  ; ALL-NEXT: bb.5:
+  ; ALL-NEXT:   $eax = COPY [[COPY]](s32)
+  ; ALL-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-brjt.mir b/llvm/test/CodeGen/X86/GlobalISel/select-brjt.mir
new file mode 100644
index 00000000000000..def4e345a274bc
--- /dev/null
+++ b/llvm/test/CodeGen/X86/GlobalISel/select-brjt.mir
@@ -0,0 +1,126 @@
+# 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=instruction-select %s -o - | FileCheck %s --check-prefix=X64
+# RUN: llc -mtriple=i386-linux-gnu   -run-pass=instruction-select %s -o - | FileCheck %s --check-prefix=X32
+
+---
+name:            test
+alignment:       16
+exposesReturnsTwice: false
+legalized:       true
+regBankSelected: true
+selected:        false
+jumpTable:
+  kind:            block-address
+  entries:
+    - id:              0
+      blocks:          [ '%bb.2', '%bb.3' ]
+body:             |
+  ; X64-LABEL: name: test
+  ; X64: bb.0.entry:
+  ; X64-NEXT:   successors: %bb.1(0x40000000), %bb.4(0x40000000)
+  ; X64-NEXT:   liveins: $edi
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT:   [[COPY:%[0-9]+]]:gr32 = COPY $edi
+  ; X64-NEXT:   [[MOV32ri:%[0-9]+]]:gr32 = MOV32ri 4
+  ; X64-NEXT:   [[SUB32ri:%[0-9]+]]:gr32 = SUB32ri [[COPY]], 0, implicit-def dead $eflags
+  ; X64-NEXT:   [[COPY1:%[0-9]+]]:gr64_nosp = COPY [[SUB32ri]]
+  ; X64-NEXT:   [[COPY2:%[0-9]+]]:gr32 = COPY [[COPY1]]
+  ; X64-NEXT:   CMP32rr [[COPY2]], [[MOV32ri]], implicit-def $eflags
+  ; X64-NEXT:   [[SETCCr:%[0-9]+]]:gr8 = SETCCr 7, implicit $eflags
+  ; X64-NEXT:   TEST8ri [[SETCCr]], 1, implicit-def $eflags
+  ; X64-NEXT:   JCC_1 %bb.4, 5, implicit $eflags
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT: bb.1.entry:
+  ; X64-NEXT:   successors: %bb.2(0x40000000), %bb.3(0x40000000)
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT:   [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm $noreg, 8, [[COPY1]], %jump-table.0, $noreg :: (load (p0) from jump-table)
+  ; X64-NEXT:   JMP64r [[MOV64rm]]
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT: bb.2:
+  ; X64-NEXT:   successors: %bb.5(0x80000000)
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT:   JMP_1 %bb.5
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT: bb.3:
+  ; X64-NEXT:   successors: %bb.5(0x80000000)
+  ; X64-NEXT: {{  $}}
+  ; X64-NEXT:   JMP_1 %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]]
+  ; X64-NEXT:   RET 0, implicit $eax
+  ;
+  ; X32-LABEL: name: test
+  ; X32: bb.0.entry:
+  ; X32-NEXT:   successors: %bb.1(0x40000000), %bb.4(0x40000000)
+  ; X32-NEXT:   liveins: $edi
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT:   [[COPY:%[0-9]+]]:gr32 = COPY $edi
+  ; X32-NEXT:   [[MOV32ri:%[0-9]+]]:gr32 = MOV32ri 4
+  ; X32-NEXT:   [[SUB32ri:%[0-9]+]]:gr32_nosp = SUB32ri [[COPY]], 0, implicit-def dead $eflags
+  ; X32-NEXT:   CMP32rr [[SUB32ri]], [[MOV32ri]], implicit-def $eflags
+  ; X32-NEXT:   [[SETCCr:%[0-9]+]]:gr8 = SETCCr 7, implicit $eflags
+  ; X32-NEXT:   TEST8ri [[SETCCr]], 1, implicit-def $eflags
+  ; X32-NEXT:   JCC_1 %bb.4, 5, implicit $eflags
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT: bb.1.entry:
+  ; X32-NEXT:   successors: %bb.2(0x40000000), %bb.3(0x40000000)
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT:   [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm $noreg, 8, [[SUB32ri]], %jump-table.0, $noreg :: (load (p0) from jump-table)
+  ; X32-NEXT:   JMP32r [[MOV32rm]]
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT: bb.2:
+  ; X32-NEXT:   successors: %bb.5(0x80000000)
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT:   JMP_1 %bb.5
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT: bb.3:
+  ; X32-NEXT:   successors: %bb.5(0x80000000)
+  ; X32-NEXT: {{  $}}
+  ; X32-NEXT:   JMP_1 %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]]
+  ; X32-NEXT:   RET 0, implicit $eax
+  bb.0.entry:
+    successors: %bb.1(0x40000000), %bb.4(0x40000000)
+    liveins: $edi
+
+    %0:gpr(s32) = COPY $edi
+    %4:gpr(s32) = G_CONSTANT i32 4
+    %1:gpr(s32) = G_CONSTANT i32 0
+    %2:gpr(s32) = G_SUB %0, %1
+    %8:gpr(s8) = G_ICMP intpred(ugt), %2(s32), %4
+    %5:gpr(s1) = G_TRUNC %8(s8)
+    G_BRCOND %5(s1), %bb.4
+
+  bb.1.entry:
+    successors: %bb.2(0x40000000), %bb.3(0x40000000)
+
+    %6:gpr(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
+
+...



More information about the llvm-commits mailing list