LLVM 23.0.0git
SwiftErrorValueTracking.cpp
Go to the documentation of this file.
1//===-- SwiftErrorValueTracking.cpp --------------------------------------===//
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// This implements a limited mem2reg-like analysis to promote uses of function
10// arguments and allocas marked with swiftalloc from memory into virtual
11// registers tracked by this class.
12//
13//===----------------------------------------------------------------------===//
14
21#include "llvm/IR/Value.h"
22
23using namespace llvm;
24
26 const Value *Val) {
27 auto Key = std::make_pair(MBB, Val);
28 auto It = VRegDefMap.find(Key);
29 // If this is the first use of this swifterror value in this basic block,
30 // create a new virtual register.
31 // After we processed all basic blocks we will satisfy this "upwards exposed
32 // use" by inserting a copy or phi at the beginning of this block.
33 if (It == VRegDefMap.end()) {
34 auto &DL = MF->getDataLayout();
35 const TargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
36 auto VReg = MF->getRegInfo().createVirtualRegister(RC);
37 VRegDefMap[Key] = VReg;
38 VRegUpwardsUse[Key] = VReg;
39 return VReg;
40 } else
41 return It->second;
42}
43
45 const Value *Val, Register VReg) {
46 VRegDefMap[std::make_pair(MBB, Val)] = VReg;
47}
48
50 const Instruction *I, const MachineBasicBlock *MBB, const Value *Val) {
52 auto It = VRegDefUses.find(Key);
53 if (It != VRegDefUses.end())
54 return It->second;
55
56 auto &DL = MF->getDataLayout();
57 const TargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
58 Register VReg = MF->getRegInfo().createVirtualRegister(RC);
59 VRegDefUses[Key] = VReg;
60 setCurrentVReg(MBB, Val, VReg);
61 return VReg;
62}
63
65 const Instruction *I, const MachineBasicBlock *MBB, const Value *Val) {
67 auto It = VRegDefUses.find(Key);
68 if (It != VRegDefUses.end())
69 return It->second;
70
71 Register VReg = getOrCreateVReg(MBB, Val);
72 VRegDefUses[Key] = VReg;
73 return VReg;
74}
75
76/// Set up SwiftErrorVals by going through the function. If the function has
77/// swifterror argument, it will be the first entry.
79 MF = &mf;
80 Fn = &MF->getFunction();
81 TLI = MF->getSubtarget().getTargetLowering();
82 TII = MF->getSubtarget().getInstrInfo();
83
84 SwiftErrorVals.clear();
85 VRegDefMap.clear();
86 VRegUpwardsUse.clear();
87 VRegDefUses.clear();
88 SwiftErrorArg = nullptr;
89
90 if (!TLI->supportSwiftError())
91 return;
92
93 // Check if function has a swifterror argument.
94 bool HaveSeenSwiftErrorArg = false;
95 for (Function::const_arg_iterator AI = Fn->arg_begin(), AE = Fn->arg_end();
96 AI != AE; ++AI)
97 if (AI->hasSwiftErrorAttr()) {
98 assert(!HaveSeenSwiftErrorArg &&
99 "Must have only one swifterror parameter");
100 (void)HaveSeenSwiftErrorArg; // silence warning.
101 HaveSeenSwiftErrorArg = true;
102 SwiftErrorArg = &*AI;
103 SwiftErrorVals.push_back(&*AI);
104 }
105
106 for (const auto &LLVMBB : *Fn)
107 for (const auto &Inst : LLVMBB) {
108 if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(&Inst))
109 if (Alloca->isSwiftError())
110 SwiftErrorVals.push_back(Alloca);
111 }
112}
113
115 if (!TLI->supportSwiftError())
116 return false;
117
118 // We only need to do this when we have swifterror parameter or swifterror
119 // alloc.
120 if (SwiftErrorVals.empty())
121 return false;
122
123 MachineBasicBlock *MBB = &*MF->begin();
124 auto &DL = MF->getDataLayout();
125 auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
126 bool Inserted = false;
127 for (const auto *SwiftErrorVal : SwiftErrorVals) {
128 // We will always generate a copy from the argument. It is always used at
129 // least by the 'return' of the swifterror.
130 if (SwiftErrorArg && SwiftErrorArg == SwiftErrorVal)
131 continue;
132 Register VReg = MF->getRegInfo().createVirtualRegister(RC);
133 // Assign Undef to Vreg. We construct MI directly to make sure it works
134 // with FastISel.
135 BuildMI(*MBB, MBB->getFirstNonPHI(), DbgLoc,
136 TII->get(TargetOpcode::IMPLICIT_DEF), VReg);
137
138 setCurrentVReg(MBB, SwiftErrorVal, VReg);
139 Inserted = true;
140 }
141
142 return Inserted;
143}
144
145/// Propagate swifterror values through the machine function CFG.
147 if (!TLI->supportSwiftError())
148 return;
149
150 // We only need to do this when we have swifterror parameter or swifterror
151 // alloc.
152 if (SwiftErrorVals.empty())
153 return;
154
155 // For each machine basic block in reverse post order.
157 for (MachineBasicBlock *MBB : RPOT) {
158 // For each swifterror value in the function.
159 for (const auto *SwiftErrorVal : SwiftErrorVals) {
160 auto Key = std::make_pair(MBB, SwiftErrorVal);
161 auto UUseIt = VRegUpwardsUse.find(Key);
162 auto VRegDefIt = VRegDefMap.find(Key);
163 bool UpwardsUse = UUseIt != VRegUpwardsUse.end();
164 Register UUseVReg = UpwardsUse ? UUseIt->second : Register();
165 bool DownwardDef = VRegDefIt != VRegDefMap.end();
166 assert(!(UpwardsUse && !DownwardDef) &&
167 "We can't have an upwards use but no downwards def");
168
169 // If there is no upwards exposed use and an entry for the swifterror in
170 // the def map for this value we don't need to do anything: We already
171 // have a downward def for this basic block.
172 if (!UpwardsUse && DownwardDef)
173 continue;
174
175 // Otherwise we either have an upwards exposed use vreg that we need to
176 // materialize or need to forward the downward def from predecessors.
177
178 // Check whether we have a single vreg def from all predecessors.
179 // Otherwise we need a phi.
182 for (auto *Pred : MBB->predecessors()) {
183 if (!Visited.insert(Pred).second)
184 continue;
185 VRegs.push_back(std::make_pair(
186 Pred, getOrCreateVReg(Pred, SwiftErrorVal)));
187 if (Pred != MBB)
188 continue;
189 // We have a self-edge.
190 // If there was no upwards use in this basic block there is now one: the
191 // phi needs to use it self.
192 if (!UpwardsUse) {
193 UpwardsUse = true;
194 UUseIt = VRegUpwardsUse.find(Key);
195 assert(UUseIt != VRegUpwardsUse.end());
196 UUseVReg = UUseIt->second;
197 }
198 }
199
200 // We need a phi node if we have more than one predecessor with different
201 // downward defs.
202 bool needPHI =
203 VRegs.size() >= 1 &&
205 VRegs,
206 [&](const std::pair<const MachineBasicBlock *, Register> &V)
207 -> bool { return V.second != VRegs[0].second; });
208
209 // If there is no upwards exposed used and we don't need a phi just
210 // forward the swifterror vreg from the predecessor(s).
211 if (!UpwardsUse && !needPHI) {
212 assert(!VRegs.empty() &&
213 "No predecessors? The entry block should bail out earlier");
214 // Just forward the swifterror vreg from the predecessor(s).
215 setCurrentVReg(MBB, SwiftErrorVal, VRegs[0].second);
216 continue;
217 }
218
219 auto DLoc = isa<Instruction>(SwiftErrorVal)
220 ? cast<Instruction>(SwiftErrorVal)->getDebugLoc()
221 : DebugLoc();
222 const auto *TII = MF->getSubtarget().getInstrInfo();
223
224 // If we don't need a phi create a copy to the upward exposed vreg.
225 if (!needPHI) {
226 assert(UpwardsUse);
227 assert(!VRegs.empty() &&
228 "No predecessors? Is the Calling Convention correct?");
229 Register DestReg = UUseVReg;
230 BuildMI(*MBB, MBB->getFirstNonPHI(), DLoc, TII->get(TargetOpcode::COPY),
231 DestReg)
232 .addReg(VRegs[0].second);
233 continue;
234 }
235
236 // We need a phi: if there is an upwards exposed use we already have a
237 // destination virtual register number otherwise we generate a new one.
238 auto &DL = MF->getDataLayout();
239 auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
240 Register PHIVReg =
241 UpwardsUse ? UUseVReg : MF->getRegInfo().createVirtualRegister(RC);
243 BuildMI(*MBB, MBB->getFirstNonPHI(), DLoc,
244 TII->get(TargetOpcode::PHI), PHIVReg);
245 for (auto BBRegPair : VRegs) {
246 PHI.addReg(BBRegPair.second).addMBB(BBRegPair.first);
247 }
248
249 // We did not have a definition in this block before: store the phi's vreg
250 // as this block downward exposed def.
251 if (!UpwardsUse)
252 setCurrentVReg(MBB, SwiftErrorVal, PHIVReg);
253 }
254 }
255
256 // Create implicit defs for upward uses from unreachable blocks
257 MachineRegisterInfo &MRI = MF->getRegInfo();
258 for (const auto &Use : VRegUpwardsUse) {
259 const MachineBasicBlock *UseBB = Use.first.first;
260 Register VReg = Use.second;
261 if (!MRI.def_empty(VReg))
262 continue;
263
264#ifdef EXPENSIVE_CHECKS
265 assert(std::find(RPOT.begin(), RPOT.end(), UseBB) == RPOT.end() &&
266 "Reachable block has VReg upward use without definition.");
267#endif
268
269 MachineBasicBlock *UseBBMut = MF->getBlockNumbered(UseBB->getNumber());
270
271 BuildMI(*UseBBMut, UseBBMut->getFirstNonPHI(), DebugLoc(),
272 TII->get(TargetOpcode::IMPLICIT_DEF), VReg);
273 }
274}
275
279 if (!TLI->supportSwiftError() || SwiftErrorVals.empty())
280 return;
281
282 // Iterator over instructions and assign vregs to swifterror defs and uses.
283 for (auto It = Begin; It != End; ++It) {
284 if (auto *CB = dyn_cast<CallBase>(&*It)) {
285 // A call-site with a swifterror argument is both use and def.
286 const Value *SwiftErrorAddr = nullptr;
287 for (const auto &Arg : CB->args()) {
288 if (!Arg->isSwiftError())
289 continue;
290 // Use of swifterror.
291 assert(!SwiftErrorAddr && "Cannot have multiple swifterror arguments");
292 SwiftErrorAddr = &*Arg;
293 assert(SwiftErrorAddr->isSwiftError() &&
294 "Must have a swifterror value argument");
295 getOrCreateVRegUseAt(&*It, MBB, SwiftErrorAddr);
296 }
297 if (!SwiftErrorAddr)
298 continue;
299
300 // Def of swifterror.
301 getOrCreateVRegDefAt(&*It, MBB, SwiftErrorAddr);
302
303 // A load is a use.
304 } else if (const LoadInst *LI = dyn_cast<const LoadInst>(&*It)) {
305 const Value *V = LI->getOperand(0);
306 if (!V->isSwiftError())
307 continue;
308
310
311 // A store is a def.
312 } else if (const StoreInst *SI = dyn_cast<const StoreInst>(&*It)) {
313 const Value *SwiftErrorAddr = SI->getOperand(1);
314 if (!SwiftErrorAddr->isSwiftError())
315 continue;
316
317 // Def of swifterror.
318 getOrCreateVRegDefAt(&*It, MBB, SwiftErrorAddr);
319
320 // A return in a swiferror returning function is a use.
321 } else if (const ReturnInst *R = dyn_cast<const ReturnInst>(&*It)) {
322 const Function *F = R->getParent()->getParent();
323 if (!F->getAttributes().hasAttrSomewhere(Attribute::SwiftError))
324 continue;
325
326 getOrCreateVRegUseAt(R, MBB, SwiftErrorArg);
327 }
328 }
329}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Rewrite undef for PHI
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Promote Memory to Register
Definition Mem2Reg.cpp:110
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
This file describes how to lower LLVM code to machine code.
an instruction to allocate memory on the stack
InstListType::const_iterator const_iterator
Definition BasicBlock.h:171
A debug info location.
Definition DebugLoc.h:124
const Argument * const_arg_iterator
Definition Function.h:74
An instruction for reading from memory.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1572
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
bool def_empty(Register RegNo) const
def_empty - Return true if there are no instructions defining the specified register (it may be live-...
PointerIntPair - This class implements a pair of a pointer and small integer.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
Return a value (possibly void), from a function.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
LLVM_ABI bool createEntriesInEntryBlock(DebugLoc DbgLoc)
Create initial definitions of swifterror values in the entry block of the current function.
LLVM_ABI void setFunction(MachineFunction &MF)
Initialize data structures for specified new function.
LLVM_ABI Register getOrCreateVReg(const MachineBasicBlock *, const Value *)
Get or create the swifterror value virtual register in VRegDefMap for this basic block.
LLVM_ABI void setCurrentVReg(const MachineBasicBlock *MBB, const Value *, Register)
Set the swifterror virtual register in the VRegDefMap for this basic block.
LLVM_ABI Register getOrCreateVRegUseAt(const Instruction *, const MachineBasicBlock *, const Value *)
Get or create the swifterror value virtual register for a use of a swifterror by an instruction.
LLVM_ABI void preassignVRegs(MachineBasicBlock *MBB, BasicBlock::const_iterator Begin, BasicBlock::const_iterator End)
LLVM_ABI Register getOrCreateVRegDefAt(const Instruction *, const MachineBasicBlock *, const Value *)
Get or create the swifterror value virtual register for a def of a swifterror by an instruction.
LLVM_ABI void propagateVRegs()
Propagate assigned swifterror vregs through a function, synthesizing PHI nodes when needed to maintai...
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM Value Representation.
Definition Value.h:75
LLVM_ABI bool isSwiftError() const
Return true if this value is a swifterror value.
Definition Value.cpp:1134
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1745
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559