139d628a0SDimitry Andric //===---- MachineCombiner.cpp - Instcombining on SSA form machine code ----===//
239d628a0SDimitry Andric //
339d628a0SDimitry Andric // The LLVM Compiler Infrastructure
439d628a0SDimitry Andric //
539d628a0SDimitry Andric // This file is distributed under the University of Illinois Open Source
639d628a0SDimitry Andric // License. See LICENSE.TXT for details.
739d628a0SDimitry Andric //
839d628a0SDimitry Andric //===----------------------------------------------------------------------===//
939d628a0SDimitry Andric //
1039d628a0SDimitry Andric // The machine combiner pass uses machine trace metrics to ensure the combined
117a7e6055SDimitry Andric // instructions do not lengthen the critical path or the resource depth.
1239d628a0SDimitry Andric //===----------------------------------------------------------------------===//
137d523365SDimitry Andric
1439d628a0SDimitry Andric #include "llvm/ADT/DenseMap.h"
153ca95b02SDimitry Andric #include "llvm/ADT/Statistic.h"
1639d628a0SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
1739d628a0SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
1839d628a0SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
1939d628a0SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
2039d628a0SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
2139d628a0SDimitry Andric #include "llvm/CodeGen/MachineTraceMetrics.h"
2239d628a0SDimitry Andric #include "llvm/CodeGen/Passes.h"
232cab237bSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
242cab237bSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
2539d628a0SDimitry Andric #include "llvm/CodeGen/TargetSchedule.h"
262cab237bSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
272cab237bSDimitry Andric #include "llvm/Support/CommandLine.h"
2839d628a0SDimitry Andric #include "llvm/Support/Debug.h"
2939d628a0SDimitry Andric #include "llvm/Support/raw_ostream.h"
3039d628a0SDimitry Andric
3139d628a0SDimitry Andric using namespace llvm;
3239d628a0SDimitry Andric
33b40b48b8SDimitry Andric #define DEBUG_TYPE "machine-combiner"
34b40b48b8SDimitry Andric
3539d628a0SDimitry Andric STATISTIC(NumInstCombined, "Number of machineinst combined");
3639d628a0SDimitry Andric
372cab237bSDimitry Andric static cl::opt<unsigned>
382cab237bSDimitry Andric inc_threshold("machine-combiner-inc-threshold", cl::Hidden,
392cab237bSDimitry Andric cl::desc("Incremental depth computation will be used for basic "
402cab237bSDimitry Andric "blocks with more instructions."), cl::init(500));
412cab237bSDimitry Andric
424ba319b5SDimitry Andric static cl::opt<bool> dump_intrs("machine-combiner-dump-subst-intrs", cl::Hidden,
434ba319b5SDimitry Andric cl::desc("Dump all substituted intrs"),
444ba319b5SDimitry Andric cl::init(false));
454ba319b5SDimitry Andric
464ba319b5SDimitry Andric #ifdef EXPENSIVE_CHECKS
474ba319b5SDimitry Andric static cl::opt<bool> VerifyPatternOrder(
484ba319b5SDimitry Andric "machine-combiner-verify-pattern-order", cl::Hidden,
494ba319b5SDimitry Andric cl::desc(
504ba319b5SDimitry Andric "Verify that the generated patterns are ordered by increasing latency"),
514ba319b5SDimitry Andric cl::init(true));
524ba319b5SDimitry Andric #else
534ba319b5SDimitry Andric static cl::opt<bool> VerifyPatternOrder(
544ba319b5SDimitry Andric "machine-combiner-verify-pattern-order", cl::Hidden,
554ba319b5SDimitry Andric cl::desc(
564ba319b5SDimitry Andric "Verify that the generated patterns are ordered by increasing latency"),
574ba319b5SDimitry Andric cl::init(false));
584ba319b5SDimitry Andric #endif
594ba319b5SDimitry Andric
6039d628a0SDimitry Andric namespace {
6139d628a0SDimitry Andric class MachineCombiner : public MachineFunctionPass {
624ba319b5SDimitry Andric const TargetSubtargetInfo *STI;
6339d628a0SDimitry Andric const TargetInstrInfo *TII;
6439d628a0SDimitry Andric const TargetRegisterInfo *TRI;
6539d628a0SDimitry Andric MCSchedModel SchedModel;
6639d628a0SDimitry Andric MachineRegisterInfo *MRI;
673ca95b02SDimitry Andric MachineLoopInfo *MLI; // Current MachineLoopInfo
6839d628a0SDimitry Andric MachineTraceMetrics *Traces;
6939d628a0SDimitry Andric MachineTraceMetrics::Ensemble *MinInstr;
7039d628a0SDimitry Andric
7139d628a0SDimitry Andric TargetSchedModel TSchedModel;
7239d628a0SDimitry Andric
73ff0cc061SDimitry Andric /// True if optimizing for code size.
7439d628a0SDimitry Andric bool OptSize;
7539d628a0SDimitry Andric
7639d628a0SDimitry Andric public:
7739d628a0SDimitry Andric static char ID;
MachineCombiner()7839d628a0SDimitry Andric MachineCombiner() : MachineFunctionPass(ID) {
7939d628a0SDimitry Andric initializeMachineCombinerPass(*PassRegistry::getPassRegistry());
8039d628a0SDimitry Andric }
8139d628a0SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override;
8239d628a0SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
getPassName() const83d88c1a5aSDimitry Andric StringRef getPassName() const override { return "Machine InstCombiner"; }
8439d628a0SDimitry Andric
8539d628a0SDimitry Andric private:
8639d628a0SDimitry Andric bool doSubstitute(unsigned NewSize, unsigned OldSize);
8739d628a0SDimitry Andric bool combineInstructions(MachineBasicBlock *);
8839d628a0SDimitry Andric MachineInstr *getOperandDef(const MachineOperand &MO);
8939d628a0SDimitry Andric unsigned getDepth(SmallVectorImpl<MachineInstr *> &InsInstrs,
9039d628a0SDimitry Andric DenseMap<unsigned, unsigned> &InstrIdxForVirtReg,
9139d628a0SDimitry Andric MachineTraceMetrics::Trace BlockTrace);
9239d628a0SDimitry Andric unsigned getLatency(MachineInstr *Root, MachineInstr *NewRoot,
9339d628a0SDimitry Andric MachineTraceMetrics::Trace BlockTrace);
9439d628a0SDimitry Andric bool
953dac3a9bSDimitry Andric improvesCriticalPathLen(MachineBasicBlock *MBB, MachineInstr *Root,
9639d628a0SDimitry Andric MachineTraceMetrics::Trace BlockTrace,
9739d628a0SDimitry Andric SmallVectorImpl<MachineInstr *> &InsInstrs,
98d88c1a5aSDimitry Andric SmallVectorImpl<MachineInstr *> &DelInstrs,
993dac3a9bSDimitry Andric DenseMap<unsigned, unsigned> &InstrIdxForVirtReg,
1002cab237bSDimitry Andric MachineCombinerPattern Pattern, bool SlackIsAccurate);
10139d628a0SDimitry Andric bool preservesResourceLen(MachineBasicBlock *MBB,
10239d628a0SDimitry Andric MachineTraceMetrics::Trace BlockTrace,
10339d628a0SDimitry Andric SmallVectorImpl<MachineInstr *> &InsInstrs,
10439d628a0SDimitry Andric SmallVectorImpl<MachineInstr *> &DelInstrs);
10539d628a0SDimitry Andric void instr2instrSC(SmallVectorImpl<MachineInstr *> &Instrs,
10639d628a0SDimitry Andric SmallVectorImpl<const MCSchedClassDesc *> &InstrsSC);
1074ba319b5SDimitry Andric std::pair<unsigned, unsigned>
1084ba319b5SDimitry Andric getLatenciesForInstrSequences(MachineInstr &MI,
1094ba319b5SDimitry Andric SmallVectorImpl<MachineInstr *> &InsInstrs,
1104ba319b5SDimitry Andric SmallVectorImpl<MachineInstr *> &DelInstrs,
1114ba319b5SDimitry Andric MachineTraceMetrics::Trace BlockTrace);
1124ba319b5SDimitry Andric
1134ba319b5SDimitry Andric void verifyPatternOrder(MachineBasicBlock *MBB, MachineInstr &Root,
1144ba319b5SDimitry Andric SmallVector<MachineCombinerPattern, 16> &Patterns);
11539d628a0SDimitry Andric };
1163dac3a9bSDimitry Andric }
11739d628a0SDimitry Andric
11839d628a0SDimitry Andric char MachineCombiner::ID = 0;
11939d628a0SDimitry Andric char &llvm::MachineCombinerID = MachineCombiner::ID;
12039d628a0SDimitry Andric
121302affcbSDimitry Andric INITIALIZE_PASS_BEGIN(MachineCombiner, DEBUG_TYPE,
12239d628a0SDimitry Andric "Machine InstCombiner", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)1233ca95b02SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
12439d628a0SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineTraceMetrics)
125302affcbSDimitry Andric INITIALIZE_PASS_END(MachineCombiner, DEBUG_TYPE, "Machine InstCombiner",
12639d628a0SDimitry Andric false, false)
12739d628a0SDimitry Andric
12839d628a0SDimitry Andric void MachineCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
12939d628a0SDimitry Andric AU.setPreservesCFG();
13039d628a0SDimitry Andric AU.addPreserved<MachineDominatorTree>();
1313ca95b02SDimitry Andric AU.addRequired<MachineLoopInfo>();
13239d628a0SDimitry Andric AU.addPreserved<MachineLoopInfo>();
13339d628a0SDimitry Andric AU.addRequired<MachineTraceMetrics>();
13439d628a0SDimitry Andric AU.addPreserved<MachineTraceMetrics>();
13539d628a0SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
13639d628a0SDimitry Andric }
13739d628a0SDimitry Andric
getOperandDef(const MachineOperand & MO)13839d628a0SDimitry Andric MachineInstr *MachineCombiner::getOperandDef(const MachineOperand &MO) {
13939d628a0SDimitry Andric MachineInstr *DefInstr = nullptr;
14039d628a0SDimitry Andric // We need a virtual register definition.
14139d628a0SDimitry Andric if (MO.isReg() && TargetRegisterInfo::isVirtualRegister(MO.getReg()))
14239d628a0SDimitry Andric DefInstr = MRI->getUniqueVRegDef(MO.getReg());
14339d628a0SDimitry Andric // PHI's have no depth etc.
14439d628a0SDimitry Andric if (DefInstr && DefInstr->isPHI())
14539d628a0SDimitry Andric DefInstr = nullptr;
14639d628a0SDimitry Andric return DefInstr;
14739d628a0SDimitry Andric }
14839d628a0SDimitry Andric
149ff0cc061SDimitry Andric /// Computes depth of instructions in vector \InsInstr.
15039d628a0SDimitry Andric ///
15139d628a0SDimitry Andric /// \param InsInstrs is a vector of machine instructions
15239d628a0SDimitry Andric /// \param InstrIdxForVirtReg is a dense map of virtual register to index
15339d628a0SDimitry Andric /// of defining machine instruction in \p InsInstrs
15439d628a0SDimitry Andric /// \param BlockTrace is a trace of machine instructions
15539d628a0SDimitry Andric ///
15639d628a0SDimitry Andric /// \returns Depth of last instruction in \InsInstrs ("NewRoot")
15739d628a0SDimitry Andric unsigned
getDepth(SmallVectorImpl<MachineInstr * > & InsInstrs,DenseMap<unsigned,unsigned> & InstrIdxForVirtReg,MachineTraceMetrics::Trace BlockTrace)15839d628a0SDimitry Andric MachineCombiner::getDepth(SmallVectorImpl<MachineInstr *> &InsInstrs,
15939d628a0SDimitry Andric DenseMap<unsigned, unsigned> &InstrIdxForVirtReg,
16039d628a0SDimitry Andric MachineTraceMetrics::Trace BlockTrace) {
16139d628a0SDimitry Andric SmallVector<unsigned, 16> InstrDepth;
1627d523365SDimitry Andric assert(TSchedModel.hasInstrSchedModelOrItineraries() &&
1637d523365SDimitry Andric "Missing machine model\n");
16439d628a0SDimitry Andric
165ff0cc061SDimitry Andric // For each instruction in the new sequence compute the depth based on the
16639d628a0SDimitry Andric // operands. Use the trace information when possible. For new operands which
16739d628a0SDimitry Andric // are tracked in the InstrIdxForVirtReg map depth is looked up in InstrDepth
16839d628a0SDimitry Andric for (auto *InstrPtr : InsInstrs) { // for each Use
16939d628a0SDimitry Andric unsigned IDepth = 0;
170ff0cc061SDimitry Andric for (const MachineOperand &MO : InstrPtr->operands()) {
17139d628a0SDimitry Andric // Check for virtual register operand.
17239d628a0SDimitry Andric if (!(MO.isReg() && TargetRegisterInfo::isVirtualRegister(MO.getReg())))
17339d628a0SDimitry Andric continue;
17439d628a0SDimitry Andric if (!MO.isUse())
17539d628a0SDimitry Andric continue;
17639d628a0SDimitry Andric unsigned DepthOp = 0;
17739d628a0SDimitry Andric unsigned LatencyOp = 0;
17839d628a0SDimitry Andric DenseMap<unsigned, unsigned>::iterator II =
17939d628a0SDimitry Andric InstrIdxForVirtReg.find(MO.getReg());
18039d628a0SDimitry Andric if (II != InstrIdxForVirtReg.end()) {
18139d628a0SDimitry Andric // Operand is new virtual register not in trace
18239d628a0SDimitry Andric assert(II->second < InstrDepth.size() && "Bad Index");
18339d628a0SDimitry Andric MachineInstr *DefInstr = InsInstrs[II->second];
18439d628a0SDimitry Andric assert(DefInstr &&
18539d628a0SDimitry Andric "There must be a definition for a new virtual register");
18639d628a0SDimitry Andric DepthOp = InstrDepth[II->second];
1872cab237bSDimitry Andric int DefIdx = DefInstr->findRegisterDefOperandIdx(MO.getReg());
1882cab237bSDimitry Andric int UseIdx = InstrPtr->findRegisterUseOperandIdx(MO.getReg());
1892cab237bSDimitry Andric LatencyOp = TSchedModel.computeOperandLatency(DefInstr, DefIdx,
1902cab237bSDimitry Andric InstrPtr, UseIdx);
19139d628a0SDimitry Andric } else {
19239d628a0SDimitry Andric MachineInstr *DefInstr = getOperandDef(MO);
19339d628a0SDimitry Andric if (DefInstr) {
1943ca95b02SDimitry Andric DepthOp = BlockTrace.getInstrCycles(*DefInstr).Depth;
19539d628a0SDimitry Andric LatencyOp = TSchedModel.computeOperandLatency(
19639d628a0SDimitry Andric DefInstr, DefInstr->findRegisterDefOperandIdx(MO.getReg()),
19739d628a0SDimitry Andric InstrPtr, InstrPtr->findRegisterUseOperandIdx(MO.getReg()));
19839d628a0SDimitry Andric }
19939d628a0SDimitry Andric }
20039d628a0SDimitry Andric IDepth = std::max(IDepth, DepthOp + LatencyOp);
20139d628a0SDimitry Andric }
20239d628a0SDimitry Andric InstrDepth.push_back(IDepth);
20339d628a0SDimitry Andric }
20439d628a0SDimitry Andric unsigned NewRootIdx = InsInstrs.size() - 1;
20539d628a0SDimitry Andric return InstrDepth[NewRootIdx];
20639d628a0SDimitry Andric }
20739d628a0SDimitry Andric
208ff0cc061SDimitry Andric /// Computes instruction latency as max of latency of defined operands.
20939d628a0SDimitry Andric ///
21039d628a0SDimitry Andric /// \param Root is a machine instruction that could be replaced by NewRoot.
21139d628a0SDimitry Andric /// It is used to compute a more accurate latency information for NewRoot in
21239d628a0SDimitry Andric /// case there is a dependent instruction in the same trace (\p BlockTrace)
21339d628a0SDimitry Andric /// \param NewRoot is the instruction for which the latency is computed
21439d628a0SDimitry Andric /// \param BlockTrace is a trace of machine instructions
21539d628a0SDimitry Andric ///
21639d628a0SDimitry Andric /// \returns Latency of \p NewRoot
getLatency(MachineInstr * Root,MachineInstr * NewRoot,MachineTraceMetrics::Trace BlockTrace)21739d628a0SDimitry Andric unsigned MachineCombiner::getLatency(MachineInstr *Root, MachineInstr *NewRoot,
21839d628a0SDimitry Andric MachineTraceMetrics::Trace BlockTrace) {
2197d523365SDimitry Andric assert(TSchedModel.hasInstrSchedModelOrItineraries() &&
2207d523365SDimitry Andric "Missing machine model\n");
22139d628a0SDimitry Andric
22239d628a0SDimitry Andric // Check each definition in NewRoot and compute the latency
22339d628a0SDimitry Andric unsigned NewRootLatency = 0;
22439d628a0SDimitry Andric
225ff0cc061SDimitry Andric for (const MachineOperand &MO : NewRoot->operands()) {
22639d628a0SDimitry Andric // Check for virtual register operand.
22739d628a0SDimitry Andric if (!(MO.isReg() && TargetRegisterInfo::isVirtualRegister(MO.getReg())))
22839d628a0SDimitry Andric continue;
22939d628a0SDimitry Andric if (!MO.isDef())
23039d628a0SDimitry Andric continue;
23139d628a0SDimitry Andric // Get the first instruction that uses MO
23239d628a0SDimitry Andric MachineRegisterInfo::reg_iterator RI = MRI->reg_begin(MO.getReg());
23339d628a0SDimitry Andric RI++;
234*b5893f02SDimitry Andric if (RI == MRI->reg_end())
235*b5893f02SDimitry Andric continue;
23639d628a0SDimitry Andric MachineInstr *UseMO = RI->getParent();
23739d628a0SDimitry Andric unsigned LatencyOp = 0;
2383ca95b02SDimitry Andric if (UseMO && BlockTrace.isDepInTrace(*Root, *UseMO)) {
23939d628a0SDimitry Andric LatencyOp = TSchedModel.computeOperandLatency(
24039d628a0SDimitry Andric NewRoot, NewRoot->findRegisterDefOperandIdx(MO.getReg()), UseMO,
24139d628a0SDimitry Andric UseMO->findRegisterUseOperandIdx(MO.getReg()));
24239d628a0SDimitry Andric } else {
2437d523365SDimitry Andric LatencyOp = TSchedModel.computeInstrLatency(NewRoot);
24439d628a0SDimitry Andric }
24539d628a0SDimitry Andric NewRootLatency = std::max(NewRootLatency, LatencyOp);
24639d628a0SDimitry Andric }
24739d628a0SDimitry Andric return NewRootLatency;
24839d628a0SDimitry Andric }
24939d628a0SDimitry Andric
2507d523365SDimitry Andric /// The combiner's goal may differ based on which pattern it is attempting
2517d523365SDimitry Andric /// to optimize.
2527d523365SDimitry Andric enum class CombinerObjective {
2537d523365SDimitry Andric MustReduceDepth, // The data dependency chain must be improved.
2547d523365SDimitry Andric Default // The critical path must not be lengthened.
2557d523365SDimitry Andric };
2567d523365SDimitry Andric
getCombinerObjective(MachineCombinerPattern P)2577d523365SDimitry Andric static CombinerObjective getCombinerObjective(MachineCombinerPattern P) {
2587d523365SDimitry Andric // TODO: If C++ ever gets a real enum class, make this part of the
2597d523365SDimitry Andric // MachineCombinerPattern class.
2607d523365SDimitry Andric switch (P) {
2617d523365SDimitry Andric case MachineCombinerPattern::REASSOC_AX_BY:
2627d523365SDimitry Andric case MachineCombinerPattern::REASSOC_AX_YB:
2637d523365SDimitry Andric case MachineCombinerPattern::REASSOC_XA_BY:
2647d523365SDimitry Andric case MachineCombinerPattern::REASSOC_XA_YB:
2657d523365SDimitry Andric return CombinerObjective::MustReduceDepth;
2667d523365SDimitry Andric default:
2677d523365SDimitry Andric return CombinerObjective::Default;
2687d523365SDimitry Andric }
2697d523365SDimitry Andric }
2707d523365SDimitry Andric
2714ba319b5SDimitry Andric /// Estimate the latency of the new and original instruction sequence by summing
2724ba319b5SDimitry Andric /// up the latencies of the inserted and deleted instructions. This assumes
2734ba319b5SDimitry Andric /// that the inserted and deleted instructions are dependent instruction chains,
2744ba319b5SDimitry Andric /// which might not hold in all cases.
getLatenciesForInstrSequences(MachineInstr & MI,SmallVectorImpl<MachineInstr * > & InsInstrs,SmallVectorImpl<MachineInstr * > & DelInstrs,MachineTraceMetrics::Trace BlockTrace)2754ba319b5SDimitry Andric std::pair<unsigned, unsigned> MachineCombiner::getLatenciesForInstrSequences(
2764ba319b5SDimitry Andric MachineInstr &MI, SmallVectorImpl<MachineInstr *> &InsInstrs,
2774ba319b5SDimitry Andric SmallVectorImpl<MachineInstr *> &DelInstrs,
2784ba319b5SDimitry Andric MachineTraceMetrics::Trace BlockTrace) {
2794ba319b5SDimitry Andric assert(!InsInstrs.empty() && "Only support sequences that insert instrs.");
2804ba319b5SDimitry Andric unsigned NewRootLatency = 0;
2814ba319b5SDimitry Andric // NewRoot is the last instruction in the \p InsInstrs vector.
2824ba319b5SDimitry Andric MachineInstr *NewRoot = InsInstrs.back();
2834ba319b5SDimitry Andric for (unsigned i = 0; i < InsInstrs.size() - 1; i++)
2844ba319b5SDimitry Andric NewRootLatency += TSchedModel.computeInstrLatency(InsInstrs[i]);
2854ba319b5SDimitry Andric NewRootLatency += getLatency(&MI, NewRoot, BlockTrace);
2864ba319b5SDimitry Andric
2874ba319b5SDimitry Andric unsigned RootLatency = 0;
2884ba319b5SDimitry Andric for (auto I : DelInstrs)
2894ba319b5SDimitry Andric RootLatency += TSchedModel.computeInstrLatency(I);
2904ba319b5SDimitry Andric
2914ba319b5SDimitry Andric return {NewRootLatency, RootLatency};
2924ba319b5SDimitry Andric }
2934ba319b5SDimitry Andric
2943dac3a9bSDimitry Andric /// The DAGCombine code sequence ends in MI (Machine Instruction) Root.
2953dac3a9bSDimitry Andric /// The new code sequence ends in MI NewRoot. A necessary condition for the new
2963dac3a9bSDimitry Andric /// sequence to replace the old sequence is that it cannot lengthen the critical
2977d523365SDimitry Andric /// path. The definition of "improve" may be restricted by specifying that the
2987d523365SDimitry Andric /// new path improves the data dependency chain (MustReduceDepth).
improvesCriticalPathLen(MachineBasicBlock * MBB,MachineInstr * Root,MachineTraceMetrics::Trace BlockTrace,SmallVectorImpl<MachineInstr * > & InsInstrs,SmallVectorImpl<MachineInstr * > & DelInstrs,DenseMap<unsigned,unsigned> & InstrIdxForVirtReg,MachineCombinerPattern Pattern,bool SlackIsAccurate)2993dac3a9bSDimitry Andric bool MachineCombiner::improvesCriticalPathLen(
30039d628a0SDimitry Andric MachineBasicBlock *MBB, MachineInstr *Root,
30139d628a0SDimitry Andric MachineTraceMetrics::Trace BlockTrace,
30239d628a0SDimitry Andric SmallVectorImpl<MachineInstr *> &InsInstrs,
303d88c1a5aSDimitry Andric SmallVectorImpl<MachineInstr *> &DelInstrs,
3043dac3a9bSDimitry Andric DenseMap<unsigned, unsigned> &InstrIdxForVirtReg,
3052cab237bSDimitry Andric MachineCombinerPattern Pattern,
3062cab237bSDimitry Andric bool SlackIsAccurate) {
3077d523365SDimitry Andric assert(TSchedModel.hasInstrSchedModelOrItineraries() &&
3087d523365SDimitry Andric "Missing machine model\n");
3097d523365SDimitry Andric // Get depth and latency of NewRoot and Root.
3107d523365SDimitry Andric unsigned NewRootDepth = getDepth(InsInstrs, InstrIdxForVirtReg, BlockTrace);
3113ca95b02SDimitry Andric unsigned RootDepth = BlockTrace.getInstrCycles(*Root).Depth;
3127d523365SDimitry Andric
3134ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " Dependence data for " << *Root << "\tNewRootDepth: "
3144ba319b5SDimitry Andric << NewRootDepth << "\tRootDepth: " << RootDepth);
3157d523365SDimitry Andric
3167d523365SDimitry Andric // For a transform such as reassociation, the cost equation is
3177d523365SDimitry Andric // conservatively calculated so that we must improve the depth (data
3187d523365SDimitry Andric // dependency cycles) in the critical path to proceed with the transform.
3197d523365SDimitry Andric // Being conservative also protects against inaccuracies in the underlying
3207d523365SDimitry Andric // machine trace metrics and CPU models.
3214ba319b5SDimitry Andric if (getCombinerObjective(Pattern) == CombinerObjective::MustReduceDepth) {
3224ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "\tIt MustReduceDepth ");
3234ba319b5SDimitry Andric LLVM_DEBUG(NewRootDepth < RootDepth
3244ba319b5SDimitry Andric ? dbgs() << "\t and it does it\n"
3254ba319b5SDimitry Andric : dbgs() << "\t but it does NOT do it\n");
3267d523365SDimitry Andric return NewRootDepth < RootDepth;
3274ba319b5SDimitry Andric }
3287d523365SDimitry Andric
3297d523365SDimitry Andric // A more flexible cost calculation for the critical path includes the slack
3307d523365SDimitry Andric // of the original code sequence. This may allow the transform to proceed
3317d523365SDimitry Andric // even if the instruction depths (data dependency cycles) become worse.
332d88c1a5aSDimitry Andric
3332cab237bSDimitry Andric // Account for the latency of the inserted and deleted instructions by
3344ba319b5SDimitry Andric unsigned NewRootLatency, RootLatency;
3354ba319b5SDimitry Andric std::tie(NewRootLatency, RootLatency) =
3364ba319b5SDimitry Andric getLatenciesForInstrSequences(*Root, InsInstrs, DelInstrs, BlockTrace);
337d88c1a5aSDimitry Andric
3383ca95b02SDimitry Andric unsigned RootSlack = BlockTrace.getInstrSlack(*Root);
3392cab237bSDimitry Andric unsigned NewCycleCount = NewRootDepth + NewRootLatency;
3404ba319b5SDimitry Andric unsigned OldCycleCount =
3414ba319b5SDimitry Andric RootDepth + RootLatency + (SlackIsAccurate ? RootSlack : 0);
3424ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "\n\tNewRootLatency: " << NewRootLatency
3434ba319b5SDimitry Andric << "\tRootLatency: " << RootLatency << "\n\tRootSlack: "
3444ba319b5SDimitry Andric << RootSlack << " SlackIsAccurate=" << SlackIsAccurate
3454ba319b5SDimitry Andric << "\n\tNewRootDepth + NewRootLatency = " << NewCycleCount
3464ba319b5SDimitry Andric << "\n\tRootDepth + RootLatency + RootSlack = "
3474ba319b5SDimitry Andric << OldCycleCount;);
3484ba319b5SDimitry Andric LLVM_DEBUG(NewCycleCount <= OldCycleCount
3494ba319b5SDimitry Andric ? dbgs() << "\n\t It IMPROVES PathLen because"
3504ba319b5SDimitry Andric : dbgs() << "\n\t It DOES NOT improve PathLen because");
3514ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "\n\t\tNewCycleCount = " << NewCycleCount
3524ba319b5SDimitry Andric << ", OldCycleCount = " << OldCycleCount << "\n");
3533dac3a9bSDimitry Andric
3543dac3a9bSDimitry Andric return NewCycleCount <= OldCycleCount;
35539d628a0SDimitry Andric }
35639d628a0SDimitry Andric
35739d628a0SDimitry Andric /// helper routine to convert instructions into SC
instr2instrSC(SmallVectorImpl<MachineInstr * > & Instrs,SmallVectorImpl<const MCSchedClassDesc * > & InstrsSC)35839d628a0SDimitry Andric void MachineCombiner::instr2instrSC(
35939d628a0SDimitry Andric SmallVectorImpl<MachineInstr *> &Instrs,
36039d628a0SDimitry Andric SmallVectorImpl<const MCSchedClassDesc *> &InstrsSC) {
36139d628a0SDimitry Andric for (auto *InstrPtr : Instrs) {
36239d628a0SDimitry Andric unsigned Opc = InstrPtr->getOpcode();
36339d628a0SDimitry Andric unsigned Idx = TII->get(Opc).getSchedClass();
36439d628a0SDimitry Andric const MCSchedClassDesc *SC = SchedModel.getSchedClassDesc(Idx);
36539d628a0SDimitry Andric InstrsSC.push_back(SC);
36639d628a0SDimitry Andric }
36739d628a0SDimitry Andric }
3687d523365SDimitry Andric
369ff0cc061SDimitry Andric /// True when the new instructions do not increase resource length
preservesResourceLen(MachineBasicBlock * MBB,MachineTraceMetrics::Trace BlockTrace,SmallVectorImpl<MachineInstr * > & InsInstrs,SmallVectorImpl<MachineInstr * > & DelInstrs)37039d628a0SDimitry Andric bool MachineCombiner::preservesResourceLen(
37139d628a0SDimitry Andric MachineBasicBlock *MBB, MachineTraceMetrics::Trace BlockTrace,
37239d628a0SDimitry Andric SmallVectorImpl<MachineInstr *> &InsInstrs,
37339d628a0SDimitry Andric SmallVectorImpl<MachineInstr *> &DelInstrs) {
3747d523365SDimitry Andric if (!TSchedModel.hasInstrSchedModel())
3757d523365SDimitry Andric return true;
37639d628a0SDimitry Andric
37739d628a0SDimitry Andric // Compute current resource length
37839d628a0SDimitry Andric
37939d628a0SDimitry Andric //ArrayRef<const MachineBasicBlock *> MBBarr(MBB);
38039d628a0SDimitry Andric SmallVector <const MachineBasicBlock *, 1> MBBarr;
38139d628a0SDimitry Andric MBBarr.push_back(MBB);
38239d628a0SDimitry Andric unsigned ResLenBeforeCombine = BlockTrace.getResourceLength(MBBarr);
38339d628a0SDimitry Andric
38439d628a0SDimitry Andric // Deal with SC rather than Instructions.
38539d628a0SDimitry Andric SmallVector<const MCSchedClassDesc *, 16> InsInstrsSC;
38639d628a0SDimitry Andric SmallVector<const MCSchedClassDesc *, 16> DelInstrsSC;
38739d628a0SDimitry Andric
38839d628a0SDimitry Andric instr2instrSC(InsInstrs, InsInstrsSC);
38939d628a0SDimitry Andric instr2instrSC(DelInstrs, DelInstrsSC);
39039d628a0SDimitry Andric
39139d628a0SDimitry Andric ArrayRef<const MCSchedClassDesc *> MSCInsArr = makeArrayRef(InsInstrsSC);
39239d628a0SDimitry Andric ArrayRef<const MCSchedClassDesc *> MSCDelArr = makeArrayRef(DelInstrsSC);
39339d628a0SDimitry Andric
3948f0fd8f6SDimitry Andric // Compute new resource length.
39539d628a0SDimitry Andric unsigned ResLenAfterCombine =
39639d628a0SDimitry Andric BlockTrace.getResourceLength(MBBarr, MSCInsArr, MSCDelArr);
39739d628a0SDimitry Andric
3984ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "\t\tResource length before replacement: "
3994ba319b5SDimitry Andric << ResLenBeforeCombine
4004ba319b5SDimitry Andric << " and after: " << ResLenAfterCombine << "\n";);
4014ba319b5SDimitry Andric LLVM_DEBUG(
4024ba319b5SDimitry Andric ResLenAfterCombine <= ResLenBeforeCombine
4034ba319b5SDimitry Andric ? dbgs() << "\t\t As result it IMPROVES/PRESERVES Resource Length\n"
4044ba319b5SDimitry Andric : dbgs() << "\t\t As result it DOES NOT improve/preserve Resource "
4054ba319b5SDimitry Andric "Length\n");
40639d628a0SDimitry Andric
40739d628a0SDimitry Andric return ResLenAfterCombine <= ResLenBeforeCombine;
40839d628a0SDimitry Andric }
40939d628a0SDimitry Andric
41039d628a0SDimitry Andric /// \returns true when new instruction sequence should be generated
411ff0cc061SDimitry Andric /// independent if it lengthens critical path or not
doSubstitute(unsigned NewSize,unsigned OldSize)41239d628a0SDimitry Andric bool MachineCombiner::doSubstitute(unsigned NewSize, unsigned OldSize) {
41339d628a0SDimitry Andric if (OptSize && (NewSize < OldSize))
41439d628a0SDimitry Andric return true;
4157d523365SDimitry Andric if (!TSchedModel.hasInstrSchedModelOrItineraries())
41639d628a0SDimitry Andric return true;
41739d628a0SDimitry Andric return false;
41839d628a0SDimitry Andric }
41939d628a0SDimitry Andric
4202cab237bSDimitry Andric /// Inserts InsInstrs and deletes DelInstrs. Incrementally updates instruction
4212cab237bSDimitry Andric /// depths if requested.
4222cab237bSDimitry Andric ///
4232cab237bSDimitry Andric /// \param MBB basic block to insert instructions in
4242cab237bSDimitry Andric /// \param MI current machine instruction
4252cab237bSDimitry Andric /// \param InsInstrs new instructions to insert in \p MBB
4262cab237bSDimitry Andric /// \param DelInstrs instruction to delete from \p MBB
4272cab237bSDimitry Andric /// \param MinInstr is a pointer to the machine trace information
4282cab237bSDimitry Andric /// \param RegUnits set of live registers, needed to compute instruction depths
4292cab237bSDimitry Andric /// \param IncrementalUpdate if true, compute instruction depths incrementally,
4302cab237bSDimitry Andric /// otherwise invalidate the trace
insertDeleteInstructions(MachineBasicBlock * MBB,MachineInstr & MI,SmallVector<MachineInstr *,16> InsInstrs,SmallVector<MachineInstr *,16> DelInstrs,MachineTraceMetrics::Ensemble * MinInstr,SparseSet<LiveRegUnit> & RegUnits,bool IncrementalUpdate)4317a7e6055SDimitry Andric static void insertDeleteInstructions(MachineBasicBlock *MBB, MachineInstr &MI,
4327a7e6055SDimitry Andric SmallVector<MachineInstr *, 16> InsInstrs,
4337a7e6055SDimitry Andric SmallVector<MachineInstr *, 16> DelInstrs,
4342cab237bSDimitry Andric MachineTraceMetrics::Ensemble *MinInstr,
4352cab237bSDimitry Andric SparseSet<LiveRegUnit> &RegUnits,
4362cab237bSDimitry Andric bool IncrementalUpdate) {
4377a7e6055SDimitry Andric for (auto *InstrPtr : InsInstrs)
4387a7e6055SDimitry Andric MBB->insert((MachineBasicBlock::iterator)&MI, InstrPtr);
4392cab237bSDimitry Andric
4402cab237bSDimitry Andric for (auto *InstrPtr : DelInstrs) {
4417a7e6055SDimitry Andric InstrPtr->eraseFromParentAndMarkDBGValuesForRemoval();
4422cab237bSDimitry Andric // Erase all LiveRegs defined by the removed instruction
4432cab237bSDimitry Andric for (auto I = RegUnits.begin(); I != RegUnits.end(); ) {
4442cab237bSDimitry Andric if (I->MI == InstrPtr)
4452cab237bSDimitry Andric I = RegUnits.erase(I);
4462cab237bSDimitry Andric else
4472cab237bSDimitry Andric I++;
4482cab237bSDimitry Andric }
4492cab237bSDimitry Andric }
4502cab237bSDimitry Andric
4512cab237bSDimitry Andric if (IncrementalUpdate)
4522cab237bSDimitry Andric for (auto *InstrPtr : InsInstrs)
4532cab237bSDimitry Andric MinInstr->updateDepth(MBB, *InstrPtr, RegUnits);
4542cab237bSDimitry Andric else
4552cab237bSDimitry Andric MinInstr->invalidate(MBB);
4562cab237bSDimitry Andric
4572cab237bSDimitry Andric NumInstCombined++;
4587a7e6055SDimitry Andric }
4597a7e6055SDimitry Andric
4604ba319b5SDimitry Andric // Check that the difference between original and new latency is decreasing for
4614ba319b5SDimitry Andric // later patterns. This helps to discover sub-optimal pattern orderings.
verifyPatternOrder(MachineBasicBlock * MBB,MachineInstr & Root,SmallVector<MachineCombinerPattern,16> & Patterns)4624ba319b5SDimitry Andric void MachineCombiner::verifyPatternOrder(
4634ba319b5SDimitry Andric MachineBasicBlock *MBB, MachineInstr &Root,
4644ba319b5SDimitry Andric SmallVector<MachineCombinerPattern, 16> &Patterns) {
4654ba319b5SDimitry Andric long PrevLatencyDiff = std::numeric_limits<long>::max();
4664ba319b5SDimitry Andric (void)PrevLatencyDiff; // Variable is used in assert only.
4674ba319b5SDimitry Andric for (auto P : Patterns) {
4684ba319b5SDimitry Andric SmallVector<MachineInstr *, 16> InsInstrs;
4694ba319b5SDimitry Andric SmallVector<MachineInstr *, 16> DelInstrs;
4704ba319b5SDimitry Andric DenseMap<unsigned, unsigned> InstrIdxForVirtReg;
4714ba319b5SDimitry Andric TII->genAlternativeCodeSequence(Root, P, InsInstrs, DelInstrs,
4724ba319b5SDimitry Andric InstrIdxForVirtReg);
4734ba319b5SDimitry Andric // Found pattern, but did not generate alternative sequence.
4744ba319b5SDimitry Andric // This can happen e.g. when an immediate could not be materialized
4754ba319b5SDimitry Andric // in a single instruction.
4764ba319b5SDimitry Andric if (InsInstrs.empty() || !TSchedModel.hasInstrSchedModelOrItineraries())
4774ba319b5SDimitry Andric continue;
4784ba319b5SDimitry Andric
4794ba319b5SDimitry Andric unsigned NewRootLatency, RootLatency;
4804ba319b5SDimitry Andric std::tie(NewRootLatency, RootLatency) = getLatenciesForInstrSequences(
4814ba319b5SDimitry Andric Root, InsInstrs, DelInstrs, MinInstr->getTrace(MBB));
4824ba319b5SDimitry Andric long CurrentLatencyDiff = ((long)RootLatency) - ((long)NewRootLatency);
4834ba319b5SDimitry Andric assert(CurrentLatencyDiff <= PrevLatencyDiff &&
4844ba319b5SDimitry Andric "Current pattern is better than previous pattern.");
4854ba319b5SDimitry Andric PrevLatencyDiff = CurrentLatencyDiff;
4864ba319b5SDimitry Andric }
4874ba319b5SDimitry Andric }
4884ba319b5SDimitry Andric
489ff0cc061SDimitry Andric /// Substitute a slow code sequence with a faster one by
49039d628a0SDimitry Andric /// evaluating instruction combining pattern.
49139d628a0SDimitry Andric /// The prototype of such a pattern is MUl + ADD -> MADD. Performs instruction
49239d628a0SDimitry Andric /// combining based on machine trace metrics. Only combine a sequence of
49339d628a0SDimitry Andric /// instructions when this neither lengthens the critical path nor increases
49439d628a0SDimitry Andric /// resource pressure. When optimizing for codesize always combine when the new
49539d628a0SDimitry Andric /// sequence is shorter.
combineInstructions(MachineBasicBlock * MBB)49639d628a0SDimitry Andric bool MachineCombiner::combineInstructions(MachineBasicBlock *MBB) {
49739d628a0SDimitry Andric bool Changed = false;
4984ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "Combining MBB " << MBB->getName() << "\n");
49939d628a0SDimitry Andric
5002cab237bSDimitry Andric bool IncrementalUpdate = false;
50139d628a0SDimitry Andric auto BlockIter = MBB->begin();
5022cab237bSDimitry Andric decltype(BlockIter) LastUpdate;
5033ca95b02SDimitry Andric // Check if the block is in a loop.
5043ca95b02SDimitry Andric const MachineLoop *ML = MLI->getLoopFor(MBB);
5052cab237bSDimitry Andric if (!MinInstr)
5062cab237bSDimitry Andric MinInstr = Traces->getEnsemble(MachineTraceMetrics::TS_MinInstrCount);
5072cab237bSDimitry Andric
5082cab237bSDimitry Andric SparseSet<LiveRegUnit> RegUnits;
5092cab237bSDimitry Andric RegUnits.setUniverse(TRI->getNumRegUnits());
51039d628a0SDimitry Andric
51139d628a0SDimitry Andric while (BlockIter != MBB->end()) {
51239d628a0SDimitry Andric auto &MI = *BlockIter++;
5137d523365SDimitry Andric SmallVector<MachineCombinerPattern, 16> Patterns;
51439d628a0SDimitry Andric // The motivating example is:
51539d628a0SDimitry Andric //
51639d628a0SDimitry Andric // MUL Other MUL_op1 MUL_op2 Other
51739d628a0SDimitry Andric // \ / \ | /
51839d628a0SDimitry Andric // ADD/SUB => MADD/MSUB
51939d628a0SDimitry Andric // (=Root) (=NewRoot)
52039d628a0SDimitry Andric
52139d628a0SDimitry Andric // The DAGCombine code always replaced MUL + ADD/SUB by MADD. While this is
52239d628a0SDimitry Andric // usually beneficial for code size it unfortunately can hurt performance
52339d628a0SDimitry Andric // when the ADD is on the critical path, but the MUL is not. With the
52439d628a0SDimitry Andric // substitution the MUL becomes part of the critical path (in form of the
52539d628a0SDimitry Andric // MADD) and can lengthen it on architectures where the MADD latency is
52639d628a0SDimitry Andric // longer than the ADD latency.
52739d628a0SDimitry Andric //
52839d628a0SDimitry Andric // For each instruction we check if it can be the root of a combiner
52939d628a0SDimitry Andric // pattern. Then for each pattern the new code sequence in form of MI is
53039d628a0SDimitry Andric // generated and evaluated. When the efficiency criteria (don't lengthen
53139d628a0SDimitry Andric // critical path, don't use more resources) is met the new sequence gets
53239d628a0SDimitry Andric // hooked up into the basic block before the old sequence is removed.
53339d628a0SDimitry Andric //
53439d628a0SDimitry Andric // The algorithm does not try to evaluate all patterns and pick the best.
53539d628a0SDimitry Andric // This is only an artificial restriction though. In practice there is
5368f0fd8f6SDimitry Andric // mostly one pattern, and getMachineCombinerPatterns() can order patterns
5374ba319b5SDimitry Andric // based on an internal cost heuristic. If
5384ba319b5SDimitry Andric // machine-combiner-verify-pattern-order is enabled, all patterns are
5394ba319b5SDimitry Andric // checked to ensure later patterns do not provide better latency savings.
54039d628a0SDimitry Andric
5417d523365SDimitry Andric if (!TII->getMachineCombinerPatterns(MI, Patterns))
5427d523365SDimitry Andric continue;
5437d523365SDimitry Andric
5444ba319b5SDimitry Andric if (VerifyPatternOrder)
5454ba319b5SDimitry Andric verifyPatternOrder(MBB, MI, Patterns);
5464ba319b5SDimitry Andric
5478f0fd8f6SDimitry Andric for (auto P : Patterns) {
54839d628a0SDimitry Andric SmallVector<MachineInstr *, 16> InsInstrs;
54939d628a0SDimitry Andric SmallVector<MachineInstr *, 16> DelInstrs;
55039d628a0SDimitry Andric DenseMap<unsigned, unsigned> InstrIdxForVirtReg;
55139d628a0SDimitry Andric TII->genAlternativeCodeSequence(MI, P, InsInstrs, DelInstrs,
55239d628a0SDimitry Andric InstrIdxForVirtReg);
5533dac3a9bSDimitry Andric unsigned NewInstCount = InsInstrs.size();
5543dac3a9bSDimitry Andric unsigned OldInstCount = DelInstrs.size();
55539d628a0SDimitry Andric // Found pattern, but did not generate alternative sequence.
55639d628a0SDimitry Andric // This can happen e.g. when an immediate could not be materialized
55739d628a0SDimitry Andric // in a single instruction.
5583dac3a9bSDimitry Andric if (!NewInstCount)
55939d628a0SDimitry Andric continue;
5607d523365SDimitry Andric
5614ba319b5SDimitry Andric LLVM_DEBUG(if (dump_intrs) {
5624ba319b5SDimitry Andric dbgs() << "\tFor the Pattern (" << (int)P << ") these instructions could be removed\n";
5634ba319b5SDimitry Andric for (auto const *InstrPtr : DelInstrs) {
5644ba319b5SDimitry Andric dbgs() << "\t\t" << STI->getSchedInfoStr(*InstrPtr) << ": ";
5654ba319b5SDimitry Andric InstrPtr->print(dbgs(), false, false, false, TII);
5664ba319b5SDimitry Andric }
5674ba319b5SDimitry Andric dbgs() << "\tThese instructions could replace the removed ones\n";
5684ba319b5SDimitry Andric for (auto const *InstrPtr : InsInstrs) {
5694ba319b5SDimitry Andric dbgs() << "\t\t" << STI->getSchedInfoStr(*InstrPtr) << ": ";
5704ba319b5SDimitry Andric InstrPtr->print(dbgs(), false, false, false, TII);
5714ba319b5SDimitry Andric }
5724ba319b5SDimitry Andric });
5734ba319b5SDimitry Andric
5743ca95b02SDimitry Andric bool SubstituteAlways = false;
5753ca95b02SDimitry Andric if (ML && TII->isThroughputPattern(P))
5763ca95b02SDimitry Andric SubstituteAlways = true;
5773ca95b02SDimitry Andric
5782cab237bSDimitry Andric if (IncrementalUpdate) {
5792cab237bSDimitry Andric // Update depths since the last incremental update.
5802cab237bSDimitry Andric MinInstr->updateDepths(LastUpdate, BlockIter, RegUnits);
5812cab237bSDimitry Andric LastUpdate = BlockIter;
5822cab237bSDimitry Andric }
5832cab237bSDimitry Andric
58439d628a0SDimitry Andric // Substitute when we optimize for codesize and the new sequence has
58539d628a0SDimitry Andric // fewer instructions OR
586ff0cc061SDimitry Andric // the new sequence neither lengthens the critical path nor increases
58739d628a0SDimitry Andric // resource pressure.
5887a7e6055SDimitry Andric if (SubstituteAlways || doSubstitute(NewInstCount, OldInstCount)) {
5892cab237bSDimitry Andric insertDeleteInstructions(MBB, MI, InsInstrs, DelInstrs, MinInstr,
5902cab237bSDimitry Andric RegUnits, IncrementalUpdate);
5918f0fd8f6SDimitry Andric // Eagerly stop after the first pattern fires.
5927a7e6055SDimitry Andric Changed = true;
59339d628a0SDimitry Andric break;
59439d628a0SDimitry Andric } else {
5952cab237bSDimitry Andric // For big basic blocks, we only compute the full trace the first time
5962cab237bSDimitry Andric // we hit this. We do not invalidate the trace, but instead update the
5972cab237bSDimitry Andric // instruction depths incrementally.
5982cab237bSDimitry Andric // NOTE: Only the instruction depths up to MI are accurate. All other
5992cab237bSDimitry Andric // trace information is not updated.
6007a7e6055SDimitry Andric MachineTraceMetrics::Trace BlockTrace = MinInstr->getTrace(MBB);
6012cab237bSDimitry Andric Traces->verifyAnalysis();
6027a7e6055SDimitry Andric if (improvesCriticalPathLen(MBB, &MI, BlockTrace, InsInstrs, DelInstrs,
6032cab237bSDimitry Andric InstrIdxForVirtReg, P,
6042cab237bSDimitry Andric !IncrementalUpdate) &&
6057a7e6055SDimitry Andric preservesResourceLen(MBB, BlockTrace, InsInstrs, DelInstrs)) {
6062cab237bSDimitry Andric if (MBB->size() > inc_threshold) {
6072cab237bSDimitry Andric // Use incremental depth updates for basic blocks above treshold
6082cab237bSDimitry Andric IncrementalUpdate = true;
6092cab237bSDimitry Andric LastUpdate = BlockIter;
6102cab237bSDimitry Andric }
6112cab237bSDimitry Andric
6122cab237bSDimitry Andric insertDeleteInstructions(MBB, MI, InsInstrs, DelInstrs, MinInstr,
6132cab237bSDimitry Andric RegUnits, IncrementalUpdate);
6142cab237bSDimitry Andric
6157a7e6055SDimitry Andric // Eagerly stop after the first pattern fires.
6167a7e6055SDimitry Andric Changed = true;
6177a7e6055SDimitry Andric break;
6187a7e6055SDimitry Andric }
61939d628a0SDimitry Andric // Cleanup instructions of the alternative code sequence. There is no
62039d628a0SDimitry Andric // use for them.
62139d628a0SDimitry Andric MachineFunction *MF = MBB->getParent();
6228f0fd8f6SDimitry Andric for (auto *InstrPtr : InsInstrs)
6238f0fd8f6SDimitry Andric MF->DeleteMachineInstr(InstrPtr);
62439d628a0SDimitry Andric }
62539d628a0SDimitry Andric InstrIdxForVirtReg.clear();
62639d628a0SDimitry Andric }
62739d628a0SDimitry Andric }
62839d628a0SDimitry Andric
6292cab237bSDimitry Andric if (Changed && IncrementalUpdate)
6302cab237bSDimitry Andric Traces->invalidate(MBB);
63139d628a0SDimitry Andric return Changed;
63239d628a0SDimitry Andric }
63339d628a0SDimitry Andric
runOnMachineFunction(MachineFunction & MF)63439d628a0SDimitry Andric bool MachineCombiner::runOnMachineFunction(MachineFunction &MF) {
6354ba319b5SDimitry Andric STI = &MF.getSubtarget();
6364ba319b5SDimitry Andric TII = STI->getInstrInfo();
6374ba319b5SDimitry Andric TRI = STI->getRegisterInfo();
6384ba319b5SDimitry Andric SchedModel = STI->getSchedModel();
6394ba319b5SDimitry Andric TSchedModel.init(STI);
64039d628a0SDimitry Andric MRI = &MF.getRegInfo();
6413ca95b02SDimitry Andric MLI = &getAnalysis<MachineLoopInfo>();
64239d628a0SDimitry Andric Traces = &getAnalysis<MachineTraceMetrics>();
6437d523365SDimitry Andric MinInstr = nullptr;
6442cab237bSDimitry Andric OptSize = MF.getFunction().optForSize();
64539d628a0SDimitry Andric
6464ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << getPassName() << ": " << MF.getName() << '\n');
64739d628a0SDimitry Andric if (!TII->useMachineCombiner()) {
6484ba319b5SDimitry Andric LLVM_DEBUG(
6494ba319b5SDimitry Andric dbgs()
6504ba319b5SDimitry Andric << " Skipping pass: Target does not support machine combiner\n");
65139d628a0SDimitry Andric return false;
65239d628a0SDimitry Andric }
65339d628a0SDimitry Andric
65439d628a0SDimitry Andric bool Changed = false;
65539d628a0SDimitry Andric
65639d628a0SDimitry Andric // Try to combine instructions.
65739d628a0SDimitry Andric for (auto &MBB : MF)
65839d628a0SDimitry Andric Changed |= combineInstructions(&MBB);
65939d628a0SDimitry Andric
66039d628a0SDimitry Andric return Changed;
66139d628a0SDimitry Andric }
662