-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[X86][GlobalISel] Enable G_BRJT #81811
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-llvm-globalisel Author: Rémi SEGARD (RemiSEGARD) Changes
Full diff: https://github.com/llvm/llvm-project/pull/81811.diff 4 Files Affected:
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
+
+...
|
@llvm/pr-subscribers-backend-x86 Author: Rémi SEGARD (RemiSEGARD) Changes
Full diff: https://github.com/llvm/llvm-project/pull/81811.diff 4 Files Affected:
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
+
+...
|
@RemiSEGARD Thanks! Let me check some tests where I've seen fallback due to |
3863c66
to
2f12cf0
Compare
@RemiSEGARD The selected instruction doesn't work in pie mode as we use absolute address of
I see that SelectionDAG expands |
I have a patch for RISC-V to legalize BR_JT to address calculation and BR_INDIRECT. #73711 some of that could be made generic. I just haven't had time to work on GISel recently. |
2f12cf0
to
3d621ee
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
3d621ee
to
22d9a0f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@RemiSEGARD could you please add an end-to-end test e.g. test/Target/X86/isel-brjt.ll
for all selectors similarly to other isel-*.ll
tests.
@e-kud Sorry for the late reply, I haven't had much time recently. I applied your suggestions. I also noticed that when compiling your example with |
In case of |
|
||
MachineMemOperand *MMO = MF.getMachineMemOperand( | ||
MachinePointerInfo::getJumpTable(MF), MachineMemOperand::MOLoad, | ||
PtrTy.getSizeInBytes(), Align(EntrySize)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PtrTy.getSizeInBytes(), Align(EntrySize)); | |
EntrySize, Align(EntrySize)); |
PtrTy.getSizeInBytes(), Align(EntrySize)); | ||
|
||
auto ShiftAmt = | ||
MIB.buildConstant(IdxTy, Log2_32(MJTI->getEntrySize(MF.getDataLayout()))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MIB.buildConstant(IdxTy, Log2_32(MJTI->getEntrySize(MF.getDataLayout()))); | |
MIB.buildConstant(IdxTy, Log2_32(EntrySize)); |
[[fallthrough]]; | ||
case MachineJumpTableInfo::EK_LabelDifference32: | ||
auto Load = MIB.buildLoadInstr( | ||
TargetOpcode::G_LOAD, LLT::scalar(PtrTy.getSizeInBits()), Target, *MMO); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TargetOpcode::G_LOAD, LLT::scalar(PtrTy.getSizeInBits()), Target, *MMO); | |
TargetOpcode::G_LOAD, LLT::scalar(EntrySize * 8), Target, *MMO); |
Fixes unable to legalize instruction: G_BRJT #47127