14 #define DEBUG_TYPE "machine-combiner"
35 STATISTIC(NumInstCombined,
"Number of machineinst combined");
59 StringRef getPassName()
const override {
return "Machine InstCombiner"; }
62 bool doSubstitute(
unsigned NewSize,
unsigned OldSize);
90 "Machine InstCombiner",
false,
false)
96 void MachineCombiner::getAnalysisUsage(
AnalysisUsage &AU)
const {
110 DefInstr =
MRI->getUniqueVRegDef(MO.
getReg());
112 if (DefInstr && DefInstr->
isPHI())
130 assert(TSchedModel.hasInstrSchedModelOrItineraries() &&
131 "Missing machine model\n");
136 for (
auto *InstrPtr : InsInstrs) {
145 unsigned DepthOp = 0;
146 unsigned LatencyOp = 0;
149 if (II != InstrIdxForVirtReg.
end()) {
151 assert(II->second < InstrDepth.
size() &&
"Bad Index");
154 "There must be a definition for a new virtual register");
155 DepthOp = InstrDepth[II->second];
156 LatencyOp = TSchedModel.computeOperandLatency(
157 DefInstr, DefInstr->findRegisterDefOperandIdx(MO.
getReg()),
158 InstrPtr, InstrPtr->findRegisterUseOperandIdx(MO.
getReg()));
163 LatencyOp = TSchedModel.computeOperandLatency(
165 InstrPtr, InstrPtr->findRegisterUseOperandIdx(MO.
getReg()));
168 IDepth = std::max(IDepth, DepthOp + LatencyOp);
172 unsigned NewRootIdx = InsInstrs.size() - 1;
173 return InstrDepth[NewRootIdx];
187 assert(TSchedModel.hasInstrSchedModelOrItineraries() &&
188 "Missing machine model\n");
191 unsigned NewRootLatency = 0;
203 unsigned LatencyOp = 0;
205 LatencyOp = TSchedModel.computeOperandLatency(
209 LatencyOp = TSchedModel.computeInstrLatency(NewRoot);
211 NewRootLatency = std::max(NewRootLatency, LatencyOp);
213 return NewRootLatency;
242 bool MachineCombiner::improvesCriticalPathLen(
249 assert(TSchedModel.hasInstrSchedModelOrItineraries() &&
250 "Missing machine model\n");
252 unsigned NewRootIdx = InsInstrs.
size() - 1;
256 unsigned NewRootDepth = getDepth(InsInstrs, InstrIdxForVirtReg, BlockTrace);
259 DEBUG(
dbgs() <<
"DEPENDENCE DATA FOR " << Root <<
"\n";
260 dbgs() <<
" NewRootDepth: " << NewRootDepth <<
"\n";
261 dbgs() <<
" RootDepth: " << RootDepth <<
"\n");
269 return NewRootDepth < RootDepth;
275 unsigned NewRootLatency =
getLatency(Root, NewRoot, BlockTrace);
276 unsigned RootLatency = 0;
278 for (
auto I : DelInstrs)
279 RootLatency += TSchedModel.computeInstrLatency(
I);
283 DEBUG(
dbgs() <<
" NewRootLatency: " << NewRootLatency <<
"\n";
284 dbgs() <<
" RootLatency: " << RootLatency <<
"\n";
285 dbgs() <<
" RootSlack: " << RootSlack <<
"\n";
286 dbgs() <<
" NewRootDepth + NewRootLatency = "
287 << NewRootDepth + NewRootLatency <<
"\n";
288 dbgs() <<
" RootDepth + RootLatency + RootSlack = "
289 << RootDepth + RootLatency + RootSlack <<
"\n";);
291 unsigned NewCycleCount = NewRootDepth + NewRootLatency;
292 unsigned OldCycleCount = RootDepth + RootLatency + RootSlack;
294 return NewCycleCount <= OldCycleCount;
298 void MachineCombiner::instr2instrSC(
301 for (
auto *InstrPtr : Instrs) {
302 unsigned Opc = InstrPtr->getOpcode();
303 unsigned Idx =
TII->get(Opc).getSchedClass();
310 bool MachineCombiner::preservesResourceLen(
314 if (!TSchedModel.hasInstrSchedModel())
328 instr2instrSC(InsInstrs, InsInstrsSC);
329 instr2instrSC(DelInstrs, DelInstrsSC);
335 unsigned ResLenAfterCombine =
339 dbgs() <<
" resource len before: " << ResLenBeforeCombine
340 <<
" after: " << ResLenAfterCombine <<
"\n";);
342 return ResLenAfterCombine <= ResLenBeforeCombine;
347 bool MachineCombiner::doSubstitute(
unsigned NewSize,
unsigned OldSize) {
348 if (OptSize && (NewSize < OldSize))
350 if (!TSchedModel.hasInstrSchedModelOrItineraries())
363 bool Changed =
false;
366 auto BlockIter = MBB->
begin();
370 while (BlockIter != MBB->
end()) {
371 auto &
MI = *BlockIter++;
400 if (!
TII->getMachineCombinerPatterns(
MI, Patterns))
403 for (
auto P : Patterns) {
410 Traces->verifyAnalysis();
411 TII->genAlternativeCodeSequence(
MI,
P, InsInstrs, DelInstrs,
413 unsigned NewInstCount = InsInstrs.
size();
414 unsigned OldInstCount = DelInstrs.
size();
421 bool SubstituteAlways =
false;
422 if (ML &&
TII->isThroughputPattern(
P))
423 SubstituteAlways =
true;
429 if (SubstituteAlways || doSubstitute(NewInstCount, OldInstCount) ||
430 (improvesCriticalPathLen(MBB, &
MI, BlockTrace, InsInstrs,
431 DelInstrs, InstrIdxForVirtReg,
P) &&
432 preservesResourceLen(MBB, BlockTrace, InsInstrs, DelInstrs))) {
433 for (
auto *InstrPtr : InsInstrs)
435 for (
auto *InstrPtr : DelInstrs)
436 InstrPtr->eraseFromParentAndMarkDBGValuesForRemoval();
441 Traces->invalidate(MBB);
442 Traces->verifyAnalysis();
449 for (
auto *InstrPtr : InsInstrs)
452 InstrIdxForVirtReg.
clear();
464 TSchedModel.init(SchedModel, &STI,
TII);
466 MLI = &getAnalysis<MachineLoopInfo>();
467 Traces = &getAnalysis<MachineTraceMetrics>();
472 if (!
TII->useMachineCombiner()) {
473 DEBUG(
dbgs() <<
" Skipping pass: Target does not support machine combiner\n");
477 bool Changed =
false;
481 Changed |= combineInstructions(&MBB);
void push_back(const T &Elt)
char & MachineCombinerID
This pass performs instruction combining using trace metrics to estimate critical-path and resource d...
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
STATISTIC(NumFunctions,"Total number of functions")
unsigned Depth
Earliest issue cycle as determined by data dependencies and instruction latencies from the beginning ...
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
A trace ensemble is a collection of traces selected using the same strategy, for example 'minimum res...
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
iterator_range< mop_iterator > operands()
bool optForSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
InstrCycles getInstrCycles(const MachineInstr &MI) const
Return the depth and height of MI.
#define INITIALIZE_PASS_DEPENDENCY(depName)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Provide an instruction scheduling machine model to CodeGen passes.
const HexagonInstrInfo * TII
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
bool isReg() const
isReg - Tests if this is a MO_Register operand.
The core instruction combiner logic.
const MCSchedModel & getSchedModel() const
Get the machine model for this subtarget's CPU.
Select the trace through a block that has the fewest instructions.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
COFF::MachineTypes Machine
static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst)
Gets latency information for Inst, based on DC information.
TargetInstrInfo - Interface to description of machine instruction set.
static CombinerObjective getCombinerObjective(MachineCombinerPattern P)
unsigned const MachineRegisterInfo * MRI
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
int findRegisterDefOperandIdx(unsigned Reg, bool isDead=false, bool Overlap=false, const TargetRegisterInfo *TRI=nullptr) const
Returns the operand index that is a def of the specified register or -1 if it is not found...
Summarize the scheduling resources required for an instruction of a particular scheduling class...
unsigned getResourceLength(ArrayRef< const MachineBasicBlock * > Extrablocks=None, ArrayRef< const MCSchedClassDesc * > ExtraInstrs=None, ArrayRef< const MCSchedClassDesc * > RemoveInstrs=None) const
Return the resource length of the trace.
Represent the analysis usage information of a pass.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
CombinerObjective
The combiner's goal may differ based on which pattern it is attempting to optimize.
MachineCombinerPattern
These are instruction patterns matched by the machine combiner pass.
void DeleteMachineInstr(MachineInstr *MI)
DeleteMachineInstr - Delete the given MachineInstr.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
A trace represents a plausible sequence of executed basic blocks that passes through the current basi...
int findRegisterUseOperandIdx(unsigned Reg, bool isKill=false, const TargetRegisterInfo *TRI=nullptr) const
Returns the operand index that is a use of the specific register or -1 if it is not found...
MachineOperand class - Representation of each machine instruction operand.
CHAIN = SC CHAIN, Imm128 - System call.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
StringRef getName() const
Return the name of the corresponding LLVM basic block, or "(null)".
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
TargetSubtargetInfo - Generic base class for all target subtargets.
unsigned getInstrSlack(const MachineInstr &MI) const
Return the slack of MI.
Representation of each machine instruction.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
iterator find(const KeyT &Val)
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
virtual const TargetInstrInfo * getInstrInfo() const
bool isDepInTrace(const MachineInstr &DefMI, const MachineInstr &UseMI) const
A dependence is useful if the basic block of the defining instruction is part of the trace of the use...
void initializeMachineCombinerPass(PassRegistry &)
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
StringRef - Represent a constant reference to a string, i.e.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
reg_begin/reg_end - Provide iteration support to walk over all definitions and uses of a register wit...
Machine model for scheduling, bundling, and heuristics.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
INITIALIZE_PASS_BEGIN(MachineCombiner,"machine-combiner","Machine InstCombiner", false, false) INITIALIZE_PASS_END(MachineCombiner