1 | //===- MachineCycleAnalysis.cpp - Compute CycleInfo for Machine IR --------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "llvm/CodeGen/MachineCycleAnalysis.h" |
10 | #include "llvm/ADT/GenericCycleImpl.h" |
11 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
12 | #include "llvm/CodeGen/MachineSSAContext.h" |
13 | #include "llvm/CodeGen/TargetInstrInfo.h" |
14 | #include "llvm/CodeGen/TargetSubtargetInfo.h" |
15 | #include "llvm/InitializePasses.h" |
16 | |
17 | using namespace llvm; |
18 | |
19 | template class llvm::GenericCycleInfo<llvm::MachineSSAContext>; |
20 | template class llvm::GenericCycle<llvm::MachineSSAContext>; |
21 | |
22 | char MachineCycleInfoWrapperPass::ID = 0; |
23 | |
24 | MachineCycleInfoWrapperPass::MachineCycleInfoWrapperPass() |
25 | : MachineFunctionPass(ID) { |
26 | initializeMachineCycleInfoWrapperPassPass(*PassRegistry::getPassRegistry()); |
27 | } |
28 | |
29 | INITIALIZE_PASS_BEGIN(MachineCycleInfoWrapperPass, "machine-cycles" , |
30 | "Machine Cycle Info Analysis" , true, true) |
31 | INITIALIZE_PASS_END(MachineCycleInfoWrapperPass, "machine-cycles" , |
32 | "Machine Cycle Info Analysis" , true, true) |
33 | |
34 | void MachineCycleInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { |
35 | AU.setPreservesAll(); |
36 | MachineFunctionPass::getAnalysisUsage(AU); |
37 | } |
38 | |
39 | bool MachineCycleInfoWrapperPass::runOnMachineFunction(MachineFunction &Func) { |
40 | CI.clear(); |
41 | |
42 | F = &Func; |
43 | CI.compute(F&: Func); |
44 | return false; |
45 | } |
46 | |
47 | void MachineCycleInfoWrapperPass::print(raw_ostream &OS, const Module *) const { |
48 | OS << "MachineCycleInfo for function: " << F->getName() << "\n" ; |
49 | CI.print(Out&: OS); |
50 | } |
51 | |
52 | void MachineCycleInfoWrapperPass::releaseMemory() { |
53 | CI.clear(); |
54 | F = nullptr; |
55 | } |
56 | |
57 | AnalysisKey MachineCycleAnalysis::Key; |
58 | |
59 | MachineCycleInfo |
60 | MachineCycleAnalysis::run(MachineFunction &MF, |
61 | MachineFunctionAnalysisManager &MFAM) { |
62 | MachineCycleInfo MCI; |
63 | MCI.compute(F&: MF); |
64 | return MCI; |
65 | } |
66 | |
67 | namespace { |
68 | class MachineCycleInfoPrinterLegacy : public MachineFunctionPass { |
69 | public: |
70 | static char ID; |
71 | |
72 | MachineCycleInfoPrinterLegacy(); |
73 | |
74 | bool runOnMachineFunction(MachineFunction &F) override; |
75 | void getAnalysisUsage(AnalysisUsage &AU) const override; |
76 | }; |
77 | } // namespace |
78 | |
79 | char MachineCycleInfoPrinterLegacy::ID = 0; |
80 | |
81 | MachineCycleInfoPrinterLegacy::MachineCycleInfoPrinterLegacy() |
82 | : MachineFunctionPass(ID) { |
83 | initializeMachineCycleInfoPrinterLegacyPass(*PassRegistry::getPassRegistry()); |
84 | } |
85 | |
86 | INITIALIZE_PASS_BEGIN(MachineCycleInfoPrinterLegacy, "print-machine-cycles" , |
87 | "Print Machine Cycle Info Analysis" , true, true) |
88 | INITIALIZE_PASS_DEPENDENCY(MachineCycleInfoWrapperPass) |
89 | INITIALIZE_PASS_END(MachineCycleInfoPrinterLegacy, "print-machine-cycles" , |
90 | "Print Machine Cycle Info Analysis" , true, true) |
91 | |
92 | void MachineCycleInfoPrinterLegacy::getAnalysisUsage(AnalysisUsage &AU) const { |
93 | AU.setPreservesAll(); |
94 | AU.addRequired<MachineCycleInfoWrapperPass>(); |
95 | MachineFunctionPass::getAnalysisUsage(AU); |
96 | } |
97 | |
98 | bool MachineCycleInfoPrinterLegacy::runOnMachineFunction(MachineFunction &F) { |
99 | auto &CI = getAnalysis<MachineCycleInfoWrapperPass>(); |
100 | CI.print(OS&: errs()); |
101 | return false; |
102 | } |
103 | |
104 | PreservedAnalyses |
105 | MachineCycleInfoPrinterPass::run(MachineFunction &MF, |
106 | MachineFunctionAnalysisManager &MFAM) { |
107 | auto &MCI = MFAM.getResult<MachineCycleAnalysis>(IR&: MF); |
108 | MCI.print(Out&: OS); |
109 | return PreservedAnalyses::all(); |
110 | } |
111 | |
112 | bool llvm::isCycleInvariant(const MachineCycle *Cycle, MachineInstr &I) { |
113 | MachineFunction *MF = I.getParent()->getParent(); |
114 | MachineRegisterInfo *MRI = &MF->getRegInfo(); |
115 | const TargetSubtargetInfo &ST = MF->getSubtarget(); |
116 | const TargetRegisterInfo *TRI = ST.getRegisterInfo(); |
117 | const TargetInstrInfo *TII = ST.getInstrInfo(); |
118 | |
119 | // The instruction is cycle invariant if all of its operands are. |
120 | for (const MachineOperand &MO : I.operands()) { |
121 | if (!MO.isReg()) |
122 | continue; |
123 | |
124 | Register Reg = MO.getReg(); |
125 | if (Reg == 0) |
126 | continue; |
127 | |
128 | // An instruction that uses or defines a physical register can't e.g. be |
129 | // hoisted, so mark this as not invariant. |
130 | if (Reg.isPhysical()) { |
131 | if (MO.isUse()) { |
132 | // If the physreg has no defs anywhere, it's just an ambient register |
133 | // and we can freely move its uses. Alternatively, if it's allocatable, |
134 | // it could get allocated to something with a def during allocation. |
135 | // However, if the physreg is known to always be caller saved/restored |
136 | // then this use is safe to hoist. |
137 | if (!MRI->isConstantPhysReg(PhysReg: Reg) && |
138 | !(TRI->isCallerPreservedPhysReg(PhysReg: Reg.asMCReg(), MF: *I.getMF())) && |
139 | !TII->isIgnorableUse(MO)) |
140 | return false; |
141 | // Otherwise it's safe to move. |
142 | continue; |
143 | } else if (!MO.isDead()) { |
144 | // A def that isn't dead can't be moved. |
145 | return false; |
146 | } else if (any_of(Range: Cycle->getEntries(), |
147 | P: [&](const MachineBasicBlock *Block) { |
148 | return Block->isLiveIn(Reg); |
149 | })) { |
150 | // If the reg is live into any header of the cycle we can't hoist an |
151 | // instruction which would clobber it. |
152 | return false; |
153 | } |
154 | } |
155 | |
156 | if (!MO.isUse()) |
157 | continue; |
158 | |
159 | assert(MRI->getVRegDef(Reg) && "Machine instr not mapped for this vreg?!" ); |
160 | |
161 | // If the cycle contains the definition of an operand, then the instruction |
162 | // isn't cycle invariant. |
163 | if (Cycle->contains(Block: MRI->getVRegDef(Reg)->getParent())) |
164 | return false; |
165 | } |
166 | |
167 | // If we got this far, the instruction is cycle invariant! |
168 | return true; |
169 | } |
170 | |