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