13 #define DEBUG_TYPE "machine-combiner"
35 STATISTIC(NumInstCombined,
"Number of machineinst combined");
58 const char *getPassName()
const override {
return "Machine InstCombiner"; }
61 bool doSubstitute(
unsigned NewSize,
unsigned OldSize);
74 bool NewCodeHasLessInsts);
88 "Machine InstCombiner",
false,
false)
93 void MachineCombiner::getAnalysisUsage(
AnalysisUsage &AU)
const {
106 DefInstr = MRI->getUniqueVRegDef(MO.
getReg());
108 if (DefInstr && DefInstr->
isPHI())
127 assert(TSchedModel.hasInstrSchedModel() &&
"Missing machine model\n");
132 for (
auto *InstrPtr : InsInstrs) {
134 DEBUG(
dbgs() <<
"NEW INSTR "; InstrPtr->dump();
dbgs() <<
"\n";);
141 unsigned DepthOp = 0;
142 unsigned LatencyOp = 0;
145 if (II != InstrIdxForVirtReg.
end()) {
147 assert(II->second < InstrDepth.
size() &&
"Bad Index");
150 "There must be a definition for a new virtual register");
151 DepthOp = InstrDepth[II->second];
152 LatencyOp = TSchedModel.computeOperandLatency(
153 DefInstr, DefInstr->findRegisterDefOperandIdx(MO.
getReg()),
154 InstrPtr, InstrPtr->findRegisterUseOperandIdx(MO.
getReg()));
159 LatencyOp = TSchedModel.computeOperandLatency(
161 InstrPtr, InstrPtr->findRegisterUseOperandIdx(MO.
getReg()));
164 IDepth = std::max(IDepth, DepthOp + LatencyOp);
168 unsigned NewRootIdx = InsInstrs.size() - 1;
169 return InstrDepth[NewRootIdx];
184 assert(TSchedModel.hasInstrSchedModel() &&
"Missing machine model\n");
187 unsigned NewRootLatency = 0;
199 unsigned LatencyOp = 0;
201 LatencyOp = TSchedModel.computeOperandLatency(
205 LatencyOp = TSchedModel.computeInstrLatency(NewRoot->
getOpcode());
207 NewRootLatency = std::max(NewRootLatency, LatencyOp);
209 return NewRootLatency;
224 bool MachineCombiner::improvesCriticalPathLen(
229 bool NewCodeHasLessInsts) {
231 assert(TSchedModel.hasInstrSchedModel() &&
"Missing machine model\n");
234 unsigned NewRootIdx = InsInstrs.
size() - 1;
236 unsigned NewRootDepth = getDepth(InsInstrs, InstrIdxForVirtReg, BlockTrace);
237 unsigned NewRootLatency =
getLatency(Root, NewRoot, BlockTrace);
241 unsigned RootLatency = TSchedModel.computeInstrLatency(Root);
244 DEBUG(
dbgs() <<
"DEPENDENCE DATA FOR " << Root <<
"\n";
245 dbgs() <<
" NewRootDepth: " << NewRootDepth
246 <<
" NewRootLatency: " << NewRootLatency <<
"\n";
247 dbgs() <<
" RootDepth: " << RootDepth <<
" RootLatency: " << RootLatency
248 <<
" RootSlack: " << RootSlack <<
"\n";
249 dbgs() <<
" NewRootDepth + NewRootLatency "
250 << NewRootDepth + NewRootLatency <<
"\n";
251 dbgs() <<
" RootDepth + RootLatency + RootSlack "
252 << RootDepth + RootLatency + RootSlack <<
"\n";);
254 unsigned NewCycleCount = NewRootDepth + NewRootLatency;
255 unsigned OldCycleCount = RootDepth + RootLatency + RootSlack;
257 if (NewCodeHasLessInsts)
258 return NewCycleCount <= OldCycleCount;
260 return NewCycleCount < OldCycleCount;
264 void MachineCombiner::instr2instrSC(
267 for (
auto *InstrPtr : Instrs) {
268 unsigned Opc = InstrPtr->getOpcode();
269 unsigned Idx =
TII->get(Opc).getSchedClass();
275 bool MachineCombiner::preservesResourceLen(
291 instr2instrSC(InsInstrs, InsInstrsSC);
292 instr2instrSC(DelInstrs, DelInstrsSC);
298 unsigned ResLenAfterCombine =
302 dbgs() <<
" resource len before: " << ResLenBeforeCombine
303 <<
" after: " << ResLenAfterCombine <<
"\n";);
305 return ResLenAfterCombine <= ResLenBeforeCombine;
310 bool MachineCombiner::doSubstitute(
unsigned NewSize,
unsigned OldSize) {
311 if (OptSize && (NewSize < OldSize))
313 if (!TSchedModel.hasInstrSchedModel())
326 bool Changed =
false;
329 auto BlockIter = MBB->
begin();
331 while (BlockIter != MBB->
end()) {
332 auto &
MI = *BlockIter++;
361 if (
TII->getMachineCombinerPatterns(
MI, Patterns)) {
362 for (
auto P : Patterns) {
369 Traces->verifyAnalysis();
370 TII->genAlternativeCodeSequence(
MI,
P, InsInstrs, DelInstrs,
372 unsigned NewInstCount = InsInstrs.
size();
373 unsigned OldInstCount = DelInstrs.
size();
383 if (doSubstitute(NewInstCount, OldInstCount) ||
384 (improvesCriticalPathLen(MBB, &
MI, BlockTrace, InsInstrs,
386 NewInstCount < OldInstCount) &&
387 preservesResourceLen(MBB, BlockTrace, InsInstrs, DelInstrs))) {
388 for (
auto *InstrPtr : InsInstrs)
390 for (
auto *InstrPtr : DelInstrs)
391 InstrPtr->eraseFromParentAndMarkDBGValuesForRemoval();
396 Traces->invalidate(MBB);
397 Traces->verifyAnalysis();
404 for (
auto *InstrPtr : InsInstrs)
407 InstrIdxForVirtReg.
clear();
420 TSchedModel.init(SchedModel, &STI,
TII);
422 Traces = &getAnalysis<MachineTraceMetrics>();
428 if (!
TII->useMachineCombiner()) {
429 DEBUG(
dbgs() <<
" Skipping pass: Target does not support machine combiner\n");
433 bool Changed =
false;
437 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
getParent - 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 ...
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...
static bool isVirtualRegister(unsigned Reg)
isVirtualRegister - 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()
#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.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
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
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst)
Gets latency information for Inst, based on DC information.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
TargetInstrInfo - Interface to description of machine instruction set.
bundle_iterator< MachineInstr, instr_iterator > iterator
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.
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
getName - 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.
InstrCycles getInstrCycles(const MachineInstr *MI) const
Return the depth and height of MI.
Representation of each machine instruction.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
iterator find(const KeyT &Val)
unsigned getReg() const
getReg - Returns the register number.
virtual const TargetInstrInfo * getInstrInfo() const
void initializeMachineCombinerPass(PassRegistry &)
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
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
unsigned getInstrSlack(const MachineInstr *MI) const
Return the slack of MI.