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)
113 if (!isInsnFrom32Def(DefInsn))
119bool BPFMIPeephole::isPhiFrom32Def(MachineInstr *PhiMI)
121 for (
unsigned i = 1, e = PhiMI->
getNumOperands(); i < e; i += 2) {
130 if (PhiDef->
isPHI()) {
131 if (!PhiInsns.insert(PhiDef).second)
133 if (!isPhiFrom32Def(PhiDef))
136 if (PhiDef->
getOpcode() == BPF::COPY && !isCopyFrom32Def(PhiDef))
144bool BPFMIPeephole::isInsnFrom32Def(MachineInstr *DefInsn)
149 if (DefInsn->
isPHI()) {
150 if (!PhiInsns.insert(DefInsn).second)
152 if (!isPhiFrom32Def(DefInsn))
154 }
else if (DefInsn->
getOpcode() == BPF::COPY) {
155 if (!isCopyFrom32Def(DefInsn))
162bool BPFMIPeephole::isMovFrom32Def(MachineInstr *MovMI)
170 if (!isInsnFrom32Def(DefInsn))
178bool BPFMIPeephole::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 BPFMIPeephole::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 BPFMIPeephole::
ID = 0;
302STATISTIC(RedundantMovElemNum,
"Number of redundant moves eliminated");
320 bool in16BitRange(
int Num);
321 bool eliminateRedundantMov();
323 bool insertMissingCallerSavedSpills();
324 bool removeMayGotoZero();
325 bool addExitAfterUnreachable();
326 bool expandStackArgPseudos();
331 bool runOnMachineFunction(MachineFunction &MF)
override {
334 bool Changed = expandStackArgPseudos();
338 Changed |= eliminateRedundantMov();
341 Changed |= insertMissingCallerSavedSpills();
342 Changed |= removeMayGotoZero();
343 Changed |= addExitAfterUnreachable();
349void BPFMIPreEmitPeephole::initialize(MachineFunction &MFParm) {
353 SupportGotol = MF->
getSubtarget<BPFSubtarget>().hasGotol();
357bool BPFMIPreEmitPeephole::eliminateRedundantMov() {
358 MachineInstr* ToErase =
nullptr;
359 bool Eliminated =
false;
361 for (MachineBasicBlock &
MBB : *MF) {
362 for (MachineInstr &
MI :
MBB) {
380 unsigned Opcode =
MI.getOpcode();
381 if (Opcode == BPF::MOV_rr) {
389 RedundantMovElemNum++;
398bool BPFMIPreEmitPeephole::in16BitRange(
int Num) {
417bool BPFMIPreEmitPeephole::adjustBranch() {
419 int CurrNumInsns = 0;
420 DenseMap<MachineBasicBlock *, int> SoFarNumInsns;
421 DenseMap<MachineBasicBlock *, MachineBasicBlock *> FollowThroughBB;
422 std::vector<MachineBasicBlock *> MBBs;
424 MachineBasicBlock *PrevBB =
nullptr;
425 for (MachineBasicBlock &
MBB : *MF) {
431 CurrNumInsns += (int)
MBB.
size();
432 SoFarNumInsns[&
MBB] = CurrNumInsns;
433 if (PrevBB !=
nullptr)
434 FollowThroughBB[PrevBB] = &
MBB;
437 MBBs.push_back(&
MBB);
439 FollowThroughBB[PrevBB] =
nullptr;
441 for (
unsigned i = 0; i < MBBs.size(); i++) {
447 MachineInstr *CondJmp =
nullptr, *UncondJmp =
nullptr;
449 MachineBasicBlock *
MBB = MBBs[i];
451 if (
Term.isConditionalBranch()) {
452 assert(CondJmp ==
nullptr);
454 }
else if (
Term.isUnconditionalBranch()) {
455 assert(UncondJmp ==
nullptr);
461 if (!CondJmp && !UncondJmp)
464 MachineBasicBlock *CondTargetBB, *JmpBB;
465 CurrNumInsns = SoFarNumInsns[
MBB];
468 if (!CondJmp && UncondJmp) {
469 JmpBB = UncondJmp->getOperand(0).getMBB();
470 if (in16BitRange(SoFarNumInsns[JmpBB] - JmpBB->
size() - CurrNumInsns))
486 MachineBasicBlock *FollowBB = FollowThroughBB[
MBB];
487 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->
size() - CurrNumInsns;
488 if (in16BitRange(Dist))
505 MachineBasicBlock *New_B0 = MF->CreateMachineBasicBlock(TermBB);
506 MachineBasicBlock *New_B1 = MF->CreateMachineBasicBlock(TermBB);
510 MF->insert(MBB_I, New_B0);
511 MF->insert(MBB_I, New_B1);
546 JmpBB = UncondJmp->getOperand(0).getMBB();
566 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->
size() - CurrNumInsns;
567 if (!in16BitRange(Dist)) {
568 MachineBasicBlock *New_B = MF->CreateMachineBasicBlock(TermBB);
585 if (CondTargetBB != JmpBB)
597 if (!in16BitRange(SoFarNumInsns[JmpBB] - CurrNumInsns)) {
607static const unsigned CallerSavedRegs[] = {BPF::R0, BPF::R1, BPF::R2,
608 BPF::R3, BPF::R4, BPF::R5};
612 unsigned LiveCallerSavedRegs;
615static void collectBPFFastCalls(
const TargetRegisterInfo *
TRI,
616 LivePhysRegs &LiveRegs, MachineBasicBlock &BB,
617 SmallVectorImpl<BPFFastCall> &Calls) {
619 LiveRegs.addLiveOuts(BB);
623 unsigned LiveCallerSavedRegs = 0;
624 for (MCRegister R : CallerSavedRegs) {
625 bool DoSpillFill =
false;
627 DoSpillFill |= !
MI.definesRegister(SR,
TRI) && LiveRegs.contains(SR);
630 LiveCallerSavedRegs |= 1 <<
R;
632 if (LiveCallerSavedRegs)
635 LiveRegs.stepBackward(
MI);
639static int64_t computeMinFixedObjOffset(MachineFrameInfo &MFI,
641 int64_t MinFixedObjOffset = 0;
649 (SlotSize + MinFixedObjOffset % SlotSize) & (SlotSize - 1);
650 return MinFixedObjOffset;
653bool BPFMIPreEmitPeephole::insertMissingCallerSavedSpills() {
654 MachineFrameInfo &MFI = MF->getFrameInfo();
656 LivePhysRegs LiveRegs;
657 const unsigned SlotSize = 8;
658 int64_t MinFixedObjOffset = computeMinFixedObjOffset(MFI, SlotSize);
660 for (MachineBasicBlock &BB : *MF) {
661 collectBPFFastCalls(
TRI, LiveRegs, BB, Calls);
663 for (BPFFastCall &
Call : Calls) {
664 int64_t CurOffset = MinFixedObjOffset;
665 for (MCRegister
Reg : CallerSavedRegs) {
666 if (((1 <<
Reg) &
Call.LiveCallerSavedRegs) == 0)
669 CurOffset -= SlotSize;
689bool BPFMIPreEmitPeephole::removeMayGotoZero() {
691 MachineBasicBlock *Prev_MBB, *Curr_MBB =
nullptr;
696 if (Prev_MBB ==
nullptr || Curr_MBB->
empty())
699 MachineInstr &
MI = Curr_MBB->
back();
700 if (
MI.getOpcode() != TargetOpcode::INLINEASM_BR)
703 const char *AsmStr =
MI.getOperand(0).getSymbolName();
708 if (AsmPieces.
size() != 1)
714 if (AsmOpPieces.
size() != 2 || AsmOpPieces[0] !=
"may_goto")
717 if (AsmOpPieces[1] !=
"${0:l}" && AsmOpPieces[1] !=
"$0")
729 for (MachineBasicBlock *Pred : Curr_MBB->
predecessors())
730 Pred->replaceSuccessor(Curr_MBB, Prev_MBB);
735 MI.eraseFromParent();
745bool BPFMIPreEmitPeephole::addExitAfterUnreachable() {
746 MachineBasicBlock &
MBB = MF->
back();
748 if (
MI.getOpcode() != BPF::JAL || !
MI.getOperand(0).isGlobal() ||
749 MI.getOperand(0).getGlobal()->getName() !=
BPF_TRAP)
756bool BPFMIPreEmitPeephole::expandStackArgPseudos() {
759 for (MachineBasicBlock &
MBB : *MF) {
761 MachineInstr &
MI = *It++;
764 switch (
MI.getOpcode()) {
768 case BPF::LOAD_STACK_ARG_PSEUDO: {
770 int16_t
Off =
MI.getOperand(1).getImm();
775 MI.eraseFromParent();
780 case BPF::STORE_STACK_ARG_PSEUDO: {
781 int16_t
Off =
MI.getOperand(0).getImm();
782 const MachineOperand &SrcMO =
MI.getOperand(1);
784 bool IsKill = SrcMO.
isKill();
790 MI.eraseFromParent();
795 case BPF::STORE_STACK_ARG_IMM_PSEUDO: {
796 int16_t
Off =
MI.getOperand(0).getImm();
797 int32_t Val =
MI.getOperand(1).getImm();
803 MI.eraseFromParent();
817 "BPF PreEmit Peephole Optimization",
false,
false)
819char BPFMIPreEmitPeephole::
ID = 0;
822 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...