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