[llvm] [X86][GlobalISel] Enable G_BRJT (PR #81811)
RĂ©mi SEGARD via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 5 14:55:18 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 1/2] [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
+
+...
>From aa9c6031c6f9fc7133cd9b9a4996f9b78b4be4da Mon Sep 17 00:00:00 2001
From: Remi SEGARD <remi.segard at epita.fr>
Date: Tue, 5 Mar 2024 23:55:02 +0100
Subject: [PATCH 2/2] Add end-to-end test and change to entrysize
---
.../lib/Target/X86/GISel/X86LegalizerInfo.cpp | 12 +-
llvm/test/CodeGen/X86/isel-brjt.ll | 206 ++++++++++++++++++
2 files changed, 212 insertions(+), 6 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/isel-brjt.ll
diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
index 72a79f17766b6f..0b8f89f2262e2d 100644
--- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
+++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
@@ -587,16 +587,16 @@ bool X86LegalizerInfo::legalizeBrJT(LegalizerHelper &Helper,
MachinePointerInfo::getJumpTable(MF), MachineMemOperand::MOLoad,
PtrTy.getSizeInBytes(), Align(EntrySize));
- auto ShiftAmt = MIB.buildConstant(IdxTy, Log2_32(PtrTy.getSizeInBytes()));
+ auto ShiftAmt =
+ MIB.buildConstant(IdxTy, Log2_32(MJTI->getEntrySize(MF.getDataLayout())));
auto Shift = MIB.buildShl(IdxTy, IdxReg, ShiftAmt);
- auto Target =
- MIB.buildPtrAdd(PtrTy, PtrReg, Shift->getOperand(0).getReg()).getReg(0);
+ auto Target = MIB.buildPtrAdd(PtrTy, PtrReg, Shift);
switch (MJTI->getEntryKind()) {
default:
return false;
case MachineJumpTableInfo::EK_BlockAddress: {
- Target = MIB.buildLoad(PtrTy, Target, *MMO).getReg(0);
+ Target = MIB.buildLoad(PtrTy, Target, *MMO);
break;
}
case MachineJumpTableInfo::EK_LabelDifference64:
@@ -606,11 +606,11 @@ bool X86LegalizerInfo::legalizeBrJT(LegalizerHelper &Helper,
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);
+ Target = MIB.buildPtrAdd(PtrTy, PtrReg, Load);
break;
}
- MIB.buildBrIndirect(Target);
+ MIB.buildBrIndirect(Target.getReg(0));
MI.removeFromParent();
diff --git a/llvm/test/CodeGen/X86/isel-brjt.ll b/llvm/test/CodeGen/X86/isel-brjt.ll
new file mode 100644
index 00000000000000..1671f9cd32bc79
--- /dev/null
+++ b/llvm/test/CodeGen/X86/isel-brjt.ll
@@ -0,0 +1,206 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
+; RUN: llc < %s -O0 -mtriple=i686-linux-gnu -global-isel=0 -verify-machineinstrs | FileCheck %s --check-prefix=DAG86
+; RUN: llc < %s -O0 -mtriple=i686-linux-gnu -fast-isel -fast-isel-abort=1 | FileCheck %s --check-prefix=DAGF86
+; RUN: llc < %s -O0 -mtriple=i686-linux-gnu -global-isel -global-isel-abort=1 -verify-machineinstrs | FileCheck %s --check-prefix=GISEL86
+; RUN: llc < %s -O0 -mtriple=x86_64-linux-gnu -global-isel=0 | FileCheck %s --check-prefix=DAG64
+; RUN: llc < %s -O0 -mtriple=x86_64-linux-gnu -fast-isel -fast-isel-abort=1 | FileCheck %s --check-prefix=DAGF64
+; RUN: llc < %s -O0 -mtriple=x86_64-linux-gnu -global-isel -global-isel-abort=1 | FileCheck %s --check-prefix=GISEL64
+
+define i32 @brjt(i32 %num, i32 %x) {
+; DAG86-LABEL: brjt:
+; DAG86: # %bb.0: # %entry
+; DAG86-NEXT: subl $8, %esp
+; DAG86-NEXT: .cfi_def_cfa_offset 12
+; DAG86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; DAG86-NEXT: movl %eax, (%esp) # 4-byte Spill
+; DAG86-NEXT: decl %eax
+; DAG86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
+; DAG86-NEXT: subl $3, %eax
+; DAG86-NEXT: ja .LBB0_4
+; DAG86-NEXT: # %bb.6: # %entry
+; DAG86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload
+; DAG86-NEXT: movl .LJTI0_0(,%eax,4), %eax
+; DAG86-NEXT: jmpl *%eax
+; DAG86-NEXT: .LBB0_1: # %sw.bb
+; DAG86-NEXT: jmp .LBB0_5
+; DAG86-NEXT: .LBB0_2: # %sw.bb1
+; DAG86-NEXT: jmp .LBB0_5
+; DAG86-NEXT: .LBB0_3: # %sw.bb3
+; DAG86-NEXT: jmp .LBB0_5
+; DAG86-NEXT: .LBB0_4: # %sw.epilog
+; DAG86-NEXT: jmp .LBB0_5
+; DAG86-NEXT: .LBB0_5: # %return
+; DAG86-NEXT: movl (%esp), %eax # 4-byte Reload
+; DAG86-NEXT: addl $8, %esp
+; DAG86-NEXT: .cfi_def_cfa_offset 4
+; DAG86-NEXT: retl
+;
+; DAGF86-LABEL: brjt:
+; DAGF86: # %bb.0: # %entry
+; DAGF86-NEXT: subl $8, %esp
+; DAGF86-NEXT: .cfi_def_cfa_offset 12
+; DAGF86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; DAGF86-NEXT: movl %eax, (%esp) # 4-byte Spill
+; DAGF86-NEXT: decl %eax
+; DAGF86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
+; DAGF86-NEXT: subl $3, %eax
+; DAGF86-NEXT: ja .LBB0_4
+; DAGF86-NEXT: # %bb.6: # %entry
+; DAGF86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %eax # 4-byte Reload
+; DAGF86-NEXT: movl .LJTI0_0(,%eax,4), %eax
+; DAGF86-NEXT: jmpl *%eax
+; DAGF86-NEXT: .LBB0_1: # %sw.bb
+; DAGF86-NEXT: jmp .LBB0_5
+; DAGF86-NEXT: .LBB0_2: # %sw.bb1
+; DAGF86-NEXT: jmp .LBB0_5
+; DAGF86-NEXT: .LBB0_3: # %sw.bb3
+; DAGF86-NEXT: jmp .LBB0_5
+; DAGF86-NEXT: .LBB0_4: # %sw.epilog
+; DAGF86-NEXT: jmp .LBB0_5
+; DAGF86-NEXT: .LBB0_5: # %return
+; DAGF86-NEXT: movl (%esp), %eax # 4-byte Reload
+; DAGF86-NEXT: addl $8, %esp
+; DAGF86-NEXT: .cfi_def_cfa_offset 4
+; DAGF86-NEXT: retl
+;
+; GISEL86-LABEL: brjt:
+; GISEL86: # %bb.1: # %entry
+; GISEL86-NEXT: subl $8, %esp
+; GISEL86-NEXT: .cfi_def_cfa_offset 12
+; GISEL86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; GISEL86-NEXT: movl %eax, (%esp) # 4-byte Spill
+; GISEL86-NEXT: movl $3, %ecx
+; GISEL86-NEXT: subl $1, %eax
+; GISEL86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
+; GISEL86-NEXT: cmpl %ecx, %eax
+; GISEL86-NEXT: seta %al
+; GISEL86-NEXT: testb $1, %al
+; GISEL86-NEXT: jne .LBB0_5
+; GISEL86-NEXT: # %bb.7: # %entry
+; GISEL86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload
+; GISEL86-NEXT: leal .LJTI0_0, %eax
+; GISEL86-NEXT: shll $2, %ecx
+; GISEL86-NEXT: leal (%eax,%ecx), %eax
+; GISEL86-NEXT: movl (%eax), %eax
+; GISEL86-NEXT: jmpl *%eax
+; GISEL86-NEXT: .LBB0_2: # %sw.bb
+; GISEL86-NEXT: jmp .LBB0_6
+; GISEL86-NEXT: .LBB0_3: # %sw.bb1
+; GISEL86-NEXT: jmp .LBB0_6
+; GISEL86-NEXT: .LBB0_4: # %sw.bb3
+; GISEL86-NEXT: jmp .LBB0_6
+; GISEL86-NEXT: .LBB0_5: # %sw.epilog
+; GISEL86-NEXT: jmp .LBB0_6
+; GISEL86-NEXT: .LBB0_6: # %return
+; GISEL86-NEXT: movl (%esp), %eax # 4-byte Reload
+; GISEL86-NEXT: addl $8, %esp
+; GISEL86-NEXT: .cfi_def_cfa_offset 4
+; GISEL86-NEXT: retl
+;
+; DAG64-LABEL: brjt:
+; DAG64: # %bb.0: # %entry
+; DAG64-NEXT: movl %edi, %eax
+; DAG64-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; DAG64-NEXT: decl %eax
+; DAG64-NEXT: movl %eax, %ecx
+; DAG64-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; DAG64-NEXT: subl $3, %eax
+; DAG64-NEXT: ja .LBB0_4
+; DAG64-NEXT: # %bb.6: # %entry
+; DAG64-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload
+; DAG64-NEXT: movq .LJTI0_0(,%rax,8), %rax
+; DAG64-NEXT: jmpq *%rax
+; DAG64-NEXT: .LBB0_1: # %sw.bb
+; DAG64-NEXT: jmp .LBB0_5
+; DAG64-NEXT: .LBB0_2: # %sw.bb1
+; DAG64-NEXT: jmp .LBB0_5
+; DAG64-NEXT: .LBB0_3: # %sw.bb3
+; DAG64-NEXT: jmp .LBB0_5
+; DAG64-NEXT: .LBB0_4: # %sw.epilog
+; DAG64-NEXT: jmp .LBB0_5
+; DAG64-NEXT: .LBB0_5: # %return
+; DAG64-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 4-byte Reload
+; DAG64-NEXT: retq
+;
+; DAGF64-LABEL: brjt:
+; DAGF64: # %bb.0: # %entry
+; DAGF64-NEXT: movl %edi, %eax
+; DAGF64-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; DAGF64-NEXT: decl %eax
+; DAGF64-NEXT: movl %eax, %ecx
+; DAGF64-NEXT: movq %rcx, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; DAGF64-NEXT: subl $3, %eax
+; DAGF64-NEXT: ja .LBB0_4
+; DAGF64-NEXT: # %bb.6: # %entry
+; DAGF64-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax # 8-byte Reload
+; DAGF64-NEXT: movq .LJTI0_0(,%rax,8), %rax
+; DAGF64-NEXT: jmpq *%rax
+; DAGF64-NEXT: .LBB0_1: # %sw.bb
+; DAGF64-NEXT: jmp .LBB0_5
+; DAGF64-NEXT: .LBB0_2: # %sw.bb1
+; DAGF64-NEXT: jmp .LBB0_5
+; DAGF64-NEXT: .LBB0_3: # %sw.bb3
+; DAGF64-NEXT: jmp .LBB0_5
+; DAGF64-NEXT: .LBB0_4: # %sw.epilog
+; DAGF64-NEXT: jmp .LBB0_5
+; DAGF64-NEXT: .LBB0_5: # %return
+; DAGF64-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 4-byte Reload
+; DAGF64-NEXT: retq
+;
+; GISEL64-LABEL: brjt:
+; GISEL64: # %bb.1: # %entry
+; GISEL64-NEXT: movl %edi, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
+; GISEL64-NEXT: subl $1, %edi
+; GISEL64-NEXT: movl %edi, %eax
+; GISEL64-NEXT: # kill: def $rax killed $eax
+; GISEL64-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill
+; GISEL64-NEXT: movl $3, %ecx
+; GISEL64-NEXT: cmpq %rcx, %rax
+; GISEL64-NEXT: seta %al
+; GISEL64-NEXT: testb $1, %al
+; GISEL64-NEXT: jne .LBB0_5
+; GISEL64-NEXT: # %bb.7: # %entry
+; GISEL64-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rcx # 8-byte Reload
+; GISEL64-NEXT: leaq .LJTI0_0, %rax
+; GISEL64-NEXT: shlq $3, %rcx
+; GISEL64-NEXT: leaq (%rax,%rcx), %rax
+; GISEL64-NEXT: movq (%rax), %rax
+; GISEL64-NEXT: jmpq *%rax
+; GISEL64-NEXT: .LBB0_2: # %sw.bb
+; GISEL64-NEXT: jmp .LBB0_6
+; GISEL64-NEXT: .LBB0_3: # %sw.bb1
+; GISEL64-NEXT: jmp .LBB0_6
+; GISEL64-NEXT: .LBB0_4: # %sw.bb3
+; GISEL64-NEXT: jmp .LBB0_6
+; GISEL64-NEXT: .LBB0_5: # %sw.epilog
+; GISEL64-NEXT: jmp .LBB0_6
+; GISEL64-NEXT: .LBB0_6: # %return
+; GISEL64-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 4-byte Reload
+; GISEL64-NEXT: retq
+entry:
+ switch i32 %num, label %sw.epilog [
+ i32 1, label %sw.bb
+ i32 2, label %sw.bb1
+ i32 3, label %return
+ i32 4, label %sw.bb3
+ ]
+
+sw.bb: ; preds = %entry
+ br label %return
+
+sw.bb1: ; preds = %entry
+ br label %return
+
+sw.bb3: ; preds = %entry
+ br label %return
+
+sw.epilog: ; preds = %entry
+ br label %return
+
+return: ; preds = %entry, %sw.epilog, %sw.bb3, %sw.bb1, %sw.bb
+ ret i32 %num
+}
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 8, !"PIC Level", i32 2}
More information about the llvm-commits
mailing list