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