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)
109 if (
MRI->getRegClass(
Reg) == &BPF::GPRRegClass)
112 MachineInstr *DefInsn =
MRI->getVRegDef(
Reg);
113 if (!isInsnFrom32Def(DefInsn))
119bool BPFMIPeephole::isPhiFrom32Def(MachineInstr *PhiMI)
121 for (
unsigned i = 1, e = PhiMI->
getNumOperands(); i < e; i += 2) {
127 MachineInstr *PhiDef =
MRI->getVRegDef(opnd.
getReg());
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();
330 bool runOnMachineFunction(MachineFunction &MF)
override {
337 Changed = eliminateRedundantMov();
340 Changed |= insertMissingCallerSavedSpills();
341 Changed |= removeMayGotoZero();
342 Changed |= addExitAfterUnreachable();
348void BPFMIPreEmitPeephole::initialize(MachineFunction &MFParm) {
352 SupportGotol = MF->
getSubtarget<BPFSubtarget>().hasGotol();
356bool BPFMIPreEmitPeephole::eliminateRedundantMov() {
357 MachineInstr* ToErase =
nullptr;
358 bool Eliminated =
false;
360 for (MachineBasicBlock &
MBB : *MF) {
361 for (MachineInstr &
MI :
MBB) {
379 unsigned Opcode =
MI.getOpcode();
380 if (Opcode == BPF::MOV_rr) {
388 RedundantMovElemNum++;
397bool BPFMIPreEmitPeephole::in16BitRange(
int Num) {
416bool BPFMIPreEmitPeephole::adjustBranch() {
418 int CurrNumInsns = 0;
419 DenseMap<MachineBasicBlock *, int> SoFarNumInsns;
420 DenseMap<MachineBasicBlock *, MachineBasicBlock *> FollowThroughBB;
421 std::vector<MachineBasicBlock *> MBBs;
423 MachineBasicBlock *PrevBB =
nullptr;
424 for (MachineBasicBlock &
MBB : *MF) {
430 CurrNumInsns += (int)
MBB.
size();
431 SoFarNumInsns[&
MBB] = CurrNumInsns;
432 if (PrevBB !=
nullptr)
433 FollowThroughBB[PrevBB] = &
MBB;
436 MBBs.push_back(&
MBB);
438 FollowThroughBB[PrevBB] =
nullptr;
440 for (
unsigned i = 0; i < MBBs.size(); i++) {
446 MachineInstr *CondJmp =
nullptr, *UncondJmp =
nullptr;
448 MachineBasicBlock *
MBB = MBBs[i];
450 if (
Term.isConditionalBranch()) {
451 assert(CondJmp ==
nullptr);
453 }
else if (
Term.isUnconditionalBranch()) {
454 assert(UncondJmp ==
nullptr);
460 if (!CondJmp && !UncondJmp)
463 MachineBasicBlock *CondTargetBB, *JmpBB;
464 CurrNumInsns = SoFarNumInsns[
MBB];
467 if (!CondJmp && UncondJmp) {
468 JmpBB = UncondJmp->getOperand(0).getMBB();
469 if (in16BitRange(SoFarNumInsns[JmpBB] - JmpBB->
size() - CurrNumInsns))
485 MachineBasicBlock *FollowBB = FollowThroughBB[
MBB];
486 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->
size() - CurrNumInsns;
487 if (in16BitRange(Dist))
504 MachineBasicBlock *New_B0 = MF->CreateMachineBasicBlock(TermBB);
505 MachineBasicBlock *New_B1 = MF->CreateMachineBasicBlock(TermBB);
509 MF->insert(MBB_I, New_B0);
510 MF->insert(MBB_I, New_B1);
545 JmpBB = UncondJmp->getOperand(0).getMBB();
565 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->
size() - CurrNumInsns;
566 if (!in16BitRange(Dist)) {
567 MachineBasicBlock *New_B = MF->CreateMachineBasicBlock(TermBB);
584 if (CondTargetBB != JmpBB)
596 if (!in16BitRange(SoFarNumInsns[JmpBB] - CurrNumInsns)) {
606static const unsigned CallerSavedRegs[] = {BPF::R0, BPF::R1, BPF::R2,
607 BPF::R3, BPF::R4, BPF::R5};
611 unsigned LiveCallerSavedRegs;
614static void collectBPFFastCalls(
const TargetRegisterInfo *
TRI,
615 LivePhysRegs &LiveRegs, MachineBasicBlock &BB,
616 SmallVectorImpl<BPFFastCall> &Calls) {
618 LiveRegs.addLiveOuts(BB);
622 unsigned LiveCallerSavedRegs = 0;
623 for (MCRegister R : CallerSavedRegs) {
624 bool DoSpillFill =
false;
626 DoSpillFill |= !
MI.definesRegister(SR,
TRI) && LiveRegs.contains(SR);
629 LiveCallerSavedRegs |= 1 <<
R;
631 if (LiveCallerSavedRegs)
634 LiveRegs.stepBackward(
MI);
638static int64_t computeMinFixedObjOffset(MachineFrameInfo &MFI,
640 int64_t MinFixedObjOffset = 0;
648 (SlotSize + MinFixedObjOffset % SlotSize) & (SlotSize - 1);
649 return MinFixedObjOffset;
652bool BPFMIPreEmitPeephole::insertMissingCallerSavedSpills() {
653 MachineFrameInfo &MFI = MF->getFrameInfo();
655 LivePhysRegs LiveRegs;
656 const unsigned SlotSize = 8;
657 int64_t MinFixedObjOffset = computeMinFixedObjOffset(MFI, SlotSize);
659 for (MachineBasicBlock &BB : *MF) {
660 collectBPFFastCalls(
TRI, LiveRegs, BB, Calls);
662 for (BPFFastCall &
Call : Calls) {
663 int64_t CurOffset = MinFixedObjOffset;
664 for (MCRegister
Reg : CallerSavedRegs) {
665 if (((1 <<
Reg) &
Call.LiveCallerSavedRegs) == 0)
668 CurOffset -= SlotSize;
688bool BPFMIPreEmitPeephole::removeMayGotoZero() {
690 MachineBasicBlock *Prev_MBB, *Curr_MBB =
nullptr;
695 if (Prev_MBB ==
nullptr || Curr_MBB->
empty())
698 MachineInstr &
MI = Curr_MBB->
back();
699 if (
MI.getOpcode() != TargetOpcode::INLINEASM_BR)
702 const char *AsmStr =
MI.getOperand(0).getSymbolName();
707 if (AsmPieces.
size() != 1)
713 if (AsmOpPieces.
size() != 2 || AsmOpPieces[0] !=
"may_goto")
716 if (AsmOpPieces[1] !=
"${0:l}" && AsmOpPieces[1] !=
"$0")
728 for (MachineBasicBlock *Pred : Curr_MBB->
predecessors())
729 Pred->replaceSuccessor(Curr_MBB, Prev_MBB);
734 MI.eraseFromParent();
744bool BPFMIPreEmitPeephole::addExitAfterUnreachable() {
745 MachineBasicBlock &
MBB = MF->
back();
747 if (
MI.getOpcode() != BPF::JAL || !
MI.getOperand(0).isGlobal() ||
748 MI.getOperand(0).getGlobal()->getName() !=
BPF_TRAP)
758 "BPF PreEmit Peephole Optimization",
false,
false)
760char BPFMIPreEmitPeephole::
ID = 0;
763 return new BPFMIPreEmitPeephole();
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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 eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
LLVM_ABI void dump() const
const MachineOperand & getOperand(unsigned i) const
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,...
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.
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...