LLVM  10.0.0svn
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 
17 #include "llvm/ADT/SmallSet.h"
22 #include "llvm/IR/Value.h"
23 
24 using namespace llvm;
25 
27  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 
46  const Value *Val, Register VReg) {
47  VRegDefMap[std::make_pair(MBB, Val)] = VReg;
48 }
49 
51  const Instruction *I, const MachineBasicBlock *MBB, const Value *Val) {
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));
59  Register VReg = MF->getRegInfo().createVirtualRegister(RC);
60  VRegDefUses[Key] = VReg;
61  setCurrentVReg(MBB, Val, VReg);
62  return VReg;
63 }
64 
66  const Instruction *I, const MachineBasicBlock *MBB, const Value *Val) {
68  auto It = VRegDefUses.find(Key);
69  if (It != VRegDefUses.end())
70  return It->second;
71 
72  Register VReg = getOrCreateVReg(MBB, Val);
73  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.
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 
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;
133  Register VReg = MF->getRegInfo().createVirtualRegister(RC);
134  // 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.
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.
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();
165  Register UUseVReg = UpwardsUse ? UUseIt->second : Register();
166  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.
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(),
207  [&](const std::pair<const MachineBasicBlock *, Register> &V)
208  -> 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?");
231  Register DestReg = UUseVReg;
232  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));
242  Register PHIVReg =
243  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 
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 }
Return a value (possibly void), from a function.
void setCurrentVReg(const MachineBasicBlock *MBB, const Value *, Register)
Set the swifterror virtual register in the VRegDefMap for this basic block.
This class represents an incoming formal argument to a Function.
Definition: Argument.h:29
This class represents lattice values for constants.
Definition: AllocatorList.h:23
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
void push_back(const T &Elt)
Definition: SmallVector.h:211
virtual const TargetLowering * getTargetLowering() const
unsigned second
arg_iterator arg_end()
Definition: Function.h:709
A debug info location.
Definition: DebugLoc.h:33
F(f)
void preassignVRegs(MachineBasicBlock *MBB, BasicBlock::const_iterator Begin, BasicBlock::const_iterator End)
An instruction for reading from memory.
Definition: Instructions.h:169
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
InstListType::const_iterator const_iterator
Definition: BasicBlock.h:90
void setFunction(MachineFunction &MF)
Initialize data structures for specified new function.
Key
PAL metadata keys.
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...
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual bool supportSwiftError() const
Return true if the target supports swifterror attribute.
bool isSwiftError() const
Return true if this value is a swifterror value.
Definition: Value.cpp:764
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition: Function.h:223
An instruction for storing to memory.
Definition: Instructions.h:325
bool createEntriesInEntryBlock(DebugLoc DbgLoc)
Create initial definitions of swifterror values in the entry block of the current function...
virtual const TargetInstrInfo * getInstrInfo() const
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...
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
bool hasAttrSomewhere(Attribute::AttrKind Kind, unsigned *Index=nullptr) const
Return true if the specified attribute is set for at least one parameter or for the return value...
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
PointerIntPair - This class implements a pair of a pointer and small integer.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:134
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
arg_iterator arg_begin()
Definition: Function.h:700
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn&#39;t already there.
Definition: SmallSet.h:180
auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1193
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...
Register getOrCreateVReg(const MachineBasicBlock *, const Value *)
Get or create the swifterror value virtual register in VRegDefMap for this basic block.
size_t size() const
Definition: SmallVector.h:52
iterator_range< IterTy > args() const
Definition: CallSite.h:222
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
Promote Memory to Register
Definition: Mem2Reg.cpp:109
const Function & getFunction() const
Return the LLVM function that this machine code represents.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:55
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:44
Establish a view to a call site for examination.
Definition: CallSite.h:906
#define I(x, y, z)
Definition: MD5.cpp:58
iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:74
void propagateVRegs()
Propagate assigned swifterror vregs through a function, synthesizing PHI nodes when needed to maintai...
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
This file describes how to lower LLVM code to machine code.
an instruction to allocate memory on the stack
Definition: Instructions.h:59