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");
246bool BPFMIPeephole::eliminateZExt() {
247 MachineInstr* ToErase =
nullptr;
248 bool Eliminated =
false;
250 for (MachineBasicBlock &
MBB : *MF) {
251 for (MachineInstr &
MI :
MBB) {
258 if (
MI.getOpcode() != BPF::MOV_32_64)
271 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();
328 bool runOnMachineFunction(MachineFunction &MF)
override {
335 Changed = eliminateRedundantMov();
338 Changed |= insertMissingCallerSavedSpills();
339 Changed |= removeMayGotoZero();
340 Changed |= addExitAfterUnreachable();
346void BPFMIPreEmitPeephole::initialize(MachineFunction &MFParm) {
350 SupportGotol = MF->
getSubtarget<BPFSubtarget>().hasGotol();
354bool BPFMIPreEmitPeephole::eliminateRedundantMov() {
355 MachineInstr* ToErase =
nullptr;
356 bool Eliminated =
false;
358 for (MachineBasicBlock &
MBB : *MF) {
359 for (MachineInstr &
MI :
MBB) {
377 unsigned Opcode =
MI.getOpcode();
378 if (Opcode == BPF::MOV_rr) {
386 RedundantMovElemNum++;
395bool BPFMIPreEmitPeephole::in16BitRange(
int Num) {
414bool BPFMIPreEmitPeephole::adjustBranch() {
416 int CurrNumInsns = 0;
417 DenseMap<MachineBasicBlock *, int> SoFarNumInsns;
418 DenseMap<MachineBasicBlock *, MachineBasicBlock *> FollowThroughBB;
419 std::vector<MachineBasicBlock *> MBBs;
421 MachineBasicBlock *PrevBB =
nullptr;
422 for (MachineBasicBlock &
MBB : *MF) {
428 CurrNumInsns += (int)
MBB.
size();
429 SoFarNumInsns[&
MBB] = CurrNumInsns;
430 if (PrevBB !=
nullptr)
431 FollowThroughBB[PrevBB] = &
MBB;
434 MBBs.push_back(&
MBB);
436 FollowThroughBB[PrevBB] =
nullptr;
438 for (
unsigned i = 0; i < MBBs.size(); i++) {
444 MachineInstr *CondJmp =
nullptr, *UncondJmp =
nullptr;
446 MachineBasicBlock *
MBB = MBBs[i];
448 if (
Term.isConditionalBranch()) {
449 assert(CondJmp ==
nullptr);
451 }
else if (
Term.isUnconditionalBranch()) {
452 assert(UncondJmp ==
nullptr);
458 if (!CondJmp && !UncondJmp)
461 MachineBasicBlock *CondTargetBB, *JmpBB;
462 CurrNumInsns = SoFarNumInsns[
MBB];
465 if (!CondJmp && UncondJmp) {
466 JmpBB = UncondJmp->getOperand(0).getMBB();
467 if (in16BitRange(SoFarNumInsns[JmpBB] - JmpBB->
size() - CurrNumInsns))
483 MachineBasicBlock *FollowBB = FollowThroughBB[
MBB];
484 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->
size() - CurrNumInsns;
485 if (in16BitRange(Dist))
502 MachineBasicBlock *New_B0 = MF->CreateMachineBasicBlock(TermBB);
503 MachineBasicBlock *New_B1 = MF->CreateMachineBasicBlock(TermBB);
507 MF->insert(MBB_I, New_B0);
508 MF->insert(MBB_I, New_B1);
543 JmpBB = UncondJmp->getOperand(0).getMBB();
563 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->
size() - CurrNumInsns;
564 if (!in16BitRange(Dist)) {
565 MachineBasicBlock *New_B = MF->CreateMachineBasicBlock(TermBB);
582 if (CondTargetBB != JmpBB)
594 if (!in16BitRange(SoFarNumInsns[JmpBB] - CurrNumInsns)) {
604static const unsigned CallerSavedRegs[] = {BPF::R0, BPF::R1, BPF::R2,
605 BPF::R3, BPF::R4, BPF::R5};
609 unsigned LiveCallerSavedRegs;
612static void collectBPFFastCalls(
const TargetRegisterInfo *
TRI,
613 LivePhysRegs &LiveRegs, MachineBasicBlock &BB,
614 SmallVectorImpl<BPFFastCall> &Calls) {
616 LiveRegs.addLiveOuts(BB);
620 unsigned LiveCallerSavedRegs = 0;
621 for (MCRegister R : CallerSavedRegs) {
622 bool DoSpillFill =
false;
624 DoSpillFill |= !
MI.definesRegister(SR,
TRI) && LiveRegs.contains(SR);
627 LiveCallerSavedRegs |= 1 <<
R;
629 if (LiveCallerSavedRegs)
632 LiveRegs.stepBackward(
MI);
636static int64_t computeMinFixedObjOffset(MachineFrameInfo &MFI,
638 int64_t MinFixedObjOffset = 0;
646 (SlotSize + MinFixedObjOffset % SlotSize) & (SlotSize - 1);
647 return MinFixedObjOffset;
650bool BPFMIPreEmitPeephole::insertMissingCallerSavedSpills() {
651 MachineFrameInfo &MFI = MF->getFrameInfo();
653 LivePhysRegs LiveRegs;
654 const unsigned SlotSize = 8;
655 int64_t MinFixedObjOffset = computeMinFixedObjOffset(MFI, SlotSize);
657 for (MachineBasicBlock &BB : *MF) {
658 collectBPFFastCalls(
TRI, LiveRegs, BB, Calls);
660 for (BPFFastCall &
Call : Calls) {
661 int64_t CurOffset = MinFixedObjOffset;
662 for (MCRegister
Reg : CallerSavedRegs) {
663 if (((1 <<
Reg) &
Call.LiveCallerSavedRegs) == 0)
666 CurOffset -= SlotSize;
686bool BPFMIPreEmitPeephole::removeMayGotoZero() {
688 MachineBasicBlock *Prev_MBB, *Curr_MBB =
nullptr;
693 if (Prev_MBB ==
nullptr || Curr_MBB->
empty())
696 MachineInstr &
MI = Curr_MBB->
back();
697 if (
MI.getOpcode() != TargetOpcode::INLINEASM_BR)
700 const char *AsmStr =
MI.getOperand(0).getSymbolName();
705 if (AsmPieces.
size() != 1)
711 if (AsmOpPieces.
size() != 2 || AsmOpPieces[0] !=
"may_goto")
714 if (AsmOpPieces[1] !=
"${0:l}" && AsmOpPieces[1] !=
"$0")
726 for (MachineBasicBlock *Pred : Curr_MBB->
predecessors())
727 Pred->replaceSuccessor(Curr_MBB, Prev_MBB);
732 MI.eraseFromParent();
742bool BPFMIPreEmitPeephole::addExitAfterUnreachable() {
743 MachineBasicBlock &
MBB = MF->
back();
745 if (
MI.getOpcode() != BPF::JAL || !
MI.getOperand(0).isGlobal() ||
746 MI.getOperand(0).getGlobal()->getName() !=
BPF_TRAP)
756 "BPF PreEmit Peephole Optimization",
false,
false)
758char BPFMIPreEmitPeephole::
ID = 0;
761 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, ArrayRef< StringLiteral > StandardNames)
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 & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register 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.
@ Define
Register definition.
@ Kill
The last use of a register.
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...