LLVM 22.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));
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 if (!TLI->supportSwiftError())
85 return;
86
87 SwiftErrorVals.clear();
88 VRegDefMap.clear();
89 VRegUpwardsUse.clear();
90 VRegDefUses.clear();
91 SwiftErrorArg = nullptr;
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;
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
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}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Rewrite undef for PHI
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
bool End
Definition: ELF_riscv.cpp:480
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
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
Definition: Instructions.h:64
This class represents an incoming formal argument to a Function.
Definition: Argument.h:32
InstListType::const_iterator const_iterator
Definition: BasicBlock.h:171
A debug info location.
Definition: DebugLoc.h:124
arg_iterator arg_end()
Definition: Function.h:875
arg_iterator arg_begin()
Definition: Function.h:866
An instruction for reading from memory.
Definition: Instructions.h:180
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:64
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.
iterator_range< pred_iterator > predecessors()
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
MachineBasicBlock * getBlockNumbered(unsigned N) const
getBlockNumbered - MachineBasicBlocks are automatically numbered when they are inserted into the mach...
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
PointerIntPair - This class implements a pair of a pointer and small integer.
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
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.
Definition: SmallPtrSet.h:401
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:541
bool empty() const
Definition: SmallVector.h:82
size_t size() const
Definition: SmallVector.h:79
void push_back(const T &Elt)
Definition: SmallVector.h:414
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
An instruction for storing to memory.
Definition: Instructions.h:296
bool createEntriesInEntryBlock(DebugLoc DbgLoc)
Create initial definitions of swifterror values in the entry block of the current function.
void setFunction(MachineFunction &MF)
Initialize data structures for specified new function.
Register getOrCreateVReg(const MachineBasicBlock *, const Value *)
Get or create the swifterror value virtual register in VRegDefMap for this basic block.
void setCurrentVReg(const MachineBasicBlock *MBB, const Value *, Register)
Set the swifterror virtual register in the VRegDefMap for this basic block.
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.
void preassignVRegs(MachineBasicBlock *MBB, BasicBlock::const_iterator Begin, BasicBlock::const_iterator End)
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.
void propagateVRegs()
Propagate assigned swifterror vregs through a function, synthesizing PHI nodes when needed to maintai...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
virtual bool supportSwiftError() const
Return true if the target supports swifterror attribute.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetLowering * getTargetLowering() const
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:1119
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
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:1751