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 | namespace { |
58 | class MachineCycleInfoPrinterPass : public MachineFunctionPass { |
59 | public: |
60 | static char ID; |
61 | |
62 | MachineCycleInfoPrinterPass(); |
63 | |
64 | bool runOnMachineFunction(MachineFunction &F) override; |
65 | void getAnalysisUsage(AnalysisUsage &AU) const override; |
66 | }; |
67 | } // namespace |
68 | |
69 | char MachineCycleInfoPrinterPass::ID = 0; |
70 | |
71 | MachineCycleInfoPrinterPass::MachineCycleInfoPrinterPass() |
72 | : MachineFunctionPass(ID) { |
73 | initializeMachineCycleInfoPrinterPassPass(*PassRegistry::getPassRegistry()); |
74 | } |
75 | |
76 | INITIALIZE_PASS_BEGIN(MachineCycleInfoPrinterPass, "print-machine-cycles" , |
77 | "Print Machine Cycle Info Analysis" , true, true) |
78 | INITIALIZE_PASS_DEPENDENCY(MachineCycleInfoWrapperPass) |
79 | INITIALIZE_PASS_END(MachineCycleInfoPrinterPass, "print-machine-cycles" , |
80 | "Print Machine Cycle Info Analysis" , true, true) |
81 | |
82 | void MachineCycleInfoPrinterPass::getAnalysisUsage(AnalysisUsage &AU) const { |
83 | AU.setPreservesAll(); |
84 | AU.addRequired<MachineCycleInfoWrapperPass>(); |
85 | MachineFunctionPass::getAnalysisUsage(AU); |
86 | } |
87 | |
88 | bool MachineCycleInfoPrinterPass::runOnMachineFunction(MachineFunction &F) { |
89 | auto &CI = getAnalysis<MachineCycleInfoWrapperPass>(); |
90 | CI.print(OS&: errs()); |
91 | return false; |
92 | } |
93 | |
94 | bool llvm::isCycleInvariant(const MachineCycle *Cycle, MachineInstr &I) { |
95 | MachineFunction *MF = I.getParent()->getParent(); |
96 | MachineRegisterInfo *MRI = &MF->getRegInfo(); |
97 | const TargetSubtargetInfo &ST = MF->getSubtarget(); |
98 | const TargetRegisterInfo *TRI = ST.getRegisterInfo(); |
99 | const TargetInstrInfo *TII = ST.getInstrInfo(); |
100 | |
101 | // The instruction is cycle invariant if all of its operands are. |
102 | for (const MachineOperand &MO : I.operands()) { |
103 | if (!MO.isReg()) |
104 | continue; |
105 | |
106 | Register Reg = MO.getReg(); |
107 | if (Reg == 0) |
108 | continue; |
109 | |
110 | // An instruction that uses or defines a physical register can't e.g. be |
111 | // hoisted, so mark this as not invariant. |
112 | if (Reg.isPhysical()) { |
113 | if (MO.isUse()) { |
114 | // If the physreg has no defs anywhere, it's just an ambient register |
115 | // and we can freely move its uses. Alternatively, if it's allocatable, |
116 | // it could get allocated to something with a def during allocation. |
117 | // However, if the physreg is known to always be caller saved/restored |
118 | // then this use is safe to hoist. |
119 | if (!MRI->isConstantPhysReg(PhysReg: Reg) && |
120 | !(TRI->isCallerPreservedPhysReg(PhysReg: Reg.asMCReg(), MF: *I.getMF())) && |
121 | !TII->isIgnorableUse(MO)) |
122 | return false; |
123 | // Otherwise it's safe to move. |
124 | continue; |
125 | } else if (!MO.isDead()) { |
126 | // A def that isn't dead can't be moved. |
127 | return false; |
128 | } else if (any_of(Range: Cycle->getEntries(), |
129 | P: [&](const MachineBasicBlock *Block) { |
130 | return Block->isLiveIn(Reg); |
131 | })) { |
132 | // If the reg is live into any header of the cycle we can't hoist an |
133 | // instruction which would clobber it. |
134 | return false; |
135 | } |
136 | } |
137 | |
138 | if (!MO.isUse()) |
139 | continue; |
140 | |
141 | assert(MRI->getVRegDef(Reg) && "Machine instr not mapped for this vreg?!" ); |
142 | |
143 | // If the cycle contains the definition of an operand, then the instruction |
144 | // isn't cycle invariant. |
145 | if (Cycle->contains(Block: MRI->getVRegDef(Reg)->getParent())) |
146 | return false; |
147 | } |
148 | |
149 | // If we got this far, the instruction is cycle invariant! |
150 | return true; |
151 | } |
152 | |