xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/MachineCycleAnalysis.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10eae32dcSDimitry Andric //===- MachineCycleAnalysis.cpp - Compute CycleInfo for Machine IR --------===//
20eae32dcSDimitry Andric //
30eae32dcSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40eae32dcSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50eae32dcSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60eae32dcSDimitry Andric //
70eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
80eae32dcSDimitry Andric 
90eae32dcSDimitry Andric #include "llvm/CodeGen/MachineCycleAnalysis.h"
100eae32dcSDimitry Andric #include "llvm/ADT/GenericCycleImpl.h"
1181ad6265SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
12*bdd1243dSDimitry Andric #include "llvm/CodeGen/MachineSSAContext.h"
1381ad6265SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
1481ad6265SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
15*bdd1243dSDimitry Andric #include "llvm/InitializePasses.h"
160eae32dcSDimitry Andric 
170eae32dcSDimitry Andric using namespace llvm;
180eae32dcSDimitry Andric 
190eae32dcSDimitry Andric template class llvm::GenericCycleInfo<llvm::MachineSSAContext>;
200eae32dcSDimitry Andric template class llvm::GenericCycle<llvm::MachineSSAContext>;
210eae32dcSDimitry Andric 
220eae32dcSDimitry Andric char MachineCycleInfoWrapperPass::ID = 0;
230eae32dcSDimitry Andric 
MachineCycleInfoWrapperPass()240eae32dcSDimitry Andric MachineCycleInfoWrapperPass::MachineCycleInfoWrapperPass()
250eae32dcSDimitry Andric     : MachineFunctionPass(ID) {
260eae32dcSDimitry Andric   initializeMachineCycleInfoWrapperPassPass(*PassRegistry::getPassRegistry());
270eae32dcSDimitry Andric }
280eae32dcSDimitry Andric 
290eae32dcSDimitry Andric INITIALIZE_PASS_BEGIN(MachineCycleInfoWrapperPass, "machine-cycles",
300eae32dcSDimitry Andric                       "Machine Cycle Info Analysis", true, true)
310eae32dcSDimitry Andric INITIALIZE_PASS_END(MachineCycleInfoWrapperPass, "machine-cycles",
320eae32dcSDimitry Andric                     "Machine Cycle Info Analysis", true, true)
330eae32dcSDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const340eae32dcSDimitry Andric void MachineCycleInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
350eae32dcSDimitry Andric   AU.setPreservesAll();
360eae32dcSDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
370eae32dcSDimitry Andric }
380eae32dcSDimitry Andric 
runOnMachineFunction(MachineFunction & Func)390eae32dcSDimitry Andric bool MachineCycleInfoWrapperPass::runOnMachineFunction(MachineFunction &Func) {
400eae32dcSDimitry Andric   CI.clear();
410eae32dcSDimitry Andric 
420eae32dcSDimitry Andric   F = &Func;
430eae32dcSDimitry Andric   CI.compute(Func);
440eae32dcSDimitry Andric   return false;
450eae32dcSDimitry Andric }
460eae32dcSDimitry Andric 
print(raw_ostream & OS,const Module *) const470eae32dcSDimitry Andric void MachineCycleInfoWrapperPass::print(raw_ostream &OS, const Module *) const {
480eae32dcSDimitry Andric   OS << "MachineCycleInfo for function: " << F->getName() << "\n";
490eae32dcSDimitry Andric   CI.print(OS);
500eae32dcSDimitry Andric }
510eae32dcSDimitry Andric 
releaseMemory()520eae32dcSDimitry Andric void MachineCycleInfoWrapperPass::releaseMemory() {
530eae32dcSDimitry Andric   CI.clear();
540eae32dcSDimitry Andric   F = nullptr;
550eae32dcSDimitry Andric }
560eae32dcSDimitry Andric 
57*bdd1243dSDimitry Andric namespace {
5881ad6265SDimitry Andric class MachineCycleInfoPrinterPass : public MachineFunctionPass {
5981ad6265SDimitry Andric public:
6081ad6265SDimitry Andric   static char ID;
6181ad6265SDimitry Andric 
6281ad6265SDimitry Andric   MachineCycleInfoPrinterPass();
6381ad6265SDimitry Andric 
6481ad6265SDimitry Andric   bool runOnMachineFunction(MachineFunction &F) override;
6581ad6265SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override;
6681ad6265SDimitry Andric };
67*bdd1243dSDimitry Andric } // namespace
6881ad6265SDimitry Andric 
690eae32dcSDimitry Andric char MachineCycleInfoPrinterPass::ID = 0;
700eae32dcSDimitry Andric 
MachineCycleInfoPrinterPass()710eae32dcSDimitry Andric MachineCycleInfoPrinterPass::MachineCycleInfoPrinterPass()
720eae32dcSDimitry Andric     : MachineFunctionPass(ID) {
730eae32dcSDimitry Andric   initializeMachineCycleInfoPrinterPassPass(*PassRegistry::getPassRegistry());
740eae32dcSDimitry Andric }
750eae32dcSDimitry Andric 
760eae32dcSDimitry Andric INITIALIZE_PASS_BEGIN(MachineCycleInfoPrinterPass, "print-machine-cycles",
770eae32dcSDimitry Andric                       "Print Machine Cycle Info Analysis", true, true)
INITIALIZE_PASS_DEPENDENCY(MachineCycleInfoWrapperPass)780eae32dcSDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineCycleInfoWrapperPass)
790eae32dcSDimitry Andric INITIALIZE_PASS_END(MachineCycleInfoPrinterPass, "print-machine-cycles",
800eae32dcSDimitry Andric                     "Print Machine Cycle Info Analysis", true, true)
810eae32dcSDimitry Andric 
820eae32dcSDimitry Andric void MachineCycleInfoPrinterPass::getAnalysisUsage(AnalysisUsage &AU) const {
830eae32dcSDimitry Andric   AU.setPreservesAll();
840eae32dcSDimitry Andric   AU.addRequired<MachineCycleInfoWrapperPass>();
850eae32dcSDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
860eae32dcSDimitry Andric }
870eae32dcSDimitry Andric 
runOnMachineFunction(MachineFunction & F)880eae32dcSDimitry Andric bool MachineCycleInfoPrinterPass::runOnMachineFunction(MachineFunction &F) {
890eae32dcSDimitry Andric   auto &CI = getAnalysis<MachineCycleInfoWrapperPass>();
900eae32dcSDimitry Andric   CI.print(errs());
910eae32dcSDimitry Andric   return false;
920eae32dcSDimitry Andric }
9381ad6265SDimitry Andric 
isCycleInvariant(const MachineCycle * Cycle,MachineInstr & I)9481ad6265SDimitry Andric bool llvm::isCycleInvariant(const MachineCycle *Cycle, MachineInstr &I) {
9581ad6265SDimitry Andric   MachineFunction *MF = I.getParent()->getParent();
9681ad6265SDimitry Andric   MachineRegisterInfo *MRI = &MF->getRegInfo();
9781ad6265SDimitry Andric   const TargetSubtargetInfo &ST = MF->getSubtarget();
9881ad6265SDimitry Andric   const TargetRegisterInfo *TRI = ST.getRegisterInfo();
9981ad6265SDimitry Andric   const TargetInstrInfo *TII = ST.getInstrInfo();
10081ad6265SDimitry Andric 
10181ad6265SDimitry Andric   // The instruction is cycle invariant if all of its operands are.
10281ad6265SDimitry Andric   for (const MachineOperand &MO : I.operands()) {
10381ad6265SDimitry Andric     if (!MO.isReg())
10481ad6265SDimitry Andric       continue;
10581ad6265SDimitry Andric 
10681ad6265SDimitry Andric     Register Reg = MO.getReg();
10781ad6265SDimitry Andric     if (Reg == 0)
10881ad6265SDimitry Andric       continue;
10981ad6265SDimitry Andric 
11081ad6265SDimitry Andric     // An instruction that uses or defines a physical register can't e.g. be
11181ad6265SDimitry Andric     // hoisted, so mark this as not invariant.
112*bdd1243dSDimitry Andric     if (Reg.isPhysical()) {
11381ad6265SDimitry Andric       if (MO.isUse()) {
11481ad6265SDimitry Andric         // If the physreg has no defs anywhere, it's just an ambient register
11581ad6265SDimitry Andric         // and we can freely move its uses. Alternatively, if it's allocatable,
11681ad6265SDimitry Andric         // it could get allocated to something with a def during allocation.
11781ad6265SDimitry Andric         // However, if the physreg is known to always be caller saved/restored
11881ad6265SDimitry Andric         // then this use is safe to hoist.
11981ad6265SDimitry Andric         if (!MRI->isConstantPhysReg(Reg) &&
12081ad6265SDimitry Andric             !(TRI->isCallerPreservedPhysReg(Reg.asMCReg(), *I.getMF())) &&
12181ad6265SDimitry Andric             !TII->isIgnorableUse(MO))
12281ad6265SDimitry Andric           return false;
12381ad6265SDimitry Andric         // Otherwise it's safe to move.
12481ad6265SDimitry Andric         continue;
12581ad6265SDimitry Andric       } else if (!MO.isDead()) {
12681ad6265SDimitry Andric         // A def that isn't dead can't be moved.
12781ad6265SDimitry Andric         return false;
12881ad6265SDimitry Andric       } else if (any_of(Cycle->getEntries(),
12981ad6265SDimitry Andric                         [&](const MachineBasicBlock *Block) {
13081ad6265SDimitry Andric                           return Block->isLiveIn(Reg);
13181ad6265SDimitry Andric                         })) {
13281ad6265SDimitry Andric         // If the reg is live into any header of the cycle we can't hoist an
13381ad6265SDimitry Andric         // instruction which would clobber it.
13481ad6265SDimitry Andric         return false;
13581ad6265SDimitry Andric       }
13681ad6265SDimitry Andric     }
13781ad6265SDimitry Andric 
13881ad6265SDimitry Andric     if (!MO.isUse())
13981ad6265SDimitry Andric       continue;
14081ad6265SDimitry Andric 
14181ad6265SDimitry Andric     assert(MRI->getVRegDef(Reg) && "Machine instr not mapped for this vreg?!");
14281ad6265SDimitry Andric 
14381ad6265SDimitry Andric     // If the cycle contains the definition of an operand, then the instruction
14481ad6265SDimitry Andric     // isn't cycle invariant.
14581ad6265SDimitry Andric     if (Cycle->contains(MRI->getVRegDef(Reg)->getParent()))
14681ad6265SDimitry Andric       return false;
14781ad6265SDimitry Andric   }
14881ad6265SDimitry Andric 
14981ad6265SDimitry Andric   // If we got this far, the instruction is cycle invariant!
15081ad6265SDimitry Andric   return true;
15181ad6265SDimitry Andric }
152