1 | //===---- RemoveLoadsIntoFakeUses.cpp - Remove loads with no real uses ----===// |
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 | /// \file |
10 | /// The FAKE_USE instruction is used to preserve certain values through |
11 | /// optimizations for the sake of debugging. This may result in spilled values |
12 | /// being loaded into registers that are only used by FAKE_USEs; this is not |
13 | /// necessary for debugging purposes, because at that point the value must be on |
14 | /// the stack and hence available for debugging. Therefore, this pass removes |
15 | /// loads that are only used by FAKE_USEs. |
16 | /// |
17 | /// This pass should run very late, to ensure that we don't inadvertently |
18 | /// shorten stack lifetimes by removing these loads, since the FAKE_USEs will |
19 | /// also no longer be in effect. Running immediately before LiveDebugValues |
20 | /// ensures that LDV will have accurate information of the machine location of |
21 | /// debug values. |
22 | /// |
23 | //===----------------------------------------------------------------------===// |
24 | |
25 | #include "llvm/CodeGen/RemoveLoadsIntoFakeUses.h" |
26 | #include "llvm/ADT/PostOrderIterator.h" |
27 | #include "llvm/ADT/Statistic.h" |
28 | #include "llvm/CodeGen/LiveRegUnits.h" |
29 | #include "llvm/CodeGen/MachineFunction.h" |
30 | #include "llvm/CodeGen/MachineFunctionPass.h" |
31 | #include "llvm/CodeGen/MachinePassManager.h" |
32 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
33 | #include "llvm/CodeGen/TargetSubtargetInfo.h" |
34 | #include "llvm/IR/Function.h" |
35 | #include "llvm/InitializePasses.h" |
36 | #include "llvm/Support/Debug.h" |
37 | #include "llvm/Target/TargetMachine.h" |
38 | |
39 | using namespace llvm; |
40 | |
41 | #define DEBUG_TYPE "remove-loads-into-fake-uses" |
42 | |
43 | STATISTIC(NumLoadsDeleted, "Number of dead load instructions deleted" ); |
44 | STATISTIC(NumFakeUsesDeleted, "Number of FAKE_USE instructions deleted" ); |
45 | |
46 | class RemoveLoadsIntoFakeUsesLegacy : public MachineFunctionPass { |
47 | public: |
48 | static char ID; |
49 | |
50 | RemoveLoadsIntoFakeUsesLegacy() : MachineFunctionPass(ID) { |
51 | initializeRemoveLoadsIntoFakeUsesLegacyPass( |
52 | *PassRegistry::getPassRegistry()); |
53 | } |
54 | |
55 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
56 | AU.setPreservesCFG(); |
57 | MachineFunctionPass::getAnalysisUsage(AU); |
58 | } |
59 | |
60 | MachineFunctionProperties getRequiredProperties() const override { |
61 | return MachineFunctionProperties().setNoVRegs(); |
62 | } |
63 | |
64 | StringRef getPassName() const override { |
65 | return "Remove Loads Into Fake Uses" ; |
66 | } |
67 | |
68 | bool runOnMachineFunction(MachineFunction &MF) override; |
69 | }; |
70 | |
71 | struct RemoveLoadsIntoFakeUses { |
72 | bool run(MachineFunction &MF); |
73 | }; |
74 | |
75 | char RemoveLoadsIntoFakeUsesLegacy::ID = 0; |
76 | char &llvm::RemoveLoadsIntoFakeUsesID = RemoveLoadsIntoFakeUsesLegacy::ID; |
77 | |
78 | INITIALIZE_PASS_BEGIN(RemoveLoadsIntoFakeUsesLegacy, DEBUG_TYPE, |
79 | "Remove Loads Into Fake Uses" , false, false) |
80 | INITIALIZE_PASS_END(RemoveLoadsIntoFakeUsesLegacy, DEBUG_TYPE, |
81 | "Remove Loads Into Fake Uses" , false, false) |
82 | |
83 | bool RemoveLoadsIntoFakeUsesLegacy::runOnMachineFunction(MachineFunction &MF) { |
84 | if (skipFunction(F: MF.getFunction())) |
85 | return false; |
86 | |
87 | return RemoveLoadsIntoFakeUses().run(MF); |
88 | } |
89 | |
90 | PreservedAnalyses |
91 | RemoveLoadsIntoFakeUsesPass::run(MachineFunction &MF, |
92 | MachineFunctionAnalysisManager &MFAM) { |
93 | MFPropsModifier _(*this, MF); |
94 | |
95 | if (!RemoveLoadsIntoFakeUses().run(MF)) |
96 | return PreservedAnalyses::all(); |
97 | |
98 | auto PA = getMachineFunctionPassPreservedAnalyses(); |
99 | PA.preserveSet<CFGAnalyses>(); |
100 | return PA; |
101 | } |
102 | |
103 | bool RemoveLoadsIntoFakeUses::run(MachineFunction &MF) { |
104 | // Skip this pass if we would use VarLoc-based LDV, as there may be DBG_VALUE |
105 | // instructions of the restored values that would become invalid. |
106 | if (!MF.useDebugInstrRef()) |
107 | return false; |
108 | // Only run this for functions that have fake uses. |
109 | if (!MF.hasFakeUses()) |
110 | return false; |
111 | |
112 | bool AnyChanges = false; |
113 | |
114 | LiveRegUnits LivePhysRegs; |
115 | const MachineRegisterInfo *MRI = &MF.getRegInfo(); |
116 | const TargetSubtargetInfo &ST = MF.getSubtarget(); |
117 | const TargetInstrInfo *TII = ST.getInstrInfo(); |
118 | const TargetRegisterInfo *TRI = ST.getRegisterInfo(); |
119 | |
120 | SmallVector<MachineInstr *> RegFakeUses; |
121 | LivePhysRegs.init(TRI: *TRI); |
122 | for (MachineBasicBlock *MBB : post_order(G: &MF)) { |
123 | RegFakeUses.clear(); |
124 | LivePhysRegs.addLiveOuts(MBB: *MBB); |
125 | |
126 | for (MachineInstr &MI : make_early_inc_range(Range: reverse(C&: *MBB))) { |
127 | if (MI.isFakeUse()) { |
128 | if (MI.getNumOperands() == 0 || !MI.getOperand(i: 0).isReg()) |
129 | continue; |
130 | // Track the Fake Uses that use these register units so that we can |
131 | // delete them if we delete the corresponding load. |
132 | RegFakeUses.push_back(Elt: &MI); |
133 | // Do not record FAKE_USE uses in LivePhysRegs so that we can recognize |
134 | // otherwise-unused loads. |
135 | continue; |
136 | } |
137 | |
138 | // If the restore size is not std::nullopt then we are dealing with a |
139 | // reload of a spilled register. |
140 | if (MI.getRestoreSize(TII)) { |
141 | Register Reg = MI.getOperand(i: 0).getReg(); |
142 | // Don't delete live physreg defs, or any reserved register defs. |
143 | if (!LivePhysRegs.available(Reg) || MRI->isReserved(PhysReg: Reg)) |
144 | continue; |
145 | // There should typically be an exact match between the loaded register |
146 | // and the FAKE_USE, but sometimes regalloc will choose to load a larger |
147 | // value than is needed. Therefore, as long as the load isn't used by |
148 | // anything except at least one FAKE_USE, we will delete it. If it isn't |
149 | // used by any fake uses, it should still be safe to delete but we |
150 | // choose to ignore it so that this pass has no side effects unrelated |
151 | // to fake uses. |
152 | SmallDenseSet<MachineInstr *> FakeUsesToDelete; |
153 | for (MachineInstr *&FakeUse : reverse(C&: RegFakeUses)) { |
154 | if (FakeUse->readsRegister(Reg, TRI)) { |
155 | FakeUsesToDelete.insert(V: FakeUse); |
156 | RegFakeUses.erase(CI: &FakeUse); |
157 | } |
158 | } |
159 | if (!FakeUsesToDelete.empty()) { |
160 | LLVM_DEBUG(dbgs() << "RemoveLoadsIntoFakeUses: DELETING: " << MI); |
161 | // Since this load only exists to restore a spilled register and we |
162 | // haven't, run LiveDebugValues yet, there shouldn't be any DBG_VALUEs |
163 | // for this load; otherwise, deleting this would be incorrect. |
164 | MI.eraseFromParent(); |
165 | AnyChanges = true; |
166 | ++NumLoadsDeleted; |
167 | for (MachineInstr *FakeUse : FakeUsesToDelete) { |
168 | LLVM_DEBUG(dbgs() |
169 | << "RemoveLoadsIntoFakeUses: DELETING: " << *FakeUse); |
170 | FakeUse->eraseFromParent(); |
171 | } |
172 | NumFakeUsesDeleted += FakeUsesToDelete.size(); |
173 | } |
174 | continue; |
175 | } |
176 | |
177 | // In addition to tracking LivePhysRegs, we need to clear RegFakeUses each |
178 | // time a register is defined, as existing FAKE_USEs no longer apply to |
179 | // that register. |
180 | if (!RegFakeUses.empty()) { |
181 | for (const MachineOperand &MO : MI.operands()) { |
182 | if (!MO.isReg()) |
183 | continue; |
184 | Register Reg = MO.getReg(); |
185 | // We clear RegFakeUses for this register and all subregisters, |
186 | // because any such FAKE_USE encountered prior is no longer relevant |
187 | // for later encountered loads. |
188 | for (MachineInstr *&FakeUse : reverse(C&: RegFakeUses)) |
189 | if (FakeUse->readsRegister(Reg, TRI)) |
190 | RegFakeUses.erase(CI: &FakeUse); |
191 | } |
192 | } |
193 | LivePhysRegs.stepBackward(MI); |
194 | } |
195 | } |
196 | |
197 | return AnyChanges; |
198 | } |
199 | |