Head First into GlobalISel Or: How to delete SelectionDAG in 100* - - PowerPoint PPT Presentation

head first into globalisel
SMART_READER_LITE
LIVE PREVIEW

Head First into GlobalISel Or: How to delete SelectionDAG in 100* - - PowerPoint PPT Presentation

Head First into GlobalISel Or: How to delete SelectionDAG in 100* easy commits 1 LLVM Dev Meeting 2017 Justin Bogner, Aditya Nandakumar, Daniel Sanders Apple Porting to GlobalISel What is the structure of a GlobalISel backend? How


slide-1
SLIDE 1

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

slide-2
SLIDE 2

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 2017 2

slide-3
SLIDE 3

A Simple Backend

GlobalISel Tutorial • LLVM Dev Meeting 2017 3

Lines of Code

AArch64 50000

slide-4
SLIDE 4

A Simple Backend

GlobalISel Tutorial • LLVM Dev Meeting 2017 4

Lines of Code

AArch64 ARM 50000

slide-5
SLIDE 5

A Simple Backend

GlobalISel Tutorial • LLVM Dev Meeting 2017 5

Lines of Code

AArch64 ARM X86 50000

slide-6
SLIDE 6

A Simple Backend

GlobalISel Tutorial • LLVM Dev Meeting 2017 6

Lines of Code

AArch64 ARM X86 AMDGPU 50000

slide-7
SLIDE 7

A Simple Backend

GlobalISel Tutorial • LLVM Dev Meeting 2017 7

Lines of Code

AArch64 ARM X86 AMDGPU BPF 50000 3000

slide-8
SLIDE 8

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 2017 8

slide-9
SLIDE 9

Anatomy of GlobalISel

GlobalISel Tutorial • LLVM Dev Meeting 2017 9

irtranslator legalizer regbankselect instruction-select

slide-10
SLIDE 10

Anatomy of GlobalISel

GlobalISel Tutorial • LLVM Dev Meeting 2017 10

irtranslator legalizer regbankselect instruction-select CallLowering LegalizerInfo InstructionSelector RegBankInfo

slide-11
SLIDE 11

Implementing GlobalISel

GlobalISel Tutorial • LLVM Dev Meeting 2017 11

irtranslator legalizer regbankselect instruction-select Wire up GISel CallLowering LegalizerInfo InstructionSelector RegBankInfo TargetMachine/SubTarget

slide-12
SLIDE 12

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 2017 12

slide-13
SLIDE 13

MIR Example

GlobalISel Tutorial • LLVM Dev Meeting 2017 13

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

slide-14
SLIDE 14

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 2017 14

%1:_(s64) = COPY %r1

slide-15
SLIDE 15

%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 2017 15

%1:_(s64) = COPY %r1

slide-16
SLIDE 16

MIR Testing

Don't match register numbers directly

GlobalISel Tutorial • LLVM Dev Meeting 2017 16

; 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

slide-17
SLIDE 17

Wire up GlobalISel

GlobalISel Tutorial • LLVM Dev Meeting 2017 17

irtranslator legalizer regbankselect instruction-select Wire up GISel CallLowering LegalizerInfo InstructionSelector RegBankInfo TargetMachine/SubTarget

slide-18
SLIDE 18

Subtarget Setup

Override GlobalISel API getters by backing with unique_ptrs

GlobalISel Tutorial • LLVM Dev Meeting 2017 18

BPFSubtarget : BPFGenSubtargetInfo getCallLowering(...) getRegBankInfo(...) getLegalizerInfo(...) getInstructionSelector(...)

slide-19
SLIDE 19

Initialize GlobalISel

GlobalISel Tutorial • LLVM Dev Meeting 2017 19

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

slide-20
SLIDE 20

Initialize GlobalISel Passes

Implement the hooks to provide the required passes

GlobalISel Tutorial • LLVM Dev Meeting 2017 20

BPFPassConfig : TargetPassConfig addIRTranslator(...) addLegalizeMachineIR(...) addRegBankSelect(...) addGlobalInstructionSelect(...)

slide-21
SLIDE 21

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

Initialize GlobalISel Passes

Optionally add extra passes in between

GlobalISel Tutorial • LLVM Dev Meeting 2017 21

BPFPassConfig : TargetPassConfig addPreLegalizeMachineIR(...) addPreRegBankSelect(...) addPreGlobalInstructionSelect(...)

slide-22
SLIDE 22

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 2017 22

slide-23
SLIDE 23

Does Anything Work Yet?

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 23

define void @f() { ret void }

slide-24
SLIDE 24

Does Anything Work Yet?

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 24 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

slide-25
SLIDE 25

The IR Translator

GlobalISel Tutorial • LLVM Dev Meeting 2017 25

irtranslator legalizer regbankselect instruction-select Wiring up GISel CallLowering LegalizerInfo InstructionSelector RegBankInfo TargetMachine/SubTarget

slide-26
SLIDE 26

Call Lowering

GlobalISel Tutorial • LLVM Dev Meeting 2017 26

IRTranslator

Uses

CallLowering

BPFCallLowering : CallLowering lowerReturn(...) lowerFormalArguments(...) lowerCall(...)

slide-27
SLIDE 27

Sketch Call Lowering

GlobalISel Tutorial • LLVM Dev Meeting 2017 27

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

slide-28
SLIDE 28

Does Anything Work Yet?

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 28

define void @f() { ret void }

slide-29
SLIDE 29

Does Anything Work Yet?

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 29

name: test_void body: | bb.0: RET

slide-30
SLIDE 30

Does Anything Work Yet?

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 30

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

slide-31
SLIDE 31

Value Handlers

  • Arg handling is mostly uniform
  • Decide where the arg/return goes
  • Exact details vary
  • ValueHandler abstracts differences

GlobalISel Tutorial • LLVM Dev Meeting 2017 31

IRTranslator CallLowering ValueHandler

handleAssignments lower

slide-32
SLIDE 32

Value Handlers

GlobalISel Tutorial • LLVM Dev Meeting 2017 32

BPFHandler : ValueHandler getStackAddress(…) assignValueToAddress(…) assignValueToReg(…)

slide-33
SLIDE 33

BPF Calling Convention

We'll ignore stack handling

GlobalISel Tutorial • LLVM Dev Meeting 2017 33

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

slide-34
SLIDE 34

Argument Handling

GlobalISel Tutorial • LLVM Dev Meeting 2017 34

FormalArgHandler : BPFHandler assignValueToReg(...)

slide-35
SLIDE 35

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

slide-36
SLIDE 36

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

slide-37
SLIDE 37

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

slide-38
SLIDE 38

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

slide-39
SLIDE 39

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

slide-40
SLIDE 40

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 2017 40

slide-41
SLIDE 41

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 2017 41

slide-42
SLIDE 42

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 2017 42

slide-43
SLIDE 43

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 2017 43

slide-44
SLIDE 44

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 2017 44

slide-45
SLIDE 45

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 2017 45

slide-46
SLIDE 46

Test Lowering

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 46

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

slide-47
SLIDE 47

Test Lowering

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 47

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

slide-48
SLIDE 48

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

Lower Return

GlobalISel Tutorial • LLVM Dev Meeting 2017 48

slide-49
SLIDE 49

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 2017 49

slide-50
SLIDE 50

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 2017 50

slide-51
SLIDE 51

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 2017 51

slide-52
SLIDE 52

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 2017 52

slide-53
SLIDE 53

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 2017 53

slide-54
SLIDE 54

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 2017 54

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

InsertPt RET

slide-55
SLIDE 55

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 2017 55

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

InsertPt RET

slide-56
SLIDE 56

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 2017 56

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

InsertPt RET implicit %r0

slide-57
SLIDE 57

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 2017 57

%0:_(s64) = COPY %r1 …G_ADD… … %1:_(s64) = G_ANYEXT %VReg %r0 = COPY %1

InsertPt RET implicit %r0

slide-58
SLIDE 58

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 2017 58

%0:_(s64) = COPY %r1 …G_ADD… … %1:_(s64) = G_ANYEXT %VReg %r0 = COPY %1 BPF::RET implicit %r0

InsertPt

slide-59
SLIDE 59

Test ArgLowering

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 59

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

slide-60
SLIDE 60

Test ArgLowering

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 60

; 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 }

slide-61
SLIDE 61

Register Banks

GlobalISel Tutorial • LLVM Dev Meeting 2017 61

irtranslator legalizer regbankselect instruction-select Wiring up GISel CallLowering LegalizerInfo InstructionSelector RegBankInfo TargetMachine/SubTarget

slide-62
SLIDE 62

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 2017 62

slide-63
SLIDE 63

Define Register Banks

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 63

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

slide-64
SLIDE 64

More Register Classes

AArch64 is a good example with more register classes

GlobalISel Tutorial • LLVM Dev Meeting 2017 64

GPR32 GPR32sp GPR32common GPR32all GPR32sponly tcGPR64 GPR64 GPR64sp GPR64common GPR64all GPR64sponly CCR FPR8 FPR16 FPR32 FPR64 DD FPR128 DDD DDDD QQ QQQ QQQQ

slide-65
SLIDE 65

AArch64 Register Banks

GlobalISel Tutorial • LLVM Dev Meeting 2017 65

GPR32 GPR32sp GPR32common GPR32all GPR32sponly tcGPR64 GPR64 GPR64sp GPR64common GPR64all GPR64sponly

GPR FPR CC

CCR FPR8 FPR16 FPR32 FPR64 DD FPR128 DDD DDDD QQ QQQ QQQQ

slide-66
SLIDE 66

AArch64 Register Banks

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 66

/// 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]>;

slide-67
SLIDE 67

Generated Bank Info

GlobalISel Tutorial • LLVM Dev Meeting 2017 67

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

slide-68
SLIDE 68

Register Bank Mapping

GlobalISel Tutorial • LLVM Dev Meeting 2017 68

BPFRegisterBankInfo : BPFGenRegisterBankInfo getRegBankFromRegClass(...) getInstrMapping(...) getInstrAlternativeMappings(...)

slide-69
SLIDE 69

Register Bank Mapping

Given a register class, return the register bank

GlobalISel Tutorial • LLVM Dev Meeting 2017 69

BPFRegisterBankInfo : BPFGenRegisterBankInfo getRegBankFromRegClass(...) getInstrMapping(...) getInstrAlternativeMappings(...)

slide-70
SLIDE 70

Register Bank Mapping

GlobalISel Tutorial • LLVM Dev Meeting 2017 70

BPFRegisterBankInfo : BPFGenRegisterBankInfo getRegBankFromRegClass(...) getInstrMapping(...) getInstrAlternativeMappings(...)

slide-71
SLIDE 71

getInstrMapping

Leverage getInstrMappingImpl to handle generic instructions

GlobalISel Tutorial • LLVM Dev Meeting 2017 71

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

slide-72
SLIDE 72

getInstrMapping

Map each operand to an appropriate bank for target instructions

GlobalISel Tutorial • LLVM Dev Meeting 2017 72

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); } }

slide-73
SLIDE 73

Test Bank Selection

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 73

; 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

slide-74
SLIDE 74

getInstrAlternativeMappings

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 74

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; }

slide-75
SLIDE 75

getInstrAlternativeMappings

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 75

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; }

slide-76
SLIDE 76

getInstrAlternativeMappings

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 76

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; }

slide-77
SLIDE 77

Legalizer

GlobalISel Tutorial • LLVM Dev Meeting 2017 77

irtranslator legalizer regbankselect instruction-select Wiring up GISel CallLowering LegalizerInfo InstructionSelector RegBankInfo TargetMachine/SubTarget

slide-78
SLIDE 78

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 2017 78

slide-79
SLIDE 79

Legalization

GlobalISel Tutorial • LLVM Dev Meeting 2017 79

Legalizer LegalizerHelper

Uses Uses

LegalizerInfo

Pass Drives Legalization Specifies Legality Helpers for Common Operations

slide-80
SLIDE 80

Legality Specifiers

GlobalISel Tutorial • LLVM Dev Meeting 2017 80

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

slide-81
SLIDE 81

Legality Specifiers

GlobalISel Tutorial • LLVM Dev Meeting 2017 81

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

slide-82
SLIDE 82

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 2017 82

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

slide-83
SLIDE 83

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 2017 83

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

slide-84
SLIDE 84

%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 2017 84

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

slide-85
SLIDE 85

Legalization in BPF

  • Set LegalizerAction in the constructor.
  • Implement legalizeCustom for custom hook if required.

GlobalISel Tutorial • LLVM Dev Meeting 2017 85

slide-86
SLIDE 86

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 2017 86

slide-87
SLIDE 87

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 2017 87

slide-88
SLIDE 88

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 2017 88

slide-89
SLIDE 89

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 2017 89

slide-90
SLIDE 90

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 2017 90

slide-91
SLIDE 91

Test Legalizer

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 91

; 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

slide-92
SLIDE 92

Test Legalizer

LLVM ERROR: unable to legalize instruction

GlobalISel Tutorial • LLVM Dev Meeting 2017 92

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

slide-93
SLIDE 93

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

BPFLegalizerInfo

GlobalISel Tutorial • LLVM Dev Meeting 2017 93

slide-94
SLIDE 94

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

BPFLegalizerInfo

GlobalISel Tutorial • LLVM Dev Meeting 2017 94

slide-95
SLIDE 95

Test Legalizer

GlobalISel Tutorial • LLVM Dev Meeting 2017 95

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

slide-96
SLIDE 96

Test Legalizer

GlobalISel Tutorial • LLVM Dev Meeting 2017 96

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

slide-97
SLIDE 97

Custom Legalization

  • Implement legalizeCustom method
  • Specify LegalizationAction as Custom
  • Legalize G_SELECT into pseudo instruction (BPF_SELECT_CC)

GlobalISel Tutorial • LLVM Dev Meeting 2017 97

slide-98
SLIDE 98

%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 2017 98

slide-99
SLIDE 99

%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 2017 99

slide-100
SLIDE 100

Custom Legalization

GlobalISel Tutorial • LLVM Dev Meeting 2017 100

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", []>;

slide-101
SLIDE 101

Custom Legalization

GlobalISel Tutorial • LLVM Dev Meeting 2017 101

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

slide-102
SLIDE 102

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017 102

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

slide-103
SLIDE 103

legalizeCustom

GlobalISel Tutorial • LLVM Dev Meeting 2017 103

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

slide-104
SLIDE 104

%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 2017 104

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);

slide-105
SLIDE 105

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 2017 105

slide-106
SLIDE 106

%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 2017 106

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;

slide-107
SLIDE 107

%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 2017 107

slide-108
SLIDE 108

%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 2017 108

slide-109
SLIDE 109

%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 2017 109

slide-110
SLIDE 110

%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 2017 110

slide-111
SLIDE 111

%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 2017 111

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

slide-112
SLIDE 112

%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 2017 112

slide-113
SLIDE 113

%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 2017 113

slide-114
SLIDE 114

%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 2017 114

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

slide-115
SLIDE 115

%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 2017 115

slide-116
SLIDE 116

%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 2017 116

InsertPt

slide-117
SLIDE 117

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 2017 117

InsertPt

slide-118
SLIDE 118

%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 2017 118

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

slide-119
SLIDE 119

%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 2017 119

InsertPt

slide-120
SLIDE 120

%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 2017 120

InsertPt

slide-121
SLIDE 121

%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 2017 121

InsertPt

slide-122
SLIDE 122

%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 2017 122

InsertPt

slide-123
SLIDE 123

%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 2017 123

MI.eraseFromParent();

InsertPt

slide-124
SLIDE 124

%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 2017 124

MI.eraseFromParent();

InsertPt

slide-125
SLIDE 125

%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 2017 125

auto &RB = MF.getSubtarget() .getRegBankInfo()

  • >getRegBankFromRegClass(BPF::GPRRegClass);

MRI.setRegBank(DstReg, RB);

InsertPt

slide-126
SLIDE 126

%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 2017 126

auto &RB = MF.getSubtarget() .getRegBankInfo()

  • >getRegBankFromRegClass(BPF::GPRRegClass);

MRI.setRegBank(DstReg, RB);

InsertPt

slide-127
SLIDE 127

%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 2017 127

return true;

InsertPt

slide-128
SLIDE 128

; 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 2017 128

slide-129
SLIDE 129

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 2017 129

slide-130
SLIDE 130

Instruction Selector

GlobalISel Tutorial • LLVM Dev Meeting 2017 130

irtranslator legalizer regbankselect instruction-select Wiring up GISel CallLowering LegalizerInfo InstructionSelector RegBankInfo TargetMachine/SubTarget

slide-131
SLIDE 131

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 2017 131

slide-132
SLIDE 132

Instruction Selection

GlobalISel Tutorial • LLVM Dev Meeting 2017 132

Implement select and use the tablegen-erated selectImpl BPFInstructionSelector : InstructionSelector select(...) selectImpl(...)

slide-133
SLIDE 133

Implement select

GlobalISel Tutorial • LLVM Dev Meeting 2017 133

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; }

slide-134
SLIDE 134

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 2017 134

slide-135
SLIDE 135

Initial Imports

GlobalISel Tutorial • LLVM Dev Meeting 2017 135

16 61

Skipped Imported

slide-136
SLIDE 136

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 2017 136

slide-137
SLIDE 137

9 3 3 13 13 20

No equivalent Instruction (BPFISD::BR_CC) Src pattern child has predicate Src pattern root isn't a trivial operator Src pattern results and Dst MI defs differ No equivalent Instruction (BPFISD::CALL) Others

Import Failures

GlobalISel Tutorial • LLVM Dev Meeting 2017 137

slide-138
SLIDE 138

Import PatLeaf

GlobalISel Tutorial • LLVM Dev Meeting 2017 138

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

Src pattern child has predicate (i64immSExt32)

slide-139
SLIDE 139

Imm

Import PatLeaf

GlobalISel Tutorial • LLVM Dev Meeting 2017 139

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

Use int64_t instead of SDNode

slide-140
SLIDE 140

Pat

Import PatLeaf

Src pattern child has predicate (BPF_CC_EQ)

GlobalISel Tutorial • LLVM Dev Meeting 2017 140

def BPF_CC_EQ : Leaf<i64, [{return N

  • >getZExtValue() == ISD::SETEQ;}]>;

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

slide-141
SLIDE 141

Import PatLeaf

Use APInt instead of SDNode

GlobalISel Tutorial • LLVM Dev Meeting 2017 141

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

  • >getZExtValue() == ISD::SETEQ;}]>;

Leaf<i64, [{return

slide-142
SLIDE 142

; 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 2017 142

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

slide-143
SLIDE 143

Import PatLeaf

GlobalISel Tutorial • LLVM Dev Meeting 2017 143

27 50

Skipped Imported

slide-144
SLIDE 144

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 2017 144

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

slide-145
SLIDE 145

Map Custom ISD Nodes

GlobalISel Tutorial • LLVM Dev Meeting 2017 145

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)

slide-146
SLIDE 146

Map Custom ISD Nodes

GlobalISel Tutorial • LLVM Dev Meeting 2017 146

49 28

Skipped Imported

slide-147
SLIDE 147

5 1 1 3 6 12

Src pattern root isn't a trivial operator Src pattern results and dst MI defs are different No equivalent Instruction (BPFISD::CALL) Unable to deduce gMIR opcode to handle Src ComplexPattern (ADDRri) not mapped Others

Import Failures

GlobalISel Tutorial • LLVM Dev Meeting 2017 147

slide-148
SLIDE 148

Import ComplexPattern

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 148

slide-149
SLIDE 149

Patterns To Match

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 149

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

slide-150
SLIDE 150

Cases To Handle

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 150

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

slide-151
SLIDE 151

G_FRAME_INDEX

GlobalISel Tutorial • LLVM Dev Meeting 2017 151

%Root G_FRAME_INDEX %fixedstack.0 getVRegDef getOperand

slide-152
SLIDE 152

G_FRAME_INDEX

GlobalISel Tutorial • LLVM Dev Meeting 2017 152

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

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

slide-153
SLIDE 153

isBaseWithConstantOffset(Root, MRI)

Base + Offset

GlobalISel Tutorial • LLVM Dev Meeting 2017 153

G_GEP G_CONSTANT simm16 %Root %1 %0 getVRegDef getOperand

slide-154
SLIDE 154

Base + Offset

GlobalISel Tutorial • LLVM Dev Meeting 2017 154

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

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

slide-155
SLIDE 155

G_GLOBAL_VALUE

155

G_GLOBAL_VALUE %Root getVRegDef

return None;

slide-156
SLIDE 156

Any Pointer

GlobalISel Tutorial • LLVM Dev Meeting 2017 156

%Root

slide-157
SLIDE 157

Any Pointer

GlobalISel Tutorial • LLVM Dev Meeting 2017 157

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

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

slide-158
SLIDE 158

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

Common Predicates

GlobalISel Tutorial • LLVM Dev Meeting 2017 158

slide-159
SLIDE 159

Good Practices

GlobalISel Tutorial • LLVM Dev Meeting 2017 159

✗ Don't modify MIR in the predicate ✓Capture locals by value in a renderer lambda ✓Only create instructions in a renderer lambda

slide-160
SLIDE 160

Import ComplexPattern

GlobalISel Tutorial • LLVM Dev Meeting 2017 160

50 27

Skipped Imported

slide-161
SLIDE 161

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 2017 161

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

slide-162
SLIDE 162

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 2017 162

Development for multiple instruction emission will start soon

slide-163
SLIDE 163

Custom Selection

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 163

slide-164
SLIDE 164

Rule Priority

GlobalISel Tutorial • LLVM Dev Meeting 2017 164

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; }

slide-165
SLIDE 165

Rule Priority

GlobalISel Tutorial • LLVM Dev Meeting 2017 165

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; }

slide-166
SLIDE 166

Rule Priority

GlobalISel Tutorial • LLVM Dev Meeting 2017 166

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; }

slide-167
SLIDE 167

Test Custom Selection

GlobalISel Tutorial • LLVM Dev Meeting 2017 167

; 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

slide-168
SLIDE 168

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 2017 168

%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

slide-169
SLIDE 169

Custom Selection

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

GlobalISel Tutorial • LLVM Dev Meeting 2017 169

%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

slide-170
SLIDE 170

%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 2017 170

slide-171
SLIDE 171

%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 2017 171

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

slide-172
SLIDE 172

%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 2017 172

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

slide-173
SLIDE 173

%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 2017 173

I.eraseFromParent(); return true;

slide-174
SLIDE 174

%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 2017 174

Dead code is automatically cleared away

slide-175
SLIDE 175

What's Left?

GlobalISel Tutorial • LLVM Dev Meeting 2017 175

1 12 50 14

Skipped Imported In Development C++

slide-176
SLIDE 176

Questions?

GlobalISel Tutorial • LLVM Dev Meeting 2017 176

slide-177
SLIDE 177

177 GlobalISel Tutorial • LLVM Dev Meeting 2017