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
39using namespace llvm;
40
41#define DEBUG_TYPE "remove-loads-into-fake-uses"
42
43STATISTIC(NumLoadsDeleted, "Number of dead load instructions deleted");
44STATISTIC(NumFakeUsesDeleted, "Number of FAKE_USE instructions deleted");
45
46class RemoveLoadsIntoFakeUsesLegacy : public MachineFunctionPass {
47public:
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
71struct RemoveLoadsIntoFakeUses {
72 bool run(MachineFunction &MF);
73};
74
75char RemoveLoadsIntoFakeUsesLegacy::ID = 0;
76char &llvm::RemoveLoadsIntoFakeUsesID = RemoveLoadsIntoFakeUsesLegacy::ID;
77
78INITIALIZE_PASS_BEGIN(RemoveLoadsIntoFakeUsesLegacy, DEBUG_TYPE,
79 "Remove Loads Into Fake Uses", false, false)
80INITIALIZE_PASS_END(RemoveLoadsIntoFakeUsesLegacy, DEBUG_TYPE,
81 "Remove Loads Into Fake Uses", false, false)
82
83bool RemoveLoadsIntoFakeUsesLegacy::runOnMachineFunction(MachineFunction &MF) {
84 if (skipFunction(F: MF.getFunction()))
85 return false;
86
87 return RemoveLoadsIntoFakeUses().run(MF);
88}
89
90PreservedAnalyses
91RemoveLoadsIntoFakeUsesPass::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
103bool 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