LLVM: lib/CodeGen/SwiftErrorValueTracking.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
22
23using namespace llvm;
24
26 const Value *Val) {
27 auto Key = std::make_pair(MBB, Val);
28 auto It = VRegDefMap.find(Key);
29
30
31
32
33 if (It == VRegDefMap.end()) {
34 auto &DL = MF->getDataLayout();
36 auto VReg = MF->getRegInfo().createVirtualRegister(RC);
37 VRegDefMap[Key] = VReg;
38 VRegUpwardsUse[Key] = VReg;
39 return VReg;
40 } else
41 return It->second;
42}
43
46 VRegDefMap[std::make_pair(MBB, Val)] = VReg;
47}
48
52 auto It = VRegDefUses.find(Key);
53 if (It != VRegDefUses.end())
54 return It->second;
55
56 auto &DL = MF->getDataLayout();
58 Register VReg = MF->getRegInfo().createVirtualRegister(RC);
59 VRegDefUses[Key] = VReg;
61 return VReg;
62}
63
67 auto It = VRegDefUses.find(Key);
68 if (It != VRegDefUses.end())
69 return It->second;
70
72 VRegDefUses[Key] = VReg;
73 return VReg;
74}
75
76
77
79 MF = &mf;
81 TLI = MF->getSubtarget().getTargetLowering();
82 TII = MF->getSubtarget().getInstrInfo();
83
84 if (!TLI->supportSwiftError())
85 return;
86
87 SwiftErrorVals.clear();
88 VRegDefMap.clear();
89 VRegUpwardsUse.clear();
90 VRegDefUses.clear();
91 SwiftErrorArg = nullptr;
92
93
94 bool HaveSeenSwiftErrorArg = false;
96 AI != AE; ++AI)
97 if (AI->hasSwiftErrorAttr()) {
98 assert(!HaveSeenSwiftErrorArg &&
99 "Must have only one swifterror parameter");
100 (void)HaveSeenSwiftErrorArg;
101 HaveSeenSwiftErrorArg = true;
102 SwiftErrorArg = &*AI;
103 SwiftErrorVals.push_back(&*AI);
104 }
105
106 for (const auto &LLVMBB : *Fn)
107 for (const auto &Inst : LLVMBB) {
109 if (Alloca->isSwiftError())
110 SwiftErrorVals.push_back(Alloca);
111 }
112}
113
115 if (!TLI->supportSwiftError())
116 return false;
117
118
119
120 if (SwiftErrorVals.empty())
121 return false;
122
124 auto &DL = MF->getDataLayout();
125 auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
126 bool Inserted = false;
127 for (const auto *SwiftErrorVal : SwiftErrorVals) {
128
129
130 if (SwiftErrorArg && SwiftErrorArg == SwiftErrorVal)
131 continue;
132 Register VReg = MF->getRegInfo().createVirtualRegister(RC);
133
134
136 TII->get(TargetOpcode::IMPLICIT_DEF), VReg);
137
139 Inserted = true;
140 }
141
142 return Inserted;
143}
144
145
147 if (!TLI->supportSwiftError())
148 return;
149
150
151
152 if (SwiftErrorVals.empty())
153 return;
154
155
158
159 for (const auto *SwiftErrorVal : SwiftErrorVals) {
160 auto Key = std::make_pair(MBB, SwiftErrorVal);
161 auto UUseIt = VRegUpwardsUse.find(Key);
162 auto VRegDefIt = VRegDefMap.find(Key);
163 bool UpwardsUse = UUseIt != VRegUpwardsUse.end();
164 Register UUseVReg = UpwardsUse ? UUseIt->second : Register();
165 bool DownwardDef = VRegDefIt != VRegDefMap.end();
166 assert(!(UpwardsUse && !DownwardDef) &&
167 "We can't have an upwards use but no downwards def");
168
169
170
171
172 if (!UpwardsUse && DownwardDef)
173 continue;
174
175
176
177
178
179
182 for (auto *Pred : MBB->predecessors()) {
183 if (!Visited.insert(Pred).second)
184 continue;
187 if (Pred != MBB)
188 continue;
189
190
191
192 if (!UpwardsUse) {
193 UpwardsUse = true;
194 UUseIt = VRegUpwardsUse.find(Key);
195 assert(UUseIt != VRegUpwardsUse.end());
196 UUseVReg = UUseIt->second;
197 }
198 }
199
200
201
202 bool needPHI =
203 VRegs.size() >= 1 &&
205 VRegs,
206 [&](const std::pair<const MachineBasicBlock *, Register> &V)
207 -> bool { return V.second != VRegs[0].second; });
208
209
210
211 if (!UpwardsUse && !needPHI) {
213 "No predecessors? The entry block should bail out earlier");
214
216 continue;
217 }
218
222 const auto *TII = MF->getSubtarget().getInstrInfo();
223
224
225 if (!needPHI) {
228 "No predecessors? Is the Calling Convention correct?");
230 BuildMI(*MBB, MBB->getFirstNonPHI(), DLoc, TII->get(TargetOpcode::COPY),
231 DestReg)
232 .addReg(VRegs[0].second);
233 continue;
234 }
235
236
237
238 auto &DL = MF->getDataLayout();
239 auto const *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
241 UpwardsUse ? UUseVReg : MF->getRegInfo().createVirtualRegister(RC);
244 TII->get(TargetOpcode::PHI), PHIVReg);
245 for (auto BBRegPair : VRegs) {
246 PHI.addReg(BBRegPair.second).addMBB(BBRegPair.first);
247 }
248
249
250
251 if (!UpwardsUse)
253 }
254 }
255
256
258 for (const auto &Use : VRegUpwardsUse) {
261 if (.def_empty(VReg))
262 continue;
263
264#ifdef EXPENSIVE_CHECKS
265 assert(std::find(RPOT.begin(), RPOT.end(), UseBB) == RPOT.end() &&
266 "Reachable block has VReg upward use without definition.");
267#endif
268
270
272 TII->get(TargetOpcode::IMPLICIT_DEF), VReg);
273 }
274}
275
279 if (!TLI->supportSwiftError() || SwiftErrorVals.empty())
280 return;
281
282
283 for (auto It = Begin; It != End; ++It) {
285
286 const Value *SwiftErrorAddr = nullptr;
287 for (const auto &Arg : CB->args()) {
288 if (!Arg->isSwiftError())
289 continue;
290
291 assert(!SwiftErrorAddr && "Cannot have multiple swifterror arguments");
292 SwiftErrorAddr = &*Arg;
294 "Must have a swifterror value argument");
296 }
297 if (!SwiftErrorAddr)
298 continue;
299
300
302
303
305 const Value *V = LI->getOperand(0);
306 if (!V->isSwiftError())
307 continue;
308
310
311
313 const Value *SwiftErrorAddr = SI->getOperand(1);
315 continue;
316
317
319
320
322 const Function *F = R->getParent()->getParent();
323 if (->getAttributes().hasAttrSomewhere(Attribute::SwiftError))
324 continue;
325
327 }
328 }
329}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Promote Memory to Register
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
This file describes how to lower LLVM code to machine code.
an instruction to allocate memory on the stack
InstListType::const_iterator const_iterator
const Argument * const_arg_iterator
An instruction for reading from memory.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
LLVM_ABI iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
PointerIntPair - This class implements a pair of a pointer and small integer.
Wrapper class representing virtual and physical registers.
Return a value (possibly void), from a function.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
bool createEntriesInEntryBlock(DebugLoc DbgLoc)
Create initial definitions of swifterror values in the entry block of the current function.
Definition SwiftErrorValueTracking.cpp:114
void setFunction(MachineFunction &MF)
Initialize data structures for specified new function.
Definition SwiftErrorValueTracking.cpp:78
Register getOrCreateVReg(const MachineBasicBlock *, const Value *)
Get or create the swifterror value virtual register in VRegDefMap for this basic block.
Definition SwiftErrorValueTracking.cpp:25
void setCurrentVReg(const MachineBasicBlock *MBB, const Value *, Register)
Set the swifterror virtual register in the VRegDefMap for this basic block.
Definition SwiftErrorValueTracking.cpp:44
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:64
void preassignVRegs(MachineBasicBlock *MBB, BasicBlock::const_iterator Begin, BasicBlock::const_iterator End)
Definition SwiftErrorValueTracking.cpp:276
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:49
void propagateVRegs()
Propagate assigned swifterror vregs through a function, synthesizing PHI nodes when needed to maintai...
Definition SwiftErrorValueTracking.cpp:146
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
LLVM_ABI bool isSwiftError() const
Return true if this value is a swifterror value.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.