xref: /src/contrib/llvm-project/llvm/lib/CodeGen/SwiftErrorValueTracking.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1e6d15924SDimitry Andric //===-- SwiftErrorValueTracking.cpp --------------------------------------===//
2e6d15924SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e6d15924SDimitry Andric //
7e6d15924SDimitry Andric //===----------------------------------------------------------------------===//
8e6d15924SDimitry Andric //
9e6d15924SDimitry Andric // This implements a limited mem2reg-like analysis to promote uses of function
10e6d15924SDimitry Andric // arguments and allocas marked with swiftalloc from memory into virtual
11e6d15924SDimitry Andric // registers tracked by this class.
12e6d15924SDimitry Andric //
13e6d15924SDimitry Andric //===----------------------------------------------------------------------===//
14e6d15924SDimitry Andric 
15e6d15924SDimitry Andric #include "llvm/CodeGen/SwiftErrorValueTracking.h"
161d5ae102SDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
17e6d15924SDimitry Andric #include "llvm/ADT/SmallSet.h"
18e6d15924SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
191d5ae102SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
20e6d15924SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
21e6d15924SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
22e6d15924SDimitry Andric #include "llvm/IR/Value.h"
23e6d15924SDimitry Andric 
24e6d15924SDimitry Andric using namespace llvm;
25e6d15924SDimitry Andric 
getOrCreateVReg(const MachineBasicBlock * MBB,const Value * Val)26e6d15924SDimitry Andric Register SwiftErrorValueTracking::getOrCreateVReg(const MachineBasicBlock *MBB,
27e6d15924SDimitry Andric                                                   const Value *Val) {
28e6d15924SDimitry Andric   auto Key = std::make_pair(MBB, Val);
29e6d15924SDimitry Andric   auto It = VRegDefMap.find(Key);
30e6d15924SDimitry Andric   // If this is the first use of this swifterror value in this basic block,
31e6d15924SDimitry Andric   // create a new virtual register.
32e6d15924SDimitry Andric   // After we processed all basic blocks we will satisfy this "upwards exposed
33e6d15924SDimitry Andric   // use" by inserting a copy or phi at the beginning of this block.
34e6d15924SDimitry Andric   if (It == VRegDefMap.end()) {
35e6d15924SDimitry Andric     auto &DL = MF->getDataLayout();
36e6d15924SDimitry Andric     const TargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
37e6d15924SDimitry Andric     auto VReg = MF->getRegInfo().createVirtualRegister(RC);
38e6d15924SDimitry Andric     VRegDefMap[Key] = VReg;
39e6d15924SDimitry Andric     VRegUpwardsUse[Key] = VReg;
40e6d15924SDimitry Andric     return VReg;
41e6d15924SDimitry Andric   } else
42e6d15924SDimitry Andric     return It->second;
43e6d15924SDimitry Andric }
44e6d15924SDimitry Andric 
setCurrentVReg(const MachineBasicBlock * MBB,const Value * Val,Register VReg)45e6d15924SDimitry Andric void SwiftErrorValueTracking::setCurrentVReg(const MachineBasicBlock *MBB,
46e6d15924SDimitry Andric                                              const Value *Val, Register VReg) {
47e6d15924SDimitry Andric   VRegDefMap[std::make_pair(MBB, Val)] = VReg;
48e6d15924SDimitry Andric }
49e6d15924SDimitry Andric 
getOrCreateVRegDefAt(const Instruction * I,const MachineBasicBlock * MBB,const Value * Val)50e6d15924SDimitry Andric Register SwiftErrorValueTracking::getOrCreateVRegDefAt(
51e6d15924SDimitry Andric     const Instruction *I, const MachineBasicBlock *MBB, const Value *Val) {
52e6d15924SDimitry Andric   auto Key = PointerIntPair<const Instruction *, 1, bool>(I, true);
53e6d15924SDimitry Andric   auto It = VRegDefUses.find(Key);
54e6d15924SDimitry Andric   if (It != VRegDefUses.end())
55e6d15924SDimitry Andric     return It->second;
56e6d15924SDimitry Andric 
57e6d15924SDimitry Andric   auto &DL = MF->getDataLayout();
58e6d15924SDimitry Andric   const TargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
59e6d15924SDimitry Andric   Register VReg = MF->getRegInfo().createVirtualRegister(RC);
60e6d15924SDimitry Andric   VRegDefUses[Key] = VReg;
61e6d15924SDimitry Andric   setCurrentVReg(MBB, Val, VReg);
62e6d15924SDimitry Andric   return VReg;
63e6d15924SDimitry Andric }
64e6d15924SDimitry Andric 
getOrCreateVRegUseAt(const Instruction * I,const MachineBasicBlock * MBB,const Value * Val)65e6d15924SDimitry Andric Register SwiftErrorValueTracking::getOrCreateVRegUseAt(
66e6d15924SDimitry Andric     const Instruction *I, const MachineBasicBlock *MBB, const Value *Val) {
67e6d15924SDimitry Andric   auto Key = PointerIntPair<const Instruction *, 1, bool>(I, false);
68e6d15924SDimitry Andric   auto It = VRegDefUses.find(Key);
69e6d15924SDimitry Andric   if (It != VRegDefUses.end())
70e6d15924SDimitry Andric     return It->second;
71e6d15924SDimitry Andric 
72e6d15924SDimitry Andric   Register VReg = getOrCreateVReg(MBB, Val);
73e6d15924SDimitry Andric   VRegDefUses[Key] = VReg;
74e6d15924SDimitry Andric   return VReg;
75e6d15924SDimitry Andric }
76e6d15924SDimitry Andric 
77e6d15924SDimitry Andric /// Set up SwiftErrorVals by going through the function. If the function has
78e6d15924SDimitry Andric /// swifterror argument, it will be the first entry.
setFunction(MachineFunction & mf)79e6d15924SDimitry Andric void SwiftErrorValueTracking::setFunction(MachineFunction &mf) {
80e6d15924SDimitry Andric   MF = &mf;
81e6d15924SDimitry Andric   Fn = &MF->getFunction();
82e6d15924SDimitry Andric   TLI = MF->getSubtarget().getTargetLowering();
83e6d15924SDimitry Andric   TII = MF->getSubtarget().getInstrInfo();
84e6d15924SDimitry Andric 
85e6d15924SDimitry Andric   if (!TLI->supportSwiftError())
86e6d15924SDimitry Andric     return;
87e6d15924SDimitry Andric 
88e6d15924SDimitry Andric   SwiftErrorVals.clear();
89e6d15924SDimitry Andric   VRegDefMap.clear();
90e6d15924SDimitry Andric   VRegUpwardsUse.clear();
91e6d15924SDimitry Andric   VRegDefUses.clear();
92e6d15924SDimitry Andric   SwiftErrorArg = nullptr;
93e6d15924SDimitry Andric 
94e6d15924SDimitry Andric   // Check if function has a swifterror argument.
95e6d15924SDimitry Andric   bool HaveSeenSwiftErrorArg = false;
96e6d15924SDimitry Andric   for (Function::const_arg_iterator AI = Fn->arg_begin(), AE = Fn->arg_end();
97e6d15924SDimitry Andric        AI != AE; ++AI)
98e6d15924SDimitry Andric     if (AI->hasSwiftErrorAttr()) {
99e6d15924SDimitry Andric       assert(!HaveSeenSwiftErrorArg &&
100e6d15924SDimitry Andric              "Must have only one swifterror parameter");
101e6d15924SDimitry Andric       (void)HaveSeenSwiftErrorArg; // silence warning.
102e6d15924SDimitry Andric       HaveSeenSwiftErrorArg = true;
103e6d15924SDimitry Andric       SwiftErrorArg = &*AI;
104e6d15924SDimitry Andric       SwiftErrorVals.push_back(&*AI);
105e6d15924SDimitry Andric     }
106e6d15924SDimitry Andric 
107e6d15924SDimitry Andric   for (const auto &LLVMBB : *Fn)
108e6d15924SDimitry Andric     for (const auto &Inst : LLVMBB) {
109e6d15924SDimitry Andric       if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(&Inst))
110e6d15924SDimitry Andric         if (Alloca->isSwiftError())
111e6d15924SDimitry Andric           SwiftErrorVals.push_back(Alloca);
112e6d15924SDimitry Andric     }
113e6d15924SDimitry Andric }
114e6d15924SDimitry Andric 
createEntriesInEntryBlock(DebugLoc DbgLoc)115e6d15924SDimitry Andric bool SwiftErrorValueTracking::createEntriesInEntryBlock(DebugLoc DbgLoc) {
116e6d15924SDimitry Andric   if (!TLI->supportSwiftError())
117e6d15924SDimitry Andric     return false;
118e6d15924SDimitry Andric 
119e6d15924SDimitry Andric   // We only need to do this when we have swifterror parameter or swifterror
120e6d15924SDimitry Andric   // alloc.
121e6d15924SDimitry Andric   if (SwiftErrorVals.empty())
122e6d15924SDimitry Andric     return false;
123e6d15924SDimitry Andric 
124e6d15924SDimitry Andric   MachineBasicBlock *MBB = &*MF->begin();
125e6d15924SDimitry Andric   auto &DL = MF->getDataLayout();
126e6d15924SDimitry Andric   auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
127e6d15924SDimitry Andric   bool Inserted = false;
128e6d15924SDimitry Andric   for (const auto *SwiftErrorVal : SwiftErrorVals) {
129e6d15924SDimitry Andric     // We will always generate a copy from the argument. It is always used at
130e6d15924SDimitry Andric     // least by the 'return' of the swifterror.
131e6d15924SDimitry Andric     if (SwiftErrorArg && SwiftErrorArg == SwiftErrorVal)
132e6d15924SDimitry Andric       continue;
133e6d15924SDimitry Andric     Register VReg = MF->getRegInfo().createVirtualRegister(RC);
134e6d15924SDimitry Andric     // Assign Undef to Vreg. We construct MI directly to make sure it works
135e6d15924SDimitry Andric     // with FastISel.
136e6d15924SDimitry Andric     BuildMI(*MBB, MBB->getFirstNonPHI(), DbgLoc,
137e6d15924SDimitry Andric             TII->get(TargetOpcode::IMPLICIT_DEF), VReg);
138e6d15924SDimitry Andric 
139e6d15924SDimitry Andric     setCurrentVReg(MBB, SwiftErrorVal, VReg);
140e6d15924SDimitry Andric     Inserted = true;
141e6d15924SDimitry Andric   }
142e6d15924SDimitry Andric 
143e6d15924SDimitry Andric   return Inserted;
144e6d15924SDimitry Andric }
145e6d15924SDimitry Andric 
146e6d15924SDimitry Andric /// Propagate swifterror values through the machine function CFG.
propagateVRegs()147e6d15924SDimitry Andric void SwiftErrorValueTracking::propagateVRegs() {
148e6d15924SDimitry Andric   if (!TLI->supportSwiftError())
149e6d15924SDimitry Andric     return;
150e6d15924SDimitry Andric 
151e6d15924SDimitry Andric   // We only need to do this when we have swifterror parameter or swifterror
152e6d15924SDimitry Andric   // alloc.
153e6d15924SDimitry Andric   if (SwiftErrorVals.empty())
154e6d15924SDimitry Andric     return;
155e6d15924SDimitry Andric 
156e6d15924SDimitry Andric   // For each machine basic block in reverse post order.
157e6d15924SDimitry Andric   ReversePostOrderTraversal<MachineFunction *> RPOT(MF);
158e6d15924SDimitry Andric   for (MachineBasicBlock *MBB : RPOT) {
159e6d15924SDimitry Andric     // For each swifterror value in the function.
160e6d15924SDimitry Andric     for (const auto *SwiftErrorVal : SwiftErrorVals) {
161e6d15924SDimitry Andric       auto Key = std::make_pair(MBB, SwiftErrorVal);
162e6d15924SDimitry Andric       auto UUseIt = VRegUpwardsUse.find(Key);
163e6d15924SDimitry Andric       auto VRegDefIt = VRegDefMap.find(Key);
164e6d15924SDimitry Andric       bool UpwardsUse = UUseIt != VRegUpwardsUse.end();
165e6d15924SDimitry Andric       Register UUseVReg = UpwardsUse ? UUseIt->second : Register();
166e6d15924SDimitry Andric       bool DownwardDef = VRegDefIt != VRegDefMap.end();
167e6d15924SDimitry Andric       assert(!(UpwardsUse && !DownwardDef) &&
168e6d15924SDimitry Andric              "We can't have an upwards use but no downwards def");
169e6d15924SDimitry Andric 
170e6d15924SDimitry Andric       // If there is no upwards exposed use and an entry for the swifterror in
171e6d15924SDimitry Andric       // the def map for this value we don't need to do anything: We already
172e6d15924SDimitry Andric       // have a downward def for this basic block.
173e6d15924SDimitry Andric       if (!UpwardsUse && DownwardDef)
174e6d15924SDimitry Andric         continue;
175e6d15924SDimitry Andric 
176e6d15924SDimitry Andric       // Otherwise we either have an upwards exposed use vreg that we need to
177e6d15924SDimitry Andric       // materialize or need to forward the downward def from predecessors.
178e6d15924SDimitry Andric 
179e6d15924SDimitry Andric       // Check whether we have a single vreg def from all predecessors.
180e6d15924SDimitry Andric       // Otherwise we need a phi.
181e6d15924SDimitry Andric       SmallVector<std::pair<MachineBasicBlock *, Register>, 4> VRegs;
182e6d15924SDimitry Andric       SmallSet<const MachineBasicBlock *, 8> Visited;
183e6d15924SDimitry Andric       for (auto *Pred : MBB->predecessors()) {
184e6d15924SDimitry Andric         if (!Visited.insert(Pred).second)
185e6d15924SDimitry Andric           continue;
186e6d15924SDimitry Andric         VRegs.push_back(std::make_pair(
187e6d15924SDimitry Andric             Pred, getOrCreateVReg(Pred, SwiftErrorVal)));
188e6d15924SDimitry Andric         if (Pred != MBB)
189e6d15924SDimitry Andric           continue;
190e6d15924SDimitry Andric         // We have a self-edge.
191e6d15924SDimitry Andric         // If there was no upwards use in this basic block there is now one: the
192e6d15924SDimitry Andric         // phi needs to use it self.
193e6d15924SDimitry Andric         if (!UpwardsUse) {
194e6d15924SDimitry Andric           UpwardsUse = true;
195e6d15924SDimitry Andric           UUseIt = VRegUpwardsUse.find(Key);
196e6d15924SDimitry Andric           assert(UUseIt != VRegUpwardsUse.end());
197e6d15924SDimitry Andric           UUseVReg = UUseIt->second;
198e6d15924SDimitry Andric         }
199e6d15924SDimitry Andric       }
200e6d15924SDimitry Andric 
201e6d15924SDimitry Andric       // We need a phi node if we have more than one predecessor with different
202e6d15924SDimitry Andric       // downward defs.
203e6d15924SDimitry Andric       bool needPHI =
204e6d15924SDimitry Andric           VRegs.size() >= 1 &&
205e3b55780SDimitry Andric           llvm::any_of(
206b60736ecSDimitry Andric               VRegs,
207e6d15924SDimitry Andric               [&](const std::pair<const MachineBasicBlock *, Register> &V)
208e3b55780SDimitry Andric                   -> bool { return V.second != VRegs[0].second; });
209e6d15924SDimitry Andric 
210e6d15924SDimitry Andric       // If there is no upwards exposed used and we don't need a phi just
211e6d15924SDimitry Andric       // forward the swifterror vreg from the predecessor(s).
212e6d15924SDimitry Andric       if (!UpwardsUse && !needPHI) {
213e6d15924SDimitry Andric         assert(!VRegs.empty() &&
214e6d15924SDimitry Andric                "No predecessors? The entry block should bail out earlier");
215e6d15924SDimitry Andric         // Just forward the swifterror vreg from the predecessor(s).
216e6d15924SDimitry Andric         setCurrentVReg(MBB, SwiftErrorVal, VRegs[0].second);
217e6d15924SDimitry Andric         continue;
218e6d15924SDimitry Andric       }
219e6d15924SDimitry Andric 
220e6d15924SDimitry Andric       auto DLoc = isa<Instruction>(SwiftErrorVal)
221e6d15924SDimitry Andric                       ? cast<Instruction>(SwiftErrorVal)->getDebugLoc()
222e6d15924SDimitry Andric                       : DebugLoc();
223e6d15924SDimitry Andric       const auto *TII = MF->getSubtarget().getInstrInfo();
224e6d15924SDimitry Andric 
225e6d15924SDimitry Andric       // If we don't need a phi create a copy to the upward exposed vreg.
226e6d15924SDimitry Andric       if (!needPHI) {
227e6d15924SDimitry Andric         assert(UpwardsUse);
228e6d15924SDimitry Andric         assert(!VRegs.empty() &&
229e6d15924SDimitry Andric                "No predecessors?  Is the Calling Convention correct?");
230e6d15924SDimitry Andric         Register DestReg = UUseVReg;
231e6d15924SDimitry Andric         BuildMI(*MBB, MBB->getFirstNonPHI(), DLoc, TII->get(TargetOpcode::COPY),
232e6d15924SDimitry Andric                 DestReg)
233e6d15924SDimitry Andric             .addReg(VRegs[0].second);
234e6d15924SDimitry Andric         continue;
235e6d15924SDimitry Andric       }
236e6d15924SDimitry Andric 
237e6d15924SDimitry Andric       // We need a phi: if there is an upwards exposed use we already have a
238e6d15924SDimitry Andric       // destination virtual register number otherwise we generate a new one.
239e6d15924SDimitry Andric       auto &DL = MF->getDataLayout();
240e6d15924SDimitry Andric       auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
241e6d15924SDimitry Andric       Register PHIVReg =
242e6d15924SDimitry Andric           UpwardsUse ? UUseVReg : MF->getRegInfo().createVirtualRegister(RC);
243e6d15924SDimitry Andric       MachineInstrBuilder PHI =
244e6d15924SDimitry Andric           BuildMI(*MBB, MBB->getFirstNonPHI(), DLoc,
245e6d15924SDimitry Andric                   TII->get(TargetOpcode::PHI), PHIVReg);
246e6d15924SDimitry Andric       for (auto BBRegPair : VRegs) {
247e6d15924SDimitry Andric         PHI.addReg(BBRegPair.second).addMBB(BBRegPair.first);
248e6d15924SDimitry Andric       }
249e6d15924SDimitry Andric 
250e6d15924SDimitry Andric       // We did not have a definition in this block before: store the phi's vreg
251e6d15924SDimitry Andric       // as this block downward exposed def.
252e6d15924SDimitry Andric       if (!UpwardsUse)
253e6d15924SDimitry Andric         setCurrentVReg(MBB, SwiftErrorVal, PHIVReg);
254e6d15924SDimitry Andric     }
255e6d15924SDimitry Andric   }
256b1c73532SDimitry Andric 
257b1c73532SDimitry Andric   // Create implicit defs for upward uses from unreachable blocks
258b1c73532SDimitry Andric   MachineRegisterInfo &MRI = MF->getRegInfo();
259b1c73532SDimitry Andric   for (const auto &Use : VRegUpwardsUse) {
260b1c73532SDimitry Andric     const MachineBasicBlock *UseBB = Use.first.first;
261b1c73532SDimitry Andric     Register VReg = Use.second;
262b1c73532SDimitry Andric     if (!MRI.def_begin(VReg).atEnd())
263b1c73532SDimitry Andric       continue;
264b1c73532SDimitry Andric 
265b1c73532SDimitry Andric #ifdef EXPENSIVE_CHECKS
266b1c73532SDimitry Andric     assert(std::find(RPOT.begin(), RPOT.end(), UseBB) == RPOT.end() &&
267b1c73532SDimitry Andric            "Reachable block has VReg upward use without definition.");
268b1c73532SDimitry Andric #endif
269b1c73532SDimitry Andric 
270b1c73532SDimitry Andric     MachineBasicBlock *UseBBMut = MF->getBlockNumbered(UseBB->getNumber());
271b1c73532SDimitry Andric 
272b1c73532SDimitry Andric     BuildMI(*UseBBMut, UseBBMut->getFirstNonPHI(), DebugLoc(),
273b1c73532SDimitry Andric             TII->get(TargetOpcode::IMPLICIT_DEF), VReg);
274b1c73532SDimitry Andric   }
275e6d15924SDimitry Andric }
276e6d15924SDimitry Andric 
preassignVRegs(MachineBasicBlock * MBB,BasicBlock::const_iterator Begin,BasicBlock::const_iterator End)277e6d15924SDimitry Andric void SwiftErrorValueTracking::preassignVRegs(
278e6d15924SDimitry Andric     MachineBasicBlock *MBB, BasicBlock::const_iterator Begin,
279e6d15924SDimitry Andric     BasicBlock::const_iterator End) {
280e6d15924SDimitry Andric   if (!TLI->supportSwiftError() || SwiftErrorVals.empty())
281e6d15924SDimitry Andric     return;
282e6d15924SDimitry Andric 
283e6d15924SDimitry Andric   // Iterator over instructions and assign vregs to swifterror defs and uses.
284e6d15924SDimitry Andric   for (auto It = Begin; It != End; ++It) {
285cfca06d7SDimitry Andric     if (auto *CB = dyn_cast<CallBase>(&*It)) {
286e6d15924SDimitry Andric       // A call-site with a swifterror argument is both use and def.
287e6d15924SDimitry Andric       const Value *SwiftErrorAddr = nullptr;
2884b4fe385SDimitry Andric       for (const auto &Arg : CB->args()) {
289e6d15924SDimitry Andric         if (!Arg->isSwiftError())
290e6d15924SDimitry Andric           continue;
291e6d15924SDimitry Andric         // Use of swifterror.
292e6d15924SDimitry Andric         assert(!SwiftErrorAddr && "Cannot have multiple swifterror arguments");
293e6d15924SDimitry Andric         SwiftErrorAddr = &*Arg;
294e6d15924SDimitry Andric         assert(SwiftErrorAddr->isSwiftError() &&
295e6d15924SDimitry Andric                "Must have a swifterror value argument");
296e6d15924SDimitry Andric         getOrCreateVRegUseAt(&*It, MBB, SwiftErrorAddr);
297e6d15924SDimitry Andric       }
298e6d15924SDimitry Andric       if (!SwiftErrorAddr)
299e6d15924SDimitry Andric         continue;
300e6d15924SDimitry Andric 
301e6d15924SDimitry Andric       // Def of swifterror.
302e6d15924SDimitry Andric       getOrCreateVRegDefAt(&*It, MBB, SwiftErrorAddr);
303e6d15924SDimitry Andric 
304e6d15924SDimitry Andric       // A load is a use.
305e6d15924SDimitry Andric     } else if (const LoadInst *LI = dyn_cast<const LoadInst>(&*It)) {
306e6d15924SDimitry Andric       const Value *V = LI->getOperand(0);
307e6d15924SDimitry Andric       if (!V->isSwiftError())
308e6d15924SDimitry Andric         continue;
309e6d15924SDimitry Andric 
310e6d15924SDimitry Andric       getOrCreateVRegUseAt(LI, MBB, V);
311e6d15924SDimitry Andric 
312e6d15924SDimitry Andric       // A store is a def.
313e6d15924SDimitry Andric     } else if (const StoreInst *SI = dyn_cast<const StoreInst>(&*It)) {
314e6d15924SDimitry Andric       const Value *SwiftErrorAddr = SI->getOperand(1);
315e6d15924SDimitry Andric       if (!SwiftErrorAddr->isSwiftError())
316e6d15924SDimitry Andric         continue;
317e6d15924SDimitry Andric 
318e6d15924SDimitry Andric       // Def of swifterror.
319e6d15924SDimitry Andric       getOrCreateVRegDefAt(&*It, MBB, SwiftErrorAddr);
320e6d15924SDimitry Andric 
321e6d15924SDimitry Andric       // A return in a swiferror returning function is a use.
322e6d15924SDimitry Andric     } else if (const ReturnInst *R = dyn_cast<const ReturnInst>(&*It)) {
323e6d15924SDimitry Andric       const Function *F = R->getParent()->getParent();
324e6d15924SDimitry Andric       if (!F->getAttributes().hasAttrSomewhere(Attribute::SwiftError))
325e6d15924SDimitry Andric         continue;
326e6d15924SDimitry Andric 
327e6d15924SDimitry Andric       getOrCreateVRegUseAt(R, MBB, SwiftErrorArg);
328e6d15924SDimitry Andric     }
329e6d15924SDimitry Andric   }
330e6d15924SDimitry Andric }
331