40#define DEBUG_TYPE "machine-combiner"
42STATISTIC(NumInstCombined,
"Number of machineinst combined");
46 cl::desc(
"Incremental depth computation will be used for basic "
47 "blocks with more instructions."),
cl::init(500));
50 cl::desc(
"Dump all substituted intrs"),
53#ifdef EXPENSIVE_CHECKS
55 "machine-combiner-verify-pattern-order",
cl::Hidden,
57 "Verify that the generated patterns are ordered by increasing latency"),
61 "machine-combiner-verify-pattern-order",
cl::Hidden,
63 "Verify that the generated patterns are ordered by increasing latency"),
68class MachineCombinerImpl {
84 MachineCombinerImpl() =
default;
104 unsigned Pattern,
bool SlackIsAccurate);
115 std::pair<unsigned, unsigned>
127 MachineCombinerLegacy() : MachineFunctionPass(ID) {}
128 void getAnalysisUsage(AnalysisUsage &AU)
const override;
130 StringRef getPassName()
const override {
return "Machine InstCombiner"; }
134char MachineCombinerLegacy::ID = 0;
145void MachineCombinerLegacy::getAnalysisUsage(
AnalysisUsage &AU)
const {
146 AU.setPreservesCFG();
157 MachineInstr *DefInstr =
nullptr;
165bool MachineCombinerImpl::isTransientMI(
const MachineInstr *
MI) {
173 if (!
MI->isFullCopy()) {
175 if (
MI->getOperand(0).getSubReg() || Src.isPhysical() || Dst.isPhysical())
178 auto SrcSub =
MI->getOperand(1).getSubReg();
181 return TRI->getMatchingSuperRegClass(SrcRC, DstRC, SrcSub) !=
nullptr;
184 if (Src.isPhysical() && Dst.isPhysical())
187 if (Src.isVirtual() && Dst.isVirtual()) {
210MachineCombinerImpl::getDepth(SmallVectorImpl<MachineInstr *> &InsInstrs,
211 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
213 const MachineBasicBlock &
MBB) {
214 SmallVector<unsigned, 16> InstrDepth;
218 for (
auto *InstrPtr : InsInstrs) {
220 for (
const MachineOperand &MO : InstrPtr->all_uses()) {
224 unsigned DepthOp = 0;
225 unsigned LatencyOp = 0;
227 if (
II != InstrIdxForVirtReg.
end()) {
230 MachineInstr *DefInstr = InsInstrs[
II->second];
232 "There must be a definition for a new virtual register");
233 DepthOp = InstrDepth[
II->second];
237 InstrPtr->findRegisterUseOperandIdx(MO.
getReg(),
nullptr);
241 MachineInstr *DefInstr = getOperandDef(MO);
242 if (DefInstr && (
TII->getMachineCombinerTraceStrategy() !=
243 MachineTraceStrategy::TS_Local ||
246 if (!isTransientMI(DefInstr))
252 InstrPtr->findRegisterUseOperandIdx(MO.
getReg(),
256 IDepth = std::max(IDepth, DepthOp + LatencyOp);
260 unsigned NewRootIdx = InsInstrs.size() - 1;
261 return InstrDepth[NewRootIdx];
274MachineCombinerImpl::getLatency(MachineInstr *Root, MachineInstr *NewRoot,
277 unsigned NewRootLatency = 0;
279 for (
const MachineOperand &MO : NewRoot->
all_defs()) {
289 unsigned LatencyOp = 0;
297 LatencyOp = TSchedModel.computeInstrLatency(NewRoot);
299 NewRootLatency = std::max(NewRootLatency, LatencyOp);
301 return NewRootLatency;
308 case MachineCombinerPattern::REASSOC_AX_BY:
309 case MachineCombinerPattern::REASSOC_AX_YB:
310 case MachineCombinerPattern::REASSOC_XA_BY:
311 case MachineCombinerPattern::REASSOC_XA_YB:
312 return CombinerObjective::MustReduceDepth;
314 return TII->getCombinerObjective(Pattern);
322std::pair<unsigned, unsigned>
323MachineCombinerImpl::getLatenciesForInstrSequences(
324 MachineInstr &
MI, SmallVectorImpl<MachineInstr *> &InsInstrs,
325 SmallVectorImpl<MachineInstr *> &DelInstrs,
327 assert(!InsInstrs.
empty() &&
"Only support sequences that insert instrs.");
328 unsigned NewRootLatency = 0;
330 MachineInstr *NewRoot = InsInstrs.
back();
331 for (
unsigned i = 0; i < InsInstrs.
size() - 1; i++)
332 NewRootLatency += TSchedModel.computeInstrLatency(InsInstrs[i]);
333 NewRootLatency += getLatency(&
MI, NewRoot, BlockTrace);
335 unsigned RootLatency = 0;
336 for (
auto *
I : DelInstrs)
337 RootLatency += TSchedModel.computeInstrLatency(
I);
339 return {NewRootLatency, RootLatency};
342bool MachineCombinerImpl::reduceRegisterPressure(
343 MachineInstr &Root, MachineBasicBlock *
MBB,
344 SmallVectorImpl<MachineInstr *> &InsInstrs,
345 SmallVectorImpl<MachineInstr *> &DelInstrs,
unsigned Pattern) {
358bool MachineCombinerImpl::improvesCriticalPathLen(
359 MachineBasicBlock *
MBB, MachineInstr *Root,
361 SmallVectorImpl<MachineInstr *> &InsInstrs,
362 SmallVectorImpl<MachineInstr *> &DelInstrs,
363 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
unsigned Pattern,
364 bool SlackIsAccurate) {
366 unsigned NewRootDepth =
367 getDepth(InsInstrs, InstrIdxForVirtReg, BlockTrace, *
MBB);
370 LLVM_DEBUG(
dbgs() <<
" Dependence data for " << *Root <<
"\tNewRootDepth: "
371 << NewRootDepth <<
"\tRootDepth: " << RootDepth);
378 if (getCombinerObjective(Pattern) == CombinerObjective::MustReduceDepth) {
381 ?
dbgs() <<
"\t and it does it\n"
382 :
dbgs() <<
"\t but it does NOT do it\n");
383 return NewRootDepth < RootDepth;
391 unsigned NewRootLatency, RootLatency;
392 if (
TII->accumulateInstrSeqToRootLatency(*Root)) {
393 std::tie(NewRootLatency, RootLatency) =
394 getLatenciesForInstrSequences(*Root, InsInstrs, DelInstrs, BlockTrace);
396 NewRootLatency = TSchedModel.computeInstrLatency(InsInstrs.
back());
397 RootLatency = TSchedModel.computeInstrLatency(Root);
401 unsigned NewCycleCount = NewRootDepth + NewRootLatency;
402 unsigned OldCycleCount =
403 RootDepth + RootLatency + (SlackIsAccurate ? RootSlack : 0);
405 <<
"\tRootLatency: " << RootLatency <<
"\n\tRootSlack: "
406 << RootSlack <<
" SlackIsAccurate=" << SlackIsAccurate
407 <<
"\n\tNewRootDepth + NewRootLatency = " << NewCycleCount
408 <<
"\n\tRootDepth + RootLatency + RootSlack = "
411 ?
dbgs() <<
"\n\t It IMPROVES PathLen because"
412 :
dbgs() <<
"\n\t It DOES NOT improve PathLen because");
414 <<
", OldCycleCount = " << OldCycleCount <<
"\n");
416 return NewCycleCount <= OldCycleCount;
420void MachineCombinerImpl::instr2instrSC(
421 SmallVectorImpl<MachineInstr *> &Instrs,
422 SmallVectorImpl<const MCSchedClassDesc *> &InstrsSC) {
423 for (
auto *InstrPtr : Instrs) {
424 unsigned Opc = InstrPtr->getOpcode();
425 unsigned Idx =
TII->get(
Opc).getSchedClass();
432bool MachineCombinerImpl::preservesResourceLen(
434 SmallVectorImpl<MachineInstr *> &InsInstrs,
435 SmallVectorImpl<MachineInstr *> &DelInstrs) {
450 instr2instrSC(InsInstrs, InsInstrsSC);
451 instr2instrSC(DelInstrs, DelInstrsSC);
457 unsigned ResLenAfterCombine =
461 << ResLenBeforeCombine
462 <<
" and after: " << ResLenAfterCombine <<
"\n");
464 ResLenAfterCombine <=
465 ResLenBeforeCombine +
TII->getExtendResourceLenLimit()
466 ?
dbgs() <<
"\t\t As result it IMPROVES/PRESERVES Resource Length\n"
467 :
dbgs() <<
"\t\t As result it DOES NOT improve/preserve Resource "
470 return ResLenAfterCombine <=
471 ResLenBeforeCombine +
TII->getExtendResourceLenLimit();
493 unsigned Pattern,
bool IncrementalUpdate) {
503 for (
auto *InstrPtr : InsInstrs)
506 for (
auto *InstrPtr : DelInstrs) {
507 InstrPtr->eraseFromParent();
509 for (
auto *
I = RegUnits.
begin();
I != RegUnits.
end();) {
510 if (
I->MI == InstrPtr)
517 if (IncrementalUpdate)
518 for (
auto *InstrPtr : InsInstrs)
533bool MachineCombinerImpl::combineInstructions(MachineBasicBlock *
MBB) {
537 bool IncrementalUpdate =
false;
539 decltype(BlockIter) LastUpdate;
543 TraceEnsemble = Traces->
getEnsemble(
TII->getMachineCombinerTraceStrategy());
550 bool DoRegPressureReduce =
551 TII->shouldReduceRegisterPressure(
MBB, RegClassInfo);
553 while (BlockIter !=
MBB->
end()) {
554 auto &
MI = *BlockIter++;
555 SmallVector<unsigned, 16> Patterns;
583 if (!
TII->getMachineCombinerPatterns(
MI, Patterns, DoRegPressureReduce))
587 [[maybe_unused]]
long PrevLatencyDiff = std::numeric_limits<long>::max();
589 for (
const auto P : Patterns) {
592 DenseMap<Register, unsigned> InstrIdxForVirtReg;
593 TII->genAlternativeCodeSequence(
MI,
P, InsInstrs, DelInstrs,
598 if (InsInstrs.
empty())
602 dbgs() <<
"\tFor the Pattern (" << (int)
P
603 <<
") these instructions could be removed\n";
604 for (
auto const *InstrPtr : DelInstrs)
605 InstrPtr->print(
dbgs(),
false,
false,
607 dbgs() <<
"\tThese instructions could replace the removed ones\n";
608 for (
auto const *InstrPtr : InsInstrs)
609 InstrPtr->print(
dbgs(),
false,
false,
617 auto [NewRootLatency, RootLatency] = getLatenciesForInstrSequences(
619 long CurrentLatencyDiff = ((long)RootLatency) - ((
long)NewRootLatency);
620 assert(CurrentLatencyDiff <= PrevLatencyDiff &&
621 "Current pattern is expected to be better than the previous "
623 PrevLatencyDiff = CurrentLatencyDiff;
626 if (IncrementalUpdate && LastUpdate != BlockIter) {
628 TraceEnsemble->
updateDepths(LastUpdate, BlockIter, RegUnits);
629 LastUpdate = BlockIter;
632 if (DoRegPressureReduce &&
633 getCombinerObjective(
P) ==
634 CombinerObjective::MustReduceRegisterPressure) {
637 IncrementalUpdate =
true;
638 LastUpdate = BlockIter;
640 if (reduceRegisterPressure(
MI,
MBB, InsInstrs, DelInstrs,
P)) {
643 RegUnits,
TII,
P, IncrementalUpdate);
653 if (
ML &&
TII->isThroughputPattern(
P)) {
654 LLVM_DEBUG(
dbgs() <<
"\t Replacing due to throughput pattern in loop\n");
656 RegUnits,
TII,
P, IncrementalUpdate);
660 }
else if (OptForSize && InsInstrs.size() < DelInstrs.size()) {
662 << InsInstrs.size() <<
" < "
663 << DelInstrs.size() <<
")\n");
665 RegUnits,
TII,
P, IncrementalUpdate);
677 if (improvesCriticalPathLen(
MBB, &
MI, BlockTrace, InsInstrs, DelInstrs,
678 InstrIdxForVirtReg,
P,
679 !IncrementalUpdate) &&
680 preservesResourceLen(
MBB, BlockTrace, InsInstrs, DelInstrs)) {
683 IncrementalUpdate =
true;
684 LastUpdate = BlockIter;
688 RegUnits,
TII,
P, IncrementalUpdate);
697 for (
auto *InstrPtr : InsInstrs)
698 MF->deleteMachineInstr(InstrPtr);
700 InstrIdxForVirtReg.
clear();
704 if (
Changed && IncrementalUpdate)
709bool MachineCombinerImpl::run(
MachineFunction &MF, MachineLoopInfo *MLI,
710 MachineTraceMetrics *Traces,
711 ProfileSummaryInfo *PSI,
712 MachineBlockFrequencyInfo *MBFI,
713 RegisterClassInfo *RegClassInfo) {
718 TSchedModel.
init(STI);
721 this->Traces = Traces;
724 this->RegClassInfo = RegClassInfo;
725 TraceEnsemble =
nullptr;
731 <<
" Skipping pass: Target does not support machine combiner\n");
745 auto *MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
746 auto *Traces = &getAnalysis<MachineTraceMetricsWrapperPass>().getMTM();
747 auto *PSI = &getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
749 ? &getAnalysis<LazyMachineBlockFrequencyInfoPass>().getBFI()
752 getAnalysis<MachineRegisterClassInfoWrapperPass>().getRCI();
753 return MachineCombinerImpl().run(MF, MLI, Traces, PSI, MBFI, &RegClassInfo);
763 .getCachedResult<ProfileSummaryAnalysis>(
765 auto *MBFI = (PSI && PSI->hasProfileSummary())
769 if (!MachineCombinerImpl().
run(MF, &MLI, &Traces, PSI, MBFI, &RegClassInfo))
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)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
Represents analyses that only rely on functions' control flow.
iterator find(const_arg_type_t< KeyT > Val)
Module * getParent()
Get the module that this global value is contained inside of...
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.
An RAII based helper class to modify MachineFunctionProperties when running pass.
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...
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
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.
bool isTransient() const
Return true if this is a transient instruction that is either very likely to be eliminated during reg...
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.
Analysis pass that exposes the MachineLoopInfo for a machine function.
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 LLVM_READONLY 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.
A trace represents a plausible sequence of executed basic blocks that passes through the current basi...
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.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
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.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
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.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
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 ...