Top Banner
Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits LLVM Dev Meeting 2017 Justin Bogner, Aditya Nandakumar, Daniel Sanders Apple 1
177

Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Mar 15, 2020

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Head First into GlobalISelOr: How to delete SelectionDAG in 100* easy commits

LLVM Dev Meeting 2017 • Justin Bogner, Aditya Nandakumar, Daniel Sanders • Apple1

Page 2: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Porting to GlobalISel

• What is the structure of a GlobalISel backend?

• How can we test an implementation in progress?

• Where can we split up and parallelize work?

• What do we need to do next?

GlobalISel Tutorial • LLVM Dev Meeting 20172

Page 3: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

A Simple Backend

GlobalISel Tutorial • LLVM Dev Meeting 20173

Lines of Code

AArch64

50000

Page 4: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

A Simple Backend

GlobalISel Tutorial • LLVM Dev Meeting 20174

Lines of Code

AArch64 ARM

50000

Page 5: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

A Simple Backend

GlobalISel Tutorial • LLVM Dev Meeting 20175

Lines of Code

AArch64 ARM X86

50000

Page 6: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

A Simple Backend

GlobalISel Tutorial • LLVM Dev Meeting 20176

Lines of Code

AArch64 ARM X86 AMDGPU

50000

Page 7: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

A Simple Backend

GlobalISel Tutorial • LLVM Dev Meeting 20177

Lines of Code

AArch64 ARM X86 AMDGPU BPF

50000

3000

Page 8: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Lines of Code

AArch64 ARM X86 AMDGPU BPF

50000

3000

A Simple Backend

• Working through the BPF backend as a reference

• 1 Register class, 1 Legal type, 1 Calling convention

• Will refer to AArch64 as necessary for illustrating complexity

GlobalISel Tutorial • LLVM Dev Meeting 20178

Page 9: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Anatomy of GlobalISel

GlobalISel Tutorial • LLVM Dev Meeting 20179

irtranslator

legalizer

regbankselect

instruction-select

Page 10: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Anatomy of GlobalISel

GlobalISel Tutorial • LLVM Dev Meeting 201710

irtranslator

legalizer

regbankselect

instruction-select

CallLowering

LegalizerInfo

InstructionSelector

RegBankInfo

Page 11: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Implementing GlobalISel

GlobalISel Tutorial • LLVM Dev Meeting 201711

irtranslator

legalizer

regbankselect

instruction-select

Wire up GISel

CallLowering

LegalizerInfo

InstructionSelector

RegBankInfo

TargetMachine/SubTarget

Page 12: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

MIR Testing

• GISel tests target a single pass in the pipeline

• Test passes using -run-pass and .mir files

• llc emits MIR when told to -stop-after machine passes

• Use -simplify-mir to generate human-editable output

GlobalISel Tutorial • LLVM Dev Meeting 201712

Page 13: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

MIR Example

GlobalISel Tutorial • LLVM Dev Meeting 201713

define i32 @double(i32 %x) { %y = add i32 %x, %x ret i32 %y }

Page 14: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

name: double legalized: false regBankSelected: false body: | bb.0: liveins: %r1, %r2 %1:_(s64) = COPY %r1 %0:_(s32) = G_TRUNC %1(s64) %2:_(s32) = G_ADD %0, %0 %r0 = COPY %2(s32) RET implicit %r0

MIR Example

llc -global-isel -march=bpf -stop-after=irtranslator -simplify-mir

GlobalISel Tutorial • LLVM Dev Meeting 201714

%1:_(s64) = COPY %r1

Page 15: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%1:_(s64) = COPY %r1

%1:<bank>(s64) = COPY %r1 %1:<class> = COPY %r1

Virtual Registers

VReg constraints change throughout the pipeline

GlobalISel Tutorial • LLVM Dev Meeting 201715

%1:_(s64) = COPY %r1

Page 16: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

MIR Testing

Don't match register numbers directly

GlobalISel Tutorial • LLVM Dev Meeting 201716

; CHECK: [[CP:%[0-9]+]]:_(s64) = COPY %r1 ; CHECK: [[TR:%[0-9]+]]:_(s32) = G_TRUNC [[CP]](s64) ; CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[TR]], [[TR]]

%1:_(s64) = COPY %r1 %0:_(s32) = G_TRUNC %1(s64) %2:_(s32) = G_ADD %0, %0

Page 17: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Wire up GlobalISel

GlobalISel Tutorial • LLVM Dev Meeting 201717

irtranslator

legalizer

regbankselect

instruction-select

Wire up GISel

CallLowering

LegalizerInfo

InstructionSelector

RegBankInfo

TargetMachine/SubTarget

Page 18: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Subtarget Setup

Override GlobalISel API getters by backing with unique_ptrs

GlobalISel Tutorial • LLVM Dev Meeting 201718

BPFSubtarget : BPFGenSubtargetInfo

getCallLowering(...) getRegBankInfo(...) getLegalizerInfo(...) getInstructionSelector(...)

Page 19: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Initialize GlobalISel

GlobalISel Tutorial • LLVM Dev Meeting 201719

extern "C" void LLVMInitializeBPFTarget() { // ... auto PR = PassRegistry::getPassRegistry(); initializeGlobalISel(*PR); }

Page 20: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Initialize GlobalISel Passes

Implement the hooks to provide the required passes

GlobalISel Tutorial • LLVM Dev Meeting 201720

BPFPassConfig : TargetPassConfig

addIRTranslator(...) addLegalizeMachineIR(...) addRegBankSelect(...) addGlobalInstructionSelect(...)

Page 21: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

addIRTranslator(...) addLegalizeMachineIR(...) addRegBankSelect(...) addGlobalInstructionSelect(...)

Initialize GlobalISel Passes

Optionally add extra passes in between

GlobalISel Tutorial • LLVM Dev Meeting 201721

BPFPassConfig : TargetPassConfig

addPreLegalizeMachineIR(...) addPreRegBankSelect(...) addPreGlobalInstructionSelect(...)

Page 22: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Build System Bookkeeping

• Update CMakeLists.txt with each .cpp file we add

• Add the GlobalISel dependency to LLVMBuild.txt

• When we add .td files, also add tablegen targets

GlobalISel Tutorial • LLVM Dev Meeting 201722

Page 23: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Does Anything Work Yet?

llc -global-isel -march=bpf -stop-after=irtranslator

GlobalISel Tutorial • LLVM Dev Meeting 201723

define void @f() { ret void }

Page 24: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Does Anything Work Yet?

llc -global-isel -march=bpf -stop-after=irtranslator

GlobalISel Tutorial • LLVM Dev Meeting 201724

0 llc 0x00000001076873f8 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40 1 llc 0x0000000107687ab6 SignalHandler(int) + 470 2 libsystem_platform.dylib 0x00007fff730f3f5a _sigtramp + 26 3 libsystem_platform.dylib 0x0000000111a8b250 _sigtramp + 2660856592 4 llc 0x0000000106e1a2a4 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) + 180 5 llc 0x00000001070ecc5d llvm::FPPassManager::runOnFunction(llvm::Function&) + 509 6 llc 0x00000001070eced3 llvm::FPPassManager::runOnModule(llvm::Module&) + 67 7 llc 0x00000001070ed410 llvm::legacy::PassManagerImpl::run(llvm::Module&) + 944 8 llc 0x0000000105e69813 compileModule(char**, llvm::LLVMContext&) + 10499 9 llc 0x0000000105e66c5b main + 1419 10 libdyld.dylib 0x00007fff72e73145 start + 1 Stack dump: 0. Program arguments: llc -o - -global-isel -march=bpf -stop-after=irtranslator test.ll 1. Running pass 'Function Pass Manager' on module '/Users/bogner/tmp/t.ll'. 2. Running pass 'IRTranslator' on function '@f' segmentation fault

Page 25: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

The IR Translator

GlobalISel Tutorial • LLVM Dev Meeting 201725

irtranslator

legalizer

regbankselect

instruction-select

Wiring up GISel

CallLowering

LegalizerInfo

InstructionSelector

RegBankInfo

TargetMachine/SubTarget

Page 26: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Call Lowering

GlobalISel Tutorial • LLVM Dev Meeting 201726

IRTranslatorUses

CallLowering

BPFCallLowering : CallLowering

lowerReturn(...) lowerFormalArguments(...) lowerCall(...)

Page 27: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Sketch Call Lowering

GlobalISel Tutorial • LLVM Dev Meeting 201727

bool BPFCallLowering::lowerReturn( MachineIRBuilder &MIRBuilder, const Value *Val, unsigned VReg) const { if (VReg) return false; MIRBuilder.buildInstr(BPF::RET); return true; }

Page 28: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Does Anything Work Yet?

llc -global-isel -march=bpf -stop-after=irtranslator

GlobalISel Tutorial • LLVM Dev Meeting 201728

define void @f() { ret void }

Page 29: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Does Anything Work Yet?

llc -global-isel -march=bpf -stop-after=irtranslator

GlobalISel Tutorial • LLVM Dev Meeting 201729

name: test_void body: | bb.0: RET

Page 30: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Does Anything Work Yet?

llc -global-isel -march=bpf -stop-after=irtranslator

GlobalISel Tutorial • LLVM Dev Meeting 201730

; CHECK: name: f ; CHECK: RET define void @f() { ret void }

Page 31: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Value Handlers

• Arg handling is mostly uniform

• Decide where the arg/return goes

• Exact details vary

• ValueHandler abstracts differences

GlobalISel Tutorial • LLVM Dev Meeting 201731

IRTranslator

CallLowering ValueHandler

handleAssignmentslower

Page 32: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Value Handlers

GlobalISel Tutorial • LLVM Dev Meeting 201732

BPFHandler : ValueHandler

getStackAddress(…) assignValueToAddress(…) assignValueToReg(…)

Page 33: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

BPF Calling Convention

We'll ignore stack handling

GlobalISel Tutorial • LLVM Dev Meeting 201733

// Promote ints to i64. CCIfType<[ i8, i16, i32 ], CCPromoteToType<i64>>, // Pass args in registers. CCIfType<[i64], CCAssignToReg<[ R1, R2, R3, R4, R5 ]>>,

Page 34: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Argument Handling

GlobalISel Tutorial • LLVM Dev Meeting 201734

FormalArgHandler : BPFHandler

assignValueToReg(...)

Page 35: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

void assignValueToReg(unsigned ValVReg, unsigned PhysReg, CCValAssign &VA) override { switch (VA.getLocInfo()) { default: MIRBuilder.buildCopy(ValVReg, PhysReg); break; case CCValAssign::LocInfo::SExt: case CCValAssign::LocInfo::ZExt: case CCValAssign::LocInfo::AExt: { auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg); MIRBuilder.buildTrunc(ValVReg, Copy); break; } } MIRBuilder.getMBB().addLiveIn(PhysReg); }

35 GlobalISel Tutorial • LLVM Dev Meeting 2017

Argument Handling

Page 36: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

void assignValueToReg(unsigned ValVReg, unsigned PhysReg, CCValAssign &VA) override { switch (VA.getLocInfo()) { default: MIRBuilder.buildCopy(ValVReg, PhysReg); break; case CCValAssign::LocInfo::SExt: case CCValAssign::LocInfo::ZExt: case CCValAssign::LocInfo::AExt: { auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg); MIRBuilder.buildTrunc(ValVReg, Copy); break; } } MIRBuilder.getMBB().addLiveIn(PhysReg); }

36 GlobalISel Tutorial • LLVM Dev Meeting 2017

Argument Handling

%ValVReg:_(s32) = COPY PhysReg

Sizes match

Page 37: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

void assignValueToReg(unsigned ValVReg, unsigned PhysReg, CCValAssign &VA) override { switch (VA.getLocInfo()) { default: MIRBuilder.buildCopy(ValVReg, PhysReg); break; case CCValAssign::LocInfo::SExt: case CCValAssign::LocInfo::ZExt: case CCValAssign::LocInfo::AExt: { auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg); MIRBuilder.buildTrunc(ValVReg, Copy); break; } } MIRBuilder.getMBB().addLiveIn(PhysReg); }

37 GlobalISel Tutorial • LLVM Dev Meeting 2017

Argument Handling

%tmp:_(s64) = COPY PhysReg

Extended Assign

Page 38: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

void assignValueToReg(unsigned ValVReg, unsigned PhysReg, CCValAssign &VA) override { switch (VA.getLocInfo()) { default: MIRBuilder.buildCopy(ValVReg, PhysReg); break; case CCValAssign::LocInfo::SExt: case CCValAssign::LocInfo::ZExt: case CCValAssign::LocInfo::AExt: { auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg); MIRBuilder.buildTrunc(ValVReg, Copy); break; } } MIRBuilder.getMBB().addLiveIn(PhysReg); }

38 GlobalISel Tutorial • LLVM Dev Meeting 2017

Argument Handling

%tmp:_(s64) = COPY PhysReg %ValVReg:_(s32) = G_TRUNC %tmp(s64)

Extended Assign

Page 39: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

void assignValueToReg(unsigned ValVReg, unsigned PhysReg, CCValAssign &VA) override { switch (VA.getLocInfo()) { default: MIRBuilder.buildCopy(ValVReg, PhysReg); break; case CCValAssign::LocInfo::SExt: case CCValAssign::LocInfo::ZExt: case CCValAssign::LocInfo::AExt: { auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg); MIRBuilder.buildTrunc(ValVReg, Copy); break; } } MIRBuilder.getMBB().addLiveIn(PhysReg); }

39 GlobalISel Tutorial • LLVM Dev Meeting 2017

Argument Handling

%tmp:_(s64) = COPY PhysReg %ValVReg:_(s32) = G_TRUNC %tmp(s64)

Extended Assign

Page 40: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

bool BPFCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef<unsigned> VRegs) { // … SmallVector<ArgInfo, 8> InArgs; unsigned i = 0; for (auto &Arg : F.args()) { ArgInfo OrigArg{VRegs[i], Arg.getType()}; setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, F); InArgs.push_back(OrigArg); ++i; } FormalArgHandler Handler(MIRBuilder, MRI, CC_BPF64); return handleAssignments(MIRBuilder, InArgs, Handler); }

Lower Formal Args

GlobalISel Tutorial • LLVM Dev Meeting 201740

Page 41: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

bool BPFCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef<unsigned> VRegs) { // … SmallVector<ArgInfo, 8> InArgs; unsigned i = 0; for (auto &Arg : F.args()) { ArgInfo OrigArg{VRegs[i], Arg.getType()}; setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, F); InArgs.push_back(OrigArg); ++i; } FormalArgHandler Handler(MIRBuilder, MRI, CC_BPF64); return handleAssignments(MIRBuilder, InArgs, Handler); }

Lower Formal Args

GlobalISel Tutorial • LLVM Dev Meeting 201741

Page 42: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

bool BPFCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef<unsigned> VRegs) { // … SmallVector<ArgInfo, 8> InArgs; unsigned i = 0; for (auto &Arg : F.args()) { ArgInfo OrigArg{VRegs[i], Arg.getType()}; setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, F); InArgs.push_back(OrigArg); ++i; } FormalArgHandler Handler(MIRBuilder, MRI, CC_BPF64); return handleAssignments(MIRBuilder, InArgs, Handler); }

Lower Formal Args

GlobalISel Tutorial • LLVM Dev Meeting 201742

Page 43: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

bool BPFCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef<unsigned> VRegs) { // … SmallVector<ArgInfo, 8> InArgs; unsigned i = 0; for (auto &Arg : F.args()) { ArgInfo OrigArg{VRegs[i], Arg.getType()}; setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, F); InArgs.push_back(OrigArg); ++i; } FormalArgHandler Handler(MIRBuilder, MRI, CC_BPF64); return handleAssignments(MIRBuilder, InArgs, Handler); }

Lower Formal Args

GlobalISel Tutorial • LLVM Dev Meeting 201743

Page 44: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

bool BPFCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef<unsigned> VRegs) { // … SmallVector<ArgInfo, 8> InArgs; unsigned i = 0; for (auto &Arg : F.args()) { ArgInfo OrigArg{VRegs[i], Arg.getType()}; setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, F); InArgs.push_back(OrigArg); ++i; } FormalArgHandler Handler(MIRBuilder, MRI, CC_BPF64); return handleAssignments(MIRBuilder, InArgs, Handler); }

Lower Formal Args

GlobalISel Tutorial • LLVM Dev Meeting 201744

Page 45: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

bool BPFCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, ArrayRef<unsigned> VRegs) { // … SmallVector<ArgInfo, 8> InArgs; unsigned i = 0; for (auto &Arg : F.args()) { ArgInfo OrigArg{VRegs[i], Arg.getType()}; setArgFlags(OrigArg, i + AttributeList::FirstArgIndex, DL, F); InArgs.push_back(OrigArg); ++i; } FormalArgHandler Handler(MIRBuilder, MRI, CC_BPF64); return handleAssignments(MIRBuilder, InArgs, Handler); }

Lower Formal Args

GlobalISel Tutorial • LLVM Dev Meeting 201745

Page 46: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Test Lowering

llc -global-isel -march=bpf -stop-after=irtranslator

GlobalISel Tutorial • LLVM Dev Meeting 201746

; CHECK: [[IN:%[0-9]+]]:_(s64) = COPY %r1 ; CHECK: RET define void @f(i64 %a) { ret void }

Page 47: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Test Lowering

llc -global-isel -march=bpf -stop-after=irtranslator

GlobalISel Tutorial • LLVM Dev Meeting 201747

; CHECK: [[CP:%[0-9]+]]:_(s64) = COPY %r1 ; CHECK: [[IN:%[0-9]+]]:_(s32) = G_TRUNC [[CP]] ; CHECK: RET define void @f(i32 %a) { ret void }

Page 48: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

struct OutgoingHandler : public BPFHandler { OutgoingHandler(…, MachineInstrBuilder &MIB) : BPFHandler(…), MIB(MIB) {} MachineInstrBuilder &MIB; // … };

Lower Return

GlobalISel Tutorial • LLVM Dev Meeting 201748

Page 49: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

void assignValueToReg(unsigned ValVReg, unsigned PhysReg, CCValAssign &VA) override { unsigned ExtReg = extendRegister(ValVReg, VA); MIRBuilder.buildCopy(PhysReg, ExtReg); MIB.addUse(PhysReg, RegState::Implicit); }

Lower Return

GlobalISel Tutorial • LLVM Dev Meeting 201749

Page 50: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

void assignValueToReg(unsigned ValVReg, unsigned PhysReg, CCValAssign &VA) override { unsigned ExtReg = extendRegister(ValVReg, VA); MIRBuilder.buildCopy(PhysReg, ExtReg); MIB.addUse(PhysReg, RegState::Implicit); }

Lower Return

GlobalISel Tutorial • LLVM Dev Meeting 201750

Page 51: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

void assignValueToReg(unsigned ValVReg, unsigned PhysReg, CCValAssign &VA) override { unsigned ExtReg = extendRegister(ValVReg, VA); MIRBuilder.buildCopy(PhysReg, ExtReg); MIB.addUse(PhysReg, RegState::Implicit); }

Lower Return

GlobalISel Tutorial • LLVM Dev Meeting 201751

Page 52: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

void assignValueToReg(unsigned ValVReg, unsigned PhysReg, CCValAssign &VA) override { unsigned ExtReg = extendRegister(ValVReg, VA); MIRBuilder.buildCopy(PhysReg, ExtReg); MIB.addUse(PhysReg, RegState::Implicit); }

Lower Return

GlobalISel Tutorial • LLVM Dev Meeting 201752

Page 53: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

bool BPFCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, unsigned VReg) { auto MIB = MIRBuilder.buildInstrNoInsert(BPF::RET); bool Success = true; if (VReg) { // … ArgInfo OrigArg{VReg, Val->getType()}; setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F); OutgoingHandler Handler(MIRBuilder, MRI, RetCC_BPF64, MIB); Success = handleAssignments(MIRBuilder, {OrigArg}, Handler); } MIRBuilder.insertInstr(MIB); return Success; }

Lower Return

GlobalISel Tutorial • LLVM Dev Meeting 201753

Page 54: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

bool BPFCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, unsigned VReg) { auto MIB = MIRBuilder.buildInstrNoInsert(BPF::RET); bool Success = true; if (VReg) { // … ArgInfo OrigArg{VReg, Val->getType()}; setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F); OutgoingHandler Handler(MIRBuilder, MRI, RetCC_BPF64, MIB); Success = handleAssignments(MIRBuilder, {OrigArg}, Handler); } MIRBuilder.insertInstr(MIB); return Success; }

Lower Return

GlobalISel Tutorial • LLVM Dev Meeting 201754

%0:_(s64) = COPY %r1 …G_ADD…

InsertPt

RET

Page 55: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

bool BPFCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, unsigned VReg) { auto MIB = MIRBuilder.buildInstrNoInsert(BPF::RET); bool Success = true; if (VReg) { // … ArgInfo OrigArg{VReg, Val->getType()}; setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F); OutgoingHandler Handler(MIRBuilder, MRI, RetCC_BPF64, MIB); Success = handleAssignments(MIRBuilder, {OrigArg}, Handler); } MIRBuilder.insertInstr(MIB); return Success; }

Lower Return

GlobalISel Tutorial • LLVM Dev Meeting 201755

%0:_(s64) = COPY %r1 …G_ADD…

InsertPt

RET

Page 56: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

bool BPFCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, unsigned VReg) { auto MIB = MIRBuilder.buildInstrNoInsert(BPF::RET); bool Success = true; if (VReg) { // … ArgInfo OrigArg{VReg, Val->getType()}; setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F); OutgoingHandler Handler(MIRBuilder, MRI, RetCC_BPF64, MIB); Success = handleAssignments(MIRBuilder, {OrigArg}, Handler); } MIRBuilder.insertInstr(MIB); return Success; }

Lower Return

GlobalISel Tutorial • LLVM Dev Meeting 201756

%0:_(s64) = COPY %r1 …G_ADD…

%r0 = COPY %VReg InsertPt

RET implicit %r0

Page 57: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

bool BPFCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, unsigned VReg) { auto MIB = MIRBuilder.buildInstrNoInsert(BPF::RET); bool Success = true; if (VReg) { // … ArgInfo OrigArg{VReg, Val->getType()}; setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F); OutgoingHandler Handler(MIRBuilder, MRI, RetCC_BPF64, MIB); Success = handleAssignments(MIRBuilder, {OrigArg}, Handler); } MIRBuilder.insertInstr(MIB); return Success; }

Lower Return

GlobalISel Tutorial • LLVM Dev Meeting 201757

%0:_(s64) = COPY %r1 …G_ADD…

%1:_(s64) = G_ANYEXT %VReg %r0 = COPY %1

InsertPtRET implicit %r0

Page 58: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

bool BPFCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val, unsigned VReg) { auto MIB = MIRBuilder.buildInstrNoInsert(BPF::RET); bool Success = true; if (VReg) { // … ArgInfo OrigArg{VReg, Val->getType()}; setArgFlags(OrigArg, AttributeList::ReturnIndex, DL, F); OutgoingHandler Handler(MIRBuilder, MRI, RetCC_BPF64, MIB); Success = handleAssignments(MIRBuilder, {OrigArg}, Handler); } MIRBuilder.insertInstr(MIB); return Success; }

Lower Return

GlobalISel Tutorial • LLVM Dev Meeting 201758

%0:_(s64) = COPY %r1 …G_ADD…

%1:_(s64) = G_ANYEXT %VReg %r0 = COPY %1

BPF::RET implicit %r0 InsertPt

Page 59: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Test ArgLowering

llc -global-isel -march=bpf -stop-after=irtranslator

GlobalISel Tutorial • LLVM Dev Meeting 201759

; CHECK: [[IN:%[0-9]+]]:_(s64) = COPY %r1 ; CHECK: %r0 = COPY [[IN]] ; CHECK: RET implicit %r0 define i64 @f(i64 %a) { ret i64 %a }

Page 60: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Test ArgLowering

llc -global-isel -march=bpf -stop-after=irtranslator

GlobalISel Tutorial • LLVM Dev Meeting 201760

; CHECK: [[TMP:%[0-9]+]]:_(s64) = COPY %r1 ; CHECK: [[IN:%[0-9]+]]:_(s32) = G_TRUNC [[TMP]] ; CHECK: [[EXT:%[0-9]+]]:_(s64) = G_ANYEXT [[IN]] ; CHECK: %r0 = COPY [[EXT]] define i32 @f(i32 %a) { ret i32 %a }

Page 61: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Register Banks

GlobalISel Tutorial • LLVM Dev Meeting 201761

irtranslator

legalizer

regbankselect

instruction-select

Wiring up GISel

CallLowering

LegalizerInfo

InstructionSelector

RegBankInfo

TargetMachine/SubTarget

Page 62: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Register Banks

• Group register classes, ignoring size and type

• Different banks imply transferring values is costly

• A typical split is general purpose vs floating point

GlobalISel Tutorial • LLVM Dev Meeting 201762

Page 63: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Define Register Banks

Define a bank for BPF's GPRs in BPFRegisterBanks.td

GlobalISel Tutorial • LLVM Dev Meeting 201763

def AnyGPRRegBank : RegisterBank<"AnyGPR", [GPR]>;

Page 64: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

More Register Classes

AArch64 is a good example with more register classes

GlobalISel Tutorial • LLVM Dev Meeting 201764

GPR32GPR32sp

GPR32common

GPR32all

GPR32sponly

tcGPR64

GPR64

GPR64sp

GPR64common

GPR64all

GPR64sponly

CCR

FPR8FPR16 FPR32

FPR64

DDFPR128

DDD

DDDD

QQ

QQQ

QQQQ

Page 65: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

AArch64 Register Banks

GlobalISel Tutorial • LLVM Dev Meeting 201765

GPR32

GPR32sp

GPR32common

GPR32all

GPR32sponly

tcGPR64

GPR64

GPR64sp

GPR64common

GPR64all

GPR64sponly

GPR FPR CC

CCRFPR8

FPR16

FPR32

FPR64

DD

FPR128

DDD

DDDD

QQ

QQQ

QQQQ

Page 66: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

AArch64 Register Banks

We only need to specify the largest register class to define each bank

GlobalISel Tutorial • LLVM Dev Meeting 201766

/// General Purpose Registers: W, X. def GPRRegBank : RegisterBank<"GPR", [GPR64all]>; /// Floating Point/Vector Registers: B, H, S, D, Q. def FPRRegBank : RegisterBank<"FPR", [QQQQ]>; /// Conditional register: NZCV. def CCRegBank : RegisterBank<"CC", [CCR]>;

Page 67: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Generated Bank Info

GlobalISel Tutorial • LLVM Dev Meeting 201767

class BPFGenRegisterBankInfo : public RegisterBankInfo { protected: #define GET_TARGET_REGBANK_CLASS #include "BPFGenRegisterBank.inc" };

Page 68: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Register Bank Mapping

GlobalISel Tutorial • LLVM Dev Meeting 201768

BPFRegisterBankInfo : BPFGenRegisterBankInfo

getRegBankFromRegClass(...) getInstrMapping(...) getInstrAlternativeMappings(...)

Page 69: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Register Bank Mapping

Given a register class, return the register bank

GlobalISel Tutorial • LLVM Dev Meeting 201769

BPFRegisterBankInfo : BPFGenRegisterBankInfo

getRegBankFromRegClass(...) getInstrMapping(...) getInstrAlternativeMappings(...)

Page 70: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Register Bank Mapping

GlobalISel Tutorial • LLVM Dev Meeting 201770

BPFRegisterBankInfo : BPFGenRegisterBankInfo

getRegBankFromRegClass(...) getInstrMapping(...) getInstrAlternativeMappings(...)

Page 71: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

getInstrMapping

Leverage getInstrMappingImpl to handle generic instructions

GlobalISel Tutorial • LLVM Dev Meeting 201771

const auto &Mapping = getInstrMappingImpl(MI); if (Mapping.isValid()) return Mapping;

Page 72: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

getInstrMapping

Map each operand to an appropriate bank for target instructions

GlobalISel Tutorial • LLVM Dev Meeting 201772

SmallVector<const ValueMapping *, 8> ValMappings(NumOperands); for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { if (MI.getOperand(Idx).isReg()) { LLT Ty = MRI.getType(MI.getOperand(Idx).getReg()); auto Size = Ty.getSizeInBits(); ValMappings[Idx] = &getValueMapping(0, Size, BPF::AnyGPRRegBank); } }

return Mapping;

Page 73: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Test Bank Selection

llc -march=bpf -global-isel -run-pass=regbankselect

GlobalISel Tutorial • LLVM Dev Meeting 201773

; CHECK-LABEL: name: defaultMapping ; CHECK: %[[CP:[0-9]+]]:anygpr(s64) = COPY %r1 ; CHECK: %[[ADD:[0-9]+]]:anygpr(s64) = G_ADD %[[CP]], %[[CP]] %0:_(s64) = COPY %r1 %1:_(s64) = G_ADD %0, %0

Page 74: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

getInstrAlternativeMappings

In AArch64, 32 and 64-bit "or" map equally well on FPR or GPR

GlobalISel Tutorial • LLVM Dev Meeting 201774

case TargetOpcode::G_OR: { InstructionMappings AltMappings; AltMappings.push_back(getInstructionMapping( /*ID*/ 1, /*Cost*/ 1, getValueMapping(PMI_FirstGPR, Size), /*NumOperands*/ 3)); AltMappings.push_back(getInstructionMapping( /*ID*/ 2, /*Cost*/ 1, getValueMapping(PMI_FirstFPR, Size), /*NumOperands*/ 3)); return AltMappings; }

Page 75: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

getInstrAlternativeMappings

In AArch64, 32 and 64-bit "or" map equally well on FPR or GPR

GlobalISel Tutorial • LLVM Dev Meeting 201775

case TargetOpcode::G_OR: { InstructionMappings AltMappings; AltMappings.push_back(getInstructionMapping( /*ID*/ 1, /*Cost*/ 1, getValueMapping(PMI_FirstGPR, Size), /*NumOperands*/ 3)); AltMappings.push_back(getInstructionMapping( /*ID*/ 2, /*Cost*/ 1, getValueMapping(PMI_FirstFPR, Size), /*NumOperands*/ 3)); return AltMappings; }

Page 76: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

getInstrAlternativeMappings

In AArch64, 32 and 64-bit "or" map equally well on FPR or GPR

GlobalISel Tutorial • LLVM Dev Meeting 201776

case TargetOpcode::G_OR: { InstructionMappings AltMappings; AltMappings.push_back(getInstructionMapping( /*ID*/ 1, /*Cost*/ 1, getValueMapping(PMI_FirstGPR, Size), /*NumOperands*/ 3)); AltMappings.push_back(getInstructionMapping( /*ID*/ 2, /*Cost*/ 1, getValueMapping(PMI_FirstFPR, Size), /*NumOperands*/ 3)); return AltMappings; }

Page 77: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Legalizer

GlobalISel Tutorial • LLVM Dev Meeting 201777

irtranslator

legalizer

regbankselect

instruction-select

Wiring up GISel

CallLowering

LegalizerInfo

InstructionSelector

RegBankInfo

TargetMachine/SubTarget

Page 78: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Legalizer

• Transform gMIR into legal instructions

• Legal is defined as

• Selectable by target

• Operating on vregs that can be loaded/stored

• No SelectionDAG like type legalization

GlobalISel Tutorial • LLVM Dev Meeting 201778

Page 79: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Legalization

GlobalISel Tutorial • LLVM Dev Meeting 201779

Legalizer

LegalizerHelper

Uses

Uses

LegalizerInfo

Pass Drives Legalization Specifies Legality

Helpers for Common Operations

Page 80: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Legality Specifiers

GlobalISel Tutorial • LLVM Dev Meeting 201780

setAction({Opcode, [OperandIdx,] Ty}, LegalizeAction)

Page 81: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Legality Specifiers

GlobalISel Tutorial • LLVM Dev Meeting 201781

setAction({G_ADD, s64}, Legal); // Want 64 bit Dest

setAction({G_ADD, s32}, WidenScalar);

setAction({Opcode, [OperandIdx,] Ty}, LegalizeAction)

%2:_(s64) = G_ADD %0, %1

%3:_(s32) = … %4:_(s32) = G_ADD %3, %3

Page 82: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

setAction({G_ADD, s64}, Legal); // Want 64 bit Dest

setAction({G_ADD, s32}, WidenScalar);

%2:_(s64) = G_ADD %0, %1

%3:_(s32) = … %4:_(s32) = G_ADD %3, %3

Legality Specifiers

GlobalISel Tutorial • LLVM Dev Meeting 201782

setAction({Opcode, [OperandIdx,] Ty}, LegalizeAction)

Page 83: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

setAction({G_ADD, s64}, Legal); // Want 64 bit Dest

setAction({G_ADD, s32}, WidenScalar);

%2:_(s64) = G_ADD %0, %1

%3:_(s32) = … %5:_(s64) = G_ANYEXT %3(s32) %6:_(s64) = G_ADD %5, %5

Legality Specifiers

GlobalISel Tutorial • LLVM Dev Meeting 201783

setAction({Opcode, [OperandIdx,] Ty}, LegalizeAction)

Page 84: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ADD %0, %1

%3:_(s32) = … %5:_(s64) = G_ANYEXT %3(s32) %6:_(s64) = G_ADD %5, %5

setAction({G_ANYEXT, 0, s64}, Legal);

setAction({G_ANYEXT, 1, s32}, Legal);

Legality Specifiers

GlobalISel Tutorial • LLVM Dev Meeting 201784

setAction({Opcode, [OperandIdx,] Ty}, LegalizeAction)

Page 85: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Legalization in BPF

• Set LegalizerAction in the constructor.

• Implement legalizeCustom for custom hook if required.

GlobalISel Tutorial • LLVM Dev Meeting 201785

Page 86: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

BPFLegalizerInfo::BPFLegalizerInfo() { using namespace TargetOpcode; const LLT p0 = LLT::pointer(0, 64); // … const LLT s32 = LLT::scalar(32); const LLT s64 = LLT::scalar(64); for (auto Ty : {p0, s1, s8, s16, s32, s64}) setAction({G_IMPLICIT_DEF, Ty}, Legal); setAction({G_PHI, s64}, Legal); for (auto Ty : {s1, s8, s16, s32}) setAction({G_PHI, Ty}, WidenScalar);

// … computeTables(); }

BPFLegalizerInfo

GlobalISel Tutorial • LLVM Dev Meeting 201786

Page 87: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

BPFLegalizerInfo::BPFLegalizerInfo() { using namespace TargetOpcode; const LLT p0 = LLT::pointer(0, 64); // … const LLT s32 = LLT::scalar(32); const LLT s64 = LLT::scalar(64); for (auto Ty : {p0, s1, s8, s16, s32, s64}) setAction({G_IMPLICIT_DEF, Ty}, Legal); setAction({G_PHI, s64}, Legal); for (auto Ty : {s1, s8, s16, s32}) setAction({G_PHI, Ty}, WidenScalar);

// … computeTables(); }

BPFLegalizerInfo

GlobalISel Tutorial • LLVM Dev Meeting 201787

Page 88: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

BPFLegalizerInfo::BPFLegalizerInfo() { using namespace TargetOpcode; const LLT p0 = LLT::pointer(0, 64); // … const LLT s32 = LLT::scalar(32); const LLT s64 = LLT::scalar(64); for (auto Ty : {p0, s1, s8, s16, s32, s64}) setAction({G_IMPLICIT_DEF, Ty}, Legal); setAction({G_PHI, s64}, Legal); for (auto Ty : {s1, s8, s16, s32}) setAction({G_PHI, Ty}, WidenScalar);

// … computeTables(); }

BPFLegalizerInfo

GlobalISel Tutorial • LLVM Dev Meeting 201788

Page 89: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

BPFLegalizerInfo::BPFLegalizerInfo() { using namespace TargetOpcode; const LLT p0 = LLT::pointer(0, 64); // … const LLT s32 = LLT::scalar(32); const LLT s64 = LLT::scalar(64); for (auto Ty : {p0, s1, s8, s16, s32, s64}) setAction({G_IMPLICIT_DEF, Ty}, Legal); setAction({G_PHI, s64}, Legal); for (auto Ty : {s1, s8, s16, s32}) setAction({G_PHI, Ty}, WidenScalar);

// … computeTables(); }

BPFLegalizerInfo

GlobalISel Tutorial • LLVM Dev Meeting 201789

Page 90: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

BPFLegalizerInfo::BPFLegalizerInfo() { using namespace TargetOpcode; const LLT p0 = LLT::pointer(0, 64); // … const LLT s32 = LLT::scalar(32); const LLT s64 = LLT::scalar(64); for (auto Ty : {p0, s1, s8, s16, s32, s64}) setAction({G_IMPLICIT_DEF, Ty}, Legal); setAction({G_PHI, s64}, Legal); for (auto Ty : {s1, s8, s16, s32}) setAction({G_PHI, Ty}, WidenScalar);

// … computeTables(); }

BPFLegalizerInfo

GlobalISel Tutorial • LLVM Dev Meeting 201790

Page 91: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Test Legalizer

llc -march=bpf -global-isel -run-pass=legalizer

GlobalISel Tutorial • LLVM Dev Meeting 201791

; CHECK: [[IN:%[0-9]+]]:_(s64) = COPY %r1 ; CHECK: %r0 = COPY [[IN]] ; CHECK: RET implicit %r0 %0:_(s64) = COPY %r1 %r0 = COPY %0(s64) RET implicit %r0

Page 92: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Test Legalizer

LLVM ERROR: unable to legalize instruction

GlobalISel Tutorial • LLVM Dev Meeting 201792

%0:_(s64) = COPY %r1 %1:_(s64) = G_ADD %0, %0 %r0 = COPY %1(s64) RET implicit %r0

Page 93: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

setAction({G_ADD, s64}, Legal); for (const auto &Ty : {s1, s8, s16, s32}) setAction({G_ADD, Ty}, WidenScalar);

BPFLegalizerInfo

GlobalISel Tutorial • LLVM Dev Meeting 201793

Page 94: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

setAction({G_ADD, s64}, Legal); for (const auto &Ty : {s1, s8, s16, s32}) setAction({G_ADD, Ty}, WidenScalar);

BPFLegalizerInfo

GlobalISel Tutorial • LLVM Dev Meeting 201794

Page 95: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Test Legalizer

GlobalISel Tutorial • LLVM Dev Meeting 201795

; CHECK: [[ADD:%[0-9]+]]:_(s64) = G_ADD %0:_(s64) = COPY %r1 %1:_(s64) = G_ADD %0, %0 %r0 = COPY %1(s64) RET implicit %r0

Page 96: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Test Legalizer

GlobalISel Tutorial • LLVM Dev Meeting 201796

; CHECK: [[ADD:%[0-9]+]]:_(s64) = G_ADD %0:_(s64) = COPY %r1 %1:_(s32) = G_TRUNC %0 %2:_(s32) = G_ADD %1, %1 ; ...

Page 97: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Custom Legalization

• Implement legalizeCustom method

• Specify LegalizationAction as Custom

• Legalize G_SELECT into pseudo instruction (BPF_SELECT_CC)

GlobalISel Tutorial • LLVM Dev Meeting 201797

Page 98: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%4:_(s64) = BPF_SELECT_CC %0, %1, <pred>, %5, %6

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

Custom Legalization

GlobalISel Tutorial • LLVM Dev Meeting 201798

Page 99: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

%4:_(s64) = BPF_SELECT_CC %0, %1, <pred>, %5, %6

Custom Legalization

GlobalISel Tutorial • LLVM Dev Meeting 201799

Page 100: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Custom Legalization

GlobalISel Tutorial • LLVM Dev Meeting 2017100

def BPF_SELECT_CC : Pseudo<(outs type1:$dst), (ins type0:$lhs, type0:$rhs, i64imm:$cc, type1:$true, type1:$false), “BPF_SELECT_CC\t$dst, $lhs, $rhs, $cc, $true, $false", []>;

Page 101: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Custom Legalization

GlobalISel Tutorial • LLVM Dev Meeting 2017101

setAction({G_SELECT, 1, s1}, Legal); for (const auto &Ty : {s1, s8, s16, s32}) setAction({G_SELECT, Ty}, WidenScalar); setAction({G_SELECT, s64}, Custom);

Page 102: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017102

bool BPFLegalizerInfo::legalizeCustom(…) { switch (MI.getOpcode()) { default: llvm_unreachable("Illegal Opcode"); case TargetOpcode::G_SELECT: return legalizeCustomSelect(MI, MRI, MIRBuilder); } }

Page 103: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017103

bool BPFLegalizerInfo::legalizeCustomSelect( MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &MIRBuilder) const { // … }

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

Page 104: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017104

MachineOperand &Op0 = MI.getOperand(0); LLT DstTy = MRI.getType(Op0.getReg()); MachineOperand &CmpOp = MI.getOperand(1); MachineOperand &Res1 = MI.getOperand(2); MachineOperand &Res2 = MI.getOperand(3);

Page 105: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

MachineOperand &Op0 = MI.getOperand(0); LLT DstTy = MRI.getType(Op0.getReg()); MachineOperand &CmpOp = MI.getOperand(1); MachineOperand &Res1 = MI.getOperand(2); MachineOperand &Res2 = MI.getOperand(3);

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017105

Page 106: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017106

MachineInstr *DefMI = MRI.getVRegDef(CmpOp.getReg()); if (DefMI->getOpcode() == TargetOpcode::G_TRUNC) DefMI = MRI.getVRegDef(DefMI->getOperand(1).getReg()); if (DefMI->getOpcode() != TargetOpcode::G_ICMP) return false;

Page 107: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

MachineInstr *DefMI = MRI.getVRegDef(CmpOp.getReg()); if (DefMI->getOpcode() == TargetOpcode::G_TRUNC) DefMI = MRI.getVRegDef(DefMI->getOperand(1).getReg()); if (DefMI->getOpcode() != TargetOpcode::G_ICMP) return false;

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017107

Page 108: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

MachineInstr *DefMI = MRI.getVRegDef(CmpOp.getReg()); if (DefMI->getOpcode() == TargetOpcode::G_TRUNC) DefMI = MRI.getVRegDef(DefMI->getOperand(1).getReg()); if (DefMI->getOpcode() != TargetOpcode::G_ICMP) return false;

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017108

Page 109: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

MachineInstr *DefMI = MRI.getVRegDef(CmpOp.getReg()); if (DefMI->getOpcode() == TargetOpcode::G_TRUNC) DefMI = MRI.getVRegDef(DefMI->getOperand(1).getReg()); if (DefMI->getOpcode() != TargetOpcode::G_ICMP) return false;

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017109

Page 110: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

MachineInstr *DefMI = MRI.getVRegDef(CmpOp.getReg()); if (DefMI->getOpcode() == TargetOpcode::G_TRUNC) DefMI = MRI.getVRegDef(DefMI->getOperand(1).getReg()); if (DefMI->getOpcode() != TargetOpcode::G_ICMP) return false;

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017110

Page 111: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017111

MachineOperand &C1 = DefMI->getOperand(2); MachineOperand &C2 = DefMI->getOperand(3); MachineOperand &PredOp = DefMI->getOperand(1);

Page 112: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

MachineOperand &C1 = DefMI->getOperand(2); MachineOperand &C2 = DefMI->getOperand(3); MachineOperand &PredOp = DefMI->getOperand(1);

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017112

Page 113: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

MachineOperand &C1 = DefMI->getOperand(2); MachineOperand &C2 = DefMI->getOperand(3); MachineOperand &PredOp = DefMI->getOperand(1);

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017113

Page 114: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017114

// Get the dest reg unsigned DstReg = MI.getOperand(0).getReg(); MIRBuilder.setInstr(MI);

Page 115: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

// Get the dest reg unsigned DstReg = MI.getOperand(0).getReg(); MIRBuilder.setInstr(MI);

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017115

Page 116: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

// Get the dest reg unsigned DstReg = MI.getOperand(0).getReg(); MIRBuilder.setInstr(MI);

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017116

InsertPt

Page 117: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

auto Cst = MIRBuilder.buildConstant( DstTy, (unsigned)PredKind);

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %7:_(s64) = G_CONSTANT pred_kind %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017117

InsertPt

Page 118: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %7:_(s64) = G_CONSTANT pred_kind %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017118

MIRBuilder.buildInstr(BPF::BPF_SELECT_CC, DstReg) .addReg(Cmp1.getReg()) .addReg(Cmp2.getReg()) .addReg(Cst->getOperand(0).getReg()) .addReg(Res1.getReg()) .addReg(Res2.getReg());

InsertPt

Page 119: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %7:_(s64) = G_CONSTANT pred_kind %4:_(s64) = BPF_SELECT_CC %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

MIRBuilder.buildInstr(BPF::BPF_SELECT_CC, DstReg) .addReg(Cmp1.getReg()) .addReg(Cmp2.getReg()) .addReg(Cst->getOperand(0).getReg()) .addReg(Res1.getReg()) .addReg(Res2.getReg());

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017119

InsertPt

Page 120: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %7:_(s64) = G_CONSTANT pred_kind %4:_(s64) = BPF_SELECT_CC, %0(s64) %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

MIRBuilder.buildInstr(BPF::BPF_SELECT_CC, DstReg) .addReg(Cmp1.getReg()) .addReg(Cmp2.getReg()) .addReg(Cst->getOperand(0).getReg()) .addReg(Res1.getReg()) .addReg(Res2.getReg());

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017120

InsertPt

Page 121: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %7:_(s64) = G_CONSTANT pred_kind %4:_(s64) = BPF_SELECT_CC, %0(s64), %1 %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

MIRBuilder.buildInstr(BPF::BPF_SELECT_CC, DstReg) .addReg(Cmp1.getReg()) .addReg(Cmp2.getReg()) .addReg(Cst->getOperand(0).getReg()) .addReg(Res1.getReg()) .addReg(Res2.getReg());

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017121

InsertPt

Page 122: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %7:_(s64) = G_CONSTANT pred_kind %4:_(s64) = BPF_SELECT_CC, %0(s64), %1, %7(s64), %5, %6 %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

MIRBuilder.buildInstr(BPF::BPF_SELECT_CC, DstReg) .addReg(Cmp1.getReg()) .addReg(Cmp2.getReg()) .addReg(Cst->getOperand(0).getReg()) .addReg(Res1.getReg()) .addReg(Res2.getReg());

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017122

InsertPt

Page 123: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %7:_(s64) = G_CONSTANT pred_kind %4:_(s64) = BPF_SELECT_CC, %0(s64), %1, %7(s64), %5, %6 %4:_(s64) = G_SELECT %3(s1), %5(s64), %6

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017123

MI.eraseFromParent();

InsertPt

Page 124: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %7:_(s64) = G_CONSTANT pred_kind %4:_(s64) = BPF_SELECT_CC, %0(s64), %1, %7(s64), %5, %6

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017124

MI.eraseFromParent();

InsertPt

Page 125: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %7:_(s64) = G_CONSTANT pred_kind %4:_(s64) = BPF_SELECT_CC, %0(s64), %1, %7(s64), %5, %6

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017125

auto &RB = MF.getSubtarget() .getRegBankInfo() ->getRegBankFromRegClass(BPF::GPRRegClass); MRI.setRegBank(DstReg, RB);

InsertPt

Page 126: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %7:_(s64) = G_CONSTANT pred_kind %4:anygpr(s64) = BPF_SELECT_CC, %0(s64), %1, %7(s64), %5, %6

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017126

auto &RB = MF.getSubtarget() .getRegBankInfo() ->getRegBankFromRegClass(BPF::GPRRegClass); MRI.setRegBank(DstReg, RB);

InsertPt

Page 127: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%2:_(s64) = G_ICMP <pred>, %0(s64), %1(s64) %3:_(s1) = G_TRUNC %2(s64) %7:_(s64) = G_CONSTANT pred_kind %4:anygpr(s64) = BPF_SELECT_CC, %0(s64), %1, %7(s64), %5, %6

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017127

return true;

InsertPt

Page 128: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

; CHECK-LABEL: name: checkcmplegal ; CHECK: [[A:%[0-9]+]]:_(s64) = COPY %r1 ; CHECK: [[B:%[0-9]+]]:_(s64) = COPY %r2 ; CHECK: [[CST:%[0-9]+]]:_(s64) = G_CONSTANT ; CHECK: [[R:%[0-9]+]]:anygpr(s64) = BPF_SELECT_CC [[A]](s64), [[B]], [[CST]], [[A]], [[B]] ; CHECK: %r0 = COPY [[R]] %2:_(s64) = COPY %r1 %3:_(s64) = COPY %r2 %4:_(s64) = G_ICMP intpred(sgt), %2(s64), %3 %5:_(s1) = G_TRUNC %4(s64) %6:_(s64) = G_SELECT %5(s1), %2(s64), %3 %r0 = COPY %5(s64) RET implicit %r0

Test Custom Legalization

GlobalISel Tutorial • LLVM Dev Meeting 2017128

Page 129: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Good Practices

✓ Incrementally add instructions and write small targeted tests

✓Always use MachineIRBuilder for building instructions

✗ Don’t erase any other instruction besides the current

✗ Do not allow legality to be conditional

GlobalISel Tutorial • LLVM Dev Meeting 2017129

Page 130: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Instruction Selector

GlobalISel Tutorial • LLVM Dev Meeting 2017130

irtranslator

legalizer

regbankselect

instruction-select

Wiring up GISel

CallLowering

LegalizerInfo

InstructionSelector

RegBankInfo

TargetMachine/SubTarget

Page 131: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Instruction Selection

• Importing rules from SelectionDAG

• Converting PatLeaf and ComplexPattern

• Handling custom SDNodes

• What to do when the importer fails

• Custom Selection

GlobalISel Tutorial • LLVM Dev Meeting 2017131

Page 132: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Instruction Selection

GlobalISel Tutorial • LLVM Dev Meeting 2017132

Implement select and use the tablegen-erated selectImpl

BPFInstructionSelector : InstructionSelector

select(...) selectImpl(...)

Page 133: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Implement select

GlobalISel Tutorial • LLVM Dev Meeting 2017133

bool BPFInstructionSelector::select(MachineInstr &I) const { // Ignore COPY's: the register allocator will handle them. if (Opcode == TargetOpcode::COPY) return true; if (selectImpl(I)) return true; return false; }

Page 134: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Imported Rule Statistics

$ rm lib/Target/BPF/BPFGenGlobalISel.inc* $ ninja -v lib/Target/BPF/BPFGenGlobalISel.inc $ llvm-tblgen -gen-global-isel ... --stats

===-------------------------------------------------------------------------=== ... Statistics Collected ... ===-------------------------------------------------------------------------===

16 gisel-emitter - Number of patterns emitted 16 gisel-emitter - Number of patterns imported from SelectionDAG 61 gisel-emitter - Number of SelectionDAG imports skipped 77 gisel-emitter - Total number of patterns

GlobalISel Tutorial • LLVM Dev Meeting 2017134

Page 135: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Initial Imports

GlobalISel Tutorial • LLVM Dev Meeting 2017135

16

61

Skipped Imported

Page 136: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Import Failures

$ rm lib/Target/BPF/BPFGenGlobalISel.inc* $ ninja -v lib/Target/BPF/BPFGenGlobalISel.inc $ llvm-tblgen -gen-global-isel ... --warn-on-skipped-patterns

Included from lib/Target/BPF/BPF.td:15: lib/Target/BPF/BPFInstrInfo.td:352:1: warning: Skipped pattern: Src pattern root isn't a trivial operator ... def STW : STOREi64<0x0, "u32", truncstorei32>; ^

GlobalISel Tutorial • LLVM Dev Meeting 2017136

Page 137: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

9

33

1313

20 No equivalent Instruction (BPFISD::BR_CC)Src pattern child has predicateSrc pattern root isn't a trivial operatorSrc pattern results and Dst MI defs differNo equivalent Instruction (BPFISD::CALL)Others

Import Failures

GlobalISel Tutorial • LLVM Dev Meeting 2017137

Page 138: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Import PatLeaf

GlobalISel Tutorial • LLVM Dev Meeting 2017138

);}]>;def i64immSExt32 : Leaf<i64, [{return isInt<32>(def i64immSExt32 : PatLeaf<i64, [{return isInt<32>(N->getSExtValue());}]>;Pat

Src pattern child has predicate (i64immSExt32)

Page 139: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Imm

Import PatLeaf

GlobalISel Tutorial • LLVM Dev Meeting 2017139

);}]>;

def i64immSExt32 : PatLeaf<i64, [{return isInt<32>(N->getSExtValue());}]>;

def i64immSExt32 : Leaf<i64, [{return isInt<32>(Imm

Use int64_t instead of SDNode

Page 140: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Pat

Import PatLeaf

Src pattern child has predicate (BPF_CC_EQ)

GlobalISel Tutorial • LLVM Dev Meeting 2017140

def BPF_CC_EQ : Leaf<i64, [{return N ->getZExtValue() == ISD::SETEQ;}]>;def BPF_CC_EQ : PatLeaf<i64, [{return N->getZExtValue() == ISD::SETEQ;}]>;

Page 141: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Import PatLeaf

Use APInt instead of SDNode

GlobalISel Tutorial • LLVM Dev Meeting 2017141

def BPF_CC_EQ : PatLeaf<i64, [{return N->getZExtValue() == ISD::SETEQ;}]>;

IntImm def BPF_CC_EQ : Imm ->getZExtValue() == ISD::SETEQ;}]>; Leaf<i64, [{return

Page 142: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

; CHECK: %{{[0-9]}}:gpr = LD_imm64 1234 %0:anygpr(s64) = G_CONSTANT i64 1234 %r0 = COPY %0(s64)

Test Instruction Selection

GlobalISel Tutorial • LLVM Dev Meeting 2017142

llc -march=bpf -global-isel -run-pass=instruction-select

Page 143: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Import PatLeaf

GlobalISel Tutorial • LLVM Dev Meeting 2017143

27

50

Skipped Imported

Page 144: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

def BPF_BR_CC : Pseudo<(outs), (ins i64imm:$cc, type0:$lhs, type0:$rhs, brtarget:$target), "BR_CC_PSEUDO\t$cc, $lhs, $rhs, $target", []>; def : GINodeEquiv<BPF_BR_CC, BPFbrcc>;

Map Custom ISD Nodes

GlobalISel Tutorial • LLVM Dev Meeting 2017144

Pattern operator lacks an equivalent Instruction (BPFISD::BR_CC)

Page 145: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Map Custom ISD Nodes

GlobalISel Tutorial • LLVM Dev Meeting 2017145

def BPF_SELECT_CC : Pseudo<(outs type1:$dst), (ins type0:$lhs, type0:$rhs, i64imm:$cc, type1:$true, type1:$false), "BPF_SELECT_CC\t$dst, $lhs, $rhs, $cc, $true, $false", []>; def : GINodeEquiv<BPF_SELECT_CC, BPFselectcc>;

Pattern operator lacks an equivalent Instruction (BPFISD::SELECT_CC)

Page 146: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Map Custom ISD Nodes

GlobalISel Tutorial • LLVM Dev Meeting 2017146

49

28

Skipped Imported

Page 147: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

5

11

3

6

12 Src pattern root isn't a trivial operatorSrc pattern results and dst MI defs are differentNo equivalent Instruction (BPFISD::CALL)Unable to deduce gMIR opcode to handle SrcComplexPattern (ADDRri) not mappedOthers

Import Failures

GlobalISel Tutorial • LLVM Dev Meeting 2017147

Page 148: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Import ComplexPattern

def ADDRri : ComplexPattern<i64, 2, "SelectAddr", [], []>; def gi_ADDRri : GIComplexOperandMatcher<s64, "selectAddr">, GIComplexPatternEquiv<ADDRri>;

GlobalISel Tutorial • LLVM Dev Meeting 2017148

Page 149: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Patterns To Match

%Root = G_FRAME_INDEX %fixedstack.0

%0 = G_CONSTANT i64 simm16 %Root = G_GEP %1, %0

GlobalISel Tutorial • LLVM Dev Meeting 2017149

%0 = G_FRAME_INDEX %fixedstack.0 %1 = G_CONSTANT i64 simm16 %Root = G_GEP %0, %1

%Root = Any Register

Page 150: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Cases To Handle

%Root = G_FRAME_INDEX %fixedstack.0

%0 = G_CONSTANT i64 simm16 %Root = G_GEP %1, %0

GlobalISel Tutorial • LLVM Dev Meeting 2017150

%0 = G_FRAME_INDEX %fixedstack.0 %1 = G_CONSTANT i64 simm16 %Root = G_GEP %0, %1

%Root = Any Register

%Root = G_GLOBAL_VALUE ...

Page 151: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

G_FRAME_INDEX

GlobalISel Tutorial • LLVM Dev Meeting 2017151

%Root

G_FRAME_INDEX

%fixedstack.0

getVRegDef

getOperand

Page 152: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

G_FRAME_INDEX

GlobalISel Tutorial • LLVM Dev Meeting 2017152

return {{ [=](auto &MIB) { MIB.add(FrameIndex->getOperand(1)); }, [=](auto &MIB) { MIB.addImm(0); } }};

%0 = INST <Ops>, ,%fixedstack.0 i64 0 0

Page 153: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

isBaseWithConstantOffset(Root, MRI)

Base + Offset

GlobalISel Tutorial • LLVM Dev Meeting 2017153

G_GEP

G_CONSTANT

simm16

%Root

%1 %0

getVRegDef

getOperand

Page 154: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Base + Offset

GlobalISel Tutorial • LLVM Dev Meeting 2017154

return {{ [=](auto &MIB) { MIB.add(Gep->getOperand(1)); }, [=](auto &MIB) { MIB.addImm(Constant->getOperand(1).getImm()); } }};

%0 = INST <Ops>, , i64 simm16%1

Page 155: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

G_GLOBAL_VALUE

155

G_GLOBAL_VALUE

%Root

getVRegDef

return None;

Page 156: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Any Pointer

GlobalISel Tutorial • LLVM Dev Meeting 2017156

%Root

Page 157: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Any Pointer

GlobalISel Tutorial • LLVM Dev Meeting 2017157

return {{ [=](auto &MIB) { MIB.add(Root); }, [=](auto &MIB) { MIB.addImm(0); } }};

%0 = INST <Ops>, ,%Root i64 0

Page 158: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

isBaseWithConstantOffset(...) isOperandImmEqual(...)

isObviouslySafeToFold(...)

Common Predicates

GlobalISel Tutorial • LLVM Dev Meeting 2017158

Page 159: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Good Practices

GlobalISel Tutorial • LLVM Dev Meeting 2017159

✗ Don't modify MIR in the predicate

✓Capture locals by value in a renderer lambda

✓Only create instructions in a renderer lambda

Page 160: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Import ComplexPattern

GlobalISel Tutorial • LLVM Dev Meeting 2017160

50

27

Skipped Imported

Page 161: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Known Issues

warning: Src pattern root isn't a trivial operator (Has a predicate (unindexedload unindexed-loadextload extloadextloadi16 LoadMemVT=i16), first-failing:extload)

GlobalISel Tutorial • LLVM Dev Meeting 2017161

[sz]extload/extload/truncstore/atomic-load/atomic-store in development

Page 162: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Known Issues

def : Pat<(i64 (and (i64 GPR:$src), 0xffffffff)), (SRL_ri (SLL_ri (i64 GPR:$src), 32), 32)>;

warning: Dst pattern child isn't a leaf node or an MBB

GlobalISel Tutorial • LLVM Dev Meeting 2017162

Development for multiple instruction emission will start soon

Page 163: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Custom Selection

def : Pat<(i64 (and (i64 GPR:$src), 0xffffffff)), (SRL_ri (SLL_ri (i64 GPR:$src), 32), 32)>;

GlobalISel Tutorial • LLVM Dev Meeting 2017163

Page 164: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Rule Priority

GlobalISel Tutorial • LLVM Dev Meeting 2017164

bool BPFInstructionSelector::select(MachineInstr &I) const { // ...

// Implement (G_AND $dst, $src1, (G_CONSTANT i64 0xffffFFFF) here if (selectImpl(I)) return true;

// Implement (G_AND $dst, $src1, (G_CONSTANT i64 0xffffFFFF) here

// ... return false; }

Page 165: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Rule Priority

GlobalISel Tutorial • LLVM Dev Meeting 2017165

bool BPFInstructionSelector::select(MachineInstr &I) const { // ...

// Implement (G_AND $dst, $src1, (G_CONSTANT i64 0xffffFFFF) here if (selectImpl(I)) return true;

// Implement (G_AND $dst, $src1, (G_CONSTANT i64 0xffffffff) here?

// ... return false; }

Page 166: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Rule Priority

GlobalISel Tutorial • LLVM Dev Meeting 2017166

bool BPFInstructionSelector::select(MachineInstr &I) const { // ...

// Implement (G_AND $dst, $src1, (G_CONSTANT i64 0xffffffff) here if (selectImpl(I)) // Contains (G_AND $dst, $src1, $src2) return true;

// Implement (G_AND $dst, $src1, (G_CONSTANT i64 0xffffFFFF) here

// ... return false; }

Page 167: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Test Custom Selection

GlobalISel Tutorial • LLVM Dev Meeting 2017167

; CHECK: %[[T0:[0-9]+]]:gpr = COPY %r0 ; CHECK: %[[T1:[0-9]+]]:gpr = SLL_ri %[[T0]], 32 ; CHECK: %[[T2:[0-9]+]]:gpr = SRL_ri %[[T1]], 32 ; CHECK: %r0 = COPY %[[T2]] liveins: %r0 %0:anygpr(s64) = COPY %r0 %1:anygpr(s64) = G_CONSTANT i64 4294967295 %2:anygpr(s64) = G_AND %0, %1 %r0 = COPY %2(s64)

llc -march=bpf -global-isel -run-pass=instruction-select

Page 168: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Custom Selection

if (Opcode == TargetOpcode::G_AND) { MachineOperand *Dst = &I.getOperand(0); MachineOperand *LHS = &I.getOperand(1); MachineOperand *RHS = &I.getOperand(2);

GlobalISel Tutorial • LLVM Dev Meeting 2017168

%0:anygpr = G_CONSTANT i64 0xffffffff %dst:anygpr = G_AND %src:anygpr, %0 %1:gpr = SLL_ri %src:gpr, i64 32 %dst:gpr = SRL_ri %1, i64 32

Page 169: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Custom Selection

if (MRI.getType(Dst->getReg()) == LLT::scalar(64) && RBI.getRegBank(Dst->getReg(), MRI, TRI)->getID() == BPF::AnyGPRRegBankID) {

GlobalISel Tutorial • LLVM Dev Meeting 2017169

%0:anygpr = G_CONSTANT i64 0xffffffff %dst:anygpr = G_AND %src:anygpr, %0 %1:gpr = SLL_ri %src:gpr, i64 32 %dst:gpr = SRL_ri %1, i64 32

Page 170: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%0:anygpr = G_CONSTANT i64 0xffffffff %dst:anygpr = G_AND %src:anygpr, %0 %1:gpr = SLL_ri %src:gpr, i64 32 %dst:gpr = SRL_ri %1, i64 32

bool LHSIsMask = isOperandImmEqual(*LHS, 0xffffffff, MRI); if (LHSIsMask) std::swap(LHS, RHS); if (LHSIsMask || isOperandImmEqual(*RHS, 0xffffffff, MRI)) {

Custom Selection

GlobalISel Tutorial • LLVM Dev Meeting 2017170

Page 171: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%0:anygpr = G_CONSTANT i64 0xffffffff %dst:anygpr = G_AND %src:anygpr, %0 %1:gpr = SLL_ri %src:gpr, i64 32 %dst:gpr = SRL_ri %1, i64 32%1:gpr = SLL_ri %src:gpr, i64 32 %dst:gpr = SRL_ri %1, i64 32

Custom Selection

GlobalISel Tutorial • LLVM Dev Meeting 2017171

MachineIRBuilder Builder(I); auto MIB = Builder.buildInstr(BPF::SLL_ri, &BPF::GPRRegClass) .add(*LHS) .addImm(32); constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);

Page 172: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%0:anygpr = G_CONSTANT i64 0xffffffff %dst:anygpr = G_AND %src:anygpr, %0 %1:gpr = SLL_ri %src:gpr, i64 32 %dst:gpr = SRL_ri %1, i64 32%1:gpr = SLL_ri %src:gpr, i64 32 %dst:gpr = SRL_ri %1, i64 32%dst:gpr = SRL_ri %1, i64 32

Custom Selection

GlobalISel Tutorial • LLVM Dev Meeting 2017172

MIB = Builder.buildInstr(BPF::SRL_ri) .add(*Dst) .addUse(MIB->getOperand(0).getReg()) .addImm(32); constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);

Page 173: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%0:anygpr = G_CONSTANT i64 0xffffffff %dst:anygpr = G_AND %src:anygpr, %0 %1:gpr = SLL_ri %src:gpr, i64 32 %dst:gpr = SRL_ri %1, i64 32%1:gpr = SLL_ri %src:gpr, i64 32 %dst:gpr = SRL_ri %1, i64 32%dst:gpr = SRL_ri %1, i64 32

Custom Selection

GlobalISel Tutorial • LLVM Dev Meeting 2017173

I.eraseFromParent(); return true;

Page 174: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

%0:anygpr = G_CONSTANT i64 0xffffffff %dst:anygpr = G_AND %src:anygpr, %0 %1:gpr = SLL_ri %src:gpr, i64 32 %dst:gpr = SRL_ri %1, i64 32%1:gpr = SLL_ri %src:gpr, i64 32 %dst:gpr = SRL_ri %1, i64 32%dst:gpr = SRL_ri %1, i64 32

Custom Selection

GlobalISel Tutorial • LLVM Dev Meeting 2017174

Dead code is automatically cleared away

Page 175: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

What's Left?

GlobalISel Tutorial • LLVM Dev Meeting 2017175

112

50

14

Skipped ImportedIn Development C++

Page 176: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

Questions?

GlobalISel Tutorial • LLVM Dev Meeting 2017176

Page 177: Head First into GlobalISel - LLVMllvm.org/devmtg/2017-10/slides/Bogner-Nandakumar-Sanders-Head First... · Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits

177 GlobalISel Tutorial • LLVM Dev Meeting 2017