46#define DEBUG_TYPE "bpf-mi-simplify-patchable"
50 cl::desc(
"Disable CORE relocation optimization"));
54struct BPFMISimplifyPatchableImpl {
59 std::set<MachineInstr *> SkipInsts;
64 bool isLoadInst(
unsigned Opcode);
71 bool doSrcRegProp,
bool IsAma);
92 BPFMISimplifyPatchableLegacy() : MachineFunctionPass(ID) {}
95 bool runOnMachineFunction(MachineFunction &MF)
override;
102 LLVM_DEBUG(
dbgs() <<
"*** BPF simplify patchable insts pass ***\n\n");
105static bool isStoreImm(
unsigned Opcode) {
106 return Opcode == BPF::STB_imm || Opcode == BPF::STH_imm ||
107 Opcode == BPF::STW_imm || Opcode == BPF::STD_imm;
110static bool isStore32(
unsigned Opcode) {
111 return Opcode == BPF::STB32 || Opcode == BPF::STH32 || Opcode == BPF::STW32 ||
112 Opcode == BPF::STBREL32 || Opcode == BPF::STHREL32 ||
113 Opcode == BPF::STWREL32;
116static bool isStore64(
unsigned Opcode) {
117 return Opcode == BPF::STB || Opcode == BPF::STH || Opcode == BPF::STW ||
118 Opcode == BPF::STD || Opcode == BPF::STDREL;
121static bool isLoad32(
unsigned Opcode) {
122 return Opcode == BPF::LDB32 || Opcode == BPF::LDH32 || Opcode == BPF::LDW32 ||
123 Opcode == BPF::LDBACQ32 || Opcode == BPF::LDHACQ32 ||
124 Opcode == BPF::LDWACQ32;
127static bool isLoad64(
unsigned Opcode) {
128 return Opcode == BPF::LDB || Opcode == BPF::LDH || Opcode == BPF::LDW ||
129 Opcode == BPF::LDD || Opcode == BPF::LDDACQ;
132static bool isLoadSext(
unsigned Opcode) {
133 return Opcode == BPF::LDBSX || Opcode == BPF::LDHSX || Opcode == BPF::LDWSX;
136bool BPFMISimplifyPatchableImpl::isLoadInst(
unsigned Opcode) {
137 return isLoad32(Opcode) || isLoad64(Opcode) || isLoadSext(Opcode);
140void BPFMISimplifyPatchableImpl::checkADDrr(MachineRegisterInfo *MRI,
141 MachineOperand *RelocOp,
142 const GlobalValue *GVal) {
143 const MachineInstr *Inst = RelocOp->
getParent();
144 const MachineOperand *Op1 = &Inst->
getOperand(1);
145 const MachineOperand *Op2 = &Inst->
getOperand(2);
146 const MachineOperand *BaseOp = (RelocOp == Op1) ? Op2 : Op1;
149 const MachineOperand Op0 = Inst->
getOperand(0);
150 for (MachineOperand &MO :
156 MachineInstr *DefInst = MO.getParent();
159 if (isLoad64(Opcode) || isLoadSext(Opcode))
160 COREOp = BPF::CORE_LD64;
161 else if (isLoad32(Opcode))
162 COREOp = BPF::CORE_LD32;
163 else if (isStore64(Opcode) || isStore32(Opcode) || isStoreImm(Opcode))
164 COREOp = BPF::CORE_ST;
169 const MachineOperand &ImmOp = DefInst->
getOperand(2);
176 if (isStore64(Opcode) || isStore32(Opcode)) {
177 const MachineOperand &Opnd = DefInst->
getOperand(0);
189void BPFMISimplifyPatchableImpl::checkShift(MachineRegisterInfo *MRI,
190 MachineBasicBlock &
MBB,
191 MachineOperand *RelocOp,
192 const GlobalValue *GVal,
195 MachineInstr *Inst = RelocOp->
getParent();
205void BPFMISimplifyPatchableImpl::processCandidate(
206 MachineRegisterInfo *MRI, MachineBasicBlock &
MBB, MachineInstr &
MI,
208 if (MRI->
getRegClass(DstReg) == &BPF::GPR32RegClass) {
218 for (
auto I = Begin;
I != End;
I = NextI) {
219 NextI = std::next(
I);
223 unsigned Opcode =
I->getParent()->getOpcode();
224 if (Opcode == BPF::SUBREG_TO_REG) {
225 Register TmpReg =
I->getParent()->getOperand(0).getReg();
226 processDstReg(MRI, TmpReg, DstReg, GVal,
false, IsAma);
232 .
addReg(SrcReg, {}, BPF::sub_32);
237 processDstReg(MRI, DstReg, SrcReg, GVal,
true, IsAma);
240void BPFMISimplifyPatchableImpl::processDstReg(MachineRegisterInfo *MRI,
243 const GlobalValue *GVal,
244 bool doSrcRegProp,
bool IsAma) {
247 for (
auto I = Begin;
I != End;
I = NextI) {
248 NextI = std::next(
I);
278 processInst(MRI,
I->getParent(), &*
I, GVal);
303void BPFMISimplifyPatchableImpl::processInst(MachineRegisterInfo *MRI,
305 MachineOperand *RelocOp,
306 const GlobalValue *GVal) {
308 if (isLoadInst(Opcode)) {
309 SkipInsts.insert(Inst);
316 if (Opcode == BPF::ADD_rr) {
318 StringRef AccessPattern = GVal->
getName();
321 size_t SecondColon = AccessPattern.
find_first_of(
':', FirstColon + 1);
322 StringRef PatchImmStr =
323 AccessPattern.
substr(SecondColon + 1, FirstDollar - SecondColon);
324 int PatchImm = std::stoll(std::string(PatchImmStr));
325 if (PatchImm <= INT16_MAX)
326 checkADDrr(MRI, RelocOp, GVal);
330 if (Opcode == BPF::SLL_rr)
331 checkShift(MRI, *Inst->
getParent(), RelocOp, GVal, BPF::SLL_ri);
332 else if (Opcode == BPF::SRA_rr)
333 checkShift(MRI, *Inst->
getParent(), RelocOp, GVal, BPF::SRA_ri);
334 else if (Opcode == BPF::SRL_rr)
335 checkShift(MRI, *Inst->
getParent(), RelocOp, GVal, BPF::SRL_ri);
339bool BPFMISimplifyPatchableImpl::removeLD() {
341 MachineInstr *ToErase =
nullptr;
344 for (MachineBasicBlock &
MBB : *MF) {
345 for (MachineInstr &
MI :
MBB) {
352 if (!isLoadInst(
MI.getOpcode()))
355 if (SkipInsts.find(&
MI) != SkipInsts.end())
358 if (!
MI.getOperand(0).isReg() || !
MI.getOperand(1).isReg())
361 if (!
MI.getOperand(2).isImm() ||
MI.getOperand(2).getImm())
371 if (DefInst->
getOpcode() != BPF::LD_imm64)
374 const MachineOperand &MO = DefInst->
getOperand(1);
378 const GlobalValue *GVal = MO.
getGlobal();
390 processCandidate(MRI,
MBB,
MI, SrcReg, DstReg, GVal, IsAma);
403 "BPF PreEmit SimplifyPatchable",
false,
false)
405char BPFMISimplifyPatchableLegacy::
ID = 0;
407 return new BPFMISimplifyPatchableLegacy();
410bool BPFMISimplifyPatchableLegacy::runOnMachineFunction(MachineFunction &MF) {
414 BPFMISimplifyPatchableImpl Impl;
415 return Impl.runOnMachineFunction(MF);
421 BPFMISimplifyPatchableImpl Impl;
422 return Impl.runOnMachineFunction(MF)
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.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Represents analyses that only rely on functions' control flow.
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
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
Representation of each machine instruction.
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.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand class - Representation of each machine instruction operand.
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.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
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...
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Wrapper class representing virtual and physical registers.
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.
Pass manager infrastructure for declaring and invalidating analyses.
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.
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...
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createBPFMISimplifyPatchableLegacyPass()