30#define DEBUG_TYPE "ppc-pre-emit-peephole"
33 "Number of r+r instructions converted to r+i in pre-emit peephole");
35 "Number of instructions deleted in pre-emit peephole");
37 "Number of self copy instructions eliminated");
39 "Number of folding frame offset by using r+r in pre-emit peephole");
41 "Number of compares eliminated in pre-emit peephole");
45 cl::desc(
"enable PC Relative linker optimization"));
49 cl::desc(
"Run pre-emit peephole optimizations."));
53 cl::desc(
"Set the Data Stream Control Register."));
58 switch (
Use.getOpcode()) {
109 MachineFunctionProperties::Property::NoVRegs);
123 LLVM_DEBUG(
dbgs() <<
"Remove redundant load immediates from MBB:\n";
130 if (InstrsToErase.contains(&*BBI))
133 unsigned Opc = BBI->getOpcode();
134 if (Opc != PPC::LI && Opc != PPC::LI8 && Opc != PPC::LIS &&
139 if (!BBI->getOperand(1).isImm())
141 assert(BBI->getOperand(0).isReg() &&
142 "Expected a register for the first operand");
144 LLVM_DEBUG(
dbgs() <<
"Scanning after load immediate: "; BBI->dump(););
147 int64_t
Imm = BBI->getOperand(1).getImm();
149 if (BBI->getOperand(0).isDead()) {
150 DeadOrKillToUnset = &BBI->getOperand(0);
152 <<
" from load immediate " << *BBI
153 <<
" is a unsetting candidate\n");
157 for (
auto AfterBBI = std::next(BBI); AfterBBI !=
MBB.
instr_end();
161 int KillIdx = AfterBBI->findRegisterUseOperandIdx(Reg,
true,
TRI);
165 if (KillIdx != -1 && AfterBBI->getOperand(KillIdx).isImplicit()) {
167 <<
"Encountered an implicit kill, cannot proceed: ");
173 assert(!DeadOrKillToUnset &&
"Shouldn't kill same register twice");
174 DeadOrKillToUnset = &AfterBBI->getOperand(KillIdx);
176 <<
" Kill flag of " << *DeadOrKillToUnset <<
" from "
177 << *AfterBBI <<
" is a unsetting candidate\n");
180 if (!AfterBBI->modifiesRegister(Reg,
TRI))
184 if (AfterBBI->getOpcode() != Opc)
186 assert(AfterBBI->getOperand(0).isReg() &&
187 "Expected a register for the first operand");
190 if (!AfterBBI->getOperand(1).isImm() ||
191 AfterBBI->getOperand(1).getImm() != Imm)
197 if (DeadOrKillToUnset) {
199 <<
" Unset dead/kill flag of " << *DeadOrKillToUnset
200 <<
" from " << *DeadOrKillToUnset->
getParent());
201 if (DeadOrKillToUnset->
isDef())
207 AfterBBI->findRegisterDefOperand(Reg,
true,
true,
TRI);
208 if (DeadOrKillToUnset)
210 <<
" Dead flag of " << *DeadOrKillToUnset <<
" from "
211 << *AfterBBI <<
" is a unsetting candidate\n");
212 InstrsToErase.insert(&*AfterBBI);
219 MI->eraseFromParent();
221 NumRemovedInPreEmit += InstrsToErase.size();
222 return !InstrsToErase.empty();
228 if (
Instr.getOpcode() != PPC::PLDpc)
233 if (!LoadedAddressReg.
isReg())
256 struct GOTDefUsePair {
266 bool MadeChange =
false;
272 if (isGOTPLDpc(*BBI)) {
274 BBI->getOperand(0).getReg(),
275 PPC::NoRegister,
true};
281 if (CandPairs.
empty())
288 GOTDefUsePair &Pair = CandPairs[
Idx];
291 if (!BBI->readsRegister(Pair.DefReg,
TRI) &&
292 !BBI->modifiesRegister(Pair.DefReg,
TRI))
298 hasPCRelativeForm(*BBI) ? &BBI->getOperand(2) :
nullptr;
301 if (UseOp && UseOp->
isReg() && UseOp->
getReg() == Pair.DefReg &&
304 Pair.UseReg = BBI->getOperand(0).getReg();
312 for (
auto Pair = ValidPairs.
begin(); Pair != ValidPairs.
end(); Pair++) {
314 assert(Pair->UseInst.isValid() && Pair->StillValid &&
315 "Kept an invalid def/use pair for GOT PCRel opt");
321 for (; BBI != Pair->UseInst; ++BBI) {
322 if (BBI->readsRegister(Pair->UseReg,
TRI) ||
323 BBI->modifiesRegister(Pair->UseReg,
TRI)) {
324 Pair->StillValid =
false;
329 if (!Pair->StillValid)
342 Pair->DefInst->addOperand(ImplDef);
343 Pair->UseInst->addOperand(ImplUse);
350 Pair->DefInst->addOperand(*MF, PCRelLabel);
351 Pair->UseInst->addOperand(*MF, PCRelLabel);
373 PPC::UACCRCRegClass.getNumRegs(),
nullptr);
376 unsigned Opc = BBI.getOpcode();
379 if (Opc == PPC::XXMTACC) {
380 Register Acc = BBI.getOperand(0).getReg();
382 "Unexpected register for XXMTACC");
383 Candidates[Acc - PPC::ACC0] = &BBI;
387 else if (Opc == PPC::XXMFACC) {
388 Register Acc = BBI.getOperand(0).getReg();
390 "Unexpected register for XXMFACC");
391 if (!Candidates[Acc - PPC::ACC0])
393 InstrsToErase.
insert(&BBI);
394 InstrsToErase.
insert(Candidates[Acc - PPC::ACC0]);
400 if (!Operand.isReg())
403 if (PPC::ACCRCRegClass.
contains(Reg))
404 Candidates[
Reg - PPC::ACC0] =
nullptr;
410 MI->eraseFromParent();
411 NumRemovedInPreEmit += InstrsToErase.size();
412 return !InstrsToErase.empty();
444 errs() <<
"Warning: Ran out of registers - Unable to set DSCR as "
455 if (
MI.getOpcode() == PPC::UNENCODED_NOP)
458 MI->eraseFromParent();
461 bool Changed =
false;
466 Changed |= removeRedundantLIs(
MBB,
TRI);
467 Changed |= addLinkerOpt(
MBB,
TRI);
468 Changed |= removeAccPrimeUnprime(
MBB);
470 unsigned Opc =
MI.getOpcode();
471 if (Opc == PPC::UNENCODED_NOP) {
479 MI.getOperand(0).getReg() ==
MI.getOperand(1).getReg() &&
480 MI.getOperand(0).getReg() ==
MI.getOperand(2).getReg()) {
481 NumberOfSelfCopies++;
488 MI.getOperand(0).getReg() ==
MI.getOperand(1).getReg()) {
489 NumberOfSelfCopies++;
498 if (
TII->convertToImmediateForm(
MI, UpdatedRegs, &DefMIToErase)) {
500 NumRRConvertedInPreEmit++;
507 if (
TII->foldFrameOffset(
MI)) {
509 NumFrameOffFoldInPreEmit++;
510 LLVM_DEBUG(
dbgs() <<
"Frame offset folding by using index form: ");
513 if (
TII->optimizeCmpPostRA(
MI)) {
535 bool SeenUse =
false;
537 for (It++; It != Er; It++) {
538 if (It->modifiesRegister(CRBit,
TRI)) {
539 if ((It->getOpcode() == PPC::CRUNSET ||
540 It->getOpcode() == PPC::CRSET) &&
541 It->getOperand(0).getReg() == CRBit)
545 if (It->readsRegister(CRBit,
TRI))
548 if (!CRSetMI)
continue;
551 if ((Br->
getOpcode() == PPC::BCn && CRSetOp == PPC::CRSET) ||
552 (Br->
getOpcode() == PPC::BC && CRSetOp == PPC::CRUNSET)) {
561 for (; It != Er; It++) {
562 if (It->isDebugInstr())
continue;
563 assert(It->isTerminator() &&
"Non-terminator after a terminator");
583 if (SuccMBB->isLiveIn(CRBit) || SuccMBB->isLiveIn(CRReg)) {
592 LLVM_DEBUG(
dbgs() <<
"PPC pre-emit peephole: erasing instruction: ");
594 MI->eraseFromParent();
595 NumRemovedInPreEmit++;
604char PPCPreEmitPeephole::
ID = 0;
607 return new PPCPreEmitPeephole();
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
unsigned const TargetRegisterInfo * TRI
static cl::opt< bool > EnablePCRelLinkerOpt("ppc-pcrel-linker-opt", cl::Hidden, cl::init(true), cl::desc("enable PC Relative linker optimization"))
static cl::opt< bool > RunPreEmitPeephole("ppc-late-peephole", cl::Hidden, cl::init(true), cl::desc("Run pre-emit peephole optimizations."))
static cl::opt< uint64_t > DSCRValue("ppc-set-dscr", cl::Hidden, cl::desc("Set the Data Stream Control Register."))
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file declares the machine register scavenger class.
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 bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Represent the analysis usage information of a pass.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Implements a dense probed hash-table based set.
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.
bool hasExternalLinkage() const
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
Insert branch code into the end of the specified MachineBasicBlock.
Context object for machine code objects.
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
instr_iterator instr_begin()
void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
bool isLayoutSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB will be emitted immediately after this block, such that if this bloc...
instr_iterator instr_end()
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
instr_iterator getFirstInstrTerminator()
Same getFirstTerminator but it ignores bundles and return an instr_iterator instead.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MCContext & getContext() const
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineBasicBlock & front() const
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.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
static MachineOperand CreateMCSymbol(MCSymbol *Sym, unsigned TargetFlags=0)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
void setIsDead(bool Val=true)
void setIsKill(bool Val=true)
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
Register getReg() const
getReg - Returns the register number.
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
static bool isSameClassPhysRegCopy(unsigned Opcode)
bool isUsingPCRelativeCalls() const
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Register FindUnusedReg(const TargetRegisterClass *RC) const
Find an unused register of the specified register class.
void enterBasicBlock(MachineBasicBlock &MBB)
Start tracking liveness from the begin of basic block MBB.
Wrapper class representing virtual and physical registers.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool equals(StringRef RHS) const
equals - Check for string equality, this is more efficient than compare() when the relative ordering ...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
A Use represents the edge between a Value definition and its users.
std::pair< iterator, bool > insert(const ValueT &V)
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ MO_GOT_FLAG
MO_GOT_FLAG - If this bit is set the symbol reference is to be computed via the GOT.
@ 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)
NodeAddr< InstrNode * > Instr
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createPPCPreEmitPeepholePass()
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static unsigned getCRFromCRBit(unsigned SrcReg)
void initializePPCPreEmitPeepholePass(PassRegistry &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.