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