37#define DEBUG_TYPE "machine-combiner"
39STATISTIC(NumInstCombined,
"Number of machineinst combined");
43 cl::desc(
"Incremental depth computation will be used for basic "
44 "blocks with more instructions."),
cl::init(500));
47 cl::desc(
"Dump all substituted intrs"),
50#ifdef EXPENSIVE_CHECKS
52 "machine-combiner-verify-pattern-order",
cl::Hidden,
54 "Verify that the generated patterns are ordered by increasing latency"),
58 "machine-combiner-verify-pattern-order",
cl::Hidden,
60 "Verify that the generated patterns are ordered by increasing latency"),
83 void getAnalysisUsage(AnalysisUsage &AU)
const override;
84 bool runOnMachineFunction(MachineFunction &MF)
override;
85 StringRef getPassName()
const override {
return "Machine InstCombiner"; }
88 bool combineInstructions(MachineBasicBlock *);
89 MachineInstr *getOperandDef(
const MachineOperand &MO);
90 bool isTransientMI(
const MachineInstr *
MI);
91 unsigned getDepth(SmallVectorImpl<MachineInstr *> &InsInstrs,
92 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
94 const MachineBasicBlock &
MBB);
95 unsigned getLatency(MachineInstr *Root, MachineInstr *NewRoot,
97 bool improvesCriticalPathLen(MachineBasicBlock *
MBB, MachineInstr *Root,
99 SmallVectorImpl<MachineInstr *> &InsInstrs,
100 SmallVectorImpl<MachineInstr *> &DelInstrs,
101 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
102 unsigned Pattern,
bool SlackIsAccurate);
103 bool reduceRegisterPressure(MachineInstr &Root, MachineBasicBlock *
MBB,
104 SmallVectorImpl<MachineInstr *> &InsInstrs,
105 SmallVectorImpl<MachineInstr *> &DelInstrs,
107 bool preservesResourceLen(MachineBasicBlock *
MBB,
109 SmallVectorImpl<MachineInstr *> &InsInstrs,
110 SmallVectorImpl<MachineInstr *> &DelInstrs);
111 void instr2instrSC(SmallVectorImpl<MachineInstr *> &Instrs,
112 SmallVectorImpl<const MCSchedClassDesc *> &InstrsSC);
113 std::pair<unsigned, unsigned>
114 getLatenciesForInstrSequences(MachineInstr &
MI,
115 SmallVectorImpl<MachineInstr *> &InsInstrs,
116 SmallVectorImpl<MachineInstr *> &DelInstrs,
123char MachineCombiner::ID = 0;
127 "Machine InstCombiner",
false,
false)
134void MachineCombiner::getAnalysisUsage(
AnalysisUsage &AU)
const {
135 AU.setPreservesCFG();
150 MachineInstr *DefInstr =
nullptr;
158bool MachineCombiner::isTransientMI(
const MachineInstr *
MI) {
160 return MI->isTransient();
166 if (!
MI->isFullCopy()) {
168 if (
MI->getOperand(0).getSubReg() || Src.isPhysical() || Dst.isPhysical())
171 auto SrcSub =
MI->getOperand(1).getSubReg();
174 return TRI->getMatchingSuperRegClass(SrcRC, DstRC, SrcSub) !=
nullptr;
177 if (Src.isPhysical() && Dst.isPhysical())
180 if (Src.isVirtual() && Dst.isVirtual()) {
203MachineCombiner::getDepth(SmallVectorImpl<MachineInstr *> &InsInstrs,
204 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
206 const MachineBasicBlock &
MBB) {
207 SmallVector<unsigned, 16> InstrDepth;
211 for (
auto *InstrPtr : InsInstrs) {
213 for (
const MachineOperand &MO : InstrPtr->all_uses()) {
217 unsigned DepthOp = 0;
218 unsigned LatencyOp = 0;
220 if (
II != InstrIdxForVirtReg.
end()) {
223 MachineInstr *DefInstr = InsInstrs[
II->second];
225 "There must be a definition for a new virtual register");
226 DepthOp = InstrDepth[
II->second];
230 InstrPtr->findRegisterUseOperandIdx(MO.
getReg(),
nullptr);
234 MachineInstr *DefInstr = getOperandDef(MO);
235 if (DefInstr && (
TII->getMachineCombinerTraceStrategy() !=
236 MachineTraceStrategy::TS_Local ||
239 if (!isTransientMI(DefInstr))
245 InstrPtr->findRegisterUseOperandIdx(MO.
getReg(),
249 IDepth = std::max(IDepth, DepthOp + LatencyOp);
253 unsigned NewRootIdx = InsInstrs.size() - 1;
254 return InstrDepth[NewRootIdx];
266unsigned MachineCombiner::getLatency(MachineInstr *Root, MachineInstr *NewRoot,
269 unsigned NewRootLatency = 0;
271 for (
const MachineOperand &MO : NewRoot->
all_defs()) {
281 unsigned LatencyOp = 0;
289 LatencyOp = TSchedModel.computeInstrLatency(NewRoot);
291 NewRootLatency = std::max(NewRootLatency, LatencyOp);
293 return NewRootLatency;
300 case MachineCombinerPattern::REASSOC_AX_BY:
301 case MachineCombinerPattern::REASSOC_AX_YB:
302 case MachineCombinerPattern::REASSOC_XA_BY:
303 case MachineCombinerPattern::REASSOC_XA_YB:
304 return CombinerObjective::MustReduceDepth;
306 return TII->getCombinerObjective(Pattern);
314std::pair<unsigned, unsigned> MachineCombiner::getLatenciesForInstrSequences(
315 MachineInstr &
MI, SmallVectorImpl<MachineInstr *> &InsInstrs,
316 SmallVectorImpl<MachineInstr *> &DelInstrs,
318 assert(!InsInstrs.
empty() &&
"Only support sequences that insert instrs.");
319 unsigned NewRootLatency = 0;
321 MachineInstr *NewRoot = InsInstrs.
back();
322 for (
unsigned i = 0; i < InsInstrs.
size() - 1; i++)
323 NewRootLatency += TSchedModel.computeInstrLatency(InsInstrs[i]);
324 NewRootLatency += getLatency(&
MI, NewRoot, BlockTrace);
326 unsigned RootLatency = 0;
327 for (
auto *
I : DelInstrs)
328 RootLatency += TSchedModel.computeInstrLatency(
I);
330 return {NewRootLatency, RootLatency};
333bool MachineCombiner::reduceRegisterPressure(
334 MachineInstr &Root, MachineBasicBlock *
MBB,
335 SmallVectorImpl<MachineInstr *> &InsInstrs,
336 SmallVectorImpl<MachineInstr *> &DelInstrs,
unsigned Pattern) {
349bool MachineCombiner::improvesCriticalPathLen(
350 MachineBasicBlock *
MBB, MachineInstr *Root,
352 SmallVectorImpl<MachineInstr *> &InsInstrs,
353 SmallVectorImpl<MachineInstr *> &DelInstrs,
354 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
unsigned Pattern,
355 bool SlackIsAccurate) {
357 unsigned NewRootDepth =
358 getDepth(InsInstrs, InstrIdxForVirtReg, BlockTrace, *
MBB);
361 LLVM_DEBUG(
dbgs() <<
" Dependence data for " << *Root <<
"\tNewRootDepth: "
362 << NewRootDepth <<
"\tRootDepth: " << RootDepth);
369 if (getCombinerObjective(Pattern) == CombinerObjective::MustReduceDepth) {
372 ?
dbgs() <<
"\t and it does it\n"
373 :
dbgs() <<
"\t but it does NOT do it\n");
374 return NewRootDepth < RootDepth;
382 unsigned NewRootLatency, RootLatency;
383 if (
TII->accumulateInstrSeqToRootLatency(*Root)) {
384 std::tie(NewRootLatency, RootLatency) =
385 getLatenciesForInstrSequences(*Root, InsInstrs, DelInstrs, BlockTrace);
387 NewRootLatency = TSchedModel.computeInstrLatency(InsInstrs.
back());
388 RootLatency = TSchedModel.computeInstrLatency(Root);
392 unsigned NewCycleCount = NewRootDepth + NewRootLatency;
393 unsigned OldCycleCount =
394 RootDepth + RootLatency + (SlackIsAccurate ? RootSlack : 0);
396 <<
"\tRootLatency: " << RootLatency <<
"\n\tRootSlack: "
397 << RootSlack <<
" SlackIsAccurate=" << SlackIsAccurate
398 <<
"\n\tNewRootDepth + NewRootLatency = " << NewCycleCount
399 <<
"\n\tRootDepth + RootLatency + RootSlack = "
402 ?
dbgs() <<
"\n\t It IMPROVES PathLen because"
403 :
dbgs() <<
"\n\t It DOES NOT improve PathLen because");
405 <<
", OldCycleCount = " << OldCycleCount <<
"\n");
407 return NewCycleCount <= OldCycleCount;
411void MachineCombiner::instr2instrSC(
412 SmallVectorImpl<MachineInstr *> &Instrs,
413 SmallVectorImpl<const MCSchedClassDesc *> &InstrsSC) {
414 for (
auto *InstrPtr : Instrs) {
415 unsigned Opc = InstrPtr->getOpcode();
416 unsigned Idx =
TII->get(
Opc).getSchedClass();
423bool MachineCombiner::preservesResourceLen(
425 SmallVectorImpl<MachineInstr *> &InsInstrs,
426 SmallVectorImpl<MachineInstr *> &DelInstrs) {
441 instr2instrSC(InsInstrs, InsInstrsSC);
442 instr2instrSC(DelInstrs, DelInstrsSC);
448 unsigned ResLenAfterCombine =
452 << ResLenBeforeCombine
453 <<
" and after: " << ResLenAfterCombine <<
"\n");
455 ResLenAfterCombine <=
456 ResLenBeforeCombine +
TII->getExtendResourceLenLimit()
457 ?
dbgs() <<
"\t\t As result it IMPROVES/PRESERVES Resource Length\n"
458 :
dbgs() <<
"\t\t As result it DOES NOT improve/preserve Resource "
461 return ResLenAfterCombine <=
462 ResLenBeforeCombine +
TII->getExtendResourceLenLimit();
484 unsigned Pattern,
bool IncrementalUpdate) {
494 for (
auto *InstrPtr : InsInstrs)
497 for (
auto *InstrPtr : DelInstrs) {
498 InstrPtr->eraseFromParent();
500 for (
auto *
I = RegUnits.
begin();
I != RegUnits.
end();) {
501 if (
I->MI == InstrPtr)
508 if (IncrementalUpdate)
509 for (
auto *InstrPtr : InsInstrs)
524bool MachineCombiner::combineInstructions(MachineBasicBlock *
MBB) {
528 bool IncrementalUpdate =
false;
530 decltype(BlockIter) LastUpdate;
534 TraceEnsemble = Traces->
getEnsemble(
TII->getMachineCombinerTraceStrategy());
541 bool DoRegPressureReduce =
542 TII->shouldReduceRegisterPressure(
MBB, RegClassInfo);
544 while (BlockIter !=
MBB->
end()) {
545 auto &
MI = *BlockIter++;
546 SmallVector<unsigned, 16> Patterns;
574 if (!
TII->getMachineCombinerPatterns(
MI, Patterns, DoRegPressureReduce))
578 [[maybe_unused]]
long PrevLatencyDiff = std::numeric_limits<long>::max();
580 for (
const auto P : Patterns) {
583 DenseMap<Register, unsigned> InstrIdxForVirtReg;
584 TII->genAlternativeCodeSequence(
MI,
P, InsInstrs, DelInstrs,
589 if (InsInstrs.
empty())
593 dbgs() <<
"\tFor the Pattern (" << (int)
P
594 <<
") these instructions could be removed\n";
595 for (
auto const *InstrPtr : DelInstrs)
596 InstrPtr->print(
dbgs(),
false,
false,
598 dbgs() <<
"\tThese instructions could replace the removed ones\n";
599 for (
auto const *InstrPtr : InsInstrs)
600 InstrPtr->print(
dbgs(),
false,
false,
608 auto [NewRootLatency, RootLatency] = getLatenciesForInstrSequences(
610 long CurrentLatencyDiff = ((long)RootLatency) - ((
long)NewRootLatency);
611 assert(CurrentLatencyDiff <= PrevLatencyDiff &&
612 "Current pattern is expected to be better than the previous "
614 PrevLatencyDiff = CurrentLatencyDiff;
617 if (IncrementalUpdate && LastUpdate != BlockIter) {
619 TraceEnsemble->
updateDepths(LastUpdate, BlockIter, RegUnits);
620 LastUpdate = BlockIter;
623 if (DoRegPressureReduce &&
624 getCombinerObjective(
P) ==
625 CombinerObjective::MustReduceRegisterPressure) {
628 IncrementalUpdate =
true;
629 LastUpdate = BlockIter;
631 if (reduceRegisterPressure(
MI,
MBB, InsInstrs, DelInstrs,
P)) {
634 RegUnits,
TII,
P, IncrementalUpdate);
644 if (
ML &&
TII->isThroughputPattern(
P)) {
645 LLVM_DEBUG(
dbgs() <<
"\t Replacing due to throughput pattern in loop\n");
647 RegUnits,
TII,
P, IncrementalUpdate);
651 }
else if (OptForSize && InsInstrs.size() < DelInstrs.size()) {
653 << InsInstrs.size() <<
" < "
654 << DelInstrs.size() <<
")\n");
656 RegUnits,
TII,
P, IncrementalUpdate);
668 if (improvesCriticalPathLen(
MBB, &
MI, BlockTrace, InsInstrs, DelInstrs,
669 InstrIdxForVirtReg,
P,
670 !IncrementalUpdate) &&
671 preservesResourceLen(
MBB, BlockTrace, InsInstrs, DelInstrs)) {
674 IncrementalUpdate =
true;
675 LastUpdate = BlockIter;
679 RegUnits,
TII,
P, IncrementalUpdate);
688 for (
auto *InstrPtr : InsInstrs)
689 MF->deleteMachineInstr(InstrPtr);
691 InstrIdxForVirtReg.
clear();
695 if (
Changed && IncrementalUpdate)
700bool MachineCombiner::runOnMachineFunction(MachineFunction &MF) {
705 TSchedModel.
init(STI);
707 MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
708 Traces = &getAnalysis<MachineTraceMetricsWrapperPass>().getMTM();
709 PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
711 &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI() :
713 TraceEnsemble =
nullptr;
714 RegClassInfo = &getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI();
720 <<
" Skipping pass: Target does not support machine combiner\n");
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the DenseMap class.
const HexagonInstrInfo * TII
===- LazyMachineBlockFrequencyInfo.h - Lazy Block Frequency -*- C++ -*–===//
static void insertDeleteInstructions(MachineBasicBlock *MBB, MachineInstr &MI, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, MachineTraceMetrics::Ensemble *TraceEnsemble, LiveRegUnitSet &RegUnits, const TargetInstrInfo *TII, unsigned Pattern, bool IncrementalUpdate)
Inserts InsInstrs and deletes DelInstrs.
static cl::opt< bool > VerifyPatternOrder("machine-combiner-verify-pattern-order", cl::Hidden, cl::desc("Verify that the generated patterns are ordered by increasing latency"), cl::init(false))
static cl::opt< unsigned > inc_threshold("machine-combiner-inc-threshold", cl::Hidden, cl::desc("Incremental depth computation will be used for basic " "blocks with more instructions."), cl::init(500))
static cl::opt< bool > dump_intrs("machine-combiner-dump-subst-intrs", cl::Hidden, cl::desc("Dump all substituted intrs"), cl::init(false))
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(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)
Represent the analysis usage information of a pass.
iterator find(const_arg_type_t< KeyT > Val)
bool useMachineCombiner() const override
This is an alternative analysis pass to MachineBlockFrequencyInfo.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
const MCSchedModel & getSchedModel() const
Get the machine model for this subtarget's CPU.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI StringRef getName() const
Return the name of the corresponding LLVM basic block, or an empty string.
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
Analysis pass which computes a MachineDominatorTree.
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.
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
filtered_mop_range all_defs()
Returns an iterator range over all operands that are (explicit or implicit) register defs.
LLVM_ABI int findRegisterUseOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isKill=false) const
Returns the operand index that is a use of the specific register or -1 if it is not found.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static reg_iterator reg_end()
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
reg_iterator reg_begin(Register RegNo) const
defusechain_iterator< true, true, false, true, false > reg_iterator
reg_iterator/reg_begin/reg_end - Walk all defs and uses of the specified register.
LLVM_ABI MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A trace ensemble is a collection of traces selected using the same strategy, for example 'minimum res...
void invalidate(const MachineBasicBlock *MBB)
Invalidate traces through BadMBB.
void updateDepth(TraceBlockInfo &TBI, const MachineInstr &, LiveRegUnitSet &RegUnits)
Updates the depth of an machine instruction, given RegUnits.
void updateDepths(MachineBasicBlock::iterator Start, MachineBasicBlock::iterator End, LiveRegUnitSet &RegUnits)
Updates the depth of the instructions from Start to End.
Trace getTrace(const MachineBasicBlock *MBB)
Get the trace that passes through MBB.
LLVM_ABI unsigned getResourceLength(ArrayRef< const MachineBasicBlock * > Extrablocks={}, ArrayRef< const MCSchedClassDesc * > ExtraInstrs={}, ArrayRef< const MCSchedClassDesc * > RemoveInstrs={}) const
Return the resource length of the trace.
InstrCycles getInstrCycles(const MachineInstr &MI) const
Return the depth and height of MI.
LLVM_ABI unsigned getInstrSlack(const MachineInstr &MI) const
Return the slack of MI.
LLVM_ABI 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...
LLVM_ABI Ensemble * getEnsemble(MachineTraceStrategy)
Get the trace ensemble representing the given trace selection strategy.
LLVM_ABI void verifyAnalysis() const
LLVM_ABI void invalidate(const MachineBasicBlock *MBB)
Invalidate cached information about MBB.
An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
Analysis providing profile information.
bool hasProfileSummary() const
Returns true if profile summary is available.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
iterator erase(iterator I)
erase - Erases an existing element identified by a valid iterator.
const_iterator begin() const
const_iterator end() const
void setUniverse(unsigned U)
setUniverse - Set the universe size which determines the largest key the set can hold.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Provide an instruction scheduling machine model to CodeGen passes.
LLVM_ABI bool hasInstrSchedModel() const
Return true if this machine model includes an instruction-level scheduling model.
LLVM_ABI void init(const TargetSubtargetInfo *TSInfo, bool EnableSModel=true, bool EnableSItins=true)
Initialize the machine model for instruction scheduling.
LLVM_ABI unsigned computeOperandLatency(const MachineInstr *DefMI, unsigned DefOperIdx, const MachineInstr *UseMI, unsigned UseOperIdx) const
Compute operand latency based on the available machine model.
bool hasInstrSchedModelOrItineraries() const
Return true if this machine model includes an instruction-level scheduling model or cycle-to-cycle it...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI bool shouldOptimizeForSize(const MachineFunction *MF, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo *BFI, PGSOQueryType QueryType=PGSOQueryType::Other)
Returns true if machine function MF is suggested to be size-optimized based on the profile.
LLVM_ABI char & MachineCombinerID
This pass performs instruction combining using trace metrics to estimate critical-path and resource d...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
CombinerObjective
The combiner's goal may differ based on which pattern it is attempting to optimize.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
SparseSet< LiveRegUnit, MCRegUnit, MCRegUnitToIndex > LiveRegUnitSet
ArrayRef(const T &OneElt) -> ArrayRef< T >
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Machine model for scheduling, bundling, and heuristics.
const MCSchedClassDesc * getSchedClassDesc(unsigned SchedClassIdx) const
unsigned Depth
Earliest issue cycle as determined by data dependencies and instruction latencies from the beginning ...