diff options
Diffstat (limited to 'llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp')
-rw-r--r-- | llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp | 163 |
1 files changed, 156 insertions, 7 deletions
diff --git a/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp b/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp index 9c689aed6417..5310f0f07b65 100644 --- a/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp +++ b/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp @@ -53,6 +53,19 @@ private: void initialize(MachineFunction &MFParm); bool removeLD(void); + void processCandidate(MachineRegisterInfo *MRI, MachineBasicBlock &MBB, + MachineInstr &MI, Register &SrcReg, Register &DstReg, + const GlobalValue *GVal); + void processDstReg(MachineRegisterInfo *MRI, Register &DstReg, + Register &SrcReg, const GlobalValue *GVal, + bool doSrcRegProp); + void processInst(MachineRegisterInfo *MRI, MachineInstr *Inst, + MachineOperand *RelocOp, const GlobalValue *GVal); + void checkADDrr(MachineRegisterInfo *MRI, MachineOperand *RelocOp, + const GlobalValue *GVal); + void checkShift(MachineRegisterInfo *MRI, MachineBasicBlock &MBB, + MachineOperand *RelocOp, const GlobalValue *GVal, + unsigned Opcode); public: // Main entry point for this pass. @@ -71,6 +84,146 @@ void BPFMISimplifyPatchable::initialize(MachineFunction &MFParm) { LLVM_DEBUG(dbgs() << "*** BPF simplify patchable insts pass ***\n\n"); } +void BPFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI, + MachineOperand *RelocOp, const GlobalValue *GVal) { + const MachineInstr *Inst = RelocOp->getParent(); + const MachineOperand *Op1 = &Inst->getOperand(1); + const MachineOperand *Op2 = &Inst->getOperand(2); + const MachineOperand *BaseOp = (RelocOp == Op1) ? Op2 : Op1; + + // Go through all uses of %1 as in %1 = ADD_rr %2, %3 + const MachineOperand Op0 = Inst->getOperand(0); + auto Begin = MRI->use_begin(Op0.getReg()), End = MRI->use_end(); + decltype(End) NextI; + for (auto I = Begin; I != End; I = NextI) { + NextI = std::next(I); + // The candidate needs to have a unique definition. + if (!MRI->getUniqueVRegDef(I->getReg())) + continue; + + MachineInstr *DefInst = I->getParent(); + unsigned Opcode = DefInst->getOpcode(); + unsigned COREOp; + if (Opcode == BPF::LDB || Opcode == BPF::LDH || Opcode == BPF::LDW || + Opcode == BPF::LDD || Opcode == BPF::STB || Opcode == BPF::STH || + Opcode == BPF::STW || Opcode == BPF::STD) + COREOp = BPF::CORE_MEM; + else if (Opcode == BPF::LDB32 || Opcode == BPF::LDH32 || + Opcode == BPF::LDW32 || Opcode == BPF::STB32 || + Opcode == BPF::STH32 || Opcode == BPF::STW32) + COREOp = BPF::CORE_ALU32_MEM; + else + continue; + + // It must be a form of %1 = *(type *)(%2 + 0) or *(type *)(%2 + 0) = %1. + const MachineOperand &ImmOp = DefInst->getOperand(2); + if (!ImmOp.isImm() || ImmOp.getImm() != 0) + continue; + + BuildMI(*DefInst->getParent(), *DefInst, DefInst->getDebugLoc(), TII->get(COREOp)) + .add(DefInst->getOperand(0)).addImm(Opcode).add(*BaseOp) + .addGlobalAddress(GVal); + DefInst->eraseFromParent(); + } +} + +void BPFMISimplifyPatchable::checkShift(MachineRegisterInfo *MRI, + MachineBasicBlock &MBB, MachineOperand *RelocOp, const GlobalValue *GVal, + unsigned Opcode) { + // Relocation operand should be the operand #2. + MachineInstr *Inst = RelocOp->getParent(); + if (RelocOp != &Inst->getOperand(2)) + return; + + BuildMI(MBB, *Inst, Inst->getDebugLoc(), TII->get(BPF::CORE_SHIFT)) + .add(Inst->getOperand(0)).addImm(Opcode) + .add(Inst->getOperand(1)).addGlobalAddress(GVal); + Inst->eraseFromParent(); +} + +void BPFMISimplifyPatchable::processCandidate(MachineRegisterInfo *MRI, + MachineBasicBlock &MBB, MachineInstr &MI, Register &SrcReg, + Register &DstReg, const GlobalValue *GVal) { + if (MRI->getRegClass(DstReg) == &BPF::GPR32RegClass) { + // We can optimize such a pattern: + // %1:gpr = LD_imm64 @"llvm.s:0:4$0:2" + // %2:gpr32 = LDW32 %1:gpr, 0 + // %3:gpr = SUBREG_TO_REG 0, %2:gpr32, %subreg.sub_32 + // %4:gpr = ADD_rr %0:gpr, %3:gpr + // or similar patterns below for non-alu32 case. + auto Begin = MRI->use_begin(DstReg), End = MRI->use_end(); + decltype(End) NextI; + for (auto I = Begin; I != End; I = NextI) { + NextI = std::next(I); + if (!MRI->getUniqueVRegDef(I->getReg())) + continue; + + unsigned Opcode = I->getParent()->getOpcode(); + if (Opcode == BPF::SUBREG_TO_REG) { + Register TmpReg = I->getParent()->getOperand(0).getReg(); + processDstReg(MRI, TmpReg, DstReg, GVal, false); + } + } + + BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(BPF::COPY), DstReg) + .addReg(SrcReg, 0, BPF::sub_32); + return; + } + + // All uses of DstReg replaced by SrcReg + processDstReg(MRI, DstReg, SrcReg, GVal, true); +} + +void BPFMISimplifyPatchable::processDstReg(MachineRegisterInfo *MRI, + Register &DstReg, Register &SrcReg, const GlobalValue *GVal, + bool doSrcRegProp) { + auto Begin = MRI->use_begin(DstReg), End = MRI->use_end(); + decltype(End) NextI; + for (auto I = Begin; I != End; I = NextI) { + NextI = std::next(I); + if (doSrcRegProp) + I->setReg(SrcReg); + + // The candidate needs to have a unique definition. + if (MRI->getUniqueVRegDef(I->getReg())) + processInst(MRI, I->getParent(), &*I, GVal); + } +} + +// Check to see whether we could do some optimization +// to attach relocation to downstream dependent instructions. +// Two kinds of patterns are recognized below: +// Pattern 1: +// %1 = LD_imm64 @"llvm.b:0:4$0:1" <== patch_imm = 4 +// %2 = LDD %1, 0 <== this insn will be removed +// %3 = ADD_rr %0, %2 +// %4 = LDW[32] %3, 0 OR STW[32] %4, %3, 0 +// The `%4 = ...` will be transformed to +// CORE_[ALU32_]MEM(%4, mem_opcode, %0, @"llvm.b:0:4$0:1") +// and later on, BTF emit phase will translate to +// %4 = LDW[32] %0, 4 STW[32] %4, %0, 4 +// and attach a relocation to it. +// Pattern 2: +// %15 = LD_imm64 @"llvm.t:5:63$0:2" <== relocation type 5 +// %16 = LDD %15, 0 <== this insn will be removed +// %17 = SRA_rr %14, %16 +// The `%17 = ...` will be transformed to +// %17 = CORE_SHIFT(SRA_ri, %14, @"llvm.t:5:63$0:2") +// and later on, BTF emit phase will translate to +// %r4 = SRA_ri %r4, 63 +void BPFMISimplifyPatchable::processInst(MachineRegisterInfo *MRI, + MachineInstr *Inst, MachineOperand *RelocOp, const GlobalValue *GVal) { + unsigned Opcode = Inst->getOpcode(); + if (Opcode == BPF::ADD_rr) + checkADDrr(MRI, RelocOp, GVal); + else if (Opcode == BPF::SLL_rr) + checkShift(MRI, *Inst->getParent(), RelocOp, GVal, BPF::SLL_ri); + else if (Opcode == BPF::SRA_rr) + checkShift(MRI, *Inst->getParent(), RelocOp, GVal, BPF::SRA_ri); + else if (Opcode == BPF::SRL_rr) + checkShift(MRI, *Inst->getParent(), RelocOp, GVal, BPF::SRL_ri); +} + /// Remove unneeded Load instructions. bool BPFMISimplifyPatchable::removeLD() { MachineRegisterInfo *MRI = &MF->getRegInfo(); @@ -105,10 +258,11 @@ bool BPFMISimplifyPatchable::removeLD() { continue; bool IsCandidate = false; + const GlobalValue *GVal = nullptr; if (DefInst->getOpcode() == BPF::LD_imm64) { const MachineOperand &MO = DefInst->getOperand(1); if (MO.isGlobal()) { - const GlobalValue *GVal = MO.getGlobal(); + GVal = MO.getGlobal(); auto *GVar = dyn_cast<GlobalVariable>(GVal); if (GVar) { // Global variables representing structure offset or @@ -124,12 +278,7 @@ bool BPFMISimplifyPatchable::removeLD() { if (!IsCandidate) continue; - auto Begin = MRI->use_begin(DstReg), End = MRI->use_end(); - decltype(End) NextI; - for (auto I = Begin; I != End; I = NextI) { - NextI = std::next(I); - I->setReg(SrcReg); - } + processCandidate(MRI, MBB, MI, SrcReg, DstReg, GVal); ToErase = &MI; Changed = true; |