Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion llvm/include/llvm/Target/GenericOpcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down
31 changes: 31 additions & 0 deletions llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 {
Expand Down
68 changes: 68 additions & 0 deletions llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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};
Expand Down Expand Up @@ -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));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
PtrTy.getSizeInBytes(), Align(EntrySize));
EntrySize, 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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
TargetOpcode::G_LOAD, LLT::scalar(PtrTy.getSizeInBits()), Target, *MMO);
TargetOpcode::G_LOAD, LLT::scalar(EntrySize * 8), 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;
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/X86/GISel/X86LegalizerInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
55 changes: 55 additions & 0 deletions llvm/test/CodeGen/X86/GlobalISel/legalize-brindirect.mir
Original file line number Diff line number Diff line change
@@ -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)
...

Loading