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 {
338 Changed = eliminateRedundantMov();
341 Changed |= insertMissingCallerSavedSpills();
342 Changed |= removeMayGotoZero();
343 Changed |= addExitAfterUnreachable();
344 Changed |= expandStackArgPseudos();
350void BPFMIPreEmitPeephole::initialize(MachineFunction &MFParm) {
354 SupportGotol = MF->
getSubtarget<BPFSubtarget>().hasGotol();
358bool BPFMIPreEmitPeephole::eliminateRedundantMov() {
359 MachineInstr* ToErase =
nullptr;
360 bool Eliminated =
false;
362 for (MachineBasicBlock &
MBB : *MF) {
363 for (MachineInstr &
MI :
MBB) {
381 unsigned Opcode =
MI.getOpcode();
382 if (Opcode == BPF::MOV_rr) {
390 RedundantMovElemNum++;
399bool BPFMIPreEmitPeephole::in16BitRange(
int Num) {
418bool BPFMIPreEmitPeephole::adjustBranch() {
420 int CurrNumInsns = 0;
421 DenseMap<MachineBasicBlock *, int> SoFarNumInsns;
422 DenseMap<MachineBasicBlock *, MachineBasicBlock *> FollowThroughBB;
423 std::vector<MachineBasicBlock *> MBBs;
425 MachineBasicBlock *PrevBB =
nullptr;
426 for (MachineBasicBlock &
MBB : *MF) {
432 CurrNumInsns += (int)
MBB.
size();
433 SoFarNumInsns[&
MBB] = CurrNumInsns;
434 if (PrevBB !=
nullptr)
435 FollowThroughBB[PrevBB] = &
MBB;
438 MBBs.push_back(&
MBB);
440 FollowThroughBB[PrevBB] =
nullptr;
442 for (
unsigned i = 0; i < MBBs.size(); i++) {
448 MachineInstr *CondJmp =
nullptr, *UncondJmp =
nullptr;
450 MachineBasicBlock *
MBB = MBBs[i];
452 if (
Term.isConditionalBranch()) {
453 assert(CondJmp ==
nullptr);
455 }
else if (
Term.isUnconditionalBranch()) {
456 assert(UncondJmp ==
nullptr);
462 if (!CondJmp && !UncondJmp)
465 MachineBasicBlock *CondTargetBB, *JmpBB;
466 CurrNumInsns = SoFarNumInsns[
MBB];
469 if (!CondJmp && UncondJmp) {
470 JmpBB = UncondJmp->getOperand(0).getMBB();
471 if (in16BitRange(SoFarNumInsns[JmpBB] - JmpBB->
size() - CurrNumInsns))
487 MachineBasicBlock *FollowBB = FollowThroughBB[
MBB];
488 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->
size() - CurrNumInsns;
489 if (in16BitRange(Dist))
506 MachineBasicBlock *New_B0 = MF->CreateMachineBasicBlock(TermBB);
507 MachineBasicBlock *New_B1 = MF->CreateMachineBasicBlock(TermBB);
511 MF->insert(MBB_I, New_B0);
512 MF->insert(MBB_I, New_B1);
547 JmpBB = UncondJmp->getOperand(0).getMBB();
567 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->
size() - CurrNumInsns;
568 if (!in16BitRange(Dist)) {
569 MachineBasicBlock *New_B = MF->CreateMachineBasicBlock(TermBB);
586 if (CondTargetBB != JmpBB)
598 if (!in16BitRange(SoFarNumInsns[JmpBB] - CurrNumInsns)) {
608static const unsigned CallerSavedRegs[] = {BPF::R0, BPF::R1, BPF::R2,
609 BPF::R3, BPF::R4, BPF::R5};
613 unsigned LiveCallerSavedRegs;
616static void collectBPFFastCalls(
const TargetRegisterInfo *
TRI,
617 LivePhysRegs &LiveRegs, MachineBasicBlock &BB,
618 SmallVectorImpl<BPFFastCall> &Calls) {
620 LiveRegs.addLiveOuts(BB);
624 unsigned LiveCallerSavedRegs = 0;
625 for (MCRegister R : CallerSavedRegs) {
626 bool DoSpillFill =
false;
628 DoSpillFill |= !
MI.definesRegister(SR,
TRI) && LiveRegs.contains(SR);
631 LiveCallerSavedRegs |= 1 <<
R;
633 if (LiveCallerSavedRegs)
636 LiveRegs.stepBackward(
MI);
640static int64_t computeMinFixedObjOffset(MachineFrameInfo &MFI,
642 int64_t MinFixedObjOffset = 0;
650 (SlotSize + MinFixedObjOffset % SlotSize) & (SlotSize - 1);
651 return MinFixedObjOffset;
654bool BPFMIPreEmitPeephole::insertMissingCallerSavedSpills() {
655 MachineFrameInfo &MFI = MF->getFrameInfo();
657 LivePhysRegs LiveRegs;
658 const unsigned SlotSize = 8;
659 int64_t MinFixedObjOffset = computeMinFixedObjOffset(MFI, SlotSize);
661 for (MachineBasicBlock &BB : *MF) {
662 collectBPFFastCalls(
TRI, LiveRegs, BB, Calls);
664 for (BPFFastCall &
Call : Calls) {
665 int64_t CurOffset = MinFixedObjOffset;
666 for (MCRegister
Reg : CallerSavedRegs) {
667 if (((1 <<
Reg) &
Call.LiveCallerSavedRegs) == 0)
670 CurOffset -= SlotSize;
690bool BPFMIPreEmitPeephole::removeMayGotoZero() {
692 MachineBasicBlock *Prev_MBB, *Curr_MBB =
nullptr;
697 if (Prev_MBB ==
nullptr || Curr_MBB->
empty())
700 MachineInstr &
MI = Curr_MBB->
back();
701 if (
MI.getOpcode() != TargetOpcode::INLINEASM_BR)
704 const char *AsmStr =
MI.getOperand(0).getSymbolName();
709 if (AsmPieces.
size() != 1)
715 if (AsmOpPieces.
size() != 2 || AsmOpPieces[0] !=
"may_goto")
718 if (AsmOpPieces[1] !=
"${0:l}" && AsmOpPieces[1] !=
"$0")
730 for (MachineBasicBlock *Pred : Curr_MBB->
predecessors())
731 Pred->replaceSuccessor(Curr_MBB, Prev_MBB);
736 MI.eraseFromParent();
746bool BPFMIPreEmitPeephole::addExitAfterUnreachable() {
747 MachineBasicBlock &
MBB = MF->
back();
749 if (
MI.getOpcode() != BPF::JAL || !
MI.getOperand(0).isGlobal() ||
750 MI.getOperand(0).getGlobal()->getName() !=
BPF_TRAP)
757bool BPFMIPreEmitPeephole::expandStackArgPseudos() {
760 for (MachineBasicBlock &
MBB : *MF) {
762 MachineInstr &
MI = *It++;
765 switch (
MI.getOpcode()) {
769 case BPF::LOAD_STACK_ARG_PSEUDO: {
771 int16_t
Off =
MI.getOperand(1).getImm();
776 MI.eraseFromParent();
781 case BPF::STORE_STACK_ARG_PSEUDO: {
782 int16_t
Off =
MI.getOperand(0).getImm();
783 const MachineOperand &SrcMO =
MI.getOperand(1);
785 bool IsKill = SrcMO.
isKill();
791 MI.eraseFromParent();
796 case BPF::STORE_STACK_ARG_IMM_PSEUDO: {
797 int16_t
Off =
MI.getOperand(0).getImm();
798 int32_t Val =
MI.getOperand(1).getImm();
804 MI.eraseFromParent();
818 "BPF PreEmit Peephole Optimization",
false,
false)
820char BPFMIPreEmitPeephole::
ID = 0;
823 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...