43#define DEBUG_TYPE "bpf-mi-simplify-patchable"
47 cl::desc(
"Disable CORE relocation optimization"));
60 std::set<MachineInstr *> SkipInsts;
65 bool isLoadInst(
unsigned Opcode);
67 void processCandidate(MachineRegisterInfo *MRI, MachineBasicBlock &
MBB,
69 const GlobalValue *GVal,
bool IsAma);
70 void processDstReg(MachineRegisterInfo *MRI,
Register &DstReg,
71 Register &SrcReg,
const GlobalValue *GVal,
72 bool doSrcRegProp,
bool IsAma);
73 void processInst(MachineRegisterInfo *MRI, MachineInstr *Inst,
74 MachineOperand *RelocOp,
const GlobalValue *GVal);
75 void checkADDrr(MachineRegisterInfo *MRI, MachineOperand *RelocOp,
76 const GlobalValue *GVal);
77 void checkShift(MachineRegisterInfo *MRI, MachineBasicBlock &
MBB,
78 MachineOperand *RelocOp,
const GlobalValue *GVal,
83 bool runOnMachineFunction(MachineFunction &MF)
override {
84 if (skipFunction(MF.getFunction()))
96 LLVM_DEBUG(
dbgs() <<
"*** BPF simplify patchable insts pass ***\n\n");
99static bool isStoreImm(
unsigned Opcode) {
100 return Opcode == BPF::STB_imm || Opcode == BPF::STH_imm ||
101 Opcode == BPF::STW_imm || Opcode == BPF::STD_imm;
104static bool isStore32(
unsigned Opcode) {
105 return Opcode == BPF::STB32 || Opcode == BPF::STH32 || Opcode == BPF::STW32 ||
106 Opcode == BPF::STBREL32 || Opcode == BPF::STHREL32 ||
107 Opcode == BPF::STWREL32;
110static bool isStore64(
unsigned Opcode) {
111 return Opcode == BPF::STB || Opcode == BPF::STH || Opcode == BPF::STW ||
112 Opcode == BPF::STD || Opcode == BPF::STDREL;
115static bool isLoad32(
unsigned Opcode) {
116 return Opcode == BPF::LDB32 || Opcode == BPF::LDH32 || Opcode == BPF::LDW32 ||
117 Opcode == BPF::LDBACQ32 || Opcode == BPF::LDHACQ32 ||
118 Opcode == BPF::LDWACQ32;
121static bool isLoad64(
unsigned Opcode) {
122 return Opcode == BPF::LDB || Opcode == BPF::LDH || Opcode == BPF::LDW ||
123 Opcode == BPF::LDD || Opcode == BPF::LDDACQ;
126static bool isLoadSext(
unsigned Opcode) {
127 return Opcode == BPF::LDBSX || Opcode == BPF::LDHSX || Opcode == BPF::LDWSX;
130bool BPFMISimplifyPatchable::isLoadInst(
unsigned Opcode) {
131 return isLoad32(Opcode) || isLoad64(Opcode) || isLoadSext(Opcode);
134void BPFMISimplifyPatchable::checkADDrr(MachineRegisterInfo *MRI,
135 MachineOperand *RelocOp,
const GlobalValue *GVal) {
136 const MachineInstr *Inst = RelocOp->
getParent();
137 const MachineOperand *Op1 = &Inst->
getOperand(1);
138 const MachineOperand *Op2 = &Inst->
getOperand(2);
139 const MachineOperand *BaseOp = (RelocOp == Op1) ? Op2 : Op1;
142 const MachineOperand Op0 = Inst->
getOperand(0);
143 for (MachineOperand &MO :
149 MachineInstr *DefInst = MO.getParent();
152 if (isLoad64(Opcode) || isLoadSext(Opcode))
153 COREOp = BPF::CORE_LD64;
154 else if (isLoad32(Opcode))
155 COREOp = BPF::CORE_LD32;
156 else if (isStore64(Opcode) || isStore32(Opcode) || isStoreImm(Opcode))
157 COREOp = BPF::CORE_ST;
162 const MachineOperand &ImmOp = DefInst->
getOperand(2);
169 if (isStore64(Opcode) || isStore32(Opcode)) {
170 const MachineOperand &Opnd = DefInst->
getOperand(0);
182void BPFMISimplifyPatchable::checkShift(MachineRegisterInfo *MRI,
183 MachineBasicBlock &
MBB, MachineOperand *RelocOp,
const GlobalValue *GVal,
186 MachineInstr *Inst = RelocOp->
getParent();
196void BPFMISimplifyPatchable::processCandidate(MachineRegisterInfo *MRI,
198 Register &DstReg,
const GlobalValue *GVal,
bool IsAma) {
199 if (MRI->
getRegClass(DstReg) == &BPF::GPR32RegClass) {
209 for (
auto I = Begin;
I != End;
I = NextI) {
210 NextI = std::next(
I);
214 unsigned Opcode =
I->getParent()->getOpcode();
215 if (Opcode == BPF::SUBREG_TO_REG) {
216 Register TmpReg =
I->getParent()->getOperand(0).getReg();
217 processDstReg(MRI, TmpReg, DstReg, GVal,
false, IsAma);
223 .
addReg(SrcReg, {}, BPF::sub_32);
228 processDstReg(MRI, DstReg, SrcReg, GVal,
true, IsAma);
231void BPFMISimplifyPatchable::processDstReg(MachineRegisterInfo *MRI,
233 bool doSrcRegProp,
bool IsAma) {
236 for (
auto I = Begin;
I != End;
I = NextI) {
237 NextI = std::next(
I);
267 processInst(MRI,
I->getParent(), &*
I, GVal);
292void BPFMISimplifyPatchable::processInst(MachineRegisterInfo *MRI,
293 MachineInstr *Inst, MachineOperand *RelocOp,
const GlobalValue *GVal) {
295 if (isLoadInst(Opcode)) {
296 SkipInsts.insert(Inst);
303 if (Opcode == BPF::ADD_rr) {
305 StringRef AccessPattern = GVal->
getName();
308 size_t SecondColon = AccessPattern.
find_first_of(
':', FirstColon + 1);
309 StringRef PatchImmStr =
310 AccessPattern.
substr(SecondColon + 1, FirstDollar - SecondColon);
311 int PatchImm = std::stoll(std::string(PatchImmStr));
312 if (PatchImm <= INT16_MAX)
313 checkADDrr(MRI, RelocOp, GVal);
317 if (Opcode == BPF::SLL_rr)
318 checkShift(MRI, *Inst->
getParent(), RelocOp, GVal, BPF::SLL_ri);
319 else if (Opcode == BPF::SRA_rr)
320 checkShift(MRI, *Inst->
getParent(), RelocOp, GVal, BPF::SRA_ri);
321 else if (Opcode == BPF::SRL_rr)
322 checkShift(MRI, *Inst->
getParent(), RelocOp, GVal, BPF::SRL_ri);
326bool BPFMISimplifyPatchable::removeLD() {
328 MachineInstr *ToErase =
nullptr;
331 for (MachineBasicBlock &
MBB : *MF) {
332 for (MachineInstr &
MI :
MBB) {
339 if (!isLoadInst(
MI.getOpcode()))
342 if (SkipInsts.find(&
MI) != SkipInsts.end())
345 if (!
MI.getOperand(0).isReg() || !
MI.getOperand(1).isReg())
348 if (!
MI.getOperand(2).isImm() ||
MI.getOperand(2).getImm())
358 if (DefInst->
getOpcode() != BPF::LD_imm64)
361 const MachineOperand &MO = DefInst->
getOperand(1);
365 const GlobalValue *GVal = MO.
getGlobal();
377 processCandidate(MRI,
MBB,
MI, SrcReg, DstReg, GVal, IsAma);
390 "BPF PreEmit SimplifyPatchable",
false,
false)
392char BPFMISimplifyPatchable::
ID = 0;
394 return new BPFMISimplifyPatchable();
static cl::opt< bool > DisableCOREOptimization("disable-bpf-core-optimization", cl::Hidden, cl::desc("Disable CORE relocation optimization"))
const HexagonInstrInfo * TII
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
static constexpr StringRef TypeIdAttr
The attribute attached to globals representing a type id.
static constexpr StringRef AmaAttr
The attribute attached to globals representing a field access.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
const GlobalValue * getGlobal() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
Register getReg() const
getReg - Returns the register number.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
use_iterator use_begin(Register RegNo) const
static use_iterator use_end()
iterator_range< use_iterator > use_operands(Register Reg) const
LLVM_ABI MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
size_t find_first_of(char C, size_t From=0) const
Find the first character in the string that is C, or npos if not found.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createBPFMISimplifyPatchablePass()
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.