37#define DEBUG_TYPE "bpf-mi-zext-elim"
42STATISTIC(ZExtElemNum,
"Number of zero extension shifts eliminated");
65 bool eliminateZExtSeq();
68 std::set<MachineInstr *> PhiInsns;
81 bool ZExtSeqExist, ZExtExist;
82 ZExtSeqExist = eliminateZExtSeq();
83 ZExtExist = eliminateZExt();
84 return ZExtSeqExist || ZExtExist;
93 LLVM_DEBUG(
dbgs() <<
"*** BPF MachineSSA ZEXT Elim peephole pass ***\n\n");
107 if (!
Reg.isVirtual())
110 if (
MRI->getRegClass(Reg) == &BPF::GPRRegClass)
114 if (!isInsnFrom32Def(DefInsn))
122 for (
unsigned i = 1, e = PhiMI->
getNumOperands(); i < e; i += 2) {
131 if (PhiDef->
isPHI()) {
132 if (!PhiInsns.insert(PhiDef).second)
134 if (!isPhiFrom32Def(PhiDef))
137 if (PhiDef->
getOpcode() == BPF::COPY && !isCopyFrom32Def(PhiDef))
145bool BPFMIPeephole::isInsnFrom32Def(
MachineInstr *DefInsn)
150 if (DefInsn->
isPHI()) {
151 if (!PhiInsns.insert(DefInsn).second)
153 if (!isPhiFrom32Def(DefInsn))
155 }
else if (DefInsn->
getOpcode() == BPF::COPY) {
156 if (!isCopyFrom32Def(DefInsn))
171 if (!isInsnFrom32Def(DefInsn))
179bool BPFMIPeephole::eliminateZExtSeq() {
181 bool Eliminated =
false;
196 if (
MI.getOpcode() == BPF::SRL_ri &&
197 MI.getOperand(2).getImm() == 32) {
224 if (!isMovFrom32Def(MovMI)) {
226 <<
" One ZExt elim sequence failed qualifying elim.\n");
247bool BPFMIPeephole::eliminateZExt() {
249 bool Eliminated =
false;
259 if (
MI.getOpcode() != BPF::MOV_32_64)
272 if (!isMovFrom32Def(&
MI))
295 "BPF MachineSSA Peephole Optimization For ZEXT Eliminate",
298char BPFMIPeephole::
ID = 0;
301STATISTIC(RedundantMovElemNum,
"Number of redundant moves eliminated");
321 bool in16BitRange(
int Num);
322 bool eliminateRedundantMov();
324 bool insertMissingCallerSavedSpills();
336 Changed = eliminateRedundantMov();
338 Changed = adjustBranch() || Changed;
339 Changed |= insertMissingCallerSavedSpills();
353bool BPFMIPreEmitPeephole::eliminateRedundantMov() {
355 bool Eliminated =
false;
376 unsigned Opcode =
MI.getOpcode();
377 if (Opcode == BPF::MOV_rr) {
385 RedundantMovElemNum++;
394bool BPFMIPreEmitPeephole::in16BitRange(
int Num) {
413bool BPFMIPreEmitPeephole::adjustBranch() {
414 bool Changed =
false;
415 int CurrNumInsns = 0;
418 std::vector<MachineBasicBlock *> MBBs;
427 CurrNumInsns += (int)
MBB.
size();
428 SoFarNumInsns[&
MBB] = CurrNumInsns;
429 if (PrevBB !=
nullptr)
430 FollowThroughBB[PrevBB] = &
MBB;
435 FollowThroughBB[PrevBB] =
nullptr;
437 for (
unsigned i = 0; i < MBBs.size(); i++) {
447 if (
Term.isConditionalBranch()) {
448 assert(CondJmp ==
nullptr);
450 }
else if (
Term.isUnconditionalBranch()) {
451 assert(UncondJmp ==
nullptr);
457 if (!CondJmp && !UncondJmp)
461 CurrNumInsns = SoFarNumInsns[
MBB];
464 if (!CondJmp && UncondJmp) {
465 JmpBB = UncondJmp->getOperand(0).getMBB();
466 if (in16BitRange(SoFarNumInsns[JmpBB] - JmpBB->
size() - CurrNumInsns))
483 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->
size() - CurrNumInsns;
484 if (in16BitRange(Dist))
506 MF->insert(MBB_I, New_B0);
507 MF->insert(MBB_I, New_B1);
542 JmpBB = UncondJmp->getOperand(0).getMBB();
562 Dist = SoFarNumInsns[CondTargetBB] - CondTargetBB->
size() - CurrNumInsns;
563 if (!in16BitRange(Dist)) {
581 if (CondTargetBB != JmpBB)
593 if (!in16BitRange(SoFarNumInsns[JmpBB] - CurrNumInsns)) {
603static const unsigned CallerSavedRegs[] = {BPF::R0, BPF::R1, BPF::R2,
604 BPF::R3, BPF::R4, BPF::R5};
608 unsigned LiveCallerSavedRegs;
619 unsigned LiveCallerSavedRegs = 0;
621 bool DoSpillFill =
false;
623 DoSpillFill |= !
MI.definesRegister(SR,
TRI) && LiveRegs.
contains(SR);
626 LiveCallerSavedRegs |= 1 <<
R;
628 if (LiveCallerSavedRegs)
637 int64_t MinFixedObjOffset = 0;
645 (SlotSize + MinFixedObjOffset % SlotSize) & (SlotSize - 1);
646 return MinFixedObjOffset;
649bool BPFMIPreEmitPeephole::insertMissingCallerSavedSpills() {
653 const unsigned SlotSize = 8;
654 int64_t MinFixedObjOffset = computeMinFixedObjOffset(MFI, SlotSize);
655 bool Changed =
false;
657 collectBPFFastCalls(
TRI, LiveRegs, BB, Calls);
658 Changed |= !Calls.
empty();
659 for (BPFFastCall &Call : Calls) {
660 int64_t CurOffset = MinFixedObjOffset;
662 if (((1 << Reg) &
Call.LiveCallerSavedRegs) == 0)
665 CurOffset -= SlotSize;
688 "BPF PreEmit Peephole Optimization",
false,
false)
690char BPFMIPreEmitPeephole::
ID = 0;
693 return new BPFMIPreEmitPeephole();
unsigned const MachineRegisterInfo * MRI
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.
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
LLVM Basic Block Representation.
FunctionPass class - This class is used to implement most global optimizations.
bool skipFunction(const Function &F) const
Optional passes call this function to check whether the pass should be skipped.
A set of physical registers with utility functions to track liveness when walking backward/forward th...
bool contains(MCPhysReg Reg) const
Returns true if register Reg is contained in the set.
void stepBackward(const MachineInstr &MI)
Simulates liveness when stepping backwards over an instruction(bundle).
void init(const TargetRegisterInfo &TRI)
(re-)initializes and clears the set.
void addLiveOuts(const MachineBasicBlock &MBB)
Adds all live-out registers of basic block MBB.
Wrapper class representing physical registers. Should be passed by value.
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
void push_back(MachineInstr *MI)
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
iterator_range< iterator > terminators()
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
int getObjectIndexEnd() const
Return one past the maximum frame object index.
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...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
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.
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
Representation of each machine instruction.
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.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Wrapper class representing virtual and physical registers.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
@ Define
Register definition.
@ Kill
The last use of a register.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
void initializeBPFMIPreEmitPeepholePass(PassRegistry &)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createBPFMIPreEmitPeepholePass()
void initializeBPFMIPeepholePass(PassRegistry &)
FunctionPass * createBPFMIPeepholePass()
auto reverse(ContainerTy &&C)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.