38#define DEBUG_TYPE "bpf-mi-zext-elim"
43STATISTIC(ZExtElemNum,
"Number of zero extension shifts eliminated");
60 bool isCopyFrom32Def(MachineInstr *CopyMI);
61 bool isInsnFrom32Def(MachineInstr *DefInsn);
62 bool isPhiFrom32Def(MachineInstr *MovMI);
63 bool isMovFrom32Def(MachineInstr *MovMI);
64 bool eliminateZExtSeq();
67 std::set<MachineInstr *> PhiInsns;
72 bool runOnMachineFunction(MachineFunction &MF)
override {
73 if (skipFunction(MF.getFunction()))
80 bool ZExtSeqExist, ZExtExist;
81 ZExtSeqExist = eliminateZExtSeq();
82 ZExtExist = eliminateZExt();
83 return ZExtSeqExist || ZExtExist;
92 LLVM_DEBUG(
dbgs() <<
"*** BPF MachineSSA ZEXT Elim peephole pass ***\n\n");
95bool BPFMIPeephole::isCopyFrom32Def(MachineInstr *CopyMI)
110 if (!isInsnFrom32Def(DefInsn))
116bool BPFMIPeephole::isPhiFrom32Def(MachineInstr *PhiMI)
118 for (
unsigned i = 1, e = PhiMI->
getNumOperands(); i < e; i += 2) {
124 if (PhiDef->
isPHI()) {
125 if (!PhiInsns.insert(PhiDef).second)
127 if (!isPhiFrom32Def(PhiDef))
130 if (PhiDef->
getOpcode() == BPF::COPY && !isCopyFrom32Def(PhiDef))
138bool BPFMIPeephole::isInsnFrom32Def(MachineInstr *DefInsn)
143 if (DefInsn->
isPHI()) {
144 if (!PhiInsns.insert(DefInsn).second)
146 if (!isPhiFrom32Def(DefInsn))
148 }
else if (DefInsn->
getOpcode() == BPF::COPY) {
149 if (!isCopyFrom32Def(DefInsn))
156bool BPFMIPeephole::isMovFrom32Def(MachineInstr *MovMI)
158 const MachineOperand &Src = MovMI->
getOperand(1);
162 MachineInstr *DefInsn = MRI->
getVRegDef(Src.getReg());
168 if (!isInsnFrom32Def(DefInsn))
176bool BPFMIPeephole::eliminateZExtSeq() {
177 MachineInstr* ToErase =
nullptr;
178 bool Eliminated =
false;
180 for (MachineBasicBlock &
MBB : *MF) {
181 for (MachineInstr &
MI :
MBB) {
193 if (
MI.getOpcode() == BPF::SRL_ri &&
194 MI.getOperand(2).getImm() == 32) {
197 MachineInstr *SllMI = MRI->
getVRegDef(ShfReg);
221 if (!isMovFrom32Def(MovMI)) {
223 <<
" One ZExt elim sequence failed qualifying elim.\n");
245bool BPFMIPeephole::eliminateZExt() {
246 MachineInstr* ToErase =
nullptr;
247 bool Eliminated =
false;
249 for (MachineBasicBlock &
MBB : *MF) {
250 for (MachineInstr &
MI :
MBB) {
257 if (
MI.getOpcode() != BPF::MOV_32_64)
270 if (!isMovFrom32Def(&
MI))
294 "BPF MachineSSA Peephole Optimization For ZEXT Eliminate",
297char BPFMIPeephole::
ID = 0;
300STATISTIC(RedundantMovElemNum,
"Number of redundant moves eliminated");
318 bool in16BitRange(
int Num);
319 bool eliminateRedundantMov();
321 bool insertMissingCallerSavedSpills();
322 bool removeMayGotoZero();
323 bool addExitAfterUnreachable();
324 bool expandStackArgPseudos();
329 bool runOnMachineFunction(MachineFunction &MF)
override {
332 bool Changed = expandStackArgPseudos();
336 Changed |= eliminateRedundantMov();
339 Changed |= insertMissingCallerSavedSpills();
340 Changed |= removeMayGotoZero();
341 Changed |= addExitAfterUnreachable();
347void BPFMIPreEmitPeephole::initialize(MachineFunction &MFParm) {
351 SupportGotol = MF->
getSubtarget<BPFSubtarget>().hasGotol();
355bool BPFMIPreEmitPeephole::eliminateRedundantMov() {
356 MachineInstr* ToErase =
nullptr;
357 bool Eliminated =
false;
359 for (MachineBasicBlock &
MBB : *MF) {
360 for (MachineInstr &
MI :
MBB) {
378 unsigned Opcode =
MI.getOpcode();
379 if (Opcode == BPF::MOV_rr) {
387 RedundantMovElemNum++;
396bool BPFMIPreEmitPeephole::in16BitRange(
int Num) {
415bool BPFMIPreEmitPeephole::adjustBranch() {
417 int CurrNumInsns = 0;
418 DenseMap<MachineBasicBlock *, int> SoFarNumInsns;
419 DenseMap<MachineBasicBlock *, MachineBasicBlock *> FollowThroughBB;
420 std::vector<MachineBasicBlock *> MBBs;
422 MachineBasicBlock *PrevBB =
nullptr;
423 for (MachineBasicBlock &
MBB : *MF) {
429 CurrNumInsns += (int)
MBB.
size();
430 SoFarNumInsns[&
MBB] = CurrNumInsns;
431 if (PrevBB !=
nullptr)
432 FollowThroughBB[PrevBB] = &
MBB;
435 MBBs.push_back(&
MBB);
437 FollowThroughBB[PrevBB] =
nullptr;
439 for (
unsigned i = 0; i < MBBs.size(); i++) {
445 MachineInstr *CondJmp =
nullptr, *UncondJmp =
nullptr;
447 MachineBasicBlock *
MBB = MBBs[i];
449 if (
Term.isConditionalBranch()) {
450 assert(CondJmp ==
nullptr);
452 }
else if (
Term.isUnconditionalBranch()) {
453 assert(UncondJmp ==
nullptr);
459 if (!CondJmp && !UncondJmp)
462 MachineBasicBlock *CondTargetBB, *JmpBB;
463 CurrNumInsns = SoFarNumInsns[
MBB];
466 if (!CondJmp && UncondJmp) {
467 JmpBB = UncondJmp->getOperand(0).getMBB();
468 if (in16BitRange(SoFarNumInsns[JmpBB] - JmpBB->
size() - CurrNumInsns))
484 MachineBasicBlock *FollowBB = FollowThroughBB[
MBB];
485 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->
size() - CurrNumInsns;
486 if (in16BitRange(Dist))
503 MachineBasicBlock *New_B0 = MF->CreateMachineBasicBlock(TermBB);
504 MachineBasicBlock *New_B1 = MF->CreateMachineBasicBlock(TermBB);
508 MF->insert(MBB_I, New_B0);
509 MF->insert(MBB_I, New_B1);
544 JmpBB = UncondJmp->getOperand(0).getMBB();
564 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->
size() - CurrNumInsns;
565 if (!in16BitRange(Dist)) {
566 MachineBasicBlock *New_B = MF->CreateMachineBasicBlock(TermBB);
583 if (CondTargetBB != JmpBB)
595 if (!in16BitRange(SoFarNumInsns[JmpBB] - CurrNumInsns)) {
605static const unsigned CallerSavedRegs[] = {BPF::R0, BPF::R1, BPF::R2,
606 BPF::R3, BPF::R4, BPF::R5};
610 unsigned LiveCallerSavedRegs;
613static void collectBPFFastCalls(
const TargetRegisterInfo *
TRI,
614 LivePhysRegs &LiveRegs, MachineBasicBlock &BB,
615 SmallVectorImpl<BPFFastCall> &Calls) {
617 LiveRegs.addLiveOuts(BB);
621 unsigned LiveCallerSavedRegs = 0;
622 for (MCRegister R : CallerSavedRegs) {
623 bool DoSpillFill =
false;
625 DoSpillFill |= !
MI.definesRegister(SR,
TRI) && LiveRegs.contains(SR);
628 LiveCallerSavedRegs |= 1 <<
R;
630 if (LiveCallerSavedRegs)
633 LiveRegs.stepBackward(
MI);
637static int64_t computeMinFixedObjOffset(MachineFrameInfo &MFI,
639 int64_t MinFixedObjOffset = 0;
647 (SlotSize + MinFixedObjOffset % SlotSize) & (SlotSize - 1);
648 return MinFixedObjOffset;
651bool BPFMIPreEmitPeephole::insertMissingCallerSavedSpills() {
652 MachineFrameInfo &MFI = MF->getFrameInfo();
654 LivePhysRegs LiveRegs;
655 const unsigned SlotSize = 8;
656 int64_t MinFixedObjOffset = computeMinFixedObjOffset(MFI, SlotSize);
658 for (MachineBasicBlock &BB : *MF) {
659 collectBPFFastCalls(
TRI, LiveRegs, BB, Calls);
661 for (BPFFastCall &
Call : Calls) {
662 int64_t CurOffset = MinFixedObjOffset;
663 for (MCRegister
Reg : CallerSavedRegs) {
664 if (((1 <<
Reg) &
Call.LiveCallerSavedRegs) == 0)
667 CurOffset -= SlotSize;
687bool BPFMIPreEmitPeephole::removeMayGotoZero() {
689 MachineBasicBlock *Prev_MBB, *Curr_MBB =
nullptr;
694 if (Prev_MBB ==
nullptr || Curr_MBB->
empty())
697 MachineInstr &
MI = Curr_MBB->
back();
698 if (
MI.getOpcode() != TargetOpcode::INLINEASM_BR)
701 const char *AsmStr =
MI.getOperand(0).getSymbolName();
706 if (AsmPieces.
size() != 1)
712 if (AsmOpPieces.
size() != 2 || AsmOpPieces[0] !=
"may_goto")
715 if (AsmOpPieces[1] !=
"${0:l}" && AsmOpPieces[1] !=
"$0")
727 for (MachineBasicBlock *Pred : Curr_MBB->
predecessors())
728 Pred->replaceSuccessor(Curr_MBB, Prev_MBB);
733 MI.eraseFromParent();
743bool BPFMIPreEmitPeephole::addExitAfterUnreachable() {
744 MachineBasicBlock &
MBB = MF->
back();
746 if (
MI.getOpcode() != BPF::JAL || !
MI.getOperand(0).isGlobal() ||
747 MI.getOperand(0).getGlobal()->getName() !=
BPF_TRAP)
754bool BPFMIPreEmitPeephole::expandStackArgPseudos() {
757 for (MachineBasicBlock &
MBB : *MF) {
759 MachineInstr &
MI = *It++;
762 switch (
MI.getOpcode()) {
766 case BPF::LOAD_STACK_ARG_PSEUDO: {
768 int16_t
Off =
MI.getOperand(1).getImm();
773 MI.eraseFromParent();
778 case BPF::STORE_STACK_ARG_PSEUDO: {
779 int16_t
Off =
MI.getOperand(0).getImm();
780 const MachineOperand &SrcMO =
MI.getOperand(1);
782 bool IsKill = SrcMO.
isKill();
788 MI.eraseFromParent();
793 case BPF::STORE_STACK_ARG_IMM_PSEUDO: {
794 int16_t
Off =
MI.getOperand(0).getImm();
795 int32_t Val =
MI.getOperand(1).getImm();
801 MI.eraseFromParent();
815 "BPF PreEmit Peephole Optimization",
false,
false)
817char BPFMIPreEmitPeephole::
ID = 0;
820 return new BPFMIPreEmitPeephole();
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.
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
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.
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 ...
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()
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)
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...
FunctionPass * createBPFMIPreEmitPeepholePass()
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,...
FunctionPass * createBPFMIPeepholePass()
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...