[llvm] [X86][GlobalISel] Enable G_BRJT (PR #81811)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 14 17:16:22 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-globalisel
Author: RĂ©mi SEGARD (RemiSEGARD)
<details>
<summary>Changes</summary>
- 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.
---
Full diff: https://github.com/llvm/llvm-project/pull/81811.diff
4 Files Affected:
- (modified) llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp (+42)
- (modified) llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp (+9)
- (added) llvm/test/CodeGen/X86/GlobalISel/legalize-brjt.mir (+84)
- (added) llvm/test/CodeGen/X86/GlobalISel/select-brjt.mir (+126)
``````````diff
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
+
+...
``````````
</details>
https://github.com/llvm/llvm-project/pull/81811
More information about the llvm-commits
mailing list