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