LLVM  13.0.0git
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 &&
206  VRegs,
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  if (auto *CB = dyn_cast<CallBase>(&*It)) {
268  // A call-site with a swifterror argument is both use and def.
269  const Value *SwiftErrorAddr = nullptr;
270  for (auto &Arg : CB->args()) {
271  if (!Arg->isSwiftError())
272  continue;
273  // Use of swifterror.
274  assert(!SwiftErrorAddr && "Cannot have multiple swifterror arguments");
275  SwiftErrorAddr = &*Arg;
276  assert(SwiftErrorAddr->isSwiftError() &&
277  "Must have a swifterror value argument");
278  getOrCreateVRegUseAt(&*It, MBB, SwiftErrorAddr);
279  }
280  if (!SwiftErrorAddr)
281  continue;
282 
283  // Def of swifterror.
284  getOrCreateVRegDefAt(&*It, MBB, SwiftErrorAddr);
285 
286  // A load is a use.
287  } else if (const LoadInst *LI = dyn_cast<const LoadInst>(&*It)) {
288  const Value *V = LI->getOperand(0);
289  if (!V->isSwiftError())
290  continue;
291 
292  getOrCreateVRegUseAt(LI, MBB, V);
293 
294  // A store is a def.
295  } else if (const StoreInst *SI = dyn_cast<const StoreInst>(&*It)) {
296  const Value *SwiftErrorAddr = SI->getOperand(1);
297  if (!SwiftErrorAddr->isSwiftError())
298  continue;
299 
300  // Def of swifterror.
301  getOrCreateVRegDefAt(&*It, MBB, SwiftErrorAddr);
302 
303  // A return in a swiferror returning function is a use.
304  } else if (const ReturnInst *R = dyn_cast<const ReturnInst>(&*It)) {
305  const Function *F = R->getParent()->getParent();
306  if (!F->getAttributes().hasAttrSomewhere(Attribute::SwiftError))
307  continue;
308 
309  getOrCreateVRegUseAt(R, MBB, SwiftErrorArg);
310  }
311  }
312 }
llvm::Argument
This class represents an incoming formal argument to a Function.
Definition: Argument.h:29
llvm
Definition: AllocatorList.h:23
llvm::ReturnInst
Return a value (possibly void), from a function.
Definition: Instructions.h:2925
llvm::MachineRegisterInfo::createVirtualRegister
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
Definition: MachineRegisterInfo.cpp:158
llvm::Function
Definition: Function.h:61
llvm::TargetSubtargetInfo::getInstrInfo
virtual const TargetInstrInfo * getInstrInfo() const
Definition: TargetSubtargetInfo.h:92
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::SwiftErrorValueTracking::createEntriesInEntryBlock
bool createEntriesInEntryBlock(DebugLoc DbgLoc)
Create initial definitions of swifterror values in the entry block of the current function.
Definition: SwiftErrorValueTracking.cpp:115
llvm::SwiftErrorValueTracking::propagateVRegs
void propagateVRegs()
Propagate assigned swifterror vregs through a function, synthesizing PHI nodes when needed to maintai...
Definition: SwiftErrorValueTracking.cpp:147
TargetInstrInfo.h
llvm::SmallSet
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition: SmallSet.h:134
F
#define F(x, y, z)
Definition: MD5.cpp:56
MachineRegisterInfo.h
llvm::Value::isSwiftError
bool isSwiftError() const
Return true if this value is a swifterror value.
Definition: Value.cpp:973
Arg
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
Definition: AMDGPULibCalls.cpp:205
TargetLowering.h
llvm::MachineFunction::getRegInfo
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Definition: MachineFunction.h:568
llvm::MachineInstrBuilder::addMBB
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Definition: MachineInstrBuilder.h:146
llvm::TargetRegisterClass
Definition: TargetRegisterInfo.h:46
llvm::AMDGPU::PALMD::Key
Key
PAL metadata keys.
Definition: AMDGPUMetadata.h:481
llvm::Function::arg_end
arg_iterator arg_end()
Definition: Function.h:802
llvm::Instruction
Definition: Instruction.h:45
llvm::SwiftErrorValueTracking::getOrCreateVRegUseAt
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.
Definition: SwiftErrorValueTracking.cpp:65
llvm::MachineFunction::begin
iterator begin()
Definition: MachineFunction.h:740
llvm::SwiftErrorValueTracking::preassignVRegs
void preassignVRegs(MachineBasicBlock *MBB, BasicBlock::const_iterator Begin, BasicBlock::const_iterator End)
Definition: SwiftErrorValueTracking.cpp:259
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:95
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:558
llvm::StoreInst
An instruction for storing to memory.
Definition: Instructions.h:303
llvm::MachineInstrBuilder
Definition: MachineInstrBuilder.h:69
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::MachineBasicBlock::getFirstNonPHI
iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
Definition: MachineBasicBlock.cpp:199
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SI
StandardInstrumentations SI(Debug, VerifyEach)
llvm::MachineInstrBuilder::addReg
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Definition: MachineInstrBuilder.h:97
llvm::SwiftErrorValueTracking::setFunction
void setFunction(MachineFunction &MF)
Initialize data structures for specified new function.
Definition: SwiftErrorValueTracking.cpp:79
llvm::MachineBasicBlock::predecessors
iterator_range< pred_iterator > predecessors()
Definition: MachineBasicBlock.h:349
SwiftErrorValueTracking.h
llvm::MachineFunction
Definition: MachineFunction.h:230
llvm::SwiftErrorValueTracking::getOrCreateVRegDefAt
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.
Definition: SwiftErrorValueTracking.cpp:50
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
llvm::SmallSet::insert
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition: SmallSet.h:180
llvm::LoadInst
An instruction for reading from memory.
Definition: Instructions.h:174
llvm::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
llvm::find_if
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1509
MBB
MachineBasicBlock & MBB
Definition: AArch64SLSHardening.cpp:74
llvm::MachineFunction::getFunction
Function & getFunction()
Return the LLVM function that this machine code represents.
Definition: MachineFunction.h:524
llvm::SmallVectorImpl::clear
void clear()
Definition: SmallVector.h:585
llvm::Function::arg_begin
arg_iterator arg_begin()
Definition: Function.h:793
llvm::ReversePostOrderTraversal
Definition: PostOrderIterator.h:290
PostOrderIterator.h
llvm::PointerIntPair
PointerIntPair - This class implements a pair of a pointer and small integer.
Definition: PointerIntPair.h:45
llvm::TargetSubtargetInfo::getTargetLowering
virtual const TargetLowering * getTargetLowering() const
Definition: TargetSubtargetInfo.h:96
MachineInstrBuilder.h
llvm::BuildMI
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Definition: MachineInstrBuilder.h:328
llvm::TargetLoweringBase::getRegClassFor
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
Definition: TargetLowering.h:846
llvm::MachineFunction::getDataLayout
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Definition: MachineFunction.cpp:260
llvm::TargetLowering::supportSwiftError
virtual bool supportSwiftError() const
Return true if the target supports swifterror attribute.
Definition: TargetLowering.h:3604
llvm::MCInstrInfo::get
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition: MCInstrInfo.h:62
llvm::SwiftErrorValueTracking::getOrCreateVReg
Register getOrCreateVReg(const MachineBasicBlock *, const Value *)
Get or create the swifterror value virtual register in VRegDefMap for this basic block.
Definition: SwiftErrorValueTracking.cpp:26
llvm::DebugLoc
A debug info location.
Definition: DebugLoc.h:33
llvm::AllocaInst
an instruction to allocate memory on the stack
Definition: Instructions.h:61
Value.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::TargetLoweringBase::getPointerTy
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...
Definition: TargetLowering.h:346
llvm::BasicBlock::const_iterator
InstListType::const_iterator const_iterator
Definition: BasicBlock.h:91
llvm::SwiftErrorValueTracking::setCurrentVReg
void setCurrentVReg(const MachineBasicBlock *MBB, const Value *, Register)
Set the swifterror virtual register in the VRegDefMap for this basic block.
Definition: SwiftErrorValueTracking.cpp:45
SmallSet.h