xref: /llvm-project/llvm/lib/CodeGen/MachineCycleAnalysis.cpp (revision e72ca520bb4806d4003ef69698089fd83a5777cb)
11d0244aeSSameer Sahasrabuddhe //===- MachineCycleAnalysis.cpp - Compute CycleInfo for Machine IR --------===//
21d0244aeSSameer Sahasrabuddhe //
31d0244aeSSameer Sahasrabuddhe // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41d0244aeSSameer Sahasrabuddhe // See https://llvm.org/LICENSE.txt for license information.
51d0244aeSSameer Sahasrabuddhe // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61d0244aeSSameer Sahasrabuddhe //
71d0244aeSSameer Sahasrabuddhe //===----------------------------------------------------------------------===//
81d0244aeSSameer Sahasrabuddhe 
91d0244aeSSameer Sahasrabuddhe #include "llvm/CodeGen/MachineCycleAnalysis.h"
101d0244aeSSameer Sahasrabuddhe #include "llvm/ADT/GenericCycleImpl.h"
11d7927523SChen Zheng #include "llvm/CodeGen/MachineRegisterInfo.h"
12475ce4c2SSameer Sahasrabuddhe #include "llvm/CodeGen/MachineSSAContext.h"
13d7927523SChen Zheng #include "llvm/CodeGen/TargetInstrInfo.h"
14d7927523SChen Zheng #include "llvm/CodeGen/TargetSubtargetInfo.h"
15475ce4c2SSameer Sahasrabuddhe #include "llvm/InitializePasses.h"
161d0244aeSSameer Sahasrabuddhe 
171d0244aeSSameer Sahasrabuddhe using namespace llvm;
181d0244aeSSameer Sahasrabuddhe 
191d0244aeSSameer Sahasrabuddhe template class llvm::GenericCycleInfo<llvm::MachineSSAContext>;
201d0244aeSSameer Sahasrabuddhe template class llvm::GenericCycle<llvm::MachineSSAContext>;
211d0244aeSSameer Sahasrabuddhe 
221d0244aeSSameer Sahasrabuddhe char MachineCycleInfoWrapperPass::ID = 0;
231d0244aeSSameer Sahasrabuddhe 
MachineCycleInfoWrapperPass()241d0244aeSSameer Sahasrabuddhe MachineCycleInfoWrapperPass::MachineCycleInfoWrapperPass()
251d0244aeSSameer Sahasrabuddhe     : MachineFunctionPass(ID) {
261d0244aeSSameer Sahasrabuddhe   initializeMachineCycleInfoWrapperPassPass(*PassRegistry::getPassRegistry());
271d0244aeSSameer Sahasrabuddhe }
281d0244aeSSameer Sahasrabuddhe 
291d0244aeSSameer Sahasrabuddhe INITIALIZE_PASS_BEGIN(MachineCycleInfoWrapperPass, "machine-cycles",
301d0244aeSSameer Sahasrabuddhe                       "Machine Cycle Info Analysis", true, true)
311d0244aeSSameer Sahasrabuddhe INITIALIZE_PASS_END(MachineCycleInfoWrapperPass, "machine-cycles",
321d0244aeSSameer Sahasrabuddhe                     "Machine Cycle Info Analysis", true, true)
331d0244aeSSameer Sahasrabuddhe 
getAnalysisUsage(AnalysisUsage & AU) const341d0244aeSSameer Sahasrabuddhe void MachineCycleInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
351d0244aeSSameer Sahasrabuddhe   AU.setPreservesAll();
361d0244aeSSameer Sahasrabuddhe   MachineFunctionPass::getAnalysisUsage(AU);
371d0244aeSSameer Sahasrabuddhe }
381d0244aeSSameer Sahasrabuddhe 
runOnMachineFunction(MachineFunction & Func)391d0244aeSSameer Sahasrabuddhe bool MachineCycleInfoWrapperPass::runOnMachineFunction(MachineFunction &Func) {
401d0244aeSSameer Sahasrabuddhe   CI.clear();
411d0244aeSSameer Sahasrabuddhe 
421d0244aeSSameer Sahasrabuddhe   F = &Func;
431d0244aeSSameer Sahasrabuddhe   CI.compute(Func);
441d0244aeSSameer Sahasrabuddhe   return false;
451d0244aeSSameer Sahasrabuddhe }
461d0244aeSSameer Sahasrabuddhe 
print(raw_ostream & OS,const Module *) const471d0244aeSSameer Sahasrabuddhe void MachineCycleInfoWrapperPass::print(raw_ostream &OS, const Module *) const {
481d0244aeSSameer Sahasrabuddhe   OS << "MachineCycleInfo for function: " << F->getName() << "\n";
491d0244aeSSameer Sahasrabuddhe   CI.print(OS);
501d0244aeSSameer Sahasrabuddhe }
511d0244aeSSameer Sahasrabuddhe 
releaseMemory()521d0244aeSSameer Sahasrabuddhe void MachineCycleInfoWrapperPass::releaseMemory() {
531d0244aeSSameer Sahasrabuddhe   CI.clear();
541d0244aeSSameer Sahasrabuddhe   F = nullptr;
551d0244aeSSameer Sahasrabuddhe }
561d0244aeSSameer Sahasrabuddhe 
57b6942a28SBenjamin Kramer namespace {
58d7927523SChen Zheng class MachineCycleInfoPrinterPass : public MachineFunctionPass {
59d7927523SChen Zheng public:
60d7927523SChen Zheng   static char ID;
61d7927523SChen Zheng 
62d7927523SChen Zheng   MachineCycleInfoPrinterPass();
63d7927523SChen Zheng 
64d7927523SChen Zheng   bool runOnMachineFunction(MachineFunction &F) override;
65d7927523SChen Zheng   void getAnalysisUsage(AnalysisUsage &AU) const override;
66d7927523SChen Zheng };
67b6942a28SBenjamin Kramer } // namespace
68d7927523SChen Zheng 
691d0244aeSSameer Sahasrabuddhe char MachineCycleInfoPrinterPass::ID = 0;
701d0244aeSSameer Sahasrabuddhe 
MachineCycleInfoPrinterPass()711d0244aeSSameer Sahasrabuddhe MachineCycleInfoPrinterPass::MachineCycleInfoPrinterPass()
721d0244aeSSameer Sahasrabuddhe     : MachineFunctionPass(ID) {
731d0244aeSSameer Sahasrabuddhe   initializeMachineCycleInfoPrinterPassPass(*PassRegistry::getPassRegistry());
741d0244aeSSameer Sahasrabuddhe }
751d0244aeSSameer Sahasrabuddhe 
761d0244aeSSameer Sahasrabuddhe INITIALIZE_PASS_BEGIN(MachineCycleInfoPrinterPass, "print-machine-cycles",
771d0244aeSSameer Sahasrabuddhe                       "Print Machine Cycle Info Analysis", true, true)
INITIALIZE_PASS_DEPENDENCY(MachineCycleInfoWrapperPass)781d0244aeSSameer Sahasrabuddhe INITIALIZE_PASS_DEPENDENCY(MachineCycleInfoWrapperPass)
791d0244aeSSameer Sahasrabuddhe INITIALIZE_PASS_END(MachineCycleInfoPrinterPass, "print-machine-cycles",
801d0244aeSSameer Sahasrabuddhe                     "Print Machine Cycle Info Analysis", true, true)
811d0244aeSSameer Sahasrabuddhe 
821d0244aeSSameer Sahasrabuddhe void MachineCycleInfoPrinterPass::getAnalysisUsage(AnalysisUsage &AU) const {
831d0244aeSSameer Sahasrabuddhe   AU.setPreservesAll();
841d0244aeSSameer Sahasrabuddhe   AU.addRequired<MachineCycleInfoWrapperPass>();
851d0244aeSSameer Sahasrabuddhe   MachineFunctionPass::getAnalysisUsage(AU);
861d0244aeSSameer Sahasrabuddhe }
871d0244aeSSameer Sahasrabuddhe 
runOnMachineFunction(MachineFunction & F)881d0244aeSSameer Sahasrabuddhe bool MachineCycleInfoPrinterPass::runOnMachineFunction(MachineFunction &F) {
891d0244aeSSameer Sahasrabuddhe   auto &CI = getAnalysis<MachineCycleInfoWrapperPass>();
901d0244aeSSameer Sahasrabuddhe   CI.print(errs());
911d0244aeSSameer Sahasrabuddhe   return false;
921d0244aeSSameer Sahasrabuddhe }
93d7927523SChen Zheng 
isCycleInvariant(const MachineCycle * Cycle,MachineInstr & I)94d7927523SChen Zheng bool llvm::isCycleInvariant(const MachineCycle *Cycle, MachineInstr &I) {
95d7927523SChen Zheng   MachineFunction *MF = I.getParent()->getParent();
96d7927523SChen Zheng   MachineRegisterInfo *MRI = &MF->getRegInfo();
97d7927523SChen Zheng   const TargetSubtargetInfo &ST = MF->getSubtarget();
98d7927523SChen Zheng   const TargetRegisterInfo *TRI = ST.getRegisterInfo();
99d7927523SChen Zheng   const TargetInstrInfo *TII = ST.getInstrInfo();
100d7927523SChen Zheng 
101d7927523SChen Zheng   // The instruction is cycle invariant if all of its operands are.
102d7927523SChen Zheng   for (const MachineOperand &MO : I.operands()) {
103d7927523SChen Zheng     if (!MO.isReg())
104d7927523SChen Zheng       continue;
105d7927523SChen Zheng 
106d7927523SChen Zheng     Register Reg = MO.getReg();
107d7927523SChen Zheng     if (Reg == 0)
108d7927523SChen Zheng       continue;
109d7927523SChen Zheng 
110d7927523SChen Zheng     // An instruction that uses or defines a physical register can't e.g. be
111d7927523SChen Zheng     // hoisted, so mark this as not invariant.
112*e72ca520SCraig Topper     if (Reg.isPhysical()) {
113d7927523SChen Zheng       if (MO.isUse()) {
114d7927523SChen Zheng         // If the physreg has no defs anywhere, it's just an ambient register
115d7927523SChen Zheng         // and we can freely move its uses. Alternatively, if it's allocatable,
116d7927523SChen Zheng         // it could get allocated to something with a def during allocation.
117d7927523SChen Zheng         // However, if the physreg is known to always be caller saved/restored
118d7927523SChen Zheng         // then this use is safe to hoist.
119d7927523SChen Zheng         if (!MRI->isConstantPhysReg(Reg) &&
120d7927523SChen Zheng             !(TRI->isCallerPreservedPhysReg(Reg.asMCReg(), *I.getMF())) &&
121d7927523SChen Zheng             !TII->isIgnorableUse(MO))
122d7927523SChen Zheng           return false;
123d7927523SChen Zheng         // Otherwise it's safe to move.
124d7927523SChen Zheng         continue;
125d7927523SChen Zheng       } else if (!MO.isDead()) {
126d7927523SChen Zheng         // A def that isn't dead can't be moved.
127d7927523SChen Zheng         return false;
128d7927523SChen Zheng       } else if (any_of(Cycle->getEntries(),
129d7927523SChen Zheng                         [&](const MachineBasicBlock *Block) {
130d7927523SChen Zheng                           return Block->isLiveIn(Reg);
131d7927523SChen Zheng                         })) {
132d7927523SChen Zheng         // If the reg is live into any header of the cycle we can't hoist an
133d7927523SChen Zheng         // instruction which would clobber it.
134d7927523SChen Zheng         return false;
135d7927523SChen Zheng       }
136d7927523SChen Zheng     }
137d7927523SChen Zheng 
138d7927523SChen Zheng     if (!MO.isUse())
139d7927523SChen Zheng       continue;
140d7927523SChen Zheng 
141d7927523SChen Zheng     assert(MRI->getVRegDef(Reg) && "Machine instr not mapped for this vreg?!");
142d7927523SChen Zheng 
143d7927523SChen Zheng     // If the cycle contains the definition of an operand, then the instruction
144d7927523SChen Zheng     // isn't cycle invariant.
145d7927523SChen Zheng     if (Cycle->contains(MRI->getVRegDef(Reg)->getParent()))
146d7927523SChen Zheng       return false;
147d7927523SChen Zheng   }
148d7927523SChen Zheng 
149d7927523SChen Zheng   // If we got this far, the instruction is cycle invariant!
150d7927523SChen Zheng   return true;
151d7927523SChen Zheng }
152