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