43#define DEBUG_TYPE "bpf-mi-zext-elim"
48STATISTIC(ZExtElemNum,
"Number of zero extension shifts eliminated");
52struct BPFMIPeepholeImpl {
65 bool eliminateZExtSeq();
68 std::set<MachineInstr *> PhiInsns;
78 bool ZExtSeqExist, ZExtExist;
79 ZExtSeqExist = eliminateZExtSeq();
80 ZExtExist = eliminateZExt();
81 return ZExtSeqExist || ZExtExist;
88 BPFMIPeepholeLegacy() : MachineFunctionPass(ID) {}
89 bool runOnMachineFunction(MachineFunction &MF)
override;
97 LLVM_DEBUG(
dbgs() <<
"*** BPF MachineSSA ZEXT Elim peephole pass ***\n\n");
100bool BPFMIPeepholeImpl::isCopyFrom32Def(MachineInstr *CopyMI) {
114 if (!isInsnFrom32Def(DefInsn))
120bool BPFMIPeepholeImpl::isPhiFrom32Def(MachineInstr *PhiMI) {
121 for (
unsigned i = 1, e = PhiMI->
getNumOperands(); i < e; i += 2) {
127 if (PhiDef->
isPHI()) {
128 if (!PhiInsns.insert(PhiDef).second)
130 if (!isPhiFrom32Def(PhiDef))
133 if (PhiDef->
getOpcode() == BPF::COPY && !isCopyFrom32Def(PhiDef))
141bool BPFMIPeepholeImpl::isInsnFrom32Def(MachineInstr *DefInsn) {
145 if (DefInsn->
isPHI()) {
146 if (!PhiInsns.insert(DefInsn).second)
148 if (!isPhiFrom32Def(DefInsn))
150 }
else if (DefInsn->
getOpcode() == BPF::COPY) {
151 if (!isCopyFrom32Def(DefInsn))
158bool BPFMIPeepholeImpl::isMovFrom32Def(MachineInstr *MovMI)
160 const MachineOperand &Src = MovMI->
getOperand(1);
164 MachineInstr *DefInsn = MRI->
getVRegDef(Src.getReg());
170 if (!isInsnFrom32Def(DefInsn))
178bool BPFMIPeepholeImpl::eliminateZExtSeq() {
179 MachineInstr* ToErase =
nullptr;
180 bool Eliminated =
false;
182 for (MachineBasicBlock &
MBB : *MF) {
183 for (MachineInstr &
MI :
MBB) {
195 if (
MI.getOpcode() == BPF::SRL_ri &&
196 MI.getOperand(2).getImm() == 32) {
199 MachineInstr *SllMI = MRI->
getVRegDef(ShfReg);
223 if (!isMovFrom32Def(MovMI)) {
225 <<
" One ZExt elim sequence failed qualifying elim.\n");
247bool BPFMIPeepholeImpl::eliminateZExt() {
248 MachineInstr* ToErase =
nullptr;
249 bool Eliminated =
false;
251 for (MachineBasicBlock &
MBB : *MF) {
252 for (MachineInstr &
MI :
MBB) {
259 if (
MI.getOpcode() != BPF::MOV_32_64)
272 if (!isMovFrom32Def(&
MI))
296 "BPF MachineSSA Peephole Optimization For ZEXT Eliminate",
299char BPFMIPeepholeLegacy::
ID = 0;
301 return new BPFMIPeepholeLegacy();
304bool BPFMIPeepholeLegacy::runOnMachineFunction(MachineFunction &MF) {
308 BPFMIPeepholeImpl Impl;
309 return Impl.runOnMachineFunction(MF);
314 BPFMIPeepholeImpl Impl;
315 return Impl.runOnMachineFunction(MF)
321STATISTIC(RedundantMovElemNum,
"Number of redundant moves eliminated");
325struct BPFMIPreEmitPeepholeImpl {
335 bool in16BitRange(
int Num);
336 bool eliminateRedundantMov();
338 bool insertMissingCallerSavedSpills();
339 bool removeMayGotoZero();
340 bool addExitAfterUnreachable();
347 bool Changed = eliminateRedundantMov();
350 Changed |= insertMissingCallerSavedSpills();
351 Changed |= removeMayGotoZero();
352 Changed |= addExitAfterUnreachable();
357class BPFMIPreEmitPeepholeLegacy :
public MachineFunctionPass {
360 BPFMIPreEmitPeepholeLegacy() : MachineFunctionPass(
ID) {}
361 bool runOnMachineFunction(MachineFunction &MF)
override;
365void BPFMIPreEmitPeepholeImpl::initialize(MachineFunction &MFParm) {
369 SupportGotol = MF->
getSubtarget<BPFSubtarget>().hasGotol();
373bool BPFMIPreEmitPeepholeImpl::eliminateRedundantMov() {
374 MachineInstr* ToErase =
nullptr;
375 bool Eliminated =
false;
377 for (MachineBasicBlock &
MBB : *MF) {
378 for (MachineInstr &
MI :
MBB) {
396 unsigned Opcode =
MI.getOpcode();
397 if (Opcode == BPF::MOV_rr) {
405 RedundantMovElemNum++;
414bool BPFMIPreEmitPeepholeImpl::in16BitRange(
int Num) {
433bool BPFMIPreEmitPeepholeImpl::adjustBranch() {
435 int CurrNumInsns = 0;
436 DenseMap<MachineBasicBlock *, int> SoFarNumInsns;
437 DenseMap<MachineBasicBlock *, MachineBasicBlock *> FollowThroughBB;
438 std::vector<MachineBasicBlock *> MBBs;
440 MachineBasicBlock *PrevBB =
nullptr;
441 for (MachineBasicBlock &
MBB : *MF) {
447 CurrNumInsns += (int)
MBB.
size();
448 SoFarNumInsns[&
MBB] = CurrNumInsns;
449 if (PrevBB !=
nullptr)
450 FollowThroughBB[PrevBB] = &
MBB;
453 MBBs.push_back(&
MBB);
455 FollowThroughBB[PrevBB] =
nullptr;
457 for (
unsigned i = 0; i < MBBs.size(); i++) {
463 MachineInstr *CondJmp =
nullptr, *UncondJmp =
nullptr;
465 MachineBasicBlock *
MBB = MBBs[i];
467 if (
Term.isConditionalBranch()) {
468 assert(CondJmp ==
nullptr);
470 }
else if (
Term.isUnconditionalBranch()) {
471 assert(UncondJmp ==
nullptr);
477 if (!CondJmp && !UncondJmp)
480 MachineBasicBlock *CondTargetBB, *JmpBB;
481 CurrNumInsns = SoFarNumInsns[
MBB];
484 if (!CondJmp && UncondJmp) {
485 JmpBB = UncondJmp->getOperand(0).getMBB();
486 if (in16BitRange(SoFarNumInsns[JmpBB] - JmpBB->
size() - CurrNumInsns))
502 MachineBasicBlock *FollowBB = FollowThroughBB[
MBB];
503 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->
size() - CurrNumInsns;
504 if (in16BitRange(Dist))
521 MachineBasicBlock *New_B0 = MF->CreateMachineBasicBlock(TermBB);
522 MachineBasicBlock *New_B1 = MF->CreateMachineBasicBlock(TermBB);
526 MF->insert(MBB_I, New_B0);
527 MF->insert(MBB_I, New_B1);
562 JmpBB = UncondJmp->getOperand(0).getMBB();
582 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->
size() - CurrNumInsns;
583 if (!in16BitRange(Dist)) {
584 MachineBasicBlock *New_B = MF->CreateMachineBasicBlock(TermBB);
601 if (CondTargetBB != JmpBB)
613 if (!in16BitRange(SoFarNumInsns[JmpBB] - CurrNumInsns)) {
623static const unsigned CallerSavedRegs[] = {BPF::R0, BPF::R1, BPF::R2,
624 BPF::R3, BPF::R4, BPF::R5};
628 unsigned LiveCallerSavedRegs;
631static void collectBPFFastCalls(
const TargetRegisterInfo *
TRI,
632 LivePhysRegs &LiveRegs, MachineBasicBlock &BB,
633 SmallVectorImpl<BPFFastCall> &Calls) {
635 LiveRegs.addLiveOuts(BB);
639 unsigned LiveCallerSavedRegs = 0;
640 for (MCRegister R : CallerSavedRegs) {
641 bool DoSpillFill =
false;
643 DoSpillFill |= !
MI.definesRegister(SR,
TRI) && LiveRegs.contains(SR);
646 LiveCallerSavedRegs |= 1 <<
R;
648 if (LiveCallerSavedRegs)
651 LiveRegs.stepBackward(
MI);
655static int64_t computeMinFixedObjOffset(MachineFrameInfo &MFI,
657 int64_t MinFixedObjOffset = 0;
665 (SlotSize + MinFixedObjOffset % SlotSize) & (SlotSize - 1);
666 return MinFixedObjOffset;
669bool BPFMIPreEmitPeepholeImpl::insertMissingCallerSavedSpills() {
670 MachineFrameInfo &MFI = MF->getFrameInfo();
672 LivePhysRegs LiveRegs;
673 const unsigned SlotSize = 8;
674 int64_t MinFixedObjOffset = computeMinFixedObjOffset(MFI, SlotSize);
676 for (MachineBasicBlock &BB : *MF) {
677 collectBPFFastCalls(
TRI, LiveRegs, BB, Calls);
679 for (BPFFastCall &
Call : Calls) {
680 int64_t CurOffset = MinFixedObjOffset;
681 for (MCRegister
Reg : CallerSavedRegs) {
682 if (((1 <<
Reg) &
Call.LiveCallerSavedRegs) == 0)
685 CurOffset -= SlotSize;
705bool BPFMIPreEmitPeepholeImpl::removeMayGotoZero() {
707 MachineBasicBlock *Prev_MBB, *Curr_MBB =
nullptr;
712 if (Prev_MBB ==
nullptr || Curr_MBB->
empty())
715 MachineInstr &
MI = Curr_MBB->
back();
716 if (
MI.getOpcode() != TargetOpcode::INLINEASM_BR)
719 const char *AsmStr =
MI.getOperand(0).getSymbolName();
724 if (AsmPieces.
size() != 1)
730 if (AsmOpPieces.
size() != 2 || AsmOpPieces[0] !=
"may_goto")
733 if (AsmOpPieces[1] !=
"${0:l}" && AsmOpPieces[1] !=
"$0")
745 for (MachineBasicBlock *Pred : Curr_MBB->
predecessors())
746 Pred->replaceSuccessor(Curr_MBB, Prev_MBB);
751 MI.eraseFromParent();
761bool BPFMIPreEmitPeepholeImpl::addExitAfterUnreachable() {
762 MachineBasicBlock &
MBB = MF->
back();
764 if (
MI.getOpcode() != BPF::JAL || !
MI.getOperand(0).isGlobal() ||
765 MI.getOperand(0).getGlobal()->getName() !=
BPF_TRAP)
775 "BPF PreEmit Peephole Optimization",
false,
false)
777char BPFMIPreEmitPeepholeLegacy::
ID = 0;
779 return new BPFMIPreEmitPeepholeLegacy();
782bool BPFMIPreEmitPeepholeLegacy::runOnMachineFunction(MachineFunction &MF) {
785 BPFMIPreEmitPeepholeImpl Impl;
786 return Impl.runOnMachineFunction(MF);
792 BPFMIPreEmitPeepholeImpl Impl;
793 return Impl.runOnMachineFunction(MF)
805 for (
auto It =
MBB.begin(), End =
MBB.end(); It != End;) {
809 switch (
MI.getOpcode()) {
813 case BPF::LOAD_STACK_ARG_PSEUDO: {
815 int16_t Off =
MI.getOperand(1).getImm();
820 MI.eraseFromParent();
825 case BPF::STORE_STACK_ARG_PSEUDO: {
826 int16_t Off =
MI.getOperand(0).getImm();
829 bool IsKill = SrcMO.
isKill();
835 MI.eraseFromParent();
840 case BPF::STORE_STACK_ARG_IMM_PSEUDO: {
841 int16_t
Off =
MI.getOperand(0).getImm();
842 int32_t Val =
MI.getOperand(1).getImm();
848 MI.eraseFromParent();
859class BPFMIExpandStackArgPseudosLegacy :
public MachineFunctionPass {
862 BPFMIExpandStackArgPseudosLegacy() : MachineFunctionPass(
ID) {}
863 bool runOnMachineFunction(MachineFunction &MF)
override;
869 "bpf-mi-expand-stack-arg-pseudos",
870 "BPF Stack argument psuedo expansion",
false,
false)
872char BPFMIExpandStackArgPseudosLegacy::
ID = 0;
874 return new BPFMIExpandStackArgPseudosLegacy();
877bool BPFMIExpandStackArgPseudosLegacy::runOnMachineFunction(
878 MachineFunction &MF) {
879 return expandStackArgPseudos(MF);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< int > GotolAbsLowBound("gotol-abs-low-bound", cl::Hidden, cl::init(INT16_MAX > > 1), cl::desc("Specify gotol lower bound"))
const HexagonInstrInfo * TII
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
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.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Represents analyses that only rely on functions' control flow.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
iterator_range< iterator > terminators()
iterator_range< pred_iterator > predecessors()
MachineInstrBundleIterator< MachineInstr > iterator
int getObjectIndexEnd() const
Return one past the maximum frame object index.
LLVM_ABI int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, bool IsImmutable=false)
Create a spill slot at a fixed location on the stack.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
int getObjectIndexBegin() const
Return the minimum frame object index.
bool isDeadObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a dead object.
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.
BasicBlockListType::iterator iterator
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 & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
unsigned getNumOperands() const
Retuns the total number of operands.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void dump() const
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.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
Register getReg() const
getReg - Returns the register number.
bool isMBB() const
isMBB - Tests if this is a MO_MachineBasicBlock operand.
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.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
A set of analyses that are preserved following a run of a transformation pass.
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 bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
void push_back(const T &Elt)
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
self_iterator getIterator()
Pass manager infrastructure for declaring and invalidating analyses.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ BasicBlock
Various leaf nodes.
initializer< Ty > init(const Ty &Val)
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.
constexpr RegState getKillRegState(bool B)
FunctionPass * createBPFMIPeepholeLegacyPass()
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 void SplitString(StringRef Source, SmallVectorImpl< StringRef > &OutFragments, StringRef Delimiters=" \t\n\v\f\r")
SplitString - Split up the specified string according to the specified delimiters,...
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionPass * createBPFMIPreEmitPeepholeLegacyPass()
FunctionPass * createBPFMIExpandStackArgPseudosLegacyPass()