xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/SwiftErrorValueTracking.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===-- SwiftErrorValueTracking.cpp --------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This implements a limited mem2reg-like analysis to promote uses of function
100b57cec5SDimitry Andric // arguments and allocas marked with swiftalloc from memory into virtual
110b57cec5SDimitry Andric // registers tracked by this class.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "llvm/CodeGen/SwiftErrorValueTracking.h"
168bcb0991SDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
170b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
198bcb0991SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
220b57cec5SDimitry Andric #include "llvm/IR/Value.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric 
getOrCreateVReg(const MachineBasicBlock * MBB,const Value * Val)260b57cec5SDimitry Andric Register SwiftErrorValueTracking::getOrCreateVReg(const MachineBasicBlock *MBB,
270b57cec5SDimitry Andric                                                   const Value *Val) {
280b57cec5SDimitry Andric   auto Key = std::make_pair(MBB, Val);
290b57cec5SDimitry Andric   auto It = VRegDefMap.find(Key);
300b57cec5SDimitry Andric   // If this is the first use of this swifterror value in this basic block,
310b57cec5SDimitry Andric   // create a new virtual register.
320b57cec5SDimitry Andric   // After we processed all basic blocks we will satisfy this "upwards exposed
330b57cec5SDimitry Andric   // use" by inserting a copy or phi at the beginning of this block.
340b57cec5SDimitry Andric   if (It == VRegDefMap.end()) {
350b57cec5SDimitry Andric     auto &DL = MF->getDataLayout();
360b57cec5SDimitry Andric     const TargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
370b57cec5SDimitry Andric     auto VReg = MF->getRegInfo().createVirtualRegister(RC);
380b57cec5SDimitry Andric     VRegDefMap[Key] = VReg;
390b57cec5SDimitry Andric     VRegUpwardsUse[Key] = VReg;
400b57cec5SDimitry Andric     return VReg;
410b57cec5SDimitry Andric   } else
420b57cec5SDimitry Andric     return It->second;
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric 
setCurrentVReg(const MachineBasicBlock * MBB,const Value * Val,Register VReg)450b57cec5SDimitry Andric void SwiftErrorValueTracking::setCurrentVReg(const MachineBasicBlock *MBB,
460b57cec5SDimitry Andric                                              const Value *Val, Register VReg) {
470b57cec5SDimitry Andric   VRegDefMap[std::make_pair(MBB, Val)] = VReg;
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
getOrCreateVRegDefAt(const Instruction * I,const MachineBasicBlock * MBB,const Value * Val)500b57cec5SDimitry Andric Register SwiftErrorValueTracking::getOrCreateVRegDefAt(
510b57cec5SDimitry Andric     const Instruction *I, const MachineBasicBlock *MBB, const Value *Val) {
520b57cec5SDimitry Andric   auto Key = PointerIntPair<const Instruction *, 1, bool>(I, true);
530b57cec5SDimitry Andric   auto It = VRegDefUses.find(Key);
540b57cec5SDimitry Andric   if (It != VRegDefUses.end())
550b57cec5SDimitry Andric     return It->second;
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   auto &DL = MF->getDataLayout();
580b57cec5SDimitry Andric   const TargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
590b57cec5SDimitry Andric   Register VReg = MF->getRegInfo().createVirtualRegister(RC);
600b57cec5SDimitry Andric   VRegDefUses[Key] = VReg;
610b57cec5SDimitry Andric   setCurrentVReg(MBB, Val, VReg);
620b57cec5SDimitry Andric   return VReg;
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
getOrCreateVRegUseAt(const Instruction * I,const MachineBasicBlock * MBB,const Value * Val)650b57cec5SDimitry Andric Register SwiftErrorValueTracking::getOrCreateVRegUseAt(
660b57cec5SDimitry Andric     const Instruction *I, const MachineBasicBlock *MBB, const Value *Val) {
670b57cec5SDimitry Andric   auto Key = PointerIntPair<const Instruction *, 1, bool>(I, false);
680b57cec5SDimitry Andric   auto It = VRegDefUses.find(Key);
690b57cec5SDimitry Andric   if (It != VRegDefUses.end())
700b57cec5SDimitry Andric     return It->second;
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   Register VReg = getOrCreateVReg(MBB, Val);
730b57cec5SDimitry Andric   VRegDefUses[Key] = VReg;
740b57cec5SDimitry Andric   return VReg;
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric /// Set up SwiftErrorVals by going through the function. If the function has
780b57cec5SDimitry Andric /// swifterror argument, it will be the first entry.
setFunction(MachineFunction & mf)790b57cec5SDimitry Andric void SwiftErrorValueTracking::setFunction(MachineFunction &mf) {
800b57cec5SDimitry Andric   MF = &mf;
810b57cec5SDimitry Andric   Fn = &MF->getFunction();
820b57cec5SDimitry Andric   TLI = MF->getSubtarget().getTargetLowering();
830b57cec5SDimitry Andric   TII = MF->getSubtarget().getInstrInfo();
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   if (!TLI->supportSwiftError())
860b57cec5SDimitry Andric     return;
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   SwiftErrorVals.clear();
890b57cec5SDimitry Andric   VRegDefMap.clear();
900b57cec5SDimitry Andric   VRegUpwardsUse.clear();
910b57cec5SDimitry Andric   VRegDefUses.clear();
920b57cec5SDimitry Andric   SwiftErrorArg = nullptr;
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   // Check if function has a swifterror argument.
950b57cec5SDimitry Andric   bool HaveSeenSwiftErrorArg = false;
960b57cec5SDimitry Andric   for (Function::const_arg_iterator AI = Fn->arg_begin(), AE = Fn->arg_end();
970b57cec5SDimitry Andric        AI != AE; ++AI)
980b57cec5SDimitry Andric     if (AI->hasSwiftErrorAttr()) {
990b57cec5SDimitry Andric       assert(!HaveSeenSwiftErrorArg &&
1000b57cec5SDimitry Andric              "Must have only one swifterror parameter");
1010b57cec5SDimitry Andric       (void)HaveSeenSwiftErrorArg; // silence warning.
1020b57cec5SDimitry Andric       HaveSeenSwiftErrorArg = true;
1030b57cec5SDimitry Andric       SwiftErrorArg = &*AI;
1040b57cec5SDimitry Andric       SwiftErrorVals.push_back(&*AI);
1050b57cec5SDimitry Andric     }
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric   for (const auto &LLVMBB : *Fn)
1080b57cec5SDimitry Andric     for (const auto &Inst : LLVMBB) {
1090b57cec5SDimitry Andric       if (const AllocaInst *Alloca = dyn_cast<AllocaInst>(&Inst))
1100b57cec5SDimitry Andric         if (Alloca->isSwiftError())
1110b57cec5SDimitry Andric           SwiftErrorVals.push_back(Alloca);
1120b57cec5SDimitry Andric     }
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric 
createEntriesInEntryBlock(DebugLoc DbgLoc)1150b57cec5SDimitry Andric bool SwiftErrorValueTracking::createEntriesInEntryBlock(DebugLoc DbgLoc) {
1160b57cec5SDimitry Andric   if (!TLI->supportSwiftError())
1170b57cec5SDimitry Andric     return false;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   // We only need to do this when we have swifterror parameter or swifterror
1200b57cec5SDimitry Andric   // alloc.
1210b57cec5SDimitry Andric   if (SwiftErrorVals.empty())
1220b57cec5SDimitry Andric     return false;
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   MachineBasicBlock *MBB = &*MF->begin();
1250b57cec5SDimitry Andric   auto &DL = MF->getDataLayout();
1260b57cec5SDimitry Andric   auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
1270b57cec5SDimitry Andric   bool Inserted = false;
1280b57cec5SDimitry Andric   for (const auto *SwiftErrorVal : SwiftErrorVals) {
1290b57cec5SDimitry Andric     // We will always generate a copy from the argument. It is always used at
1300b57cec5SDimitry Andric     // least by the 'return' of the swifterror.
1310b57cec5SDimitry Andric     if (SwiftErrorArg && SwiftErrorArg == SwiftErrorVal)
1320b57cec5SDimitry Andric       continue;
1330b57cec5SDimitry Andric     Register VReg = MF->getRegInfo().createVirtualRegister(RC);
1340b57cec5SDimitry Andric     // Assign Undef to Vreg. We construct MI directly to make sure it works
1350b57cec5SDimitry Andric     // with FastISel.
1360b57cec5SDimitry Andric     BuildMI(*MBB, MBB->getFirstNonPHI(), DbgLoc,
1370b57cec5SDimitry Andric             TII->get(TargetOpcode::IMPLICIT_DEF), VReg);
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric     setCurrentVReg(MBB, SwiftErrorVal, VReg);
1400b57cec5SDimitry Andric     Inserted = true;
1410b57cec5SDimitry Andric   }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   return Inserted;
1440b57cec5SDimitry Andric }
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric /// Propagate swifterror values through the machine function CFG.
propagateVRegs()1470b57cec5SDimitry Andric void SwiftErrorValueTracking::propagateVRegs() {
1480b57cec5SDimitry Andric   if (!TLI->supportSwiftError())
1490b57cec5SDimitry Andric     return;
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   // We only need to do this when we have swifterror parameter or swifterror
1520b57cec5SDimitry Andric   // alloc.
1530b57cec5SDimitry Andric   if (SwiftErrorVals.empty())
1540b57cec5SDimitry Andric     return;
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   // For each machine basic block in reverse post order.
1570b57cec5SDimitry Andric   ReversePostOrderTraversal<MachineFunction *> RPOT(MF);
1580b57cec5SDimitry Andric   for (MachineBasicBlock *MBB : RPOT) {
1590b57cec5SDimitry Andric     // For each swifterror value in the function.
1600b57cec5SDimitry Andric     for (const auto *SwiftErrorVal : SwiftErrorVals) {
1610b57cec5SDimitry Andric       auto Key = std::make_pair(MBB, SwiftErrorVal);
1620b57cec5SDimitry Andric       auto UUseIt = VRegUpwardsUse.find(Key);
1630b57cec5SDimitry Andric       auto VRegDefIt = VRegDefMap.find(Key);
1640b57cec5SDimitry Andric       bool UpwardsUse = UUseIt != VRegUpwardsUse.end();
1650b57cec5SDimitry Andric       Register UUseVReg = UpwardsUse ? UUseIt->second : Register();
1660b57cec5SDimitry Andric       bool DownwardDef = VRegDefIt != VRegDefMap.end();
1670b57cec5SDimitry Andric       assert(!(UpwardsUse && !DownwardDef) &&
1680b57cec5SDimitry Andric              "We can't have an upwards use but no downwards def");
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric       // If there is no upwards exposed use and an entry for the swifterror in
1710b57cec5SDimitry Andric       // the def map for this value we don't need to do anything: We already
1720b57cec5SDimitry Andric       // have a downward def for this basic block.
1730b57cec5SDimitry Andric       if (!UpwardsUse && DownwardDef)
1740b57cec5SDimitry Andric         continue;
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric       // Otherwise we either have an upwards exposed use vreg that we need to
1770b57cec5SDimitry Andric       // materialize or need to forward the downward def from predecessors.
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric       // Check whether we have a single vreg def from all predecessors.
1800b57cec5SDimitry Andric       // Otherwise we need a phi.
1810b57cec5SDimitry Andric       SmallVector<std::pair<MachineBasicBlock *, Register>, 4> VRegs;
1820b57cec5SDimitry Andric       SmallSet<const MachineBasicBlock *, 8> Visited;
1830b57cec5SDimitry Andric       for (auto *Pred : MBB->predecessors()) {
1840b57cec5SDimitry Andric         if (!Visited.insert(Pred).second)
1850b57cec5SDimitry Andric           continue;
1860b57cec5SDimitry Andric         VRegs.push_back(std::make_pair(
1870b57cec5SDimitry Andric             Pred, getOrCreateVReg(Pred, SwiftErrorVal)));
1880b57cec5SDimitry Andric         if (Pred != MBB)
1890b57cec5SDimitry Andric           continue;
1900b57cec5SDimitry Andric         // We have a self-edge.
1910b57cec5SDimitry Andric         // If there was no upwards use in this basic block there is now one: the
1920b57cec5SDimitry Andric         // phi needs to use it self.
1930b57cec5SDimitry Andric         if (!UpwardsUse) {
1940b57cec5SDimitry Andric           UpwardsUse = true;
1950b57cec5SDimitry Andric           UUseIt = VRegUpwardsUse.find(Key);
1960b57cec5SDimitry Andric           assert(UUseIt != VRegUpwardsUse.end());
1970b57cec5SDimitry Andric           UUseVReg = UUseIt->second;
1980b57cec5SDimitry Andric         }
1990b57cec5SDimitry Andric       }
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric       // We need a phi node if we have more than one predecessor with different
2020b57cec5SDimitry Andric       // downward defs.
2030b57cec5SDimitry Andric       bool needPHI =
2040b57cec5SDimitry Andric           VRegs.size() >= 1 &&
205bdd1243dSDimitry Andric           llvm::any_of(
206e8d8bef9SDimitry Andric               VRegs,
2070b57cec5SDimitry Andric               [&](const std::pair<const MachineBasicBlock *, Register> &V)
208bdd1243dSDimitry Andric                   -> bool { return V.second != VRegs[0].second; });
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric       // If there is no upwards exposed used and we don't need a phi just
2110b57cec5SDimitry Andric       // forward the swifterror vreg from the predecessor(s).
2120b57cec5SDimitry Andric       if (!UpwardsUse && !needPHI) {
2130b57cec5SDimitry Andric         assert(!VRegs.empty() &&
2140b57cec5SDimitry Andric                "No predecessors? The entry block should bail out earlier");
2150b57cec5SDimitry Andric         // Just forward the swifterror vreg from the predecessor(s).
2160b57cec5SDimitry Andric         setCurrentVReg(MBB, SwiftErrorVal, VRegs[0].second);
2170b57cec5SDimitry Andric         continue;
2180b57cec5SDimitry Andric       }
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric       auto DLoc = isa<Instruction>(SwiftErrorVal)
2210b57cec5SDimitry Andric                       ? cast<Instruction>(SwiftErrorVal)->getDebugLoc()
2220b57cec5SDimitry Andric                       : DebugLoc();
2230b57cec5SDimitry Andric       const auto *TII = MF->getSubtarget().getInstrInfo();
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric       // If we don't need a phi create a copy to the upward exposed vreg.
2260b57cec5SDimitry Andric       if (!needPHI) {
2270b57cec5SDimitry Andric         assert(UpwardsUse);
2280b57cec5SDimitry Andric         assert(!VRegs.empty() &&
2290b57cec5SDimitry Andric                "No predecessors?  Is the Calling Convention correct?");
2300b57cec5SDimitry Andric         Register DestReg = UUseVReg;
2310b57cec5SDimitry Andric         BuildMI(*MBB, MBB->getFirstNonPHI(), DLoc, TII->get(TargetOpcode::COPY),
2320b57cec5SDimitry Andric                 DestReg)
2330b57cec5SDimitry Andric             .addReg(VRegs[0].second);
2340b57cec5SDimitry Andric         continue;
2350b57cec5SDimitry Andric       }
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric       // We need a phi: if there is an upwards exposed use we already have a
2380b57cec5SDimitry Andric       // destination virtual register number otherwise we generate a new one.
2390b57cec5SDimitry Andric       auto &DL = MF->getDataLayout();
2400b57cec5SDimitry Andric       auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
2410b57cec5SDimitry Andric       Register PHIVReg =
2420b57cec5SDimitry Andric           UpwardsUse ? UUseVReg : MF->getRegInfo().createVirtualRegister(RC);
2430b57cec5SDimitry Andric       MachineInstrBuilder PHI =
2440b57cec5SDimitry Andric           BuildMI(*MBB, MBB->getFirstNonPHI(), DLoc,
2450b57cec5SDimitry Andric                   TII->get(TargetOpcode::PHI), PHIVReg);
2460b57cec5SDimitry Andric       for (auto BBRegPair : VRegs) {
2470b57cec5SDimitry Andric         PHI.addReg(BBRegPair.second).addMBB(BBRegPair.first);
2480b57cec5SDimitry Andric       }
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric       // We did not have a definition in this block before: store the phi's vreg
2510b57cec5SDimitry Andric       // as this block downward exposed def.
2520b57cec5SDimitry Andric       if (!UpwardsUse)
2530b57cec5SDimitry Andric         setCurrentVReg(MBB, SwiftErrorVal, PHIVReg);
2540b57cec5SDimitry Andric     }
2550b57cec5SDimitry Andric   }
256*5f757f3fSDimitry Andric 
257*5f757f3fSDimitry Andric   // Create implicit defs for upward uses from unreachable blocks
258*5f757f3fSDimitry Andric   MachineRegisterInfo &MRI = MF->getRegInfo();
259*5f757f3fSDimitry Andric   for (const auto &Use : VRegUpwardsUse) {
260*5f757f3fSDimitry Andric     const MachineBasicBlock *UseBB = Use.first.first;
261*5f757f3fSDimitry Andric     Register VReg = Use.second;
262*5f757f3fSDimitry Andric     if (!MRI.def_begin(VReg).atEnd())
263*5f757f3fSDimitry Andric       continue;
264*5f757f3fSDimitry Andric 
265*5f757f3fSDimitry Andric #ifdef EXPENSIVE_CHECKS
266*5f757f3fSDimitry Andric     assert(std::find(RPOT.begin(), RPOT.end(), UseBB) == RPOT.end() &&
267*5f757f3fSDimitry Andric            "Reachable block has VReg upward use without definition.");
268*5f757f3fSDimitry Andric #endif
269*5f757f3fSDimitry Andric 
270*5f757f3fSDimitry Andric     MachineBasicBlock *UseBBMut = MF->getBlockNumbered(UseBB->getNumber());
271*5f757f3fSDimitry Andric 
272*5f757f3fSDimitry Andric     BuildMI(*UseBBMut, UseBBMut->getFirstNonPHI(), DebugLoc(),
273*5f757f3fSDimitry Andric             TII->get(TargetOpcode::IMPLICIT_DEF), VReg);
274*5f757f3fSDimitry Andric   }
2750b57cec5SDimitry Andric }
2760b57cec5SDimitry Andric 
preassignVRegs(MachineBasicBlock * MBB,BasicBlock::const_iterator Begin,BasicBlock::const_iterator End)2770b57cec5SDimitry Andric void SwiftErrorValueTracking::preassignVRegs(
2780b57cec5SDimitry Andric     MachineBasicBlock *MBB, BasicBlock::const_iterator Begin,
2790b57cec5SDimitry Andric     BasicBlock::const_iterator End) {
2800b57cec5SDimitry Andric   if (!TLI->supportSwiftError() || SwiftErrorVals.empty())
2810b57cec5SDimitry Andric     return;
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric   // Iterator over instructions and assign vregs to swifterror defs and uses.
2840b57cec5SDimitry Andric   for (auto It = Begin; It != End; ++It) {
2855ffd83dbSDimitry Andric     if (auto *CB = dyn_cast<CallBase>(&*It)) {
2860b57cec5SDimitry Andric       // A call-site with a swifterror argument is both use and def.
2870b57cec5SDimitry Andric       const Value *SwiftErrorAddr = nullptr;
288fcaf7f86SDimitry Andric       for (const auto &Arg : CB->args()) {
2890b57cec5SDimitry Andric         if (!Arg->isSwiftError())
2900b57cec5SDimitry Andric           continue;
2910b57cec5SDimitry Andric         // Use of swifterror.
2920b57cec5SDimitry Andric         assert(!SwiftErrorAddr && "Cannot have multiple swifterror arguments");
2930b57cec5SDimitry Andric         SwiftErrorAddr = &*Arg;
2940b57cec5SDimitry Andric         assert(SwiftErrorAddr->isSwiftError() &&
2950b57cec5SDimitry Andric                "Must have a swifterror value argument");
2960b57cec5SDimitry Andric         getOrCreateVRegUseAt(&*It, MBB, SwiftErrorAddr);
2970b57cec5SDimitry Andric       }
2980b57cec5SDimitry Andric       if (!SwiftErrorAddr)
2990b57cec5SDimitry Andric         continue;
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric       // Def of swifterror.
3020b57cec5SDimitry Andric       getOrCreateVRegDefAt(&*It, MBB, SwiftErrorAddr);
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric       // A load is a use.
3050b57cec5SDimitry Andric     } else if (const LoadInst *LI = dyn_cast<const LoadInst>(&*It)) {
3060b57cec5SDimitry Andric       const Value *V = LI->getOperand(0);
3070b57cec5SDimitry Andric       if (!V->isSwiftError())
3080b57cec5SDimitry Andric         continue;
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric       getOrCreateVRegUseAt(LI, MBB, V);
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric       // A store is a def.
3130b57cec5SDimitry Andric     } else if (const StoreInst *SI = dyn_cast<const StoreInst>(&*It)) {
3140b57cec5SDimitry Andric       const Value *SwiftErrorAddr = SI->getOperand(1);
3150b57cec5SDimitry Andric       if (!SwiftErrorAddr->isSwiftError())
3160b57cec5SDimitry Andric         continue;
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric       // Def of swifterror.
3190b57cec5SDimitry Andric       getOrCreateVRegDefAt(&*It, MBB, SwiftErrorAddr);
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric       // A return in a swiferror returning function is a use.
3220b57cec5SDimitry Andric     } else if (const ReturnInst *R = dyn_cast<const ReturnInst>(&*It)) {
3230b57cec5SDimitry Andric       const Function *F = R->getParent()->getParent();
3240b57cec5SDimitry Andric       if (!F->getAttributes().hasAttrSomewhere(Attribute::SwiftError))
3250b57cec5SDimitry Andric         continue;
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric       getOrCreateVRegUseAt(R, MBB, SwiftErrorArg);
3280b57cec5SDimitry Andric     }
3290b57cec5SDimitry Andric   }
3300b57cec5SDimitry Andric }
331