File: | llvm/include/llvm/IR/IntrinsicInst.h |
Warning: | line 218, column 43 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- CoroFrame.cpp - Builds and manipulates coroutine frame -------------===// | ||||||||||||
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 | // This file contains classes used to discover if for a particular value | ||||||||||||
9 | // there from sue to definition that crosses a suspend block. | ||||||||||||
10 | // | ||||||||||||
11 | // Using the information discovered we form a Coroutine Frame structure to | ||||||||||||
12 | // contain those values. All uses of those values are replaced with appropriate | ||||||||||||
13 | // GEP + load from the coroutine frame. At the point of the definition we spill | ||||||||||||
14 | // the value into the coroutine frame. | ||||||||||||
15 | //===----------------------------------------------------------------------===// | ||||||||||||
16 | |||||||||||||
17 | #include "CoroInternal.h" | ||||||||||||
18 | #include "llvm/ADT/BitVector.h" | ||||||||||||
19 | #include "llvm/ADT/ScopeExit.h" | ||||||||||||
20 | #include "llvm/ADT/SmallString.h" | ||||||||||||
21 | #include "llvm/Analysis/PtrUseVisitor.h" | ||||||||||||
22 | #include "llvm/Analysis/StackLifetime.h" | ||||||||||||
23 | #include "llvm/Config/llvm-config.h" | ||||||||||||
24 | #include "llvm/IR/CFG.h" | ||||||||||||
25 | #include "llvm/IR/DIBuilder.h" | ||||||||||||
26 | #include "llvm/IR/DebugInfo.h" | ||||||||||||
27 | #include "llvm/IR/Dominators.h" | ||||||||||||
28 | #include "llvm/IR/IRBuilder.h" | ||||||||||||
29 | #include "llvm/IR/InstIterator.h" | ||||||||||||
30 | #include "llvm/Support/CommandLine.h" | ||||||||||||
31 | #include "llvm/Support/Debug.h" | ||||||||||||
32 | #include "llvm/Support/MathExtras.h" | ||||||||||||
33 | #include "llvm/Support/OptimizedStructLayout.h" | ||||||||||||
34 | #include "llvm/Support/circular_raw_ostream.h" | ||||||||||||
35 | #include "llvm/Support/raw_ostream.h" | ||||||||||||
36 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" | ||||||||||||
37 | #include "llvm/Transforms/Utils/Local.h" | ||||||||||||
38 | #include "llvm/Transforms/Utils/PromoteMemToReg.h" | ||||||||||||
39 | #include <algorithm> | ||||||||||||
40 | |||||||||||||
41 | using namespace llvm; | ||||||||||||
42 | |||||||||||||
43 | // The "coro-suspend-crossing" flag is very noisy. There is another debug type, | ||||||||||||
44 | // "coro-frame", which results in leaner debug spew. | ||||||||||||
45 | #define DEBUG_TYPE"coro-frame" "coro-suspend-crossing" | ||||||||||||
46 | |||||||||||||
47 | static cl::opt<bool> EnableReuseStorageInFrame( | ||||||||||||
48 | "reuse-storage-in-coroutine-frame", cl::Hidden, | ||||||||||||
49 | cl::desc( | ||||||||||||
50 | "Enable the optimization which would reuse the storage in the coroutine \ | ||||||||||||
51 | frame for allocas whose liferanges are not overlapped, for testing purposes"), | ||||||||||||
52 | llvm::cl::init(false)); | ||||||||||||
53 | |||||||||||||
54 | enum { SmallVectorThreshold = 32 }; | ||||||||||||
55 | |||||||||||||
56 | // Provides two way mapping between the blocks and numbers. | ||||||||||||
57 | namespace { | ||||||||||||
58 | class BlockToIndexMapping { | ||||||||||||
59 | SmallVector<BasicBlock *, SmallVectorThreshold> V; | ||||||||||||
60 | |||||||||||||
61 | public: | ||||||||||||
62 | size_t size() const { return V.size(); } | ||||||||||||
63 | |||||||||||||
64 | BlockToIndexMapping(Function &F) { | ||||||||||||
65 | for (BasicBlock &BB : F) | ||||||||||||
66 | V.push_back(&BB); | ||||||||||||
67 | llvm::sort(V); | ||||||||||||
68 | } | ||||||||||||
69 | |||||||||||||
70 | size_t blockToIndex(BasicBlock *BB) const { | ||||||||||||
71 | auto *I = llvm::lower_bound(V, BB); | ||||||||||||
72 | assert(I != V.end() && *I == BB && "BasicBlockNumberng: Unknown block")(static_cast <bool> (I != V.end() && *I == BB && "BasicBlockNumberng: Unknown block") ? void (0) : __assert_fail ("I != V.end() && *I == BB && \"BasicBlockNumberng: Unknown block\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 72, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
73 | return I - V.begin(); | ||||||||||||
74 | } | ||||||||||||
75 | |||||||||||||
76 | BasicBlock *indexToBlock(unsigned Index) const { return V[Index]; } | ||||||||||||
77 | }; | ||||||||||||
78 | } // end anonymous namespace | ||||||||||||
79 | |||||||||||||
80 | // The SuspendCrossingInfo maintains data that allows to answer a question | ||||||||||||
81 | // whether given two BasicBlocks A and B there is a path from A to B that | ||||||||||||
82 | // passes through a suspend point. | ||||||||||||
83 | // | ||||||||||||
84 | // For every basic block 'i' it maintains a BlockData that consists of: | ||||||||||||
85 | // Consumes: a bit vector which contains a set of indices of blocks that can | ||||||||||||
86 | // reach block 'i' | ||||||||||||
87 | // Kills: a bit vector which contains a set of indices of blocks that can | ||||||||||||
88 | // reach block 'i', but one of the path will cross a suspend point | ||||||||||||
89 | // Suspend: a boolean indicating whether block 'i' contains a suspend point. | ||||||||||||
90 | // End: a boolean indicating whether block 'i' contains a coro.end intrinsic. | ||||||||||||
91 | // | ||||||||||||
92 | namespace { | ||||||||||||
93 | struct SuspendCrossingInfo { | ||||||||||||
94 | BlockToIndexMapping Mapping; | ||||||||||||
95 | |||||||||||||
96 | struct BlockData { | ||||||||||||
97 | BitVector Consumes; | ||||||||||||
98 | BitVector Kills; | ||||||||||||
99 | bool Suspend = false; | ||||||||||||
100 | bool End = false; | ||||||||||||
101 | }; | ||||||||||||
102 | SmallVector<BlockData, SmallVectorThreshold> Block; | ||||||||||||
103 | |||||||||||||
104 | iterator_range<succ_iterator> successors(BlockData const &BD) const { | ||||||||||||
105 | BasicBlock *BB = Mapping.indexToBlock(&BD - &Block[0]); | ||||||||||||
106 | return llvm::successors(BB); | ||||||||||||
107 | } | ||||||||||||
108 | |||||||||||||
109 | BlockData &getBlockData(BasicBlock *BB) { | ||||||||||||
110 | return Block[Mapping.blockToIndex(BB)]; | ||||||||||||
111 | } | ||||||||||||
112 | |||||||||||||
113 | void dump() const; | ||||||||||||
114 | void dump(StringRef Label, BitVector const &BV) const; | ||||||||||||
115 | |||||||||||||
116 | SuspendCrossingInfo(Function &F, coro::Shape &Shape); | ||||||||||||
117 | |||||||||||||
118 | bool hasPathCrossingSuspendPoint(BasicBlock *DefBB, BasicBlock *UseBB) const { | ||||||||||||
119 | size_t const DefIndex = Mapping.blockToIndex(DefBB); | ||||||||||||
120 | size_t const UseIndex = Mapping.blockToIndex(UseBB); | ||||||||||||
121 | |||||||||||||
122 | bool const Result = Block[UseIndex].Kills[DefIndex]; | ||||||||||||
123 | LLVM_DEBUG(dbgs() << UseBB->getName() << " => " << DefBB->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dbgs() << UseBB->getName() << " => " << DefBB->getName() << " answer is " << Result << "\n"; } } while (false) | ||||||||||||
124 | << " answer is " << Result << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dbgs() << UseBB->getName() << " => " << DefBB->getName() << " answer is " << Result << "\n"; } } while (false); | ||||||||||||
125 | return Result; | ||||||||||||
126 | } | ||||||||||||
127 | |||||||||||||
128 | bool isDefinitionAcrossSuspend(BasicBlock *DefBB, User *U) const { | ||||||||||||
129 | auto *I = cast<Instruction>(U); | ||||||||||||
130 | |||||||||||||
131 | // We rewrote PHINodes, so that only the ones with exactly one incoming | ||||||||||||
132 | // value need to be analyzed. | ||||||||||||
133 | if (auto *PN = dyn_cast<PHINode>(I)) | ||||||||||||
134 | if (PN->getNumIncomingValues() > 1) | ||||||||||||
135 | return false; | ||||||||||||
136 | |||||||||||||
137 | BasicBlock *UseBB = I->getParent(); | ||||||||||||
138 | |||||||||||||
139 | // As a special case, treat uses by an llvm.coro.suspend.retcon or an | ||||||||||||
140 | // llvm.coro.suspend.async as if they were uses in the suspend's single | ||||||||||||
141 | // predecessor: the uses conceptually occur before the suspend. | ||||||||||||
142 | if (isa<CoroSuspendRetconInst>(I) || isa<CoroSuspendAsyncInst>(I)) { | ||||||||||||
143 | UseBB = UseBB->getSinglePredecessor(); | ||||||||||||
144 | assert(UseBB && "should have split coro.suspend into its own block")(static_cast <bool> (UseBB && "should have split coro.suspend into its own block" ) ? void (0) : __assert_fail ("UseBB && \"should have split coro.suspend into its own block\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 144, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
145 | } | ||||||||||||
146 | |||||||||||||
147 | return hasPathCrossingSuspendPoint(DefBB, UseBB); | ||||||||||||
148 | } | ||||||||||||
149 | |||||||||||||
150 | bool isDefinitionAcrossSuspend(Argument &A, User *U) const { | ||||||||||||
151 | return isDefinitionAcrossSuspend(&A.getParent()->getEntryBlock(), U); | ||||||||||||
152 | } | ||||||||||||
153 | |||||||||||||
154 | bool isDefinitionAcrossSuspend(Instruction &I, User *U) const { | ||||||||||||
155 | auto *DefBB = I.getParent(); | ||||||||||||
156 | |||||||||||||
157 | // As a special case, treat values produced by an llvm.coro.suspend.* | ||||||||||||
158 | // as if they were defined in the single successor: the uses | ||||||||||||
159 | // conceptually occur after the suspend. | ||||||||||||
160 | if (isa<AnyCoroSuspendInst>(I)) { | ||||||||||||
161 | DefBB = DefBB->getSingleSuccessor(); | ||||||||||||
162 | assert(DefBB && "should have split coro.suspend into its own block")(static_cast <bool> (DefBB && "should have split coro.suspend into its own block" ) ? void (0) : __assert_fail ("DefBB && \"should have split coro.suspend into its own block\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 162, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
163 | } | ||||||||||||
164 | |||||||||||||
165 | return isDefinitionAcrossSuspend(DefBB, U); | ||||||||||||
166 | } | ||||||||||||
167 | |||||||||||||
168 | bool isDefinitionAcrossSuspend(Value &V, User *U) const { | ||||||||||||
169 | if (auto *Arg = dyn_cast<Argument>(&V)) | ||||||||||||
170 | return isDefinitionAcrossSuspend(*Arg, U); | ||||||||||||
171 | if (auto *Inst = dyn_cast<Instruction>(&V)) | ||||||||||||
172 | return isDefinitionAcrossSuspend(*Inst, U); | ||||||||||||
173 | |||||||||||||
174 | llvm_unreachable(::llvm::llvm_unreachable_internal("Coroutine could only collect Argument and Instruction now." , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 175) | ||||||||||||
175 | "Coroutine could only collect Argument and Instruction now.")::llvm::llvm_unreachable_internal("Coroutine could only collect Argument and Instruction now." , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 175); | ||||||||||||
176 | } | ||||||||||||
177 | }; | ||||||||||||
178 | } // end anonymous namespace | ||||||||||||
179 | |||||||||||||
180 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | ||||||||||||
181 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void SuspendCrossingInfo::dump(StringRef Label, | ||||||||||||
182 | BitVector const &BV) const { | ||||||||||||
183 | dbgs() << Label << ":"; | ||||||||||||
184 | for (size_t I = 0, N = BV.size(); I < N; ++I) | ||||||||||||
185 | if (BV[I]) | ||||||||||||
186 | dbgs() << " " << Mapping.indexToBlock(I)->getName(); | ||||||||||||
187 | dbgs() << "\n"; | ||||||||||||
188 | } | ||||||||||||
189 | |||||||||||||
190 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void SuspendCrossingInfo::dump() const { | ||||||||||||
191 | for (size_t I = 0, N = Block.size(); I < N; ++I) { | ||||||||||||
192 | BasicBlock *const B = Mapping.indexToBlock(I); | ||||||||||||
193 | dbgs() << B->getName() << ":\n"; | ||||||||||||
194 | dump(" Consumes", Block[I].Consumes); | ||||||||||||
195 | dump(" Kills", Block[I].Kills); | ||||||||||||
196 | } | ||||||||||||
197 | dbgs() << "\n"; | ||||||||||||
198 | } | ||||||||||||
199 | #endif | ||||||||||||
200 | |||||||||||||
201 | SuspendCrossingInfo::SuspendCrossingInfo(Function &F, coro::Shape &Shape) | ||||||||||||
202 | : Mapping(F) { | ||||||||||||
203 | const size_t N = Mapping.size(); | ||||||||||||
204 | Block.resize(N); | ||||||||||||
205 | |||||||||||||
206 | // Initialize every block so that it consumes itself | ||||||||||||
207 | for (size_t I = 0; I < N; ++I) { | ||||||||||||
208 | auto &B = Block[I]; | ||||||||||||
209 | B.Consumes.resize(N); | ||||||||||||
210 | B.Kills.resize(N); | ||||||||||||
211 | B.Consumes.set(I); | ||||||||||||
212 | } | ||||||||||||
213 | |||||||||||||
214 | // Mark all CoroEnd Blocks. We do not propagate Kills beyond coro.ends as | ||||||||||||
215 | // the code beyond coro.end is reachable during initial invocation of the | ||||||||||||
216 | // coroutine. | ||||||||||||
217 | for (auto *CE : Shape.CoroEnds) | ||||||||||||
218 | getBlockData(CE->getParent()).End = true; | ||||||||||||
219 | |||||||||||||
220 | // Mark all suspend blocks and indicate that they kill everything they | ||||||||||||
221 | // consume. Note, that crossing coro.save also requires a spill, as any code | ||||||||||||
222 | // between coro.save and coro.suspend may resume the coroutine and all of the | ||||||||||||
223 | // state needs to be saved by that time. | ||||||||||||
224 | auto markSuspendBlock = [&](IntrinsicInst *BarrierInst) { | ||||||||||||
225 | BasicBlock *SuspendBlock = BarrierInst->getParent(); | ||||||||||||
226 | auto &B = getBlockData(SuspendBlock); | ||||||||||||
227 | B.Suspend = true; | ||||||||||||
228 | B.Kills |= B.Consumes; | ||||||||||||
229 | }; | ||||||||||||
230 | for (auto *CSI : Shape.CoroSuspends) { | ||||||||||||
231 | markSuspendBlock(CSI); | ||||||||||||
232 | if (auto *Save = CSI->getCoroSave()) | ||||||||||||
233 | markSuspendBlock(Save); | ||||||||||||
234 | } | ||||||||||||
235 | |||||||||||||
236 | // Iterate propagating consumes and kills until they stop changing. | ||||||||||||
237 | int Iteration = 0; | ||||||||||||
238 | (void)Iteration; | ||||||||||||
239 | |||||||||||||
240 | bool Changed; | ||||||||||||
241 | do { | ||||||||||||
242 | LLVM_DEBUG(dbgs() << "iteration " << ++Iteration)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dbgs() << "iteration " << ++Iteration ; } } while (false); | ||||||||||||
243 | LLVM_DEBUG(dbgs() << "==============\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dbgs() << "==============\n"; } } while (false); | ||||||||||||
244 | |||||||||||||
245 | Changed = false; | ||||||||||||
246 | for (size_t I = 0; I < N; ++I) { | ||||||||||||
247 | auto &B = Block[I]; | ||||||||||||
248 | for (BasicBlock *SI : successors(B)) { | ||||||||||||
249 | |||||||||||||
250 | auto SuccNo = Mapping.blockToIndex(SI); | ||||||||||||
251 | |||||||||||||
252 | // Saved Consumes and Kills bitsets so that it is easy to see | ||||||||||||
253 | // if anything changed after propagation. | ||||||||||||
254 | auto &S = Block[SuccNo]; | ||||||||||||
255 | auto SavedConsumes = S.Consumes; | ||||||||||||
256 | auto SavedKills = S.Kills; | ||||||||||||
257 | |||||||||||||
258 | // Propagate Kills and Consumes from block B into its successor S. | ||||||||||||
259 | S.Consumes |= B.Consumes; | ||||||||||||
260 | S.Kills |= B.Kills; | ||||||||||||
261 | |||||||||||||
262 | // If block B is a suspend block, it should propagate kills into the | ||||||||||||
263 | // its successor for every block B consumes. | ||||||||||||
264 | if (B.Suspend) { | ||||||||||||
265 | S.Kills |= B.Consumes; | ||||||||||||
266 | } | ||||||||||||
267 | if (S.Suspend) { | ||||||||||||
268 | // If block S is a suspend block, it should kill all of the blocks it | ||||||||||||
269 | // consumes. | ||||||||||||
270 | S.Kills |= S.Consumes; | ||||||||||||
271 | } else if (S.End) { | ||||||||||||
272 | // If block S is an end block, it should not propagate kills as the | ||||||||||||
273 | // blocks following coro.end() are reached during initial invocation | ||||||||||||
274 | // of the coroutine while all the data are still available on the | ||||||||||||
275 | // stack or in the registers. | ||||||||||||
276 | S.Kills.reset(); | ||||||||||||
277 | } else { | ||||||||||||
278 | // This is reached when S block it not Suspend nor coro.end and it | ||||||||||||
279 | // need to make sure that it is not in the kill set. | ||||||||||||
280 | S.Kills.reset(SuccNo); | ||||||||||||
281 | } | ||||||||||||
282 | |||||||||||||
283 | // See if anything changed. | ||||||||||||
284 | Changed |= (S.Kills != SavedKills) || (S.Consumes != SavedConsumes); | ||||||||||||
285 | |||||||||||||
286 | if (S.Kills != SavedKills) { | ||||||||||||
287 | LLVM_DEBUG(dbgs() << "\nblock " << I << " follower " << SI->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dbgs() << "\nblock " << I << " follower " << SI->getName() << "\n"; } } while (false) | ||||||||||||
288 | << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dbgs() << "\nblock " << I << " follower " << SI->getName() << "\n"; } } while (false); | ||||||||||||
289 | LLVM_DEBUG(dump("S.Kills", S.Kills))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dump("S.Kills", S.Kills); } } while (false); | ||||||||||||
290 | LLVM_DEBUG(dump("SavedKills", SavedKills))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dump("SavedKills", SavedKills); } } while ( false); | ||||||||||||
291 | } | ||||||||||||
292 | if (S.Consumes != SavedConsumes) { | ||||||||||||
293 | LLVM_DEBUG(dbgs() << "\nblock " << I << " follower " << SI << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dbgs() << "\nblock " << I << " follower " << SI << "\n"; } } while (false); | ||||||||||||
294 | LLVM_DEBUG(dump("S.Consume", S.Consumes))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dump("S.Consume", S.Consumes); } } while (false ); | ||||||||||||
295 | LLVM_DEBUG(dump("SavedCons", SavedConsumes))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dump("SavedCons", SavedConsumes); } } while (false); | ||||||||||||
296 | } | ||||||||||||
297 | } | ||||||||||||
298 | } | ||||||||||||
299 | } while (Changed); | ||||||||||||
300 | LLVM_DEBUG(dump())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dump(); } } while (false); | ||||||||||||
301 | } | ||||||||||||
302 | |||||||||||||
303 | #undef DEBUG_TYPE"coro-frame" // "coro-suspend-crossing" | ||||||||||||
304 | #define DEBUG_TYPE"coro-frame" "coro-frame" | ||||||||||||
305 | |||||||||||||
306 | namespace { | ||||||||||||
307 | class FrameTypeBuilder; | ||||||||||||
308 | // Mapping from the to-be-spilled value to all the users that need reload. | ||||||||||||
309 | using SpillInfo = SmallMapVector<Value *, SmallVector<Instruction *, 2>, 8>; | ||||||||||||
310 | struct AllocaInfo { | ||||||||||||
311 | AllocaInst *Alloca; | ||||||||||||
312 | DenseMap<Instruction *, llvm::Optional<APInt>> Aliases; | ||||||||||||
313 | bool MayWriteBeforeCoroBegin; | ||||||||||||
314 | AllocaInfo(AllocaInst *Alloca, | ||||||||||||
315 | DenseMap<Instruction *, llvm::Optional<APInt>> Aliases, | ||||||||||||
316 | bool MayWriteBeforeCoroBegin) | ||||||||||||
317 | : Alloca(Alloca), Aliases(std::move(Aliases)), | ||||||||||||
318 | MayWriteBeforeCoroBegin(MayWriteBeforeCoroBegin) {} | ||||||||||||
319 | }; | ||||||||||||
320 | struct FrameDataInfo { | ||||||||||||
321 | // All the values (that are not allocas) that needs to be spilled to the | ||||||||||||
322 | // frame. | ||||||||||||
323 | SpillInfo Spills; | ||||||||||||
324 | // Allocas contains all values defined as allocas that need to live in the | ||||||||||||
325 | // frame. | ||||||||||||
326 | SmallVector<AllocaInfo, 8> Allocas; | ||||||||||||
327 | |||||||||||||
328 | SmallVector<Value *, 8> getAllDefs() const { | ||||||||||||
329 | SmallVector<Value *, 8> Defs; | ||||||||||||
330 | for (const auto &P : Spills) | ||||||||||||
331 | Defs.push_back(P.first); | ||||||||||||
332 | for (const auto &A : Allocas) | ||||||||||||
333 | Defs.push_back(A.Alloca); | ||||||||||||
334 | return Defs; | ||||||||||||
335 | } | ||||||||||||
336 | |||||||||||||
337 | uint32_t getFieldIndex(Value *V) const { | ||||||||||||
338 | auto Itr = FieldIndexMap.find(V); | ||||||||||||
339 | assert(Itr != FieldIndexMap.end() &&(static_cast <bool> (Itr != FieldIndexMap.end() && "Value does not have a frame field index") ? void (0) : __assert_fail ("Itr != FieldIndexMap.end() && \"Value does not have a frame field index\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 340, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
340 | "Value does not have a frame field index")(static_cast <bool> (Itr != FieldIndexMap.end() && "Value does not have a frame field index") ? void (0) : __assert_fail ("Itr != FieldIndexMap.end() && \"Value does not have a frame field index\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 340, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
341 | return Itr->second; | ||||||||||||
342 | } | ||||||||||||
343 | |||||||||||||
344 | void setFieldIndex(Value *V, uint32_t Index) { | ||||||||||||
345 | assert((LayoutIndexUpdateStarted || FieldIndexMap.count(V) == 0) &&(static_cast <bool> ((LayoutIndexUpdateStarted || FieldIndexMap .count(V) == 0) && "Cannot set the index for the same field twice." ) ? void (0) : __assert_fail ("(LayoutIndexUpdateStarted || FieldIndexMap.count(V) == 0) && \"Cannot set the index for the same field twice.\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 346, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
346 | "Cannot set the index for the same field twice.")(static_cast <bool> ((LayoutIndexUpdateStarted || FieldIndexMap .count(V) == 0) && "Cannot set the index for the same field twice." ) ? void (0) : __assert_fail ("(LayoutIndexUpdateStarted || FieldIndexMap.count(V) == 0) && \"Cannot set the index for the same field twice.\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 346, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
347 | FieldIndexMap[V] = Index; | ||||||||||||
348 | } | ||||||||||||
349 | |||||||||||||
350 | uint64_t getAlign(Value *V) const { | ||||||||||||
351 | auto Iter = FieldAlignMap.find(V); | ||||||||||||
352 | assert(Iter != FieldAlignMap.end())(static_cast <bool> (Iter != FieldAlignMap.end()) ? void (0) : __assert_fail ("Iter != FieldAlignMap.end()", "llvm/lib/Transforms/Coroutines/CoroFrame.cpp" , 352, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
353 | return Iter->second; | ||||||||||||
354 | } | ||||||||||||
355 | |||||||||||||
356 | void setAlign(Value *V, uint64_t Align) { | ||||||||||||
357 | assert(FieldAlignMap.count(V) == 0)(static_cast <bool> (FieldAlignMap.count(V) == 0) ? void (0) : __assert_fail ("FieldAlignMap.count(V) == 0", "llvm/lib/Transforms/Coroutines/CoroFrame.cpp" , 357, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
358 | FieldAlignMap.insert({V, Align}); | ||||||||||||
359 | } | ||||||||||||
360 | |||||||||||||
361 | uint64_t getOffset(Value *V) const { | ||||||||||||
362 | auto Iter = FieldOffsetMap.find(V); | ||||||||||||
363 | assert(Iter != FieldOffsetMap.end())(static_cast <bool> (Iter != FieldOffsetMap.end()) ? void (0) : __assert_fail ("Iter != FieldOffsetMap.end()", "llvm/lib/Transforms/Coroutines/CoroFrame.cpp" , 363, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
364 | return Iter->second; | ||||||||||||
365 | } | ||||||||||||
366 | |||||||||||||
367 | void setOffset(Value *V, uint64_t Offset) { | ||||||||||||
368 | assert(FieldOffsetMap.count(V) == 0)(static_cast <bool> (FieldOffsetMap.count(V) == 0) ? void (0) : __assert_fail ("FieldOffsetMap.count(V) == 0", "llvm/lib/Transforms/Coroutines/CoroFrame.cpp" , 368, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
369 | FieldOffsetMap.insert({V, Offset}); | ||||||||||||
370 | } | ||||||||||||
371 | |||||||||||||
372 | // Remap the index of every field in the frame, using the final layout index. | ||||||||||||
373 | void updateLayoutIndex(FrameTypeBuilder &B); | ||||||||||||
374 | |||||||||||||
375 | private: | ||||||||||||
376 | // LayoutIndexUpdateStarted is used to avoid updating the index of any field | ||||||||||||
377 | // twice by mistake. | ||||||||||||
378 | bool LayoutIndexUpdateStarted = false; | ||||||||||||
379 | // Map from values to their slot indexes on the frame. They will be first set | ||||||||||||
380 | // with their original insertion field index. After the frame is built, their | ||||||||||||
381 | // indexes will be updated into the final layout index. | ||||||||||||
382 | DenseMap<Value *, uint32_t> FieldIndexMap; | ||||||||||||
383 | // Map from values to their alignment on the frame. They would be set after | ||||||||||||
384 | // the frame is built. | ||||||||||||
385 | DenseMap<Value *, uint64_t> FieldAlignMap; | ||||||||||||
386 | // Map from values to their offset on the frame. They would be set after | ||||||||||||
387 | // the frame is built. | ||||||||||||
388 | DenseMap<Value *, uint64_t> FieldOffsetMap; | ||||||||||||
389 | }; | ||||||||||||
390 | } // namespace | ||||||||||||
391 | |||||||||||||
392 | #ifndef NDEBUG | ||||||||||||
393 | static void dumpSpills(StringRef Title, const SpillInfo &Spills) { | ||||||||||||
394 | dbgs() << "------------- " << Title << "--------------\n"; | ||||||||||||
395 | for (const auto &E : Spills) { | ||||||||||||
396 | E.first->dump(); | ||||||||||||
397 | dbgs() << " user: "; | ||||||||||||
398 | for (auto *I : E.second) | ||||||||||||
399 | I->dump(); | ||||||||||||
400 | } | ||||||||||||
401 | } | ||||||||||||
402 | |||||||||||||
403 | static void dumpAllocas(const SmallVectorImpl<AllocaInfo> &Allocas) { | ||||||||||||
404 | dbgs() << "------------- Allocas --------------\n"; | ||||||||||||
405 | for (const auto &A : Allocas) { | ||||||||||||
406 | A.Alloca->dump(); | ||||||||||||
407 | } | ||||||||||||
408 | } | ||||||||||||
409 | #endif | ||||||||||||
410 | |||||||||||||
411 | namespace { | ||||||||||||
412 | using FieldIDType = size_t; | ||||||||||||
413 | // We cannot rely solely on natural alignment of a type when building a | ||||||||||||
414 | // coroutine frame and if the alignment specified on the Alloca instruction | ||||||||||||
415 | // differs from the natural alignment of the alloca type we will need to insert | ||||||||||||
416 | // padding. | ||||||||||||
417 | class FrameTypeBuilder { | ||||||||||||
418 | private: | ||||||||||||
419 | struct Field { | ||||||||||||
420 | uint64_t Size; | ||||||||||||
421 | uint64_t Offset; | ||||||||||||
422 | Type *Ty; | ||||||||||||
423 | FieldIDType LayoutFieldIndex; | ||||||||||||
424 | Align Alignment; | ||||||||||||
425 | Align TyAlignment; | ||||||||||||
426 | }; | ||||||||||||
427 | |||||||||||||
428 | const DataLayout &DL; | ||||||||||||
429 | LLVMContext &Context; | ||||||||||||
430 | uint64_t StructSize = 0; | ||||||||||||
431 | Align StructAlign; | ||||||||||||
432 | bool IsFinished = false; | ||||||||||||
433 | |||||||||||||
434 | Optional<Align> MaxFrameAlignment; | ||||||||||||
435 | |||||||||||||
436 | SmallVector<Field, 8> Fields; | ||||||||||||
437 | DenseMap<Value*, unsigned> FieldIndexByKey; | ||||||||||||
438 | |||||||||||||
439 | public: | ||||||||||||
440 | FrameTypeBuilder(LLVMContext &Context, const DataLayout &DL, | ||||||||||||
441 | Optional<Align> MaxFrameAlignment) | ||||||||||||
442 | : DL(DL), Context(Context), MaxFrameAlignment(MaxFrameAlignment) {} | ||||||||||||
443 | |||||||||||||
444 | /// Add a field to this structure for the storage of an `alloca` | ||||||||||||
445 | /// instruction. | ||||||||||||
446 | LLVM_NODISCARD[[clang::warn_unused_result]] FieldIDType addFieldForAlloca(AllocaInst *AI, | ||||||||||||
447 | bool IsHeader = false) { | ||||||||||||
448 | Type *Ty = AI->getAllocatedType(); | ||||||||||||
449 | |||||||||||||
450 | // Make an array type if this is a static array allocation. | ||||||||||||
451 | if (AI->isArrayAllocation()) { | ||||||||||||
452 | if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize())) | ||||||||||||
453 | Ty = ArrayType::get(Ty, CI->getValue().getZExtValue()); | ||||||||||||
454 | else | ||||||||||||
455 | report_fatal_error("Coroutines cannot handle non static allocas yet"); | ||||||||||||
456 | } | ||||||||||||
457 | |||||||||||||
458 | return addField(Ty, AI->getAlign(), IsHeader); | ||||||||||||
459 | } | ||||||||||||
460 | |||||||||||||
461 | /// We want to put the allocas whose lifetime-ranges are not overlapped | ||||||||||||
462 | /// into one slot of coroutine frame. | ||||||||||||
463 | /// Consider the example at:https://bugs.llvm.org/show_bug.cgi?id=45566 | ||||||||||||
464 | /// | ||||||||||||
465 | /// cppcoro::task<void> alternative_paths(bool cond) { | ||||||||||||
466 | /// if (cond) { | ||||||||||||
467 | /// big_structure a; | ||||||||||||
468 | /// process(a); | ||||||||||||
469 | /// co_await something(); | ||||||||||||
470 | /// } else { | ||||||||||||
471 | /// big_structure b; | ||||||||||||
472 | /// process2(b); | ||||||||||||
473 | /// co_await something(); | ||||||||||||
474 | /// } | ||||||||||||
475 | /// } | ||||||||||||
476 | /// | ||||||||||||
477 | /// We want to put variable a and variable b in the same slot to | ||||||||||||
478 | /// reduce the size of coroutine frame. | ||||||||||||
479 | /// | ||||||||||||
480 | /// This function use StackLifetime algorithm to partition the AllocaInsts in | ||||||||||||
481 | /// Spills to non-overlapped sets in order to put Alloca in the same | ||||||||||||
482 | /// non-overlapped set into the same slot in the Coroutine Frame. Then add | ||||||||||||
483 | /// field for the allocas in the same non-overlapped set by using the largest | ||||||||||||
484 | /// type as the field type. | ||||||||||||
485 | /// | ||||||||||||
486 | /// Side Effects: Because We sort the allocas, the order of allocas in the | ||||||||||||
487 | /// frame may be different with the order in the source code. | ||||||||||||
488 | void addFieldForAllocas(const Function &F, FrameDataInfo &FrameData, | ||||||||||||
489 | coro::Shape &Shape); | ||||||||||||
490 | |||||||||||||
491 | /// Add a field to this structure. | ||||||||||||
492 | LLVM_NODISCARD[[clang::warn_unused_result]] FieldIDType addField(Type *Ty, MaybeAlign FieldAlignment, | ||||||||||||
493 | bool IsHeader = false, | ||||||||||||
494 | bool IsSpillOfValue = false) { | ||||||||||||
495 | assert(!IsFinished && "adding fields to a finished builder")(static_cast <bool> (!IsFinished && "adding fields to a finished builder" ) ? void (0) : __assert_fail ("!IsFinished && \"adding fields to a finished builder\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 495, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
496 | assert(Ty && "must provide a type for a field")(static_cast <bool> (Ty && "must provide a type for a field" ) ? void (0) : __assert_fail ("Ty && \"must provide a type for a field\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 496, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
497 | |||||||||||||
498 | // The field size is always the alloc size of the type. | ||||||||||||
499 | uint64_t FieldSize = DL.getTypeAllocSize(Ty); | ||||||||||||
500 | |||||||||||||
501 | // For an alloca with size=0, we don't need to add a field and they | ||||||||||||
502 | // can just point to any index in the frame. Use index 0. | ||||||||||||
503 | if (FieldSize == 0) { | ||||||||||||
504 | return 0; | ||||||||||||
505 | } | ||||||||||||
506 | |||||||||||||
507 | // The field alignment might not be the type alignment, but we need | ||||||||||||
508 | // to remember the type alignment anyway to build the type. | ||||||||||||
509 | // If we are spilling values we don't need to worry about ABI alignment | ||||||||||||
510 | // concerns. | ||||||||||||
511 | auto ABIAlign = DL.getABITypeAlign(Ty); | ||||||||||||
512 | Align TyAlignment = | ||||||||||||
513 | (IsSpillOfValue && MaxFrameAlignment) | ||||||||||||
514 | ? (*MaxFrameAlignment < ABIAlign ? *MaxFrameAlignment : ABIAlign) | ||||||||||||
515 | : ABIAlign; | ||||||||||||
516 | if (!FieldAlignment) { | ||||||||||||
517 | FieldAlignment = TyAlignment; | ||||||||||||
518 | } | ||||||||||||
519 | |||||||||||||
520 | // Lay out header fields immediately. | ||||||||||||
521 | uint64_t Offset; | ||||||||||||
522 | if (IsHeader) { | ||||||||||||
523 | Offset = alignTo(StructSize, FieldAlignment); | ||||||||||||
524 | StructSize = Offset + FieldSize; | ||||||||||||
525 | |||||||||||||
526 | // Everything else has a flexible offset. | ||||||||||||
527 | } else { | ||||||||||||
528 | Offset = OptimizedStructLayoutField::FlexibleOffset; | ||||||||||||
529 | } | ||||||||||||
530 | |||||||||||||
531 | Fields.push_back({FieldSize, Offset, Ty, 0, *FieldAlignment, TyAlignment}); | ||||||||||||
532 | return Fields.size() - 1; | ||||||||||||
533 | } | ||||||||||||
534 | |||||||||||||
535 | /// Finish the layout and set the body on the given type. | ||||||||||||
536 | void finish(StructType *Ty); | ||||||||||||
537 | |||||||||||||
538 | uint64_t getStructSize() const { | ||||||||||||
539 | assert(IsFinished && "not yet finished!")(static_cast <bool> (IsFinished && "not yet finished!" ) ? void (0) : __assert_fail ("IsFinished && \"not yet finished!\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 539, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
540 | return StructSize; | ||||||||||||
541 | } | ||||||||||||
542 | |||||||||||||
543 | Align getStructAlign() const { | ||||||||||||
544 | assert(IsFinished && "not yet finished!")(static_cast <bool> (IsFinished && "not yet finished!" ) ? void (0) : __assert_fail ("IsFinished && \"not yet finished!\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 544, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
545 | return StructAlign; | ||||||||||||
546 | } | ||||||||||||
547 | |||||||||||||
548 | FieldIDType getLayoutFieldIndex(FieldIDType Id) const { | ||||||||||||
549 | assert(IsFinished && "not yet finished!")(static_cast <bool> (IsFinished && "not yet finished!" ) ? void (0) : __assert_fail ("IsFinished && \"not yet finished!\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 549, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
550 | return Fields[Id].LayoutFieldIndex; | ||||||||||||
551 | } | ||||||||||||
552 | |||||||||||||
553 | Field getLayoutField(FieldIDType Id) const { | ||||||||||||
554 | assert(IsFinished && "not yet finished!")(static_cast <bool> (IsFinished && "not yet finished!" ) ? void (0) : __assert_fail ("IsFinished && \"not yet finished!\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 554, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
555 | return Fields[Id]; | ||||||||||||
556 | } | ||||||||||||
557 | }; | ||||||||||||
558 | } // namespace | ||||||||||||
559 | |||||||||||||
560 | void FrameDataInfo::updateLayoutIndex(FrameTypeBuilder &B) { | ||||||||||||
561 | auto Updater = [&](Value *I) { | ||||||||||||
562 | auto Field = B.getLayoutField(getFieldIndex(I)); | ||||||||||||
563 | setFieldIndex(I, Field.LayoutFieldIndex); | ||||||||||||
564 | setAlign(I, Field.Alignment.value()); | ||||||||||||
565 | setOffset(I, Field.Offset); | ||||||||||||
566 | }; | ||||||||||||
567 | LayoutIndexUpdateStarted = true; | ||||||||||||
568 | for (auto &S : Spills) | ||||||||||||
569 | Updater(S.first); | ||||||||||||
570 | for (const auto &A : Allocas) | ||||||||||||
571 | Updater(A.Alloca); | ||||||||||||
572 | LayoutIndexUpdateStarted = false; | ||||||||||||
573 | } | ||||||||||||
574 | |||||||||||||
575 | void FrameTypeBuilder::addFieldForAllocas(const Function &F, | ||||||||||||
576 | FrameDataInfo &FrameData, | ||||||||||||
577 | coro::Shape &Shape) { | ||||||||||||
578 | using AllocaSetType = SmallVector<AllocaInst *, 4>; | ||||||||||||
579 | SmallVector<AllocaSetType, 4> NonOverlapedAllocas; | ||||||||||||
580 | |||||||||||||
581 | // We need to add field for allocas at the end of this function. | ||||||||||||
582 | auto AddFieldForAllocasAtExit = make_scope_exit([&]() { | ||||||||||||
583 | for (auto AllocaList : NonOverlapedAllocas) { | ||||||||||||
584 | auto *LargestAI = *AllocaList.begin(); | ||||||||||||
585 | FieldIDType Id = addFieldForAlloca(LargestAI); | ||||||||||||
586 | for (auto *Alloca : AllocaList) | ||||||||||||
587 | FrameData.setFieldIndex(Alloca, Id); | ||||||||||||
588 | } | ||||||||||||
589 | }); | ||||||||||||
590 | |||||||||||||
591 | if (!Shape.OptimizeFrame && !EnableReuseStorageInFrame) { | ||||||||||||
592 | for (const auto &A : FrameData.Allocas) { | ||||||||||||
593 | AllocaInst *Alloca = A.Alloca; | ||||||||||||
594 | NonOverlapedAllocas.emplace_back(AllocaSetType(1, Alloca)); | ||||||||||||
595 | } | ||||||||||||
596 | return; | ||||||||||||
597 | } | ||||||||||||
598 | |||||||||||||
599 | // Because there are pathes from the lifetime.start to coro.end | ||||||||||||
600 | // for each alloca, the liferanges for every alloca is overlaped | ||||||||||||
601 | // in the blocks who contain coro.end and the successor blocks. | ||||||||||||
602 | // So we choose to skip there blocks when we calculates the liferange | ||||||||||||
603 | // for each alloca. It should be reasonable since there shouldn't be uses | ||||||||||||
604 | // in these blocks and the coroutine frame shouldn't be used outside the | ||||||||||||
605 | // coroutine body. | ||||||||||||
606 | // | ||||||||||||
607 | // Note that the user of coro.suspend may not be SwitchInst. However, this | ||||||||||||
608 | // case seems too complex to handle. And it is harmless to skip these | ||||||||||||
609 | // patterns since it just prevend putting the allocas to live in the same | ||||||||||||
610 | // slot. | ||||||||||||
611 | DenseMap<SwitchInst *, BasicBlock *> DefaultSuspendDest; | ||||||||||||
612 | for (auto CoroSuspendInst : Shape.CoroSuspends) { | ||||||||||||
613 | for (auto U : CoroSuspendInst->users()) { | ||||||||||||
614 | if (auto *ConstSWI = dyn_cast<SwitchInst>(U)) { | ||||||||||||
615 | auto *SWI = const_cast<SwitchInst *>(ConstSWI); | ||||||||||||
616 | DefaultSuspendDest[SWI] = SWI->getDefaultDest(); | ||||||||||||
617 | SWI->setDefaultDest(SWI->getSuccessor(1)); | ||||||||||||
618 | } | ||||||||||||
619 | } | ||||||||||||
620 | } | ||||||||||||
621 | |||||||||||||
622 | auto ExtractAllocas = [&]() { | ||||||||||||
623 | AllocaSetType Allocas; | ||||||||||||
624 | Allocas.reserve(FrameData.Allocas.size()); | ||||||||||||
625 | for (const auto &A : FrameData.Allocas) | ||||||||||||
626 | Allocas.push_back(A.Alloca); | ||||||||||||
627 | return Allocas; | ||||||||||||
628 | }; | ||||||||||||
629 | StackLifetime StackLifetimeAnalyzer(F, ExtractAllocas(), | ||||||||||||
630 | StackLifetime::LivenessType::May); | ||||||||||||
631 | StackLifetimeAnalyzer.run(); | ||||||||||||
632 | auto IsAllocaInferenre = [&](const AllocaInst *AI1, const AllocaInst *AI2) { | ||||||||||||
633 | return StackLifetimeAnalyzer.getLiveRange(AI1).overlaps( | ||||||||||||
634 | StackLifetimeAnalyzer.getLiveRange(AI2)); | ||||||||||||
635 | }; | ||||||||||||
636 | auto GetAllocaSize = [&](const AllocaInfo &A) { | ||||||||||||
637 | Optional<TypeSize> RetSize = A.Alloca->getAllocationSizeInBits(DL); | ||||||||||||
638 | assert(RetSize && "Variable Length Arrays (VLA) are not supported.\n")(static_cast <bool> (RetSize && "Variable Length Arrays (VLA) are not supported.\n" ) ? void (0) : __assert_fail ("RetSize && \"Variable Length Arrays (VLA) are not supported.\\n\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 638, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
639 | assert(!RetSize->isScalable() && "Scalable vectors are not yet supported")(static_cast <bool> (!RetSize->isScalable() && "Scalable vectors are not yet supported") ? void (0) : __assert_fail ("!RetSize->isScalable() && \"Scalable vectors are not yet supported\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 639, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
640 | return RetSize->getFixedSize(); | ||||||||||||
641 | }; | ||||||||||||
642 | // Put larger allocas in the front. So the larger allocas have higher | ||||||||||||
643 | // priority to merge, which can save more space potentially. Also each | ||||||||||||
644 | // AllocaSet would be ordered. So we can get the largest Alloca in one | ||||||||||||
645 | // AllocaSet easily. | ||||||||||||
646 | sort(FrameData.Allocas, [&](const auto &Iter1, const auto &Iter2) { | ||||||||||||
647 | return GetAllocaSize(Iter1) > GetAllocaSize(Iter2); | ||||||||||||
648 | }); | ||||||||||||
649 | for (const auto &A : FrameData.Allocas) { | ||||||||||||
650 | AllocaInst *Alloca = A.Alloca; | ||||||||||||
651 | bool Merged = false; | ||||||||||||
652 | // Try to find if the Alloca is not inferenced with any existing | ||||||||||||
653 | // NonOverlappedAllocaSet. If it is true, insert the alloca to that | ||||||||||||
654 | // NonOverlappedAllocaSet. | ||||||||||||
655 | for (auto &AllocaSet : NonOverlapedAllocas) { | ||||||||||||
656 | assert(!AllocaSet.empty() && "Processing Alloca Set is not empty.\n")(static_cast <bool> (!AllocaSet.empty() && "Processing Alloca Set is not empty.\n" ) ? void (0) : __assert_fail ("!AllocaSet.empty() && \"Processing Alloca Set is not empty.\\n\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 656, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
657 | bool NoInference = none_of(AllocaSet, [&](auto Iter) { | ||||||||||||
658 | return IsAllocaInferenre(Alloca, Iter); | ||||||||||||
659 | }); | ||||||||||||
660 | // If the alignment of A is multiple of the alignment of B, the address | ||||||||||||
661 | // of A should satisfy the requirement for aligning for B. | ||||||||||||
662 | // | ||||||||||||
663 | // There may be other more fine-grained strategies to handle the alignment | ||||||||||||
664 | // infomation during the merging process. But it seems hard to handle | ||||||||||||
665 | // these strategies and benefit little. | ||||||||||||
666 | bool Alignable = [&]() -> bool { | ||||||||||||
667 | auto *LargestAlloca = *AllocaSet.begin(); | ||||||||||||
668 | return LargestAlloca->getAlign().value() % Alloca->getAlign().value() == | ||||||||||||
669 | 0; | ||||||||||||
670 | }(); | ||||||||||||
671 | bool CouldMerge = NoInference && Alignable; | ||||||||||||
672 | if (!CouldMerge) | ||||||||||||
673 | continue; | ||||||||||||
674 | AllocaSet.push_back(Alloca); | ||||||||||||
675 | Merged = true; | ||||||||||||
676 | break; | ||||||||||||
677 | } | ||||||||||||
678 | if (!Merged) { | ||||||||||||
679 | NonOverlapedAllocas.emplace_back(AllocaSetType(1, Alloca)); | ||||||||||||
680 | } | ||||||||||||
681 | } | ||||||||||||
682 | // Recover the default target destination for each Switch statement | ||||||||||||
683 | // reserved. | ||||||||||||
684 | for (auto SwitchAndDefaultDest : DefaultSuspendDest) { | ||||||||||||
685 | SwitchInst *SWI = SwitchAndDefaultDest.first; | ||||||||||||
686 | BasicBlock *DestBB = SwitchAndDefaultDest.second; | ||||||||||||
687 | SWI->setDefaultDest(DestBB); | ||||||||||||
688 | } | ||||||||||||
689 | // This Debug Info could tell us which allocas are merged into one slot. | ||||||||||||
690 | LLVM_DEBUG(for (auto &AllocaSetdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { for (auto &AllocaSet : NonOverlapedAllocas ) { if (AllocaSet.size() > 1) { dbgs() << "In Function:" << F.getName() << "\n"; dbgs() << "Find Union Set " << "\n"; dbgs() << "\tAllocas are \n"; for (auto Alloca : AllocaSet) dbgs() << "\t\t" << *Alloca << "\n"; } }; } } while (false) | ||||||||||||
691 | : NonOverlapedAllocas) {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { for (auto &AllocaSet : NonOverlapedAllocas ) { if (AllocaSet.size() > 1) { dbgs() << "In Function:" << F.getName() << "\n"; dbgs() << "Find Union Set " << "\n"; dbgs() << "\tAllocas are \n"; for (auto Alloca : AllocaSet) dbgs() << "\t\t" << *Alloca << "\n"; } }; } } while (false) | ||||||||||||
692 | if (AllocaSet.size() > 1) {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { for (auto &AllocaSet : NonOverlapedAllocas ) { if (AllocaSet.size() > 1) { dbgs() << "In Function:" << F.getName() << "\n"; dbgs() << "Find Union Set " << "\n"; dbgs() << "\tAllocas are \n"; for (auto Alloca : AllocaSet) dbgs() << "\t\t" << *Alloca << "\n"; } }; } } while (false) | ||||||||||||
693 | dbgs() << "In Function:" << F.getName() << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { for (auto &AllocaSet : NonOverlapedAllocas ) { if (AllocaSet.size() > 1) { dbgs() << "In Function:" << F.getName() << "\n"; dbgs() << "Find Union Set " << "\n"; dbgs() << "\tAllocas are \n"; for (auto Alloca : AllocaSet) dbgs() << "\t\t" << *Alloca << "\n"; } }; } } while (false) | ||||||||||||
694 | dbgs() << "Find Union Set "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { for (auto &AllocaSet : NonOverlapedAllocas ) { if (AllocaSet.size() > 1) { dbgs() << "In Function:" << F.getName() << "\n"; dbgs() << "Find Union Set " << "\n"; dbgs() << "\tAllocas are \n"; for (auto Alloca : AllocaSet) dbgs() << "\t\t" << *Alloca << "\n"; } }; } } while (false) | ||||||||||||
695 | << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { for (auto &AllocaSet : NonOverlapedAllocas ) { if (AllocaSet.size() > 1) { dbgs() << "In Function:" << F.getName() << "\n"; dbgs() << "Find Union Set " << "\n"; dbgs() << "\tAllocas are \n"; for (auto Alloca : AllocaSet) dbgs() << "\t\t" << *Alloca << "\n"; } }; } } while (false) | ||||||||||||
696 | dbgs() << "\tAllocas are \n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { for (auto &AllocaSet : NonOverlapedAllocas ) { if (AllocaSet.size() > 1) { dbgs() << "In Function:" << F.getName() << "\n"; dbgs() << "Find Union Set " << "\n"; dbgs() << "\tAllocas are \n"; for (auto Alloca : AllocaSet) dbgs() << "\t\t" << *Alloca << "\n"; } }; } } while (false) | ||||||||||||
697 | for (auto Alloca : AllocaSet)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { for (auto &AllocaSet : NonOverlapedAllocas ) { if (AllocaSet.size() > 1) { dbgs() << "In Function:" << F.getName() << "\n"; dbgs() << "Find Union Set " << "\n"; dbgs() << "\tAllocas are \n"; for (auto Alloca : AllocaSet) dbgs() << "\t\t" << *Alloca << "\n"; } }; } } while (false) | ||||||||||||
698 | dbgs() << "\t\t" << *Alloca << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { for (auto &AllocaSet : NonOverlapedAllocas ) { if (AllocaSet.size() > 1) { dbgs() << "In Function:" << F.getName() << "\n"; dbgs() << "Find Union Set " << "\n"; dbgs() << "\tAllocas are \n"; for (auto Alloca : AllocaSet) dbgs() << "\t\t" << *Alloca << "\n"; } }; } } while (false) | ||||||||||||
699 | }do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { for (auto &AllocaSet : NonOverlapedAllocas ) { if (AllocaSet.size() > 1) { dbgs() << "In Function:" << F.getName() << "\n"; dbgs() << "Find Union Set " << "\n"; dbgs() << "\tAllocas are \n"; for (auto Alloca : AllocaSet) dbgs() << "\t\t" << *Alloca << "\n"; } }; } } while (false) | ||||||||||||
700 | })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { for (auto &AllocaSet : NonOverlapedAllocas ) { if (AllocaSet.size() > 1) { dbgs() << "In Function:" << F.getName() << "\n"; dbgs() << "Find Union Set " << "\n"; dbgs() << "\tAllocas are \n"; for (auto Alloca : AllocaSet) dbgs() << "\t\t" << *Alloca << "\n"; } }; } } while (false); | ||||||||||||
701 | } | ||||||||||||
702 | |||||||||||||
703 | void FrameTypeBuilder::finish(StructType *Ty) { | ||||||||||||
704 | assert(!IsFinished && "already finished!")(static_cast <bool> (!IsFinished && "already finished!" ) ? void (0) : __assert_fail ("!IsFinished && \"already finished!\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 704, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
705 | |||||||||||||
706 | // Prepare the optimal-layout field array. | ||||||||||||
707 | // The Id in the layout field is a pointer to our Field for it. | ||||||||||||
708 | SmallVector<OptimizedStructLayoutField, 8> LayoutFields; | ||||||||||||
709 | LayoutFields.reserve(Fields.size()); | ||||||||||||
710 | for (auto &Field : Fields) { | ||||||||||||
711 | LayoutFields.emplace_back(&Field, Field.Size, Field.Alignment, | ||||||||||||
712 | Field.Offset); | ||||||||||||
713 | } | ||||||||||||
714 | |||||||||||||
715 | // Perform layout. | ||||||||||||
716 | auto SizeAndAlign = performOptimizedStructLayout(LayoutFields); | ||||||||||||
717 | StructSize = SizeAndAlign.first; | ||||||||||||
718 | StructAlign = SizeAndAlign.second; | ||||||||||||
719 | |||||||||||||
720 | auto getField = [](const OptimizedStructLayoutField &LayoutField) -> Field & { | ||||||||||||
721 | return *static_cast<Field *>(const_cast<void*>(LayoutField.Id)); | ||||||||||||
722 | }; | ||||||||||||
723 | |||||||||||||
724 | // We need to produce a packed struct type if there's a field whose | ||||||||||||
725 | // assigned offset isn't a multiple of its natural type alignment. | ||||||||||||
726 | bool Packed = [&] { | ||||||||||||
727 | for (auto &LayoutField : LayoutFields) { | ||||||||||||
728 | auto &F = getField(LayoutField); | ||||||||||||
729 | if (!isAligned(F.TyAlignment, LayoutField.Offset)) | ||||||||||||
730 | return true; | ||||||||||||
731 | } | ||||||||||||
732 | return false; | ||||||||||||
733 | }(); | ||||||||||||
734 | |||||||||||||
735 | // Build the struct body. | ||||||||||||
736 | SmallVector<Type*, 16> FieldTypes; | ||||||||||||
737 | FieldTypes.reserve(LayoutFields.size() * 3 / 2); | ||||||||||||
738 | uint64_t LastOffset = 0; | ||||||||||||
739 | for (auto &LayoutField : LayoutFields) { | ||||||||||||
740 | auto &F = getField(LayoutField); | ||||||||||||
741 | |||||||||||||
742 | auto Offset = LayoutField.Offset; | ||||||||||||
743 | |||||||||||||
744 | // Add a padding field if there's a padding gap and we're either | ||||||||||||
745 | // building a packed struct or the padding gap is more than we'd | ||||||||||||
746 | // get from aligning to the field type's natural alignment. | ||||||||||||
747 | assert(Offset >= LastOffset)(static_cast <bool> (Offset >= LastOffset) ? void (0 ) : __assert_fail ("Offset >= LastOffset", "llvm/lib/Transforms/Coroutines/CoroFrame.cpp" , 747, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
748 | if (Offset != LastOffset) { | ||||||||||||
749 | if (Packed || alignTo(LastOffset, F.TyAlignment) != Offset) | ||||||||||||
750 | FieldTypes.push_back(ArrayType::get(Type::getInt8Ty(Context), | ||||||||||||
751 | Offset - LastOffset)); | ||||||||||||
752 | } | ||||||||||||
753 | |||||||||||||
754 | F.Offset = Offset; | ||||||||||||
755 | F.LayoutFieldIndex = FieldTypes.size(); | ||||||||||||
756 | |||||||||||||
757 | FieldTypes.push_back(F.Ty); | ||||||||||||
758 | LastOffset = Offset + F.Size; | ||||||||||||
759 | } | ||||||||||||
760 | |||||||||||||
761 | Ty->setBody(FieldTypes, Packed); | ||||||||||||
762 | |||||||||||||
763 | #ifndef NDEBUG | ||||||||||||
764 | // Check that the IR layout matches the offsets we expect. | ||||||||||||
765 | auto Layout = DL.getStructLayout(Ty); | ||||||||||||
766 | for (auto &F : Fields) { | ||||||||||||
767 | assert(Ty->getElementType(F.LayoutFieldIndex) == F.Ty)(static_cast <bool> (Ty->getElementType(F.LayoutFieldIndex ) == F.Ty) ? void (0) : __assert_fail ("Ty->getElementType(F.LayoutFieldIndex) == F.Ty" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 767, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
768 | assert(Layout->getElementOffset(F.LayoutFieldIndex) == F.Offset)(static_cast <bool> (Layout->getElementOffset(F.LayoutFieldIndex ) == F.Offset) ? void (0) : __assert_fail ("Layout->getElementOffset(F.LayoutFieldIndex) == F.Offset" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 768, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
769 | } | ||||||||||||
770 | #endif | ||||||||||||
771 | |||||||||||||
772 | IsFinished = true; | ||||||||||||
773 | } | ||||||||||||
774 | |||||||||||||
775 | static void cacheDIVar(FrameDataInfo &FrameData, | ||||||||||||
776 | DenseMap<Value *, DILocalVariable *> &DIVarCache) { | ||||||||||||
777 | for (auto *V : FrameData.getAllDefs()) { | ||||||||||||
778 | if (DIVarCache.find(V) != DIVarCache.end()) | ||||||||||||
779 | continue; | ||||||||||||
780 | |||||||||||||
781 | auto DDIs = FindDbgDeclareUses(V); | ||||||||||||
782 | auto *I = llvm::find_if(DDIs, [](DbgDeclareInst *DDI) { | ||||||||||||
783 | return DDI->getExpression()->getNumElements() == 0; | ||||||||||||
784 | }); | ||||||||||||
785 | if (I != DDIs.end()) | ||||||||||||
786 | DIVarCache.insert({V, (*I)->getVariable()}); | ||||||||||||
787 | } | ||||||||||||
788 | } | ||||||||||||
789 | |||||||||||||
790 | /// Create name for Type. It uses MDString to store new created string to | ||||||||||||
791 | /// avoid memory leak. | ||||||||||||
792 | static StringRef solveTypeName(Type *Ty) { | ||||||||||||
793 | if (Ty->isIntegerTy()) { | ||||||||||||
794 | // The longest name in common may be '__int_128', which has 9 bits. | ||||||||||||
795 | SmallString<16> Buffer; | ||||||||||||
796 | raw_svector_ostream OS(Buffer); | ||||||||||||
797 | OS << "__int_" << cast<IntegerType>(Ty)->getBitWidth(); | ||||||||||||
798 | auto *MDName = MDString::get(Ty->getContext(), OS.str()); | ||||||||||||
799 | return MDName->getString(); | ||||||||||||
800 | } | ||||||||||||
801 | |||||||||||||
802 | if (Ty->isFloatingPointTy()) { | ||||||||||||
803 | if (Ty->isFloatTy()) | ||||||||||||
804 | return "__float_"; | ||||||||||||
805 | if (Ty->isDoubleTy()) | ||||||||||||
806 | return "__double_"; | ||||||||||||
807 | return "__floating_type_"; | ||||||||||||
808 | } | ||||||||||||
809 | |||||||||||||
810 | if (Ty->isPointerTy()) { | ||||||||||||
811 | auto *PtrTy = cast<PointerType>(Ty); | ||||||||||||
812 | Type *PointeeTy = PtrTy->getPointerElementType(); | ||||||||||||
813 | auto Name = solveTypeName(PointeeTy); | ||||||||||||
814 | if (Name == "UnknownType") | ||||||||||||
815 | return "PointerType"; | ||||||||||||
816 | SmallString<16> Buffer; | ||||||||||||
817 | Twine(Name + "_Ptr").toStringRef(Buffer); | ||||||||||||
818 | auto *MDName = MDString::get(Ty->getContext(), Buffer.str()); | ||||||||||||
819 | return MDName->getString(); | ||||||||||||
820 | } | ||||||||||||
821 | |||||||||||||
822 | if (Ty->isStructTy()) { | ||||||||||||
823 | if (!cast<StructType>(Ty)->hasName()) | ||||||||||||
824 | return "__LiteralStructType_"; | ||||||||||||
825 | |||||||||||||
826 | auto Name = Ty->getStructName(); | ||||||||||||
827 | |||||||||||||
828 | SmallString<16> Buffer(Name); | ||||||||||||
829 | for_each(Buffer, [](auto &Iter) { | ||||||||||||
830 | if (Iter == '.' || Iter == ':') | ||||||||||||
831 | Iter = '_'; | ||||||||||||
832 | }); | ||||||||||||
833 | auto *MDName = MDString::get(Ty->getContext(), Buffer.str()); | ||||||||||||
834 | return MDName->getString(); | ||||||||||||
835 | } | ||||||||||||
836 | |||||||||||||
837 | return "UnknownType"; | ||||||||||||
838 | } | ||||||||||||
839 | |||||||||||||
840 | static DIType *solveDIType(DIBuilder &Builder, Type *Ty, | ||||||||||||
841 | const DataLayout &Layout, DIScope *Scope, | ||||||||||||
842 | unsigned LineNum, | ||||||||||||
843 | DenseMap<Type *, DIType *> &DITypeCache) { | ||||||||||||
844 | if (DIType *DT = DITypeCache.lookup(Ty)) | ||||||||||||
845 | return DT; | ||||||||||||
846 | |||||||||||||
847 | StringRef Name = solveTypeName(Ty); | ||||||||||||
848 | |||||||||||||
849 | DIType *RetType = nullptr; | ||||||||||||
850 | |||||||||||||
851 | if (Ty->isIntegerTy()) { | ||||||||||||
852 | auto BitWidth = cast<IntegerType>(Ty)->getBitWidth(); | ||||||||||||
853 | RetType = Builder.createBasicType(Name, BitWidth, dwarf::DW_ATE_signed, | ||||||||||||
854 | llvm::DINode::FlagArtificial); | ||||||||||||
855 | } else if (Ty->isFloatingPointTy()) { | ||||||||||||
856 | RetType = Builder.createBasicType(Name, Layout.getTypeSizeInBits(Ty), | ||||||||||||
857 | dwarf::DW_ATE_float, | ||||||||||||
858 | llvm::DINode::FlagArtificial); | ||||||||||||
859 | } else if (Ty->isPointerTy()) { | ||||||||||||
860 | // Construct BasicType instead of PointerType to avoid infinite | ||||||||||||
861 | // search problem. | ||||||||||||
862 | // For example, we would be in trouble if we traverse recursively: | ||||||||||||
863 | // | ||||||||||||
864 | // struct Node { | ||||||||||||
865 | // Node* ptr; | ||||||||||||
866 | // }; | ||||||||||||
867 | RetType = Builder.createBasicType(Name, Layout.getTypeSizeInBits(Ty), | ||||||||||||
868 | dwarf::DW_ATE_address, | ||||||||||||
869 | llvm::DINode::FlagArtificial); | ||||||||||||
870 | } else if (Ty->isStructTy()) { | ||||||||||||
871 | auto *DIStruct = Builder.createStructType( | ||||||||||||
872 | Scope, Name, Scope->getFile(), LineNum, Layout.getTypeSizeInBits(Ty), | ||||||||||||
873 | Layout.getPrefTypeAlignment(Ty), llvm::DINode::FlagArtificial, nullptr, | ||||||||||||
874 | llvm::DINodeArray()); | ||||||||||||
875 | |||||||||||||
876 | auto *StructTy = cast<StructType>(Ty); | ||||||||||||
877 | SmallVector<Metadata *, 16> Elements; | ||||||||||||
878 | for (unsigned I = 0; I < StructTy->getNumElements(); I++) { | ||||||||||||
879 | DIType *DITy = solveDIType(Builder, StructTy->getElementType(I), Layout, | ||||||||||||
880 | Scope, LineNum, DITypeCache); | ||||||||||||
881 | assert(DITy)(static_cast <bool> (DITy) ? void (0) : __assert_fail ( "DITy", "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 881, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
882 | Elements.push_back(Builder.createMemberType( | ||||||||||||
883 | Scope, DITy->getName(), Scope->getFile(), LineNum, | ||||||||||||
884 | DITy->getSizeInBits(), DITy->getAlignInBits(), | ||||||||||||
885 | Layout.getStructLayout(StructTy)->getElementOffsetInBits(I), | ||||||||||||
886 | llvm::DINode::FlagArtificial, DITy)); | ||||||||||||
887 | } | ||||||||||||
888 | |||||||||||||
889 | Builder.replaceArrays(DIStruct, Builder.getOrCreateArray(Elements)); | ||||||||||||
890 | |||||||||||||
891 | RetType = DIStruct; | ||||||||||||
892 | } else { | ||||||||||||
893 | LLVM_DEBUG(dbgs() << "Unresolved Type: " << *Ty << "\n";)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dbgs() << "Unresolved Type: " << *Ty << "\n";; } } while (false); | ||||||||||||
894 | SmallString<32> Buffer; | ||||||||||||
895 | raw_svector_ostream OS(Buffer); | ||||||||||||
896 | OS << Name.str() << "_" << Layout.getTypeSizeInBits(Ty); | ||||||||||||
897 | RetType = Builder.createBasicType(OS.str(), Layout.getTypeSizeInBits(Ty), | ||||||||||||
898 | dwarf::DW_ATE_address, | ||||||||||||
899 | llvm::DINode::FlagArtificial); | ||||||||||||
900 | } | ||||||||||||
901 | |||||||||||||
902 | DITypeCache.insert({Ty, RetType}); | ||||||||||||
903 | return RetType; | ||||||||||||
904 | } | ||||||||||||
905 | |||||||||||||
906 | /// Build artificial debug info for C++ coroutine frames to allow users to | ||||||||||||
907 | /// inspect the contents of the frame directly | ||||||||||||
908 | /// | ||||||||||||
909 | /// Create Debug information for coroutine frame with debug name "__coro_frame". | ||||||||||||
910 | /// The debug information for the fields of coroutine frame is constructed from | ||||||||||||
911 | /// the following way: | ||||||||||||
912 | /// 1. For all the value in the Frame, we search the use of dbg.declare to find | ||||||||||||
913 | /// the corresponding debug variables for the value. If we can find the | ||||||||||||
914 | /// debug variable, we can get full and accurate debug information. | ||||||||||||
915 | /// 2. If we can't get debug information in step 1 and 2, we could only try to | ||||||||||||
916 | /// build the DIType by Type. We did this in solveDIType. We only handle | ||||||||||||
917 | /// integer, float, double, integer type and struct type for now. | ||||||||||||
918 | static void buildFrameDebugInfo(Function &F, coro::Shape &Shape, | ||||||||||||
919 | FrameDataInfo &FrameData) { | ||||||||||||
920 | DISubprogram *DIS = F.getSubprogram(); | ||||||||||||
921 | // If there is no DISubprogram for F, it implies the Function are not compiled | ||||||||||||
922 | // with debug info. So we also don't need to generate debug info for the frame | ||||||||||||
923 | // neither. | ||||||||||||
924 | if (!DIS || !DIS->getUnit() || | ||||||||||||
925 | !dwarf::isCPlusPlus( | ||||||||||||
926 | (dwarf::SourceLanguage)DIS->getUnit()->getSourceLanguage())) | ||||||||||||
927 | return; | ||||||||||||
928 | |||||||||||||
929 | assert(Shape.ABI == coro::ABI::Switch &&(static_cast <bool> (Shape.ABI == coro::ABI::Switch && "We could only build debug infomation for C++ coroutine now.\n" ) ? void (0) : __assert_fail ("Shape.ABI == coro::ABI::Switch && \"We could only build debug infomation for C++ coroutine now.\\n\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 930, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
930 | "We could only build debug infomation for C++ coroutine now.\n")(static_cast <bool> (Shape.ABI == coro::ABI::Switch && "We could only build debug infomation for C++ coroutine now.\n" ) ? void (0) : __assert_fail ("Shape.ABI == coro::ABI::Switch && \"We could only build debug infomation for C++ coroutine now.\\n\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 930, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
931 | |||||||||||||
932 | DIBuilder DBuilder(*F.getParent(), /*AllowUnresolved*/ false); | ||||||||||||
933 | |||||||||||||
934 | AllocaInst *PromiseAlloca = Shape.getPromiseAlloca(); | ||||||||||||
935 | assert(PromiseAlloca &&(static_cast <bool> (PromiseAlloca && "Coroutine with switch ABI should own Promise alloca" ) ? void (0) : __assert_fail ("PromiseAlloca && \"Coroutine with switch ABI should own Promise alloca\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 936, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
936 | "Coroutine with switch ABI should own Promise alloca")(static_cast <bool> (PromiseAlloca && "Coroutine with switch ABI should own Promise alloca" ) ? void (0) : __assert_fail ("PromiseAlloca && \"Coroutine with switch ABI should own Promise alloca\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 936, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
937 | |||||||||||||
938 | TinyPtrVector<DbgDeclareInst *> DIs = FindDbgDeclareUses(PromiseAlloca); | ||||||||||||
939 | if (DIs.empty()) | ||||||||||||
940 | return; | ||||||||||||
941 | |||||||||||||
942 | DbgDeclareInst *PromiseDDI = DIs.front(); | ||||||||||||
943 | DILocalVariable *PromiseDIVariable = PromiseDDI->getVariable(); | ||||||||||||
944 | DILocalScope *PromiseDIScope = PromiseDIVariable->getScope(); | ||||||||||||
945 | DIFile *DFile = PromiseDIScope->getFile(); | ||||||||||||
946 | DILocation *DILoc = PromiseDDI->getDebugLoc().get(); | ||||||||||||
947 | unsigned LineNum = PromiseDIVariable->getLine(); | ||||||||||||
948 | |||||||||||||
949 | DICompositeType *FrameDITy = DBuilder.createStructType( | ||||||||||||
950 | DIS, "__coro_frame_ty", DFile, LineNum, Shape.FrameSize * 8, | ||||||||||||
951 | Shape.FrameAlign.value() * 8, llvm::DINode::FlagArtificial, nullptr, | ||||||||||||
952 | llvm::DINodeArray()); | ||||||||||||
953 | StructType *FrameTy = Shape.FrameTy; | ||||||||||||
954 | SmallVector<Metadata *, 16> Elements; | ||||||||||||
955 | DataLayout Layout = F.getParent()->getDataLayout(); | ||||||||||||
956 | |||||||||||||
957 | DenseMap<Value *, DILocalVariable *> DIVarCache; | ||||||||||||
958 | cacheDIVar(FrameData, DIVarCache); | ||||||||||||
959 | |||||||||||||
960 | unsigned ResumeIndex = coro::Shape::SwitchFieldIndex::Resume; | ||||||||||||
961 | unsigned DestroyIndex = coro::Shape::SwitchFieldIndex::Destroy; | ||||||||||||
962 | unsigned IndexIndex = Shape.SwitchLowering.IndexField; | ||||||||||||
963 | |||||||||||||
964 | DenseMap<unsigned, StringRef> NameCache; | ||||||||||||
965 | NameCache.insert({ResumeIndex, "__resume_fn"}); | ||||||||||||
966 | NameCache.insert({DestroyIndex, "__destroy_fn"}); | ||||||||||||
967 | NameCache.insert({IndexIndex, "__coro_index"}); | ||||||||||||
968 | |||||||||||||
969 | Type *ResumeFnTy = FrameTy->getElementType(ResumeIndex), | ||||||||||||
970 | *DestroyFnTy = FrameTy->getElementType(DestroyIndex), | ||||||||||||
971 | *IndexTy = FrameTy->getElementType(IndexIndex); | ||||||||||||
972 | |||||||||||||
973 | DenseMap<unsigned, DIType *> TyCache; | ||||||||||||
974 | TyCache.insert({ResumeIndex, | ||||||||||||
975 | DBuilder.createBasicType("__resume_fn", | ||||||||||||
976 | Layout.getTypeSizeInBits(ResumeFnTy), | ||||||||||||
977 | dwarf::DW_ATE_address)}); | ||||||||||||
978 | TyCache.insert( | ||||||||||||
979 | {DestroyIndex, DBuilder.createBasicType( | ||||||||||||
980 | "__destroy_fn", Layout.getTypeSizeInBits(DestroyFnTy), | ||||||||||||
981 | dwarf::DW_ATE_address)}); | ||||||||||||
982 | |||||||||||||
983 | /// FIXME: If we fill the field `SizeInBits` with the actual size of | ||||||||||||
984 | /// __coro_index in bits, then __coro_index wouldn't show in the debugger. | ||||||||||||
985 | TyCache.insert({IndexIndex, DBuilder.createBasicType( | ||||||||||||
986 | "__coro_index", | ||||||||||||
987 | (Layout.getTypeSizeInBits(IndexTy) < 8) | ||||||||||||
988 | ? 8 | ||||||||||||
989 | : Layout.getTypeSizeInBits(IndexTy), | ||||||||||||
990 | dwarf::DW_ATE_unsigned_char)}); | ||||||||||||
991 | |||||||||||||
992 | for (auto *V : FrameData.getAllDefs()) { | ||||||||||||
993 | if (DIVarCache.find(V) == DIVarCache.end()) | ||||||||||||
994 | continue; | ||||||||||||
995 | |||||||||||||
996 | auto Index = FrameData.getFieldIndex(V); | ||||||||||||
997 | |||||||||||||
998 | NameCache.insert({Index, DIVarCache[V]->getName()}); | ||||||||||||
999 | TyCache.insert({Index, DIVarCache[V]->getType()}); | ||||||||||||
1000 | } | ||||||||||||
1001 | |||||||||||||
1002 | // Cache from index to (Align, Offset Pair) | ||||||||||||
1003 | DenseMap<unsigned, std::pair<unsigned, unsigned>> OffsetCache; | ||||||||||||
1004 | // The Align and Offset of Resume function and Destroy function are fixed. | ||||||||||||
1005 | OffsetCache.insert({ResumeIndex, {8, 0}}); | ||||||||||||
1006 | OffsetCache.insert({DestroyIndex, {8, 8}}); | ||||||||||||
1007 | OffsetCache.insert( | ||||||||||||
1008 | {IndexIndex, | ||||||||||||
1009 | {Shape.SwitchLowering.IndexAlign, Shape.SwitchLowering.IndexOffset}}); | ||||||||||||
1010 | |||||||||||||
1011 | for (auto *V : FrameData.getAllDefs()) { | ||||||||||||
1012 | auto Index = FrameData.getFieldIndex(V); | ||||||||||||
1013 | |||||||||||||
1014 | OffsetCache.insert( | ||||||||||||
1015 | {Index, {FrameData.getAlign(V), FrameData.getOffset(V)}}); | ||||||||||||
1016 | } | ||||||||||||
1017 | |||||||||||||
1018 | DenseMap<Type *, DIType *> DITypeCache; | ||||||||||||
1019 | // This counter is used to avoid same type names. e.g., there would be | ||||||||||||
1020 | // many i32 and i64 types in one coroutine. And we would use i32_0 and | ||||||||||||
1021 | // i32_1 to avoid the same type. Since it makes no sense the name of the | ||||||||||||
1022 | // fields confilicts with each other. | ||||||||||||
1023 | unsigned UnknownTypeNum = 0; | ||||||||||||
1024 | for (unsigned Index = 0; Index < FrameTy->getNumElements(); Index++) { | ||||||||||||
1025 | if (OffsetCache.find(Index) == OffsetCache.end()) | ||||||||||||
1026 | continue; | ||||||||||||
1027 | |||||||||||||
1028 | std::string Name; | ||||||||||||
1029 | uint64_t SizeInBits; | ||||||||||||
1030 | uint32_t AlignInBits; | ||||||||||||
1031 | uint64_t OffsetInBits; | ||||||||||||
1032 | DIType *DITy = nullptr; | ||||||||||||
1033 | |||||||||||||
1034 | Type *Ty = FrameTy->getElementType(Index); | ||||||||||||
1035 | assert(Ty->isSized() && "We can't handle type which is not sized.\n")(static_cast <bool> (Ty->isSized() && "We can't handle type which is not sized.\n" ) ? void (0) : __assert_fail ("Ty->isSized() && \"We can't handle type which is not sized.\\n\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 1035, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1036 | SizeInBits = Layout.getTypeSizeInBits(Ty).getFixedSize(); | ||||||||||||
1037 | AlignInBits = OffsetCache[Index].first * 8; | ||||||||||||
1038 | OffsetInBits = OffsetCache[Index].second * 8; | ||||||||||||
1039 | |||||||||||||
1040 | if (NameCache.find(Index) != NameCache.end()) { | ||||||||||||
1041 | Name = NameCache[Index].str(); | ||||||||||||
1042 | DITy = TyCache[Index]; | ||||||||||||
1043 | } else { | ||||||||||||
1044 | DITy = solveDIType(DBuilder, Ty, Layout, FrameDITy, LineNum, DITypeCache); | ||||||||||||
1045 | assert(DITy && "SolveDIType shouldn't return nullptr.\n")(static_cast <bool> (DITy && "SolveDIType shouldn't return nullptr.\n" ) ? void (0) : __assert_fail ("DITy && \"SolveDIType shouldn't return nullptr.\\n\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 1045, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1046 | Name = DITy->getName().str(); | ||||||||||||
1047 | Name += "_" + std::to_string(UnknownTypeNum); | ||||||||||||
1048 | UnknownTypeNum++; | ||||||||||||
1049 | } | ||||||||||||
1050 | |||||||||||||
1051 | Elements.push_back(DBuilder.createMemberType( | ||||||||||||
1052 | FrameDITy, Name, DFile, LineNum, SizeInBits, AlignInBits, OffsetInBits, | ||||||||||||
1053 | llvm::DINode::FlagArtificial, DITy)); | ||||||||||||
1054 | } | ||||||||||||
1055 | |||||||||||||
1056 | DBuilder.replaceArrays(FrameDITy, DBuilder.getOrCreateArray(Elements)); | ||||||||||||
1057 | |||||||||||||
1058 | auto *FrameDIVar = DBuilder.createAutoVariable(PromiseDIScope, "__coro_frame", | ||||||||||||
1059 | DFile, LineNum, FrameDITy, | ||||||||||||
1060 | true, DINode::FlagArtificial); | ||||||||||||
1061 | assert(FrameDIVar->isValidLocationForIntrinsic(PromiseDDI->getDebugLoc()))(static_cast <bool> (FrameDIVar->isValidLocationForIntrinsic (PromiseDDI->getDebugLoc())) ? void (0) : __assert_fail ("FrameDIVar->isValidLocationForIntrinsic(PromiseDDI->getDebugLoc())" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 1061, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1062 | |||||||||||||
1063 | // Subprogram would have ContainedNodes field which records the debug | ||||||||||||
1064 | // variables it contained. So we need to add __coro_frame to the | ||||||||||||
1065 | // ContainedNodes of it. | ||||||||||||
1066 | // | ||||||||||||
1067 | // If we don't add __coro_frame to the RetainedNodes, user may get | ||||||||||||
1068 | // `no symbol __coro_frame in context` rather than `__coro_frame` | ||||||||||||
1069 | // is optimized out, which is more precise. | ||||||||||||
1070 | if (auto *SubProgram = dyn_cast<DISubprogram>(PromiseDIScope)) { | ||||||||||||
1071 | auto RetainedNodes = SubProgram->getRetainedNodes(); | ||||||||||||
1072 | SmallVector<Metadata *, 32> RetainedNodesVec(RetainedNodes.begin(), | ||||||||||||
1073 | RetainedNodes.end()); | ||||||||||||
1074 | RetainedNodesVec.push_back(FrameDIVar); | ||||||||||||
1075 | SubProgram->replaceOperandWith( | ||||||||||||
1076 | 7, (MDTuple::get(F.getContext(), RetainedNodesVec))); | ||||||||||||
1077 | } | ||||||||||||
1078 | |||||||||||||
1079 | DBuilder.insertDeclare(Shape.FramePtr, FrameDIVar, | ||||||||||||
1080 | DBuilder.createExpression(), DILoc, | ||||||||||||
1081 | Shape.FramePtr->getNextNode()); | ||||||||||||
1082 | } | ||||||||||||
1083 | |||||||||||||
1084 | // Build a struct that will keep state for an active coroutine. | ||||||||||||
1085 | // struct f.frame { | ||||||||||||
1086 | // ResumeFnTy ResumeFnAddr; | ||||||||||||
1087 | // ResumeFnTy DestroyFnAddr; | ||||||||||||
1088 | // int ResumeIndex; | ||||||||||||
1089 | // ... promise (if present) ... | ||||||||||||
1090 | // ... spills ... | ||||||||||||
1091 | // }; | ||||||||||||
1092 | static StructType *buildFrameType(Function &F, coro::Shape &Shape, | ||||||||||||
1093 | FrameDataInfo &FrameData) { | ||||||||||||
1094 | LLVMContext &C = F.getContext(); | ||||||||||||
1095 | const DataLayout &DL = F.getParent()->getDataLayout(); | ||||||||||||
1096 | StructType *FrameTy = [&] { | ||||||||||||
1097 | SmallString<32> Name(F.getName()); | ||||||||||||
1098 | Name.append(".Frame"); | ||||||||||||
1099 | return StructType::create(C, Name); | ||||||||||||
1100 | }(); | ||||||||||||
1101 | |||||||||||||
1102 | // We will use this value to cap the alignment of spilled values. | ||||||||||||
1103 | Optional<Align> MaxFrameAlignment; | ||||||||||||
1104 | if (Shape.ABI == coro::ABI::Async) | ||||||||||||
1105 | MaxFrameAlignment = Shape.AsyncLowering.getContextAlignment(); | ||||||||||||
1106 | FrameTypeBuilder B(C, DL, MaxFrameAlignment); | ||||||||||||
1107 | |||||||||||||
1108 | AllocaInst *PromiseAlloca = Shape.getPromiseAlloca(); | ||||||||||||
1109 | Optional<FieldIDType> SwitchIndexFieldId; | ||||||||||||
1110 | |||||||||||||
1111 | if (Shape.ABI == coro::ABI::Switch) { | ||||||||||||
1112 | auto *FramePtrTy = FrameTy->getPointerTo(); | ||||||||||||
1113 | auto *FnTy = FunctionType::get(Type::getVoidTy(C), FramePtrTy, | ||||||||||||
1114 | /*IsVarArg=*/false); | ||||||||||||
1115 | auto *FnPtrTy = FnTy->getPointerTo(); | ||||||||||||
1116 | |||||||||||||
1117 | // Add header fields for the resume and destroy functions. | ||||||||||||
1118 | // We can rely on these being perfectly packed. | ||||||||||||
1119 | (void)B.addField(FnPtrTy, None, /*header*/ true); | ||||||||||||
1120 | (void)B.addField(FnPtrTy, None, /*header*/ true); | ||||||||||||
1121 | |||||||||||||
1122 | // PromiseAlloca field needs to be explicitly added here because it's | ||||||||||||
1123 | // a header field with a fixed offset based on its alignment. Hence it | ||||||||||||
1124 | // needs special handling and cannot be added to FrameData.Allocas. | ||||||||||||
1125 | if (PromiseAlloca) | ||||||||||||
1126 | FrameData.setFieldIndex( | ||||||||||||
1127 | PromiseAlloca, B.addFieldForAlloca(PromiseAlloca, /*header*/ true)); | ||||||||||||
1128 | |||||||||||||
1129 | // Add a field to store the suspend index. This doesn't need to | ||||||||||||
1130 | // be in the header. | ||||||||||||
1131 | unsigned IndexBits = std::max(1U, Log2_64_Ceil(Shape.CoroSuspends.size())); | ||||||||||||
1132 | Type *IndexType = Type::getIntNTy(C, IndexBits); | ||||||||||||
1133 | |||||||||||||
1134 | SwitchIndexFieldId = B.addField(IndexType, None); | ||||||||||||
1135 | } else { | ||||||||||||
1136 | assert(PromiseAlloca == nullptr && "lowering doesn't support promises")(static_cast <bool> (PromiseAlloca == nullptr && "lowering doesn't support promises") ? void (0) : __assert_fail ("PromiseAlloca == nullptr && \"lowering doesn't support promises\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 1136, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1137 | } | ||||||||||||
1138 | |||||||||||||
1139 | // Because multiple allocas may own the same field slot, | ||||||||||||
1140 | // we add allocas to field here. | ||||||||||||
1141 | B.addFieldForAllocas(F, FrameData, Shape); | ||||||||||||
1142 | // Add PromiseAlloca to Allocas list so that | ||||||||||||
1143 | // 1. updateLayoutIndex could update its index after | ||||||||||||
1144 | // `performOptimizedStructLayout` | ||||||||||||
1145 | // 2. it is processed in insertSpills. | ||||||||||||
1146 | if (Shape.ABI == coro::ABI::Switch && PromiseAlloca) | ||||||||||||
1147 | // We assume that the promise alloca won't be modified before | ||||||||||||
1148 | // CoroBegin and no alias will be create before CoroBegin. | ||||||||||||
1149 | FrameData.Allocas.emplace_back( | ||||||||||||
1150 | PromiseAlloca, DenseMap<Instruction *, llvm::Optional<APInt>>{}, false); | ||||||||||||
1151 | // Create an entry for every spilled value. | ||||||||||||
1152 | for (auto &S : FrameData.Spills) { | ||||||||||||
1153 | Type *FieldType = S.first->getType(); | ||||||||||||
1154 | // For byval arguments, we need to store the pointed value in the frame, | ||||||||||||
1155 | // instead of the pointer itself. | ||||||||||||
1156 | if (const Argument *A = dyn_cast<Argument>(S.first)) | ||||||||||||
1157 | if (A->hasByValAttr()) | ||||||||||||
1158 | FieldType = A->getParamByValType(); | ||||||||||||
1159 | FieldIDType Id = | ||||||||||||
1160 | B.addField(FieldType, None, false /*header*/, true /*IsSpillOfValue*/); | ||||||||||||
1161 | FrameData.setFieldIndex(S.first, Id); | ||||||||||||
1162 | } | ||||||||||||
1163 | |||||||||||||
1164 | B.finish(FrameTy); | ||||||||||||
1165 | FrameData.updateLayoutIndex(B); | ||||||||||||
1166 | Shape.FrameAlign = B.getStructAlign(); | ||||||||||||
1167 | Shape.FrameSize = B.getStructSize(); | ||||||||||||
1168 | |||||||||||||
1169 | switch (Shape.ABI) { | ||||||||||||
1170 | case coro::ABI::Switch: { | ||||||||||||
1171 | // In the switch ABI, remember the switch-index field. | ||||||||||||
1172 | auto IndexField = B.getLayoutField(*SwitchIndexFieldId); | ||||||||||||
1173 | Shape.SwitchLowering.IndexField = IndexField.LayoutFieldIndex; | ||||||||||||
1174 | Shape.SwitchLowering.IndexAlign = IndexField.Alignment.value(); | ||||||||||||
1175 | Shape.SwitchLowering.IndexOffset = IndexField.Offset; | ||||||||||||
1176 | |||||||||||||
1177 | // Also round the frame size up to a multiple of its alignment, as is | ||||||||||||
1178 | // generally expected in C/C++. | ||||||||||||
1179 | Shape.FrameSize = alignTo(Shape.FrameSize, Shape.FrameAlign); | ||||||||||||
1180 | break; | ||||||||||||
1181 | } | ||||||||||||
1182 | |||||||||||||
1183 | // In the retcon ABI, remember whether the frame is inline in the storage. | ||||||||||||
1184 | case coro::ABI::Retcon: | ||||||||||||
1185 | case coro::ABI::RetconOnce: { | ||||||||||||
1186 | auto Id = Shape.getRetconCoroId(); | ||||||||||||
1187 | Shape.RetconLowering.IsFrameInlineInStorage | ||||||||||||
1188 | = (B.getStructSize() <= Id->getStorageSize() && | ||||||||||||
1189 | B.getStructAlign() <= Id->getStorageAlignment()); | ||||||||||||
1190 | break; | ||||||||||||
1191 | } | ||||||||||||
1192 | case coro::ABI::Async: { | ||||||||||||
1193 | Shape.AsyncLowering.FrameOffset = | ||||||||||||
1194 | alignTo(Shape.AsyncLowering.ContextHeaderSize, Shape.FrameAlign); | ||||||||||||
1195 | // Also make the final context size a multiple of the context alignment to | ||||||||||||
1196 | // make allocation easier for allocators. | ||||||||||||
1197 | Shape.AsyncLowering.ContextSize = | ||||||||||||
1198 | alignTo(Shape.AsyncLowering.FrameOffset + Shape.FrameSize, | ||||||||||||
1199 | Shape.AsyncLowering.getContextAlignment()); | ||||||||||||
1200 | if (Shape.AsyncLowering.getContextAlignment() < Shape.FrameAlign) { | ||||||||||||
1201 | report_fatal_error( | ||||||||||||
1202 | "The alignment requirment of frame variables cannot be higher than " | ||||||||||||
1203 | "the alignment of the async function context"); | ||||||||||||
1204 | } | ||||||||||||
1205 | break; | ||||||||||||
1206 | } | ||||||||||||
1207 | } | ||||||||||||
1208 | |||||||||||||
1209 | return FrameTy; | ||||||||||||
1210 | } | ||||||||||||
1211 | |||||||||||||
1212 | // We use a pointer use visitor to track how an alloca is being used. | ||||||||||||
1213 | // The goal is to be able to answer the following three questions: | ||||||||||||
1214 | // 1. Should this alloca be allocated on the frame instead. | ||||||||||||
1215 | // 2. Could the content of the alloca be modified prior to CoroBegn, which would | ||||||||||||
1216 | // require copying the data from alloca to the frame after CoroBegin. | ||||||||||||
1217 | // 3. Is there any alias created for this alloca prior to CoroBegin, but used | ||||||||||||
1218 | // after CoroBegin. In that case, we will need to recreate the alias after | ||||||||||||
1219 | // CoroBegin based off the frame. To answer question 1, we track two things: | ||||||||||||
1220 | // a. List of all BasicBlocks that use this alloca or any of the aliases of | ||||||||||||
1221 | // the alloca. In the end, we check if there exists any two basic blocks that | ||||||||||||
1222 | // cross suspension points. If so, this alloca must be put on the frame. b. | ||||||||||||
1223 | // Whether the alloca or any alias of the alloca is escaped at some point, | ||||||||||||
1224 | // either by storing the address somewhere, or the address is used in a | ||||||||||||
1225 | // function call that might capture. If it's ever escaped, this alloca must be | ||||||||||||
1226 | // put on the frame conservatively. | ||||||||||||
1227 | // To answer quetion 2, we track through the variable MayWriteBeforeCoroBegin. | ||||||||||||
1228 | // Whenever a potential write happens, either through a store instruction, a | ||||||||||||
1229 | // function call or any of the memory intrinsics, we check whether this | ||||||||||||
1230 | // instruction is prior to CoroBegin. To answer question 3, we track the offsets | ||||||||||||
1231 | // of all aliases created for the alloca prior to CoroBegin but used after | ||||||||||||
1232 | // CoroBegin. llvm::Optional is used to be able to represent the case when the | ||||||||||||
1233 | // offset is unknown (e.g. when you have a PHINode that takes in different | ||||||||||||
1234 | // offset values). We cannot handle unknown offsets and will assert. This is the | ||||||||||||
1235 | // potential issue left out. An ideal solution would likely require a | ||||||||||||
1236 | // significant redesign. | ||||||||||||
1237 | namespace { | ||||||||||||
1238 | struct AllocaUseVisitor : PtrUseVisitor<AllocaUseVisitor> { | ||||||||||||
1239 | using Base = PtrUseVisitor<AllocaUseVisitor>; | ||||||||||||
1240 | AllocaUseVisitor(const DataLayout &DL, const DominatorTree &DT, | ||||||||||||
1241 | const CoroBeginInst &CB, const SuspendCrossingInfo &Checker, | ||||||||||||
1242 | bool ShouldUseLifetimeStartInfo) | ||||||||||||
1243 | : PtrUseVisitor(DL), DT(DT), CoroBegin(CB), Checker(Checker), | ||||||||||||
1244 | ShouldUseLifetimeStartInfo(ShouldUseLifetimeStartInfo) {} | ||||||||||||
1245 | |||||||||||||
1246 | void visit(Instruction &I) { | ||||||||||||
1247 | Users.insert(&I); | ||||||||||||
1248 | Base::visit(I); | ||||||||||||
1249 | // If the pointer is escaped prior to CoroBegin, we have to assume it would | ||||||||||||
1250 | // be written into before CoroBegin as well. | ||||||||||||
1251 | if (PI.isEscaped() && !DT.dominates(&CoroBegin, PI.getEscapingInst())) { | ||||||||||||
1252 | MayWriteBeforeCoroBegin = true; | ||||||||||||
1253 | } | ||||||||||||
1254 | } | ||||||||||||
1255 | // We need to provide this overload as PtrUseVisitor uses a pointer based | ||||||||||||
1256 | // visiting function. | ||||||||||||
1257 | void visit(Instruction *I) { return visit(*I); } | ||||||||||||
1258 | |||||||||||||
1259 | void visitPHINode(PHINode &I) { | ||||||||||||
1260 | enqueueUsers(I); | ||||||||||||
1261 | handleAlias(I); | ||||||||||||
1262 | } | ||||||||||||
1263 | |||||||||||||
1264 | void visitSelectInst(SelectInst &I) { | ||||||||||||
1265 | enqueueUsers(I); | ||||||||||||
1266 | handleAlias(I); | ||||||||||||
1267 | } | ||||||||||||
1268 | |||||||||||||
1269 | void visitStoreInst(StoreInst &SI) { | ||||||||||||
1270 | // Regardless whether the alias of the alloca is the value operand or the | ||||||||||||
1271 | // pointer operand, we need to assume the alloca is been written. | ||||||||||||
1272 | handleMayWrite(SI); | ||||||||||||
1273 | |||||||||||||
1274 | if (SI.getValueOperand() != U->get()) | ||||||||||||
1275 | return; | ||||||||||||
1276 | |||||||||||||
1277 | // We are storing the pointer into a memory location, potentially escaping. | ||||||||||||
1278 | // As an optimization, we try to detect simple cases where it doesn't | ||||||||||||
1279 | // actually escape, for example: | ||||||||||||
1280 | // %ptr = alloca .. | ||||||||||||
1281 | // %addr = alloca .. | ||||||||||||
1282 | // store %ptr, %addr | ||||||||||||
1283 | // %x = load %addr | ||||||||||||
1284 | // .. | ||||||||||||
1285 | // If %addr is only used by loading from it, we could simply treat %x as | ||||||||||||
1286 | // another alias of %ptr, and not considering %ptr being escaped. | ||||||||||||
1287 | auto IsSimpleStoreThenLoad = [&]() { | ||||||||||||
1288 | auto *AI = dyn_cast<AllocaInst>(SI.getPointerOperand()); | ||||||||||||
1289 | // If the memory location we are storing to is not an alloca, it | ||||||||||||
1290 | // could be an alias of some other memory locations, which is difficult | ||||||||||||
1291 | // to analyze. | ||||||||||||
1292 | if (!AI) | ||||||||||||
1293 | return false; | ||||||||||||
1294 | // StoreAliases contains aliases of the memory location stored into. | ||||||||||||
1295 | SmallVector<Instruction *, 4> StoreAliases = {AI}; | ||||||||||||
1296 | while (!StoreAliases.empty()) { | ||||||||||||
1297 | Instruction *I = StoreAliases.pop_back_val(); | ||||||||||||
1298 | for (User *U : I->users()) { | ||||||||||||
1299 | // If we are loading from the memory location, we are creating an | ||||||||||||
1300 | // alias of the original pointer. | ||||||||||||
1301 | if (auto *LI = dyn_cast<LoadInst>(U)) { | ||||||||||||
1302 | enqueueUsers(*LI); | ||||||||||||
1303 | handleAlias(*LI); | ||||||||||||
1304 | continue; | ||||||||||||
1305 | } | ||||||||||||
1306 | // If we are overriding the memory location, the pointer certainly | ||||||||||||
1307 | // won't escape. | ||||||||||||
1308 | if (auto *S = dyn_cast<StoreInst>(U)) | ||||||||||||
1309 | if (S->getPointerOperand() == I) | ||||||||||||
1310 | continue; | ||||||||||||
1311 | if (auto *II = dyn_cast<IntrinsicInst>(U)) | ||||||||||||
1312 | if (II->isLifetimeStartOrEnd()) | ||||||||||||
1313 | continue; | ||||||||||||
1314 | // BitCastInst creats aliases of the memory location being stored | ||||||||||||
1315 | // into. | ||||||||||||
1316 | if (auto *BI = dyn_cast<BitCastInst>(U)) { | ||||||||||||
1317 | StoreAliases.push_back(BI); | ||||||||||||
1318 | continue; | ||||||||||||
1319 | } | ||||||||||||
1320 | return false; | ||||||||||||
1321 | } | ||||||||||||
1322 | } | ||||||||||||
1323 | |||||||||||||
1324 | return true; | ||||||||||||
1325 | }; | ||||||||||||
1326 | |||||||||||||
1327 | if (!IsSimpleStoreThenLoad()) | ||||||||||||
1328 | PI.setEscaped(&SI); | ||||||||||||
1329 | } | ||||||||||||
1330 | |||||||||||||
1331 | // All mem intrinsics modify the data. | ||||||||||||
1332 | void visitMemIntrinsic(MemIntrinsic &MI) { handleMayWrite(MI); } | ||||||||||||
1333 | |||||||||||||
1334 | void visitBitCastInst(BitCastInst &BC) { | ||||||||||||
1335 | Base::visitBitCastInst(BC); | ||||||||||||
1336 | handleAlias(BC); | ||||||||||||
1337 | } | ||||||||||||
1338 | |||||||||||||
1339 | void visitAddrSpaceCastInst(AddrSpaceCastInst &ASC) { | ||||||||||||
1340 | Base::visitAddrSpaceCastInst(ASC); | ||||||||||||
1341 | handleAlias(ASC); | ||||||||||||
1342 | } | ||||||||||||
1343 | |||||||||||||
1344 | void visitGetElementPtrInst(GetElementPtrInst &GEPI) { | ||||||||||||
1345 | // The base visitor will adjust Offset accordingly. | ||||||||||||
1346 | Base::visitGetElementPtrInst(GEPI); | ||||||||||||
1347 | handleAlias(GEPI); | ||||||||||||
1348 | } | ||||||||||||
1349 | |||||||||||||
1350 | void visitIntrinsicInst(IntrinsicInst &II) { | ||||||||||||
1351 | // When we found the lifetime markers refers to a | ||||||||||||
1352 | // subrange of the original alloca, ignore the lifetime | ||||||||||||
1353 | // markers to avoid misleading the analysis. | ||||||||||||
1354 | if (II.getIntrinsicID() != Intrinsic::lifetime_start || !IsOffsetKnown || | ||||||||||||
1355 | !Offset.isZero()) | ||||||||||||
1356 | return Base::visitIntrinsicInst(II); | ||||||||||||
1357 | LifetimeStarts.insert(&II); | ||||||||||||
1358 | } | ||||||||||||
1359 | |||||||||||||
1360 | void visitCallBase(CallBase &CB) { | ||||||||||||
1361 | for (unsigned Op = 0, OpCount = CB.arg_size(); Op < OpCount; ++Op) | ||||||||||||
1362 | if (U->get() == CB.getArgOperand(Op) && !CB.doesNotCapture(Op)) | ||||||||||||
1363 | PI.setEscaped(&CB); | ||||||||||||
1364 | handleMayWrite(CB); | ||||||||||||
1365 | } | ||||||||||||
1366 | |||||||||||||
1367 | bool getShouldLiveOnFrame() const { | ||||||||||||
1368 | if (!ShouldLiveOnFrame) | ||||||||||||
1369 | ShouldLiveOnFrame = computeShouldLiveOnFrame(); | ||||||||||||
1370 | return ShouldLiveOnFrame.getValue(); | ||||||||||||
1371 | } | ||||||||||||
1372 | |||||||||||||
1373 | bool getMayWriteBeforeCoroBegin() const { return MayWriteBeforeCoroBegin; } | ||||||||||||
1374 | |||||||||||||
1375 | DenseMap<Instruction *, llvm::Optional<APInt>> getAliasesCopy() const { | ||||||||||||
1376 | assert(getShouldLiveOnFrame() && "This method should only be called if the "(static_cast <bool> (getShouldLiveOnFrame() && "This method should only be called if the " "alloca needs to live on the frame.") ? void (0) : __assert_fail ("getShouldLiveOnFrame() && \"This method should only be called if the \" \"alloca needs to live on the frame.\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 1377, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
1377 | "alloca needs to live on the frame.")(static_cast <bool> (getShouldLiveOnFrame() && "This method should only be called if the " "alloca needs to live on the frame.") ? void (0) : __assert_fail ("getShouldLiveOnFrame() && \"This method should only be called if the \" \"alloca needs to live on the frame.\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 1377, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1378 | for (const auto &P : AliasOffetMap) | ||||||||||||
1379 | if (!P.second) | ||||||||||||
1380 | report_fatal_error("Unable to handle an alias with unknown offset " | ||||||||||||
1381 | "created before CoroBegin."); | ||||||||||||
1382 | return AliasOffetMap; | ||||||||||||
1383 | } | ||||||||||||
1384 | |||||||||||||
1385 | private: | ||||||||||||
1386 | const DominatorTree &DT; | ||||||||||||
1387 | const CoroBeginInst &CoroBegin; | ||||||||||||
1388 | const SuspendCrossingInfo &Checker; | ||||||||||||
1389 | // All alias to the original AllocaInst, created before CoroBegin and used | ||||||||||||
1390 | // after CoroBegin. Each entry contains the instruction and the offset in the | ||||||||||||
1391 | // original Alloca. They need to be recreated after CoroBegin off the frame. | ||||||||||||
1392 | DenseMap<Instruction *, llvm::Optional<APInt>> AliasOffetMap{}; | ||||||||||||
1393 | SmallPtrSet<Instruction *, 4> Users{}; | ||||||||||||
1394 | SmallPtrSet<IntrinsicInst *, 2> LifetimeStarts{}; | ||||||||||||
1395 | bool MayWriteBeforeCoroBegin{false}; | ||||||||||||
1396 | bool ShouldUseLifetimeStartInfo{true}; | ||||||||||||
1397 | |||||||||||||
1398 | mutable llvm::Optional<bool> ShouldLiveOnFrame{}; | ||||||||||||
1399 | |||||||||||||
1400 | bool computeShouldLiveOnFrame() const { | ||||||||||||
1401 | // If lifetime information is available, we check it first since it's | ||||||||||||
1402 | // more precise. We look at every pair of lifetime.start intrinsic and | ||||||||||||
1403 | // every basic block that uses the pointer to see if they cross suspension | ||||||||||||
1404 | // points. The uses cover both direct uses as well as indirect uses. | ||||||||||||
1405 | if (ShouldUseLifetimeStartInfo && !LifetimeStarts.empty()) { | ||||||||||||
1406 | for (auto *I : Users) | ||||||||||||
1407 | for (auto *S : LifetimeStarts) | ||||||||||||
1408 | if (Checker.isDefinitionAcrossSuspend(*S, I)) | ||||||||||||
1409 | return true; | ||||||||||||
1410 | return false; | ||||||||||||
1411 | } | ||||||||||||
1412 | // FIXME: Ideally the isEscaped check should come at the beginning. | ||||||||||||
1413 | // However there are a few loose ends that need to be fixed first before | ||||||||||||
1414 | // we can do that. We need to make sure we are not over-conservative, so | ||||||||||||
1415 | // that the data accessed in-between await_suspend and symmetric transfer | ||||||||||||
1416 | // is always put on the stack, and also data accessed after coro.end is | ||||||||||||
1417 | // always put on the stack (esp the return object). To fix that, we need | ||||||||||||
1418 | // to: | ||||||||||||
1419 | // 1) Potentially treat sret as nocapture in calls | ||||||||||||
1420 | // 2) Special handle the return object and put it on the stack | ||||||||||||
1421 | // 3) Utilize lifetime.end intrinsic | ||||||||||||
1422 | if (PI.isEscaped()) | ||||||||||||
1423 | return true; | ||||||||||||
1424 | |||||||||||||
1425 | for (auto *U1 : Users) | ||||||||||||
1426 | for (auto *U2 : Users) | ||||||||||||
1427 | if (Checker.isDefinitionAcrossSuspend(*U1, U2)) | ||||||||||||
1428 | return true; | ||||||||||||
1429 | |||||||||||||
1430 | return false; | ||||||||||||
1431 | } | ||||||||||||
1432 | |||||||||||||
1433 | void handleMayWrite(const Instruction &I) { | ||||||||||||
1434 | if (!DT.dominates(&CoroBegin, &I)) | ||||||||||||
1435 | MayWriteBeforeCoroBegin = true; | ||||||||||||
1436 | } | ||||||||||||
1437 | |||||||||||||
1438 | bool usedAfterCoroBegin(Instruction &I) { | ||||||||||||
1439 | for (auto &U : I.uses()) | ||||||||||||
1440 | if (DT.dominates(&CoroBegin, U)) | ||||||||||||
1441 | return true; | ||||||||||||
1442 | return false; | ||||||||||||
1443 | } | ||||||||||||
1444 | |||||||||||||
1445 | void handleAlias(Instruction &I) { | ||||||||||||
1446 | // We track all aliases created prior to CoroBegin but used after. | ||||||||||||
1447 | // These aliases may need to be recreated after CoroBegin if the alloca | ||||||||||||
1448 | // need to live on the frame. | ||||||||||||
1449 | if (DT.dominates(&CoroBegin, &I) || !usedAfterCoroBegin(I)) | ||||||||||||
1450 | return; | ||||||||||||
1451 | |||||||||||||
1452 | if (!IsOffsetKnown) { | ||||||||||||
1453 | AliasOffetMap[&I].reset(); | ||||||||||||
1454 | } else { | ||||||||||||
1455 | auto Itr = AliasOffetMap.find(&I); | ||||||||||||
1456 | if (Itr == AliasOffetMap.end()) { | ||||||||||||
1457 | AliasOffetMap[&I] = Offset; | ||||||||||||
1458 | } else if (Itr->second.hasValue() && Itr->second.getValue() != Offset) { | ||||||||||||
1459 | // If we have seen two different possible values for this alias, we set | ||||||||||||
1460 | // it to empty. | ||||||||||||
1461 | AliasOffetMap[&I].reset(); | ||||||||||||
1462 | } | ||||||||||||
1463 | } | ||||||||||||
1464 | } | ||||||||||||
1465 | }; | ||||||||||||
1466 | } // namespace | ||||||||||||
1467 | |||||||||||||
1468 | // We need to make room to insert a spill after initial PHIs, but before | ||||||||||||
1469 | // catchswitch instruction. Placing it before violates the requirement that | ||||||||||||
1470 | // catchswitch, like all other EHPads must be the first nonPHI in a block. | ||||||||||||
1471 | // | ||||||||||||
1472 | // Split away catchswitch into a separate block and insert in its place: | ||||||||||||
1473 | // | ||||||||||||
1474 | // cleanuppad <InsertPt> cleanupret. | ||||||||||||
1475 | // | ||||||||||||
1476 | // cleanupret instruction will act as an insert point for the spill. | ||||||||||||
1477 | static Instruction *splitBeforeCatchSwitch(CatchSwitchInst *CatchSwitch) { | ||||||||||||
1478 | BasicBlock *CurrentBlock = CatchSwitch->getParent(); | ||||||||||||
1479 | BasicBlock *NewBlock = CurrentBlock->splitBasicBlock(CatchSwitch); | ||||||||||||
1480 | CurrentBlock->getTerminator()->eraseFromParent(); | ||||||||||||
1481 | |||||||||||||
1482 | auto *CleanupPad = | ||||||||||||
1483 | CleanupPadInst::Create(CatchSwitch->getParentPad(), {}, "", CurrentBlock); | ||||||||||||
1484 | auto *CleanupRet = | ||||||||||||
1485 | CleanupReturnInst::Create(CleanupPad, NewBlock, CurrentBlock); | ||||||||||||
1486 | return CleanupRet; | ||||||||||||
1487 | } | ||||||||||||
1488 | |||||||||||||
1489 | static void createFramePtr(coro::Shape &Shape) { | ||||||||||||
1490 | auto *CB = Shape.CoroBegin; | ||||||||||||
1491 | IRBuilder<> Builder(CB->getNextNode()); | ||||||||||||
1492 | StructType *FrameTy = Shape.FrameTy; | ||||||||||||
1493 | PointerType *FramePtrTy = FrameTy->getPointerTo(); | ||||||||||||
1494 | Shape.FramePtr = | ||||||||||||
1495 | cast<Instruction>(Builder.CreateBitCast(CB, FramePtrTy, "FramePtr")); | ||||||||||||
1496 | } | ||||||||||||
1497 | |||||||||||||
1498 | // Replace all alloca and SSA values that are accessed across suspend points | ||||||||||||
1499 | // with GetElementPointer from coroutine frame + loads and stores. Create an | ||||||||||||
1500 | // AllocaSpillBB that will become the new entry block for the resume parts of | ||||||||||||
1501 | // the coroutine: | ||||||||||||
1502 | // | ||||||||||||
1503 | // %hdl = coro.begin(...) | ||||||||||||
1504 | // whatever | ||||||||||||
1505 | // | ||||||||||||
1506 | // becomes: | ||||||||||||
1507 | // | ||||||||||||
1508 | // %hdl = coro.begin(...) | ||||||||||||
1509 | // %FramePtr = bitcast i8* hdl to %f.frame* | ||||||||||||
1510 | // br label %AllocaSpillBB | ||||||||||||
1511 | // | ||||||||||||
1512 | // AllocaSpillBB: | ||||||||||||
1513 | // ; geps corresponding to allocas that were moved to coroutine frame | ||||||||||||
1514 | // br label PostSpill | ||||||||||||
1515 | // | ||||||||||||
1516 | // PostSpill: | ||||||||||||
1517 | // whatever | ||||||||||||
1518 | // | ||||||||||||
1519 | // | ||||||||||||
1520 | static Instruction *insertSpills(const FrameDataInfo &FrameData, | ||||||||||||
1521 | coro::Shape &Shape) { | ||||||||||||
1522 | auto *CB = Shape.CoroBegin; | ||||||||||||
1523 | LLVMContext &C = CB->getContext(); | ||||||||||||
1524 | IRBuilder<> Builder(C); | ||||||||||||
1525 | StructType *FrameTy = Shape.FrameTy; | ||||||||||||
1526 | Instruction *FramePtr = Shape.FramePtr; | ||||||||||||
1527 | DominatorTree DT(*CB->getFunction()); | ||||||||||||
1528 | SmallDenseMap<llvm::Value *, llvm::AllocaInst *, 4> DbgPtrAllocaCache; | ||||||||||||
1529 | |||||||||||||
1530 | // Create a GEP with the given index into the coroutine frame for the original | ||||||||||||
1531 | // value Orig. Appends an extra 0 index for array-allocas, preserving the | ||||||||||||
1532 | // original type. | ||||||||||||
1533 | auto GetFramePointer = [&](Value *Orig) -> Value * { | ||||||||||||
1534 | FieldIDType Index = FrameData.getFieldIndex(Orig); | ||||||||||||
1535 | SmallVector<Value *, 3> Indices = { | ||||||||||||
1536 | ConstantInt::get(Type::getInt32Ty(C), 0), | ||||||||||||
1537 | ConstantInt::get(Type::getInt32Ty(C), Index), | ||||||||||||
1538 | }; | ||||||||||||
1539 | |||||||||||||
1540 | if (auto *AI = dyn_cast<AllocaInst>(Orig)) { | ||||||||||||
1541 | if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize())) { | ||||||||||||
1542 | auto Count = CI->getValue().getZExtValue(); | ||||||||||||
1543 | if (Count > 1) { | ||||||||||||
1544 | Indices.push_back(ConstantInt::get(Type::getInt32Ty(C), 0)); | ||||||||||||
1545 | } | ||||||||||||
1546 | } else { | ||||||||||||
1547 | report_fatal_error("Coroutines cannot handle non static allocas yet"); | ||||||||||||
1548 | } | ||||||||||||
1549 | } | ||||||||||||
1550 | |||||||||||||
1551 | auto GEP = cast<GetElementPtrInst>( | ||||||||||||
1552 | Builder.CreateInBoundsGEP(FrameTy, FramePtr, Indices)); | ||||||||||||
1553 | if (isa<AllocaInst>(Orig)) { | ||||||||||||
1554 | // If the type of GEP is not equal to the type of AllocaInst, it implies | ||||||||||||
1555 | // that the AllocaInst may be reused in the Frame slot of other | ||||||||||||
1556 | // AllocaInst. So We cast GEP to the AllocaInst here to re-use | ||||||||||||
1557 | // the Frame storage. | ||||||||||||
1558 | // | ||||||||||||
1559 | // Note: If we change the strategy dealing with alignment, we need to refine | ||||||||||||
1560 | // this casting. | ||||||||||||
1561 | if (GEP->getResultElementType() != Orig->getType()) | ||||||||||||
1562 | return Builder.CreateBitCast(GEP, Orig->getType(), | ||||||||||||
1563 | Orig->getName() + Twine(".cast")); | ||||||||||||
1564 | } | ||||||||||||
1565 | return GEP; | ||||||||||||
1566 | }; | ||||||||||||
1567 | |||||||||||||
1568 | for (auto const &E : FrameData.Spills) { | ||||||||||||
1569 | Value *Def = E.first; | ||||||||||||
1570 | auto SpillAlignment = Align(FrameData.getAlign(Def)); | ||||||||||||
1571 | // Create a store instruction storing the value into the | ||||||||||||
1572 | // coroutine frame. | ||||||||||||
1573 | Instruction *InsertPt = nullptr; | ||||||||||||
1574 | Type *ByValTy = nullptr; | ||||||||||||
1575 | if (auto *Arg = dyn_cast<Argument>(Def)) { | ||||||||||||
1576 | // For arguments, we will place the store instruction right after | ||||||||||||
1577 | // the coroutine frame pointer instruction, i.e. bitcast of | ||||||||||||
1578 | // coro.begin from i8* to %f.frame*. | ||||||||||||
1579 | InsertPt = FramePtr->getNextNode(); | ||||||||||||
1580 | |||||||||||||
1581 | // If we're spilling an Argument, make sure we clear 'nocapture' | ||||||||||||
1582 | // from the coroutine function. | ||||||||||||
1583 | Arg->getParent()->removeParamAttr(Arg->getArgNo(), Attribute::NoCapture); | ||||||||||||
1584 | |||||||||||||
1585 | if (Arg->hasByValAttr()) | ||||||||||||
1586 | ByValTy = Arg->getParamByValType(); | ||||||||||||
1587 | } else if (auto *CSI = dyn_cast<AnyCoroSuspendInst>(Def)) { | ||||||||||||
1588 | // Don't spill immediately after a suspend; splitting assumes | ||||||||||||
1589 | // that the suspend will be followed by a branch. | ||||||||||||
1590 | InsertPt = CSI->getParent()->getSingleSuccessor()->getFirstNonPHI(); | ||||||||||||
1591 | } else { | ||||||||||||
1592 | auto *I = cast<Instruction>(Def); | ||||||||||||
1593 | if (!DT.dominates(CB, I)) { | ||||||||||||
1594 | // If it is not dominated by CoroBegin, then spill should be | ||||||||||||
1595 | // inserted immediately after CoroFrame is computed. | ||||||||||||
1596 | InsertPt = FramePtr->getNextNode(); | ||||||||||||
1597 | } else if (auto *II = dyn_cast<InvokeInst>(I)) { | ||||||||||||
1598 | // If we are spilling the result of the invoke instruction, split | ||||||||||||
1599 | // the normal edge and insert the spill in the new block. | ||||||||||||
1600 | auto *NewBB = SplitEdge(II->getParent(), II->getNormalDest()); | ||||||||||||
1601 | InsertPt = NewBB->getTerminator(); | ||||||||||||
1602 | } else if (isa<PHINode>(I)) { | ||||||||||||
1603 | // Skip the PHINodes and EH pads instructions. | ||||||||||||
1604 | BasicBlock *DefBlock = I->getParent(); | ||||||||||||
1605 | if (auto *CSI = dyn_cast<CatchSwitchInst>(DefBlock->getTerminator())) | ||||||||||||
1606 | InsertPt = splitBeforeCatchSwitch(CSI); | ||||||||||||
1607 | else | ||||||||||||
1608 | InsertPt = &*DefBlock->getFirstInsertionPt(); | ||||||||||||
1609 | } else { | ||||||||||||
1610 | assert(!I->isTerminator() && "unexpected terminator")(static_cast <bool> (!I->isTerminator() && "unexpected terminator" ) ? void (0) : __assert_fail ("!I->isTerminator() && \"unexpected terminator\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 1610, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1611 | // For all other values, the spill is placed immediately after | ||||||||||||
1612 | // the definition. | ||||||||||||
1613 | InsertPt = I->getNextNode(); | ||||||||||||
1614 | } | ||||||||||||
1615 | } | ||||||||||||
1616 | |||||||||||||
1617 | auto Index = FrameData.getFieldIndex(Def); | ||||||||||||
1618 | Builder.SetInsertPoint(InsertPt); | ||||||||||||
1619 | auto *G = Builder.CreateConstInBoundsGEP2_32( | ||||||||||||
1620 | FrameTy, FramePtr, 0, Index, Def->getName() + Twine(".spill.addr")); | ||||||||||||
1621 | if (ByValTy) { | ||||||||||||
1622 | // For byval arguments, we need to store the pointed value in the frame, | ||||||||||||
1623 | // instead of the pointer itself. | ||||||||||||
1624 | auto *Value = Builder.CreateLoad(ByValTy, Def); | ||||||||||||
1625 | Builder.CreateAlignedStore(Value, G, SpillAlignment); | ||||||||||||
1626 | } else { | ||||||||||||
1627 | Builder.CreateAlignedStore(Def, G, SpillAlignment); | ||||||||||||
1628 | } | ||||||||||||
1629 | |||||||||||||
1630 | BasicBlock *CurrentBlock = nullptr; | ||||||||||||
1631 | Value *CurrentReload = nullptr; | ||||||||||||
1632 | for (auto *U : E.second) { | ||||||||||||
1633 | // If we have not seen the use block, create a load instruction to reload | ||||||||||||
1634 | // the spilled value from the coroutine frame. Populates the Value pointer | ||||||||||||
1635 | // reference provided with the frame GEP. | ||||||||||||
1636 | if (CurrentBlock != U->getParent()) { | ||||||||||||
1637 | CurrentBlock = U->getParent(); | ||||||||||||
1638 | Builder.SetInsertPoint(&*CurrentBlock->getFirstInsertionPt()); | ||||||||||||
1639 | |||||||||||||
1640 | auto *GEP = GetFramePointer(E.first); | ||||||||||||
1641 | GEP->setName(E.first->getName() + Twine(".reload.addr")); | ||||||||||||
1642 | if (ByValTy) | ||||||||||||
1643 | CurrentReload = GEP; | ||||||||||||
1644 | else | ||||||||||||
1645 | CurrentReload = Builder.CreateAlignedLoad( | ||||||||||||
1646 | FrameTy->getElementType(FrameData.getFieldIndex(E.first)), GEP, | ||||||||||||
1647 | SpillAlignment, E.first->getName() + Twine(".reload")); | ||||||||||||
1648 | |||||||||||||
1649 | TinyPtrVector<DbgDeclareInst *> DIs = FindDbgDeclareUses(Def); | ||||||||||||
1650 | for (DbgDeclareInst *DDI : DIs) { | ||||||||||||
1651 | bool AllowUnresolved = false; | ||||||||||||
1652 | // This dbg.declare is preserved for all coro-split function | ||||||||||||
1653 | // fragments. It will be unreachable in the main function, and | ||||||||||||
1654 | // processed by coro::salvageDebugInfo() by CoroCloner. | ||||||||||||
1655 | DIBuilder(*CurrentBlock->getParent()->getParent(), AllowUnresolved) | ||||||||||||
1656 | .insertDeclare(CurrentReload, DDI->getVariable(), | ||||||||||||
1657 | DDI->getExpression(), DDI->getDebugLoc(), | ||||||||||||
1658 | &*Builder.GetInsertPoint()); | ||||||||||||
1659 | // This dbg.declare is for the main function entry point. It | ||||||||||||
1660 | // will be deleted in all coro-split functions. | ||||||||||||
1661 | coro::salvageDebugInfo(DbgPtrAllocaCache, DDI, Shape.OptimizeFrame); | ||||||||||||
1662 | } | ||||||||||||
1663 | } | ||||||||||||
1664 | |||||||||||||
1665 | // If we have a single edge PHINode, remove it and replace it with a | ||||||||||||
1666 | // reload from the coroutine frame. (We already took care of multi edge | ||||||||||||
1667 | // PHINodes by rewriting them in the rewritePHIs function). | ||||||||||||
1668 | if (auto *PN = dyn_cast<PHINode>(U)) { | ||||||||||||
1669 | assert(PN->getNumIncomingValues() == 1 &&(static_cast <bool> (PN->getNumIncomingValues() == 1 && "unexpected number of incoming " "values in the PHINode" ) ? void (0) : __assert_fail ("PN->getNumIncomingValues() == 1 && \"unexpected number of incoming \" \"values in the PHINode\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 1671, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
1670 | "unexpected number of incoming "(static_cast <bool> (PN->getNumIncomingValues() == 1 && "unexpected number of incoming " "values in the PHINode" ) ? void (0) : __assert_fail ("PN->getNumIncomingValues() == 1 && \"unexpected number of incoming \" \"values in the PHINode\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 1671, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
1671 | "values in the PHINode")(static_cast <bool> (PN->getNumIncomingValues() == 1 && "unexpected number of incoming " "values in the PHINode" ) ? void (0) : __assert_fail ("PN->getNumIncomingValues() == 1 && \"unexpected number of incoming \" \"values in the PHINode\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 1671, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1672 | PN->replaceAllUsesWith(CurrentReload); | ||||||||||||
1673 | PN->eraseFromParent(); | ||||||||||||
1674 | continue; | ||||||||||||
1675 | } | ||||||||||||
1676 | |||||||||||||
1677 | // Replace all uses of CurrentValue in the current instruction with | ||||||||||||
1678 | // reload. | ||||||||||||
1679 | U->replaceUsesOfWith(Def, CurrentReload); | ||||||||||||
1680 | } | ||||||||||||
1681 | } | ||||||||||||
1682 | |||||||||||||
1683 | BasicBlock *FramePtrBB = FramePtr->getParent(); | ||||||||||||
1684 | |||||||||||||
1685 | auto SpillBlock = | ||||||||||||
1686 | FramePtrBB->splitBasicBlock(FramePtr->getNextNode(), "AllocaSpillBB"); | ||||||||||||
1687 | SpillBlock->splitBasicBlock(&SpillBlock->front(), "PostSpill"); | ||||||||||||
1688 | Shape.AllocaSpillBlock = SpillBlock; | ||||||||||||
1689 | |||||||||||||
1690 | // retcon and retcon.once lowering assumes all uses have been sunk. | ||||||||||||
1691 | if (Shape.ABI == coro::ABI::Retcon || Shape.ABI == coro::ABI::RetconOnce || | ||||||||||||
1692 | Shape.ABI == coro::ABI::Async) { | ||||||||||||
1693 | // If we found any allocas, replace all of their remaining uses with Geps. | ||||||||||||
1694 | Builder.SetInsertPoint(&SpillBlock->front()); | ||||||||||||
1695 | for (const auto &P : FrameData.Allocas) { | ||||||||||||
1696 | AllocaInst *Alloca = P.Alloca; | ||||||||||||
1697 | auto *G = GetFramePointer(Alloca); | ||||||||||||
1698 | |||||||||||||
1699 | // We are not using ReplaceInstWithInst(P.first, cast<Instruction>(G)) | ||||||||||||
1700 | // here, as we are changing location of the instruction. | ||||||||||||
1701 | G->takeName(Alloca); | ||||||||||||
1702 | Alloca->replaceAllUsesWith(G); | ||||||||||||
1703 | Alloca->eraseFromParent(); | ||||||||||||
1704 | } | ||||||||||||
1705 | return FramePtr; | ||||||||||||
1706 | } | ||||||||||||
1707 | |||||||||||||
1708 | // If we found any alloca, replace all of their remaining uses with GEP | ||||||||||||
1709 | // instructions. To remain debugbility, we replace the uses of allocas for | ||||||||||||
1710 | // dbg.declares and dbg.values with the reload from the frame. | ||||||||||||
1711 | // Note: We cannot replace the alloca with GEP instructions indiscriminately, | ||||||||||||
1712 | // as some of the uses may not be dominated by CoroBegin. | ||||||||||||
1713 | Builder.SetInsertPoint(&Shape.AllocaSpillBlock->front()); | ||||||||||||
1714 | SmallVector<Instruction *, 4> UsersToUpdate; | ||||||||||||
1715 | for (const auto &A : FrameData.Allocas) { | ||||||||||||
1716 | AllocaInst *Alloca = A.Alloca; | ||||||||||||
1717 | UsersToUpdate.clear(); | ||||||||||||
1718 | for (User *U : Alloca->users()) { | ||||||||||||
1719 | auto *I = cast<Instruction>(U); | ||||||||||||
1720 | if (DT.dominates(CB, I)) | ||||||||||||
1721 | UsersToUpdate.push_back(I); | ||||||||||||
1722 | } | ||||||||||||
1723 | if (UsersToUpdate.empty()) | ||||||||||||
1724 | continue; | ||||||||||||
1725 | auto *G = GetFramePointer(Alloca); | ||||||||||||
1726 | G->setName(Alloca->getName() + Twine(".reload.addr")); | ||||||||||||
1727 | |||||||||||||
1728 | SmallVector<DbgVariableIntrinsic *, 4> DIs; | ||||||||||||
1729 | findDbgUsers(DIs, Alloca); | ||||||||||||
1730 | for (auto *DVI : DIs) | ||||||||||||
1731 | DVI->replaceUsesOfWith(Alloca, G); | ||||||||||||
1732 | |||||||||||||
1733 | for (Instruction *I : UsersToUpdate) | ||||||||||||
1734 | I->replaceUsesOfWith(Alloca, G); | ||||||||||||
1735 | } | ||||||||||||
1736 | Builder.SetInsertPoint(FramePtr->getNextNode()); | ||||||||||||
1737 | for (const auto &A : FrameData.Allocas) { | ||||||||||||
1738 | AllocaInst *Alloca = A.Alloca; | ||||||||||||
1739 | if (A.MayWriteBeforeCoroBegin) { | ||||||||||||
1740 | // isEscaped really means potentially modified before CoroBegin. | ||||||||||||
1741 | if (Alloca->isArrayAllocation()) | ||||||||||||
1742 | report_fatal_error( | ||||||||||||
1743 | "Coroutines cannot handle copying of array allocas yet"); | ||||||||||||
1744 | |||||||||||||
1745 | auto *G = GetFramePointer(Alloca); | ||||||||||||
1746 | auto *Value = Builder.CreateLoad(Alloca->getAllocatedType(), Alloca); | ||||||||||||
1747 | Builder.CreateStore(Value, G); | ||||||||||||
1748 | } | ||||||||||||
1749 | // For each alias to Alloca created before CoroBegin but used after | ||||||||||||
1750 | // CoroBegin, we recreate them after CoroBegin by appplying the offset | ||||||||||||
1751 | // to the pointer in the frame. | ||||||||||||
1752 | for (const auto &Alias : A.Aliases) { | ||||||||||||
1753 | auto *FramePtr = GetFramePointer(Alloca); | ||||||||||||
1754 | auto *FramePtrRaw = | ||||||||||||
1755 | Builder.CreateBitCast(FramePtr, Type::getInt8PtrTy(C)); | ||||||||||||
1756 | auto *AliasPtr = Builder.CreateGEP( | ||||||||||||
1757 | Type::getInt8Ty(C), FramePtrRaw, | ||||||||||||
1758 | ConstantInt::get(Type::getInt64Ty(C), Alias.second.getValue())); | ||||||||||||
1759 | auto *AliasPtrTyped = | ||||||||||||
1760 | Builder.CreateBitCast(AliasPtr, Alias.first->getType()); | ||||||||||||
1761 | Alias.first->replaceUsesWithIf( | ||||||||||||
1762 | AliasPtrTyped, [&](Use &U) { return DT.dominates(CB, U); }); | ||||||||||||
1763 | } | ||||||||||||
1764 | } | ||||||||||||
1765 | return FramePtr; | ||||||||||||
1766 | } | ||||||||||||
1767 | |||||||||||||
1768 | // Moves the values in the PHIs in SuccBB that correspong to PredBB into a new | ||||||||||||
1769 | // PHI in InsertedBB. | ||||||||||||
1770 | static void movePHIValuesToInsertedBlock(BasicBlock *SuccBB, | ||||||||||||
1771 | BasicBlock *InsertedBB, | ||||||||||||
1772 | BasicBlock *PredBB, | ||||||||||||
1773 | PHINode *UntilPHI = nullptr) { | ||||||||||||
1774 | auto *PN = cast<PHINode>(&SuccBB->front()); | ||||||||||||
1775 | do { | ||||||||||||
1776 | int Index = PN->getBasicBlockIndex(InsertedBB); | ||||||||||||
1777 | Value *V = PN->getIncomingValue(Index); | ||||||||||||
1778 | PHINode *InputV = PHINode::Create( | ||||||||||||
1779 | V->getType(), 1, V->getName() + Twine(".") + SuccBB->getName(), | ||||||||||||
1780 | &InsertedBB->front()); | ||||||||||||
1781 | InputV->addIncoming(V, PredBB); | ||||||||||||
1782 | PN->setIncomingValue(Index, InputV); | ||||||||||||
1783 | PN = dyn_cast<PHINode>(PN->getNextNode()); | ||||||||||||
1784 | } while (PN != UntilPHI); | ||||||||||||
1785 | } | ||||||||||||
1786 | |||||||||||||
1787 | // Rewrites the PHI Nodes in a cleanuppad. | ||||||||||||
1788 | static void rewritePHIsForCleanupPad(BasicBlock *CleanupPadBB, | ||||||||||||
1789 | CleanupPadInst *CleanupPad) { | ||||||||||||
1790 | // For every incoming edge to a CleanupPad we will create a new block holding | ||||||||||||
1791 | // all incoming values in single-value PHI nodes. We will then create another | ||||||||||||
1792 | // block to act as a dispather (as all unwind edges for related EH blocks | ||||||||||||
1793 | // must be the same). | ||||||||||||
1794 | // | ||||||||||||
1795 | // cleanuppad: | ||||||||||||
1796 | // %2 = phi i32[%0, %catchswitch], [%1, %catch.1] | ||||||||||||
1797 | // %3 = cleanuppad within none [] | ||||||||||||
1798 | // | ||||||||||||
1799 | // It will create: | ||||||||||||
1800 | // | ||||||||||||
1801 | // cleanuppad.corodispatch | ||||||||||||
1802 | // %2 = phi i8[0, %catchswitch], [1, %catch.1] | ||||||||||||
1803 | // %3 = cleanuppad within none [] | ||||||||||||
1804 | // switch i8 % 2, label %unreachable | ||||||||||||
1805 | // [i8 0, label %cleanuppad.from.catchswitch | ||||||||||||
1806 | // i8 1, label %cleanuppad.from.catch.1] | ||||||||||||
1807 | // cleanuppad.from.catchswitch: | ||||||||||||
1808 | // %4 = phi i32 [%0, %catchswitch] | ||||||||||||
1809 | // br %label cleanuppad | ||||||||||||
1810 | // cleanuppad.from.catch.1: | ||||||||||||
1811 | // %6 = phi i32 [%1, %catch.1] | ||||||||||||
1812 | // br %label cleanuppad | ||||||||||||
1813 | // cleanuppad: | ||||||||||||
1814 | // %8 = phi i32 [%4, %cleanuppad.from.catchswitch], | ||||||||||||
1815 | // [%6, %cleanuppad.from.catch.1] | ||||||||||||
1816 | |||||||||||||
1817 | // Unreachable BB, in case switching on an invalid value in the dispatcher. | ||||||||||||
1818 | auto *UnreachBB = BasicBlock::Create( | ||||||||||||
1819 | CleanupPadBB->getContext(), "unreachable", CleanupPadBB->getParent()); | ||||||||||||
1820 | IRBuilder<> Builder(UnreachBB); | ||||||||||||
1821 | Builder.CreateUnreachable(); | ||||||||||||
1822 | |||||||||||||
1823 | // Create a new cleanuppad which will be the dispatcher. | ||||||||||||
1824 | auto *NewCleanupPadBB = | ||||||||||||
1825 | BasicBlock::Create(CleanupPadBB->getContext(), | ||||||||||||
1826 | CleanupPadBB->getName() + Twine(".corodispatch"), | ||||||||||||
1827 | CleanupPadBB->getParent(), CleanupPadBB); | ||||||||||||
1828 | Builder.SetInsertPoint(NewCleanupPadBB); | ||||||||||||
1829 | auto *SwitchType = Builder.getInt8Ty(); | ||||||||||||
1830 | auto *SetDispatchValuePN = | ||||||||||||
1831 | Builder.CreatePHI(SwitchType, pred_size(CleanupPadBB)); | ||||||||||||
1832 | CleanupPad->removeFromParent(); | ||||||||||||
1833 | CleanupPad->insertAfter(SetDispatchValuePN); | ||||||||||||
1834 | auto *SwitchOnDispatch = Builder.CreateSwitch(SetDispatchValuePN, UnreachBB, | ||||||||||||
1835 | pred_size(CleanupPadBB)); | ||||||||||||
1836 | |||||||||||||
1837 | int SwitchIndex = 0; | ||||||||||||
1838 | SmallVector<BasicBlock *, 8> Preds(predecessors(CleanupPadBB)); | ||||||||||||
1839 | for (BasicBlock *Pred : Preds) { | ||||||||||||
1840 | // Create a new cleanuppad and move the PHI values to there. | ||||||||||||
1841 | auto *CaseBB = BasicBlock::Create(CleanupPadBB->getContext(), | ||||||||||||
1842 | CleanupPadBB->getName() + | ||||||||||||
1843 | Twine(".from.") + Pred->getName(), | ||||||||||||
1844 | CleanupPadBB->getParent(), CleanupPadBB); | ||||||||||||
1845 | updatePhiNodes(CleanupPadBB, Pred, CaseBB); | ||||||||||||
1846 | CaseBB->setName(CleanupPadBB->getName() + Twine(".from.") + | ||||||||||||
1847 | Pred->getName()); | ||||||||||||
1848 | Builder.SetInsertPoint(CaseBB); | ||||||||||||
1849 | Builder.CreateBr(CleanupPadBB); | ||||||||||||
1850 | movePHIValuesToInsertedBlock(CleanupPadBB, CaseBB, NewCleanupPadBB); | ||||||||||||
1851 | |||||||||||||
1852 | // Update this Pred to the new unwind point. | ||||||||||||
1853 | setUnwindEdgeTo(Pred->getTerminator(), NewCleanupPadBB); | ||||||||||||
1854 | |||||||||||||
1855 | // Setup the switch in the dispatcher. | ||||||||||||
1856 | auto *SwitchConstant = ConstantInt::get(SwitchType, SwitchIndex); | ||||||||||||
1857 | SetDispatchValuePN->addIncoming(SwitchConstant, Pred); | ||||||||||||
1858 | SwitchOnDispatch->addCase(SwitchConstant, CaseBB); | ||||||||||||
1859 | SwitchIndex++; | ||||||||||||
1860 | } | ||||||||||||
1861 | } | ||||||||||||
1862 | |||||||||||||
1863 | static void cleanupSinglePredPHIs(Function &F) { | ||||||||||||
1864 | SmallVector<PHINode *, 32> Worklist; | ||||||||||||
1865 | for (auto &BB : F) { | ||||||||||||
1866 | for (auto &Phi : BB.phis()) { | ||||||||||||
1867 | if (Phi.getNumIncomingValues() == 1) { | ||||||||||||
1868 | Worklist.push_back(&Phi); | ||||||||||||
1869 | } else | ||||||||||||
1870 | break; | ||||||||||||
1871 | } | ||||||||||||
1872 | } | ||||||||||||
1873 | while (!Worklist.empty()) { | ||||||||||||
1874 | auto *Phi = Worklist.pop_back_val(); | ||||||||||||
1875 | auto *OriginalValue = Phi->getIncomingValue(0); | ||||||||||||
1876 | Phi->replaceAllUsesWith(OriginalValue); | ||||||||||||
1877 | } | ||||||||||||
1878 | } | ||||||||||||
1879 | |||||||||||||
1880 | static void rewritePHIs(BasicBlock &BB) { | ||||||||||||
1881 | // For every incoming edge we will create a block holding all | ||||||||||||
1882 | // incoming values in a single PHI nodes. | ||||||||||||
1883 | // | ||||||||||||
1884 | // loop: | ||||||||||||
1885 | // %n.val = phi i32[%n, %entry], [%inc, %loop] | ||||||||||||
1886 | // | ||||||||||||
1887 | // It will create: | ||||||||||||
1888 | // | ||||||||||||
1889 | // loop.from.entry: | ||||||||||||
1890 | // %n.loop.pre = phi i32 [%n, %entry] | ||||||||||||
1891 | // br %label loop | ||||||||||||
1892 | // loop.from.loop: | ||||||||||||
1893 | // %inc.loop.pre = phi i32 [%inc, %loop] | ||||||||||||
1894 | // br %label loop | ||||||||||||
1895 | // | ||||||||||||
1896 | // After this rewrite, further analysis will ignore any phi nodes with more | ||||||||||||
1897 | // than one incoming edge. | ||||||||||||
1898 | |||||||||||||
1899 | // TODO: Simplify PHINodes in the basic block to remove duplicate | ||||||||||||
1900 | // predecessors. | ||||||||||||
1901 | |||||||||||||
1902 | // Special case for CleanupPad: all EH blocks must have the same unwind edge | ||||||||||||
1903 | // so we need to create an additional "dispatcher" block. | ||||||||||||
1904 | if (auto *CleanupPad = | ||||||||||||
1905 | dyn_cast_or_null<CleanupPadInst>(BB.getFirstNonPHI())) { | ||||||||||||
1906 | SmallVector<BasicBlock *, 8> Preds(predecessors(&BB)); | ||||||||||||
1907 | for (BasicBlock *Pred : Preds) { | ||||||||||||
1908 | if (CatchSwitchInst *CS = | ||||||||||||
1909 | dyn_cast<CatchSwitchInst>(Pred->getTerminator())) { | ||||||||||||
1910 | // CleanupPad with a CatchSwitch predecessor: therefore this is an | ||||||||||||
1911 | // unwind destination that needs to be handle specially. | ||||||||||||
1912 | assert(CS->getUnwindDest() == &BB)(static_cast <bool> (CS->getUnwindDest() == &BB) ? void (0) : __assert_fail ("CS->getUnwindDest() == &BB" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 1912, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
1913 | (void)CS; | ||||||||||||
1914 | rewritePHIsForCleanupPad(&BB, CleanupPad); | ||||||||||||
1915 | return; | ||||||||||||
1916 | } | ||||||||||||
1917 | } | ||||||||||||
1918 | } | ||||||||||||
1919 | |||||||||||||
1920 | LandingPadInst *LandingPad = nullptr; | ||||||||||||
1921 | PHINode *ReplPHI = nullptr; | ||||||||||||
1922 | if ((LandingPad = dyn_cast_or_null<LandingPadInst>(BB.getFirstNonPHI()))) { | ||||||||||||
1923 | // ehAwareSplitEdge will clone the LandingPad in all the edge blocks. | ||||||||||||
1924 | // We replace the original landing pad with a PHINode that will collect the | ||||||||||||
1925 | // results from all of them. | ||||||||||||
1926 | ReplPHI = PHINode::Create(LandingPad->getType(), 1, "", LandingPad); | ||||||||||||
1927 | ReplPHI->takeName(LandingPad); | ||||||||||||
1928 | LandingPad->replaceAllUsesWith(ReplPHI); | ||||||||||||
1929 | // We will erase the original landing pad at the end of this function after | ||||||||||||
1930 | // ehAwareSplitEdge cloned it in the transition blocks. | ||||||||||||
1931 | } | ||||||||||||
1932 | |||||||||||||
1933 | SmallVector<BasicBlock *, 8> Preds(predecessors(&BB)); | ||||||||||||
1934 | for (BasicBlock *Pred : Preds) { | ||||||||||||
1935 | auto *IncomingBB = ehAwareSplitEdge(Pred, &BB, LandingPad, ReplPHI); | ||||||||||||
1936 | IncomingBB->setName(BB.getName() + Twine(".from.") + Pred->getName()); | ||||||||||||
1937 | |||||||||||||
1938 | // Stop the moving of values at ReplPHI, as this is either null or the PHI | ||||||||||||
1939 | // that replaced the landing pad. | ||||||||||||
1940 | movePHIValuesToInsertedBlock(&BB, IncomingBB, Pred, ReplPHI); | ||||||||||||
1941 | } | ||||||||||||
1942 | |||||||||||||
1943 | if (LandingPad) { | ||||||||||||
1944 | // Calls to ehAwareSplitEdge function cloned the original lading pad. | ||||||||||||
1945 | // No longer need it. | ||||||||||||
1946 | LandingPad->eraseFromParent(); | ||||||||||||
1947 | } | ||||||||||||
1948 | } | ||||||||||||
1949 | |||||||||||||
1950 | static void rewritePHIs(Function &F) { | ||||||||||||
1951 | SmallVector<BasicBlock *, 8> WorkList; | ||||||||||||
1952 | |||||||||||||
1953 | for (BasicBlock &BB : F) | ||||||||||||
1954 | if (auto *PN = dyn_cast<PHINode>(&BB.front())) | ||||||||||||
1955 | if (PN->getNumIncomingValues() > 1) | ||||||||||||
1956 | WorkList.push_back(&BB); | ||||||||||||
1957 | |||||||||||||
1958 | for (BasicBlock *BB : WorkList) | ||||||||||||
1959 | rewritePHIs(*BB); | ||||||||||||
1960 | } | ||||||||||||
1961 | |||||||||||||
1962 | // Check for instructions that we can recreate on resume as opposed to spill | ||||||||||||
1963 | // the result into a coroutine frame. | ||||||||||||
1964 | static bool materializable(Instruction &V) { | ||||||||||||
1965 | return isa<CastInst>(&V) || isa<GetElementPtrInst>(&V) || | ||||||||||||
1966 | isa<BinaryOperator>(&V) || isa<CmpInst>(&V) || isa<SelectInst>(&V); | ||||||||||||
1967 | } | ||||||||||||
1968 | |||||||||||||
1969 | // Check for structural coroutine intrinsics that should not be spilled into | ||||||||||||
1970 | // the coroutine frame. | ||||||||||||
1971 | static bool isCoroutineStructureIntrinsic(Instruction &I) { | ||||||||||||
1972 | return isa<CoroIdInst>(&I) || isa<CoroSaveInst>(&I) || | ||||||||||||
1973 | isa<CoroSuspendInst>(&I); | ||||||||||||
1974 | } | ||||||||||||
1975 | |||||||||||||
1976 | // For every use of the value that is across suspend point, recreate that value | ||||||||||||
1977 | // after a suspend point. | ||||||||||||
1978 | static void rewriteMaterializableInstructions(IRBuilder<> &IRB, | ||||||||||||
1979 | const SpillInfo &Spills) { | ||||||||||||
1980 | for (const auto &E : Spills) { | ||||||||||||
1981 | Value *Def = E.first; | ||||||||||||
1982 | BasicBlock *CurrentBlock = nullptr; | ||||||||||||
1983 | Instruction *CurrentMaterialization = nullptr; | ||||||||||||
1984 | for (Instruction *U : E.second) { | ||||||||||||
1985 | // If we have not seen this block, materialize the value. | ||||||||||||
1986 | if (CurrentBlock != U->getParent()) { | ||||||||||||
1987 | |||||||||||||
1988 | bool IsInCoroSuspendBlock = isa<AnyCoroSuspendInst>(U); | ||||||||||||
1989 | CurrentBlock = U->getParent(); | ||||||||||||
1990 | auto *InsertBlock = IsInCoroSuspendBlock | ||||||||||||
1991 | ? CurrentBlock->getSinglePredecessor() | ||||||||||||
1992 | : CurrentBlock; | ||||||||||||
1993 | CurrentMaterialization = cast<Instruction>(Def)->clone(); | ||||||||||||
1994 | CurrentMaterialization->setName(Def->getName()); | ||||||||||||
1995 | CurrentMaterialization->insertBefore( | ||||||||||||
1996 | IsInCoroSuspendBlock ? InsertBlock->getTerminator() | ||||||||||||
1997 | : &*InsertBlock->getFirstInsertionPt()); | ||||||||||||
1998 | } | ||||||||||||
1999 | if (auto *PN = dyn_cast<PHINode>(U)) { | ||||||||||||
2000 | assert(PN->getNumIncomingValues() == 1 &&(static_cast <bool> (PN->getNumIncomingValues() == 1 && "unexpected number of incoming " "values in the PHINode" ) ? void (0) : __assert_fail ("PN->getNumIncomingValues() == 1 && \"unexpected number of incoming \" \"values in the PHINode\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 2002, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
2001 | "unexpected number of incoming "(static_cast <bool> (PN->getNumIncomingValues() == 1 && "unexpected number of incoming " "values in the PHINode" ) ? void (0) : __assert_fail ("PN->getNumIncomingValues() == 1 && \"unexpected number of incoming \" \"values in the PHINode\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 2002, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
2002 | "values in the PHINode")(static_cast <bool> (PN->getNumIncomingValues() == 1 && "unexpected number of incoming " "values in the PHINode" ) ? void (0) : __assert_fail ("PN->getNumIncomingValues() == 1 && \"unexpected number of incoming \" \"values in the PHINode\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 2002, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
2003 | PN->replaceAllUsesWith(CurrentMaterialization); | ||||||||||||
2004 | PN->eraseFromParent(); | ||||||||||||
2005 | continue; | ||||||||||||
2006 | } | ||||||||||||
2007 | // Replace all uses of Def in the current instruction with the | ||||||||||||
2008 | // CurrentMaterialization for the block. | ||||||||||||
2009 | U->replaceUsesOfWith(Def, CurrentMaterialization); | ||||||||||||
2010 | } | ||||||||||||
2011 | } | ||||||||||||
2012 | } | ||||||||||||
2013 | |||||||||||||
2014 | // Splits the block at a particular instruction unless it is the first | ||||||||||||
2015 | // instruction in the block with a single predecessor. | ||||||||||||
2016 | static BasicBlock *splitBlockIfNotFirst(Instruction *I, const Twine &Name) { | ||||||||||||
2017 | auto *BB = I->getParent(); | ||||||||||||
2018 | if (&BB->front() == I) { | ||||||||||||
2019 | if (BB->getSinglePredecessor()) { | ||||||||||||
2020 | BB->setName(Name); | ||||||||||||
2021 | return BB; | ||||||||||||
2022 | } | ||||||||||||
2023 | } | ||||||||||||
2024 | return BB->splitBasicBlock(I, Name); | ||||||||||||
2025 | } | ||||||||||||
2026 | |||||||||||||
2027 | // Split above and below a particular instruction so that it | ||||||||||||
2028 | // will be all alone by itself in a block. | ||||||||||||
2029 | static void splitAround(Instruction *I, const Twine &Name) { | ||||||||||||
2030 | splitBlockIfNotFirst(I, Name); | ||||||||||||
2031 | splitBlockIfNotFirst(I->getNextNode(), "After" + Name); | ||||||||||||
2032 | } | ||||||||||||
2033 | |||||||||||||
2034 | static bool isSuspendBlock(BasicBlock *BB) { | ||||||||||||
2035 | return isa<AnyCoroSuspendInst>(BB->front()); | ||||||||||||
2036 | } | ||||||||||||
2037 | |||||||||||||
2038 | typedef SmallPtrSet<BasicBlock*, 8> VisitedBlocksSet; | ||||||||||||
2039 | |||||||||||||
2040 | /// Does control flow starting at the given block ever reach a suspend | ||||||||||||
2041 | /// instruction before reaching a block in VisitedOrFreeBBs? | ||||||||||||
2042 | static bool isSuspendReachableFrom(BasicBlock *From, | ||||||||||||
2043 | VisitedBlocksSet &VisitedOrFreeBBs) { | ||||||||||||
2044 | // Eagerly try to add this block to the visited set. If it's already | ||||||||||||
2045 | // there, stop recursing; this path doesn't reach a suspend before | ||||||||||||
2046 | // either looping or reaching a freeing block. | ||||||||||||
2047 | if (!VisitedOrFreeBBs.insert(From).second) | ||||||||||||
2048 | return false; | ||||||||||||
2049 | |||||||||||||
2050 | // We assume that we'll already have split suspends into their own blocks. | ||||||||||||
2051 | if (isSuspendBlock(From)) | ||||||||||||
2052 | return true; | ||||||||||||
2053 | |||||||||||||
2054 | // Recurse on the successors. | ||||||||||||
2055 | for (auto Succ : successors(From)) { | ||||||||||||
2056 | if (isSuspendReachableFrom(Succ, VisitedOrFreeBBs)) | ||||||||||||
2057 | return true; | ||||||||||||
2058 | } | ||||||||||||
2059 | |||||||||||||
2060 | return false; | ||||||||||||
2061 | } | ||||||||||||
2062 | |||||||||||||
2063 | /// Is the given alloca "local", i.e. bounded in lifetime to not cross a | ||||||||||||
2064 | /// suspend point? | ||||||||||||
2065 | static bool isLocalAlloca(CoroAllocaAllocInst *AI) { | ||||||||||||
2066 | // Seed the visited set with all the basic blocks containing a free | ||||||||||||
2067 | // so that we won't pass them up. | ||||||||||||
2068 | VisitedBlocksSet VisitedOrFreeBBs; | ||||||||||||
2069 | for (auto User : AI->users()) { | ||||||||||||
2070 | if (auto FI = dyn_cast<CoroAllocaFreeInst>(User)) | ||||||||||||
2071 | VisitedOrFreeBBs.insert(FI->getParent()); | ||||||||||||
2072 | } | ||||||||||||
2073 | |||||||||||||
2074 | return !isSuspendReachableFrom(AI->getParent(), VisitedOrFreeBBs); | ||||||||||||
2075 | } | ||||||||||||
2076 | |||||||||||||
2077 | /// After we split the coroutine, will the given basic block be along | ||||||||||||
2078 | /// an obvious exit path for the resumption function? | ||||||||||||
2079 | static bool willLeaveFunctionImmediatelyAfter(BasicBlock *BB, | ||||||||||||
2080 | unsigned depth = 3) { | ||||||||||||
2081 | // If we've bottomed out our depth count, stop searching and assume | ||||||||||||
2082 | // that the path might loop back. | ||||||||||||
2083 | if (depth == 0) return false; | ||||||||||||
2084 | |||||||||||||
2085 | // If this is a suspend block, we're about to exit the resumption function. | ||||||||||||
2086 | if (isSuspendBlock(BB)) return true; | ||||||||||||
2087 | |||||||||||||
2088 | // Recurse into the successors. | ||||||||||||
2089 | for (auto Succ : successors(BB)) { | ||||||||||||
2090 | if (!willLeaveFunctionImmediatelyAfter(Succ, depth - 1)) | ||||||||||||
2091 | return false; | ||||||||||||
2092 | } | ||||||||||||
2093 | |||||||||||||
2094 | // If none of the successors leads back in a loop, we're on an exit/abort. | ||||||||||||
2095 | return true; | ||||||||||||
2096 | } | ||||||||||||
2097 | |||||||||||||
2098 | static bool localAllocaNeedsStackSave(CoroAllocaAllocInst *AI) { | ||||||||||||
2099 | // Look for a free that isn't sufficiently obviously followed by | ||||||||||||
2100 | // either a suspend or a termination, i.e. something that will leave | ||||||||||||
2101 | // the coro resumption frame. | ||||||||||||
2102 | for (auto U : AI->users()) { | ||||||||||||
2103 | auto FI = dyn_cast<CoroAllocaFreeInst>(U); | ||||||||||||
2104 | if (!FI) continue; | ||||||||||||
2105 | |||||||||||||
2106 | if (!willLeaveFunctionImmediatelyAfter(FI->getParent())) | ||||||||||||
2107 | return true; | ||||||||||||
2108 | } | ||||||||||||
2109 | |||||||||||||
2110 | // If we never found one, we don't need a stack save. | ||||||||||||
2111 | return false; | ||||||||||||
2112 | } | ||||||||||||
2113 | |||||||||||||
2114 | /// Turn each of the given local allocas into a normal (dynamic) alloca | ||||||||||||
2115 | /// instruction. | ||||||||||||
2116 | static void lowerLocalAllocas(ArrayRef<CoroAllocaAllocInst*> LocalAllocas, | ||||||||||||
2117 | SmallVectorImpl<Instruction*> &DeadInsts) { | ||||||||||||
2118 | for (auto AI : LocalAllocas) { | ||||||||||||
2119 | auto M = AI->getModule(); | ||||||||||||
2120 | IRBuilder<> Builder(AI); | ||||||||||||
2121 | |||||||||||||
2122 | // Save the stack depth. Try to avoid doing this if the stackrestore | ||||||||||||
2123 | // is going to immediately precede a return or something. | ||||||||||||
2124 | Value *StackSave = nullptr; | ||||||||||||
2125 | if (localAllocaNeedsStackSave(AI)) | ||||||||||||
2126 | StackSave = Builder.CreateCall( | ||||||||||||
2127 | Intrinsic::getDeclaration(M, Intrinsic::stacksave)); | ||||||||||||
2128 | |||||||||||||
2129 | // Allocate memory. | ||||||||||||
2130 | auto Alloca = Builder.CreateAlloca(Builder.getInt8Ty(), AI->getSize()); | ||||||||||||
2131 | Alloca->setAlignment(Align(AI->getAlignment())); | ||||||||||||
2132 | |||||||||||||
2133 | for (auto U : AI->users()) { | ||||||||||||
2134 | // Replace gets with the allocation. | ||||||||||||
2135 | if (isa<CoroAllocaGetInst>(U)) { | ||||||||||||
2136 | U->replaceAllUsesWith(Alloca); | ||||||||||||
2137 | |||||||||||||
2138 | // Replace frees with stackrestores. This is safe because | ||||||||||||
2139 | // alloca.alloc is required to obey a stack discipline, although we | ||||||||||||
2140 | // don't enforce that structurally. | ||||||||||||
2141 | } else { | ||||||||||||
2142 | auto FI = cast<CoroAllocaFreeInst>(U); | ||||||||||||
2143 | if (StackSave) { | ||||||||||||
2144 | Builder.SetInsertPoint(FI); | ||||||||||||
2145 | Builder.CreateCall( | ||||||||||||
2146 | Intrinsic::getDeclaration(M, Intrinsic::stackrestore), | ||||||||||||
2147 | StackSave); | ||||||||||||
2148 | } | ||||||||||||
2149 | } | ||||||||||||
2150 | DeadInsts.push_back(cast<Instruction>(U)); | ||||||||||||
2151 | } | ||||||||||||
2152 | |||||||||||||
2153 | DeadInsts.push_back(AI); | ||||||||||||
2154 | } | ||||||||||||
2155 | } | ||||||||||||
2156 | |||||||||||||
2157 | /// Turn the given coro.alloca.alloc call into a dynamic allocation. | ||||||||||||
2158 | /// This happens during the all-instructions iteration, so it must not | ||||||||||||
2159 | /// delete the call. | ||||||||||||
2160 | static Instruction *lowerNonLocalAlloca(CoroAllocaAllocInst *AI, | ||||||||||||
2161 | coro::Shape &Shape, | ||||||||||||
2162 | SmallVectorImpl<Instruction*> &DeadInsts) { | ||||||||||||
2163 | IRBuilder<> Builder(AI); | ||||||||||||
2164 | auto Alloc = Shape.emitAlloc(Builder, AI->getSize(), nullptr); | ||||||||||||
2165 | |||||||||||||
2166 | for (User *U : AI->users()) { | ||||||||||||
2167 | if (isa<CoroAllocaGetInst>(U)) { | ||||||||||||
2168 | U->replaceAllUsesWith(Alloc); | ||||||||||||
2169 | } else { | ||||||||||||
2170 | auto FI = cast<CoroAllocaFreeInst>(U); | ||||||||||||
2171 | Builder.SetInsertPoint(FI); | ||||||||||||
2172 | Shape.emitDealloc(Builder, Alloc, nullptr); | ||||||||||||
2173 | } | ||||||||||||
2174 | DeadInsts.push_back(cast<Instruction>(U)); | ||||||||||||
2175 | } | ||||||||||||
2176 | |||||||||||||
2177 | // Push this on last so that it gets deleted after all the others. | ||||||||||||
2178 | DeadInsts.push_back(AI); | ||||||||||||
2179 | |||||||||||||
2180 | // Return the new allocation value so that we can check for needed spills. | ||||||||||||
2181 | return cast<Instruction>(Alloc); | ||||||||||||
2182 | } | ||||||||||||
2183 | |||||||||||||
2184 | /// Get the current swifterror value. | ||||||||||||
2185 | static Value *emitGetSwiftErrorValue(IRBuilder<> &Builder, Type *ValueTy, | ||||||||||||
2186 | coro::Shape &Shape) { | ||||||||||||
2187 | // Make a fake function pointer as a sort of intrinsic. | ||||||||||||
2188 | auto FnTy = FunctionType::get(ValueTy, {}, false); | ||||||||||||
2189 | auto Fn = ConstantPointerNull::get(FnTy->getPointerTo()); | ||||||||||||
2190 | |||||||||||||
2191 | auto Call = Builder.CreateCall(FnTy, Fn, {}); | ||||||||||||
2192 | Shape.SwiftErrorOps.push_back(Call); | ||||||||||||
2193 | |||||||||||||
2194 | return Call; | ||||||||||||
2195 | } | ||||||||||||
2196 | |||||||||||||
2197 | /// Set the given value as the current swifterror value. | ||||||||||||
2198 | /// | ||||||||||||
2199 | /// Returns a slot that can be used as a swifterror slot. | ||||||||||||
2200 | static Value *emitSetSwiftErrorValue(IRBuilder<> &Builder, Value *V, | ||||||||||||
2201 | coro::Shape &Shape) { | ||||||||||||
2202 | // Make a fake function pointer as a sort of intrinsic. | ||||||||||||
2203 | auto FnTy = FunctionType::get(V->getType()->getPointerTo(), | ||||||||||||
2204 | {V->getType()}, false); | ||||||||||||
2205 | auto Fn = ConstantPointerNull::get(FnTy->getPointerTo()); | ||||||||||||
2206 | |||||||||||||
2207 | auto Call = Builder.CreateCall(FnTy, Fn, { V }); | ||||||||||||
2208 | Shape.SwiftErrorOps.push_back(Call); | ||||||||||||
2209 | |||||||||||||
2210 | return Call; | ||||||||||||
2211 | } | ||||||||||||
2212 | |||||||||||||
2213 | /// Set the swifterror value from the given alloca before a call, | ||||||||||||
2214 | /// then put in back in the alloca afterwards. | ||||||||||||
2215 | /// | ||||||||||||
2216 | /// Returns an address that will stand in for the swifterror slot | ||||||||||||
2217 | /// until splitting. | ||||||||||||
2218 | static Value *emitSetAndGetSwiftErrorValueAround(Instruction *Call, | ||||||||||||
2219 | AllocaInst *Alloca, | ||||||||||||
2220 | coro::Shape &Shape) { | ||||||||||||
2221 | auto ValueTy = Alloca->getAllocatedType(); | ||||||||||||
2222 | IRBuilder<> Builder(Call); | ||||||||||||
2223 | |||||||||||||
2224 | // Load the current value from the alloca and set it as the | ||||||||||||
2225 | // swifterror value. | ||||||||||||
2226 | auto ValueBeforeCall = Builder.CreateLoad(ValueTy, Alloca); | ||||||||||||
2227 | auto Addr = emitSetSwiftErrorValue(Builder, ValueBeforeCall, Shape); | ||||||||||||
2228 | |||||||||||||
2229 | // Move to after the call. Since swifterror only has a guaranteed | ||||||||||||
2230 | // value on normal exits, we can ignore implicit and explicit unwind | ||||||||||||
2231 | // edges. | ||||||||||||
2232 | if (isa<CallInst>(Call)) { | ||||||||||||
2233 | Builder.SetInsertPoint(Call->getNextNode()); | ||||||||||||
2234 | } else { | ||||||||||||
2235 | auto Invoke = cast<InvokeInst>(Call); | ||||||||||||
2236 | Builder.SetInsertPoint(Invoke->getNormalDest()->getFirstNonPHIOrDbg()); | ||||||||||||
2237 | } | ||||||||||||
2238 | |||||||||||||
2239 | // Get the current swifterror value and store it to the alloca. | ||||||||||||
2240 | auto ValueAfterCall = emitGetSwiftErrorValue(Builder, ValueTy, Shape); | ||||||||||||
2241 | Builder.CreateStore(ValueAfterCall, Alloca); | ||||||||||||
2242 | |||||||||||||
2243 | return Addr; | ||||||||||||
2244 | } | ||||||||||||
2245 | |||||||||||||
2246 | /// Eliminate a formerly-swifterror alloca by inserting the get/set | ||||||||||||
2247 | /// intrinsics and attempting to MemToReg the alloca away. | ||||||||||||
2248 | static void eliminateSwiftErrorAlloca(Function &F, AllocaInst *Alloca, | ||||||||||||
2249 | coro::Shape &Shape) { | ||||||||||||
2250 | for (Use &Use : llvm::make_early_inc_range(Alloca->uses())) { | ||||||||||||
2251 | // swifterror values can only be used in very specific ways. | ||||||||||||
2252 | // We take advantage of that here. | ||||||||||||
2253 | auto User = Use.getUser(); | ||||||||||||
2254 | if (isa<LoadInst>(User) || isa<StoreInst>(User)) | ||||||||||||
2255 | continue; | ||||||||||||
2256 | |||||||||||||
2257 | assert(isa<CallInst>(User) || isa<InvokeInst>(User))(static_cast <bool> (isa<CallInst>(User) || isa< InvokeInst>(User)) ? void (0) : __assert_fail ("isa<CallInst>(User) || isa<InvokeInst>(User)" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 2257, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
2258 | auto Call = cast<Instruction>(User); | ||||||||||||
2259 | |||||||||||||
2260 | auto Addr = emitSetAndGetSwiftErrorValueAround(Call, Alloca, Shape); | ||||||||||||
2261 | |||||||||||||
2262 | // Use the returned slot address as the call argument. | ||||||||||||
2263 | Use.set(Addr); | ||||||||||||
2264 | } | ||||||||||||
2265 | |||||||||||||
2266 | // All the uses should be loads and stores now. | ||||||||||||
2267 | assert(isAllocaPromotable(Alloca))(static_cast <bool> (isAllocaPromotable(Alloca)) ? void (0) : __assert_fail ("isAllocaPromotable(Alloca)", "llvm/lib/Transforms/Coroutines/CoroFrame.cpp" , 2267, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
2268 | } | ||||||||||||
2269 | |||||||||||||
2270 | /// "Eliminate" a swifterror argument by reducing it to the alloca case | ||||||||||||
2271 | /// and then loading and storing in the prologue and epilog. | ||||||||||||
2272 | /// | ||||||||||||
2273 | /// The argument keeps the swifterror flag. | ||||||||||||
2274 | static void eliminateSwiftErrorArgument(Function &F, Argument &Arg, | ||||||||||||
2275 | coro::Shape &Shape, | ||||||||||||
2276 | SmallVectorImpl<AllocaInst*> &AllocasToPromote) { | ||||||||||||
2277 | IRBuilder<> Builder(F.getEntryBlock().getFirstNonPHIOrDbg()); | ||||||||||||
2278 | |||||||||||||
2279 | auto ArgTy = cast<PointerType>(Arg.getType()); | ||||||||||||
2280 | auto ValueTy = ArgTy->getPointerElementType(); | ||||||||||||
2281 | |||||||||||||
2282 | // Reduce to the alloca case: | ||||||||||||
2283 | |||||||||||||
2284 | // Create an alloca and replace all uses of the arg with it. | ||||||||||||
2285 | auto Alloca = Builder.CreateAlloca(ValueTy, ArgTy->getAddressSpace()); | ||||||||||||
2286 | Arg.replaceAllUsesWith(Alloca); | ||||||||||||
2287 | |||||||||||||
2288 | // Set an initial value in the alloca. swifterror is always null on entry. | ||||||||||||
2289 | auto InitialValue = Constant::getNullValue(ValueTy); | ||||||||||||
2290 | Builder.CreateStore(InitialValue, Alloca); | ||||||||||||
2291 | |||||||||||||
2292 | // Find all the suspends in the function and save and restore around them. | ||||||||||||
2293 | for (auto Suspend : Shape.CoroSuspends) { | ||||||||||||
2294 | (void) emitSetAndGetSwiftErrorValueAround(Suspend, Alloca, Shape); | ||||||||||||
2295 | } | ||||||||||||
2296 | |||||||||||||
2297 | // Find all the coro.ends in the function and restore the error value. | ||||||||||||
2298 | for (auto End : Shape.CoroEnds) { | ||||||||||||
2299 | Builder.SetInsertPoint(End); | ||||||||||||
2300 | auto FinalValue = Builder.CreateLoad(ValueTy, Alloca); | ||||||||||||
2301 | (void) emitSetSwiftErrorValue(Builder, FinalValue, Shape); | ||||||||||||
2302 | } | ||||||||||||
2303 | |||||||||||||
2304 | // Now we can use the alloca logic. | ||||||||||||
2305 | AllocasToPromote.push_back(Alloca); | ||||||||||||
2306 | eliminateSwiftErrorAlloca(F, Alloca, Shape); | ||||||||||||
2307 | } | ||||||||||||
2308 | |||||||||||||
2309 | /// Eliminate all problematic uses of swifterror arguments and allocas | ||||||||||||
2310 | /// from the function. We'll fix them up later when splitting the function. | ||||||||||||
2311 | static void eliminateSwiftError(Function &F, coro::Shape &Shape) { | ||||||||||||
2312 | SmallVector<AllocaInst*, 4> AllocasToPromote; | ||||||||||||
2313 | |||||||||||||
2314 | // Look for a swifterror argument. | ||||||||||||
2315 | for (auto &Arg : F.args()) { | ||||||||||||
2316 | if (!Arg.hasSwiftErrorAttr()) continue; | ||||||||||||
2317 | |||||||||||||
2318 | eliminateSwiftErrorArgument(F, Arg, Shape, AllocasToPromote); | ||||||||||||
2319 | break; | ||||||||||||
2320 | } | ||||||||||||
2321 | |||||||||||||
2322 | // Look for swifterror allocas. | ||||||||||||
2323 | for (auto &Inst : F.getEntryBlock()) { | ||||||||||||
2324 | auto Alloca = dyn_cast<AllocaInst>(&Inst); | ||||||||||||
2325 | if (!Alloca || !Alloca->isSwiftError()) continue; | ||||||||||||
2326 | |||||||||||||
2327 | // Clear the swifterror flag. | ||||||||||||
2328 | Alloca->setSwiftError(false); | ||||||||||||
2329 | |||||||||||||
2330 | AllocasToPromote.push_back(Alloca); | ||||||||||||
2331 | eliminateSwiftErrorAlloca(F, Alloca, Shape); | ||||||||||||
2332 | } | ||||||||||||
2333 | |||||||||||||
2334 | // If we have any allocas to promote, compute a dominator tree and | ||||||||||||
2335 | // promote them en masse. | ||||||||||||
2336 | if (!AllocasToPromote.empty()) { | ||||||||||||
2337 | DominatorTree DT(F); | ||||||||||||
2338 | PromoteMemToReg(AllocasToPromote, DT); | ||||||||||||
2339 | } | ||||||||||||
2340 | } | ||||||||||||
2341 | |||||||||||||
2342 | /// retcon and retcon.once conventions assume that all spill uses can be sunk | ||||||||||||
2343 | /// after the coro.begin intrinsic. | ||||||||||||
2344 | static void sinkSpillUsesAfterCoroBegin(Function &F, | ||||||||||||
2345 | const FrameDataInfo &FrameData, | ||||||||||||
2346 | CoroBeginInst *CoroBegin) { | ||||||||||||
2347 | DominatorTree Dom(F); | ||||||||||||
2348 | |||||||||||||
2349 | SmallSetVector<Instruction *, 32> ToMove; | ||||||||||||
2350 | SmallVector<Instruction *, 32> Worklist; | ||||||||||||
2351 | |||||||||||||
2352 | // Collect all users that precede coro.begin. | ||||||||||||
2353 | for (auto *Def : FrameData.getAllDefs()) { | ||||||||||||
2354 | for (User *U : Def->users()) { | ||||||||||||
2355 | auto Inst = cast<Instruction>(U); | ||||||||||||
2356 | if (Inst->getParent() != CoroBegin->getParent() || | ||||||||||||
2357 | Dom.dominates(CoroBegin, Inst)) | ||||||||||||
2358 | continue; | ||||||||||||
2359 | if (ToMove.insert(Inst)) | ||||||||||||
2360 | Worklist.push_back(Inst); | ||||||||||||
2361 | } | ||||||||||||
2362 | } | ||||||||||||
2363 | // Recursively collect users before coro.begin. | ||||||||||||
2364 | while (!Worklist.empty()) { | ||||||||||||
2365 | auto *Def = Worklist.pop_back_val(); | ||||||||||||
2366 | for (User *U : Def->users()) { | ||||||||||||
2367 | auto Inst = cast<Instruction>(U); | ||||||||||||
2368 | if (Dom.dominates(CoroBegin, Inst)) | ||||||||||||
2369 | continue; | ||||||||||||
2370 | if (ToMove.insert(Inst)) | ||||||||||||
2371 | Worklist.push_back(Inst); | ||||||||||||
2372 | } | ||||||||||||
2373 | } | ||||||||||||
2374 | |||||||||||||
2375 | // Sort by dominance. | ||||||||||||
2376 | SmallVector<Instruction *, 64> InsertionList(ToMove.begin(), ToMove.end()); | ||||||||||||
2377 | llvm::sort(InsertionList, [&Dom](Instruction *A, Instruction *B) -> bool { | ||||||||||||
2378 | // If a dominates b it should preceed (<) b. | ||||||||||||
2379 | return Dom.dominates(A, B); | ||||||||||||
2380 | }); | ||||||||||||
2381 | |||||||||||||
2382 | Instruction *InsertPt = CoroBegin->getNextNode(); | ||||||||||||
2383 | for (Instruction *Inst : InsertionList) | ||||||||||||
2384 | Inst->moveBefore(InsertPt); | ||||||||||||
2385 | } | ||||||||||||
2386 | |||||||||||||
2387 | /// For each local variable that all of its user are only used inside one of | ||||||||||||
2388 | /// suspended region, we sink their lifetime.start markers to the place where | ||||||||||||
2389 | /// after the suspend block. Doing so minimizes the lifetime of each variable, | ||||||||||||
2390 | /// hence minimizing the amount of data we end up putting on the frame. | ||||||||||||
2391 | static void sinkLifetimeStartMarkers(Function &F, coro::Shape &Shape, | ||||||||||||
2392 | SuspendCrossingInfo &Checker) { | ||||||||||||
2393 | DominatorTree DT(F); | ||||||||||||
2394 | |||||||||||||
2395 | // Collect all possible basic blocks which may dominate all uses of allocas. | ||||||||||||
2396 | SmallPtrSet<BasicBlock *, 4> DomSet; | ||||||||||||
2397 | DomSet.insert(&F.getEntryBlock()); | ||||||||||||
2398 | for (auto *CSI : Shape.CoroSuspends) { | ||||||||||||
2399 | BasicBlock *SuspendBlock = CSI->getParent(); | ||||||||||||
2400 | assert(isSuspendBlock(SuspendBlock) && SuspendBlock->getSingleSuccessor() &&(static_cast <bool> (isSuspendBlock(SuspendBlock) && SuspendBlock->getSingleSuccessor() && "should have split coro.suspend into its own block" ) ? void (0) : __assert_fail ("isSuspendBlock(SuspendBlock) && SuspendBlock->getSingleSuccessor() && \"should have split coro.suspend into its own block\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 2401, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
2401 | "should have split coro.suspend into its own block")(static_cast <bool> (isSuspendBlock(SuspendBlock) && SuspendBlock->getSingleSuccessor() && "should have split coro.suspend into its own block" ) ? void (0) : __assert_fail ("isSuspendBlock(SuspendBlock) && SuspendBlock->getSingleSuccessor() && \"should have split coro.suspend into its own block\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 2401, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
2402 | DomSet.insert(SuspendBlock->getSingleSuccessor()); | ||||||||||||
2403 | } | ||||||||||||
2404 | |||||||||||||
2405 | for (Instruction &I : instructions(F)) { | ||||||||||||
2406 | AllocaInst* AI = dyn_cast<AllocaInst>(&I); | ||||||||||||
2407 | if (!AI) | ||||||||||||
2408 | continue; | ||||||||||||
2409 | |||||||||||||
2410 | for (BasicBlock *DomBB : DomSet) { | ||||||||||||
2411 | bool Valid = true; | ||||||||||||
2412 | SmallVector<Instruction *, 1> Lifetimes; | ||||||||||||
2413 | |||||||||||||
2414 | auto isLifetimeStart = [](Instruction* I) { | ||||||||||||
2415 | if (auto* II = dyn_cast<IntrinsicInst>(I)) | ||||||||||||
2416 | return II->getIntrinsicID() == Intrinsic::lifetime_start; | ||||||||||||
2417 | return false; | ||||||||||||
2418 | }; | ||||||||||||
2419 | |||||||||||||
2420 | auto collectLifetimeStart = [&](Instruction *U, AllocaInst *AI) { | ||||||||||||
2421 | if (isLifetimeStart(U)) { | ||||||||||||
2422 | Lifetimes.push_back(U); | ||||||||||||
2423 | return true; | ||||||||||||
2424 | } | ||||||||||||
2425 | if (!U->hasOneUse() || U->stripPointerCasts() != AI) | ||||||||||||
2426 | return false; | ||||||||||||
2427 | if (isLifetimeStart(U->user_back())) { | ||||||||||||
2428 | Lifetimes.push_back(U->user_back()); | ||||||||||||
2429 | return true; | ||||||||||||
2430 | } | ||||||||||||
2431 | return false; | ||||||||||||
2432 | }; | ||||||||||||
2433 | |||||||||||||
2434 | for (User *U : AI->users()) { | ||||||||||||
2435 | Instruction *UI = cast<Instruction>(U); | ||||||||||||
2436 | // For all users except lifetime.start markers, if they are all | ||||||||||||
2437 | // dominated by one of the basic blocks and do not cross | ||||||||||||
2438 | // suspend points as well, then there is no need to spill the | ||||||||||||
2439 | // instruction. | ||||||||||||
2440 | if (!DT.dominates(DomBB, UI->getParent()) || | ||||||||||||
2441 | Checker.isDefinitionAcrossSuspend(DomBB, UI)) { | ||||||||||||
2442 | // Skip lifetime.start, GEP and bitcast used by lifetime.start | ||||||||||||
2443 | // markers. | ||||||||||||
2444 | if (collectLifetimeStart(UI, AI)) | ||||||||||||
2445 | continue; | ||||||||||||
2446 | Valid = false; | ||||||||||||
2447 | break; | ||||||||||||
2448 | } | ||||||||||||
2449 | } | ||||||||||||
2450 | // Sink lifetime.start markers to dominate block when they are | ||||||||||||
2451 | // only used outside the region. | ||||||||||||
2452 | if (Valid && Lifetimes.size() != 0) { | ||||||||||||
2453 | // May be AI itself, when the type of AI is i8* | ||||||||||||
2454 | auto *NewBitCast = [&](AllocaInst *AI) -> Value* { | ||||||||||||
2455 | if (isa<AllocaInst>(Lifetimes[0]->getOperand(1))) | ||||||||||||
2456 | return AI; | ||||||||||||
2457 | auto *Int8PtrTy = Type::getInt8PtrTy(F.getContext()); | ||||||||||||
2458 | return CastInst::Create(Instruction::BitCast, AI, Int8PtrTy, "", | ||||||||||||
2459 | DomBB->getTerminator()); | ||||||||||||
2460 | }(AI); | ||||||||||||
2461 | |||||||||||||
2462 | auto *NewLifetime = Lifetimes[0]->clone(); | ||||||||||||
2463 | NewLifetime->replaceUsesOfWith(NewLifetime->getOperand(1), NewBitCast); | ||||||||||||
2464 | NewLifetime->insertBefore(DomBB->getTerminator()); | ||||||||||||
2465 | |||||||||||||
2466 | // All the outsided lifetime.start markers are no longer necessary. | ||||||||||||
2467 | for (Instruction *S : Lifetimes) | ||||||||||||
2468 | S->eraseFromParent(); | ||||||||||||
2469 | |||||||||||||
2470 | break; | ||||||||||||
2471 | } | ||||||||||||
2472 | } | ||||||||||||
2473 | } | ||||||||||||
2474 | } | ||||||||||||
2475 | |||||||||||||
2476 | static void collectFrameAllocas(Function &F, coro::Shape &Shape, | ||||||||||||
2477 | const SuspendCrossingInfo &Checker, | ||||||||||||
2478 | SmallVectorImpl<AllocaInfo> &Allocas) { | ||||||||||||
2479 | for (Instruction &I : instructions(F)) { | ||||||||||||
2480 | auto *AI = dyn_cast<AllocaInst>(&I); | ||||||||||||
2481 | if (!AI) | ||||||||||||
2482 | continue; | ||||||||||||
2483 | // The PromiseAlloca will be specially handled since it needs to be in a | ||||||||||||
2484 | // fixed position in the frame. | ||||||||||||
2485 | if (AI == Shape.SwitchLowering.PromiseAlloca) { | ||||||||||||
2486 | continue; | ||||||||||||
2487 | } | ||||||||||||
2488 | DominatorTree DT(F); | ||||||||||||
2489 | // The code that uses lifetime.start intrinsic does not work for functions | ||||||||||||
2490 | // with loops without exit. Disable it on ABIs we know to generate such | ||||||||||||
2491 | // code. | ||||||||||||
2492 | bool ShouldUseLifetimeStartInfo = | ||||||||||||
2493 | (Shape.ABI != coro::ABI::Async && Shape.ABI != coro::ABI::Retcon && | ||||||||||||
2494 | Shape.ABI != coro::ABI::RetconOnce); | ||||||||||||
2495 | AllocaUseVisitor Visitor{F.getParent()->getDataLayout(), DT, | ||||||||||||
2496 | *Shape.CoroBegin, Checker, | ||||||||||||
2497 | ShouldUseLifetimeStartInfo}; | ||||||||||||
2498 | Visitor.visitPtr(*AI); | ||||||||||||
2499 | if (!Visitor.getShouldLiveOnFrame()) | ||||||||||||
2500 | continue; | ||||||||||||
2501 | Allocas.emplace_back(AI, Visitor.getAliasesCopy(), | ||||||||||||
2502 | Visitor.getMayWriteBeforeCoroBegin()); | ||||||||||||
2503 | } | ||||||||||||
2504 | } | ||||||||||||
2505 | |||||||||||||
2506 | void coro::salvageDebugInfo( | ||||||||||||
2507 | SmallDenseMap<llvm::Value *, llvm::AllocaInst *, 4> &DbgPtrAllocaCache, | ||||||||||||
2508 | DbgVariableIntrinsic *DVI, bool OptimizeFrame) { | ||||||||||||
2509 | Function *F = DVI->getFunction(); | ||||||||||||
2510 | IRBuilder<> Builder(F->getContext()); | ||||||||||||
2511 | auto InsertPt = F->getEntryBlock().getFirstInsertionPt(); | ||||||||||||
2512 | while (isa<IntrinsicInst>(InsertPt)) | ||||||||||||
| |||||||||||||
2513 | ++InsertPt; | ||||||||||||
2514 | Builder.SetInsertPoint(&F->getEntryBlock(), InsertPt); | ||||||||||||
2515 | DIExpression *Expr = DVI->getExpression(); | ||||||||||||
2516 | // Follow the pointer arithmetic all the way to the incoming | ||||||||||||
2517 | // function argument and convert into a DIExpression. | ||||||||||||
2518 | bool SkipOutermostLoad = !isa<DbgValueInst>(DVI); | ||||||||||||
2519 | Value *Storage = DVI->getVariableLocationOp(0); | ||||||||||||
2520 | Value *OriginalStorage = Storage; | ||||||||||||
2521 | while (auto *Inst = dyn_cast_or_null<Instruction>(Storage)) { | ||||||||||||
2522 | if (auto *LdInst
| ||||||||||||
2523 | Storage = LdInst->getOperand(0); | ||||||||||||
2524 | // FIXME: This is a heuristic that works around the fact that | ||||||||||||
2525 | // LLVM IR debug intrinsics cannot yet distinguish between | ||||||||||||
2526 | // memory and value locations: Because a dbg.declare(alloca) is | ||||||||||||
2527 | // implicitly a memory location no DW_OP_deref operation for the | ||||||||||||
2528 | // last direct load from an alloca is necessary. This condition | ||||||||||||
2529 | // effectively drops the *last* DW_OP_deref in the expression. | ||||||||||||
2530 | if (!SkipOutermostLoad) | ||||||||||||
2531 | Expr = DIExpression::prepend(Expr, DIExpression::DerefBefore); | ||||||||||||
2532 | } else if (auto *StInst
| ||||||||||||
2533 | Storage = StInst->getOperand(0); | ||||||||||||
2534 | } else { | ||||||||||||
2535 | SmallVector<uint64_t, 16> Ops; | ||||||||||||
2536 | SmallVector<Value *, 0> AdditionalValues; | ||||||||||||
2537 | Value *Op = llvm::salvageDebugInfoImpl( | ||||||||||||
2538 | *Inst, Expr
| ||||||||||||
2539 | AdditionalValues); | ||||||||||||
2540 | if (!Op || !AdditionalValues.empty()) { | ||||||||||||
2541 | // If salvaging failed or salvaging produced more than one location | ||||||||||||
2542 | // operand, give up. | ||||||||||||
2543 | break; | ||||||||||||
2544 | } | ||||||||||||
2545 | Storage = Op; | ||||||||||||
2546 | Expr = DIExpression::appendOpsToArg(Expr, Ops, 0, /*StackValue*/ false); | ||||||||||||
2547 | } | ||||||||||||
2548 | SkipOutermostLoad = false; | ||||||||||||
2549 | } | ||||||||||||
2550 | if (!Storage
| ||||||||||||
2551 | return; | ||||||||||||
2552 | |||||||||||||
2553 | // Store a pointer to the coroutine frame object in an alloca so it | ||||||||||||
2554 | // is available throughout the function when producing unoptimized | ||||||||||||
2555 | // code. Extending the lifetime this way is correct because the | ||||||||||||
2556 | // variable has been declared by a dbg.declare intrinsic. | ||||||||||||
2557 | // | ||||||||||||
2558 | // Avoid to create the alloca would be eliminated by optimization | ||||||||||||
2559 | // passes and the corresponding dbg.declares would be invalid. | ||||||||||||
2560 | if (!OptimizeFrame && !EnableReuseStorageInFrame) | ||||||||||||
2561 | if (auto *Arg = dyn_cast<llvm::Argument>(Storage)) { | ||||||||||||
2562 | auto &Cached = DbgPtrAllocaCache[Storage]; | ||||||||||||
2563 | if (!Cached) { | ||||||||||||
2564 | Cached = Builder.CreateAlloca(Storage->getType(), 0, nullptr, | ||||||||||||
2565 | Arg->getName() + ".debug"); | ||||||||||||
2566 | Builder.CreateStore(Storage, Cached); | ||||||||||||
2567 | } | ||||||||||||
2568 | Storage = Cached; | ||||||||||||
2569 | // FIXME: LLVM lacks nuanced semantics to differentiate between | ||||||||||||
2570 | // memory and direct locations at the IR level. The backend will | ||||||||||||
2571 | // turn a dbg.declare(alloca, ..., DIExpression()) into a memory | ||||||||||||
2572 | // location. Thus, if there are deref and offset operations in the | ||||||||||||
2573 | // expression, we need to add a DW_OP_deref at the *start* of the | ||||||||||||
2574 | // expression to first load the contents of the alloca before | ||||||||||||
2575 | // adjusting it with the expression. | ||||||||||||
2576 | if (Expr && Expr->isComplex()) | ||||||||||||
2577 | Expr = DIExpression::prepend(Expr, DIExpression::DerefBefore); | ||||||||||||
2578 | } | ||||||||||||
2579 | |||||||||||||
2580 | DVI->replaceVariableLocationOp(OriginalStorage, Storage); | ||||||||||||
2581 | DVI->setExpression(Expr); | ||||||||||||
2582 | /// It makes no sense to move the dbg.value intrinsic. | ||||||||||||
2583 | if (!isa<DbgValueInst>(DVI)) { | ||||||||||||
2584 | if (auto *II = dyn_cast<InvokeInst>(Storage)) | ||||||||||||
2585 | DVI->moveBefore(II->getNormalDest()->getFirstNonPHI()); | ||||||||||||
2586 | else if (auto *CBI = dyn_cast<CallBrInst>(Storage)) | ||||||||||||
2587 | DVI->moveBefore(CBI->getDefaultDest()->getFirstNonPHI()); | ||||||||||||
2588 | else if (auto *InsertPt = dyn_cast<Instruction>(Storage)) { | ||||||||||||
2589 | assert(!InsertPt->isTerminator() &&(static_cast <bool> (!InsertPt->isTerminator() && "Unimaged terminator that could return a storage.") ? void ( 0) : __assert_fail ("!InsertPt->isTerminator() && \"Unimaged terminator that could return a storage.\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 2590, __extension__ __PRETTY_FUNCTION__)) | ||||||||||||
2590 | "Unimaged terminator that could return a storage.")(static_cast <bool> (!InsertPt->isTerminator() && "Unimaged terminator that could return a storage.") ? void ( 0) : __assert_fail ("!InsertPt->isTerminator() && \"Unimaged terminator that could return a storage.\"" , "llvm/lib/Transforms/Coroutines/CoroFrame.cpp", 2590, __extension__ __PRETTY_FUNCTION__)); | ||||||||||||
2591 | DVI->moveAfter(InsertPt); | ||||||||||||
2592 | } else if (isa<Argument>(Storage)) | ||||||||||||
2593 | DVI->moveAfter(F->getEntryBlock().getFirstNonPHI()); | ||||||||||||
2594 | } | ||||||||||||
2595 | } | ||||||||||||
2596 | |||||||||||||
2597 | void coro::buildCoroutineFrame(Function &F, Shape &Shape) { | ||||||||||||
2598 | // Don't eliminate swifterror in async functions that won't be split. | ||||||||||||
2599 | if (Shape.ABI != coro::ABI::Async || !Shape.CoroSuspends.empty()) | ||||||||||||
2600 | eliminateSwiftError(F, Shape); | ||||||||||||
2601 | |||||||||||||
2602 | if (Shape.ABI == coro::ABI::Switch && | ||||||||||||
2603 | Shape.SwitchLowering.PromiseAlloca) { | ||||||||||||
2604 | Shape.getSwitchCoroId()->clearPromise(); | ||||||||||||
2605 | } | ||||||||||||
2606 | |||||||||||||
2607 | // Make sure that all coro.save, coro.suspend and the fallthrough coro.end | ||||||||||||
2608 | // intrinsics are in their own blocks to simplify the logic of building up | ||||||||||||
2609 | // SuspendCrossing data. | ||||||||||||
2610 | for (auto *CSI : Shape.CoroSuspends) { | ||||||||||||
2611 | if (auto *Save = CSI->getCoroSave()) | ||||||||||||
2612 | splitAround(Save, "CoroSave"); | ||||||||||||
2613 | splitAround(CSI, "CoroSuspend"); | ||||||||||||
2614 | } | ||||||||||||
2615 | |||||||||||||
2616 | // Put CoroEnds into their own blocks. | ||||||||||||
2617 | for (AnyCoroEndInst *CE : Shape.CoroEnds) { | ||||||||||||
2618 | splitAround(CE, "CoroEnd"); | ||||||||||||
2619 | |||||||||||||
2620 | // Emit the musttail call function in a new block before the CoroEnd. | ||||||||||||
2621 | // We do this here so that the right suspend crossing info is computed for | ||||||||||||
2622 | // the uses of the musttail call function call. (Arguments to the coro.end | ||||||||||||
2623 | // instructions would be ignored) | ||||||||||||
2624 | if (auto *AsyncEnd = dyn_cast<CoroAsyncEndInst>(CE)) { | ||||||||||||
2625 | auto *MustTailCallFn = AsyncEnd->getMustTailCallFunction(); | ||||||||||||
2626 | if (!MustTailCallFn) | ||||||||||||
2627 | continue; | ||||||||||||
2628 | IRBuilder<> Builder(AsyncEnd); | ||||||||||||
2629 | SmallVector<Value *, 8> Args(AsyncEnd->args()); | ||||||||||||
2630 | auto Arguments = ArrayRef<Value *>(Args).drop_front(3); | ||||||||||||
2631 | auto *Call = createMustTailCall(AsyncEnd->getDebugLoc(), MustTailCallFn, | ||||||||||||
2632 | Arguments, Builder); | ||||||||||||
2633 | splitAround(Call, "MustTailCall.Before.CoroEnd"); | ||||||||||||
2634 | } | ||||||||||||
2635 | } | ||||||||||||
2636 | |||||||||||||
2637 | // Later code makes structural assumptions about single predecessors phis e.g | ||||||||||||
2638 | // that they are not live accross a suspend point. | ||||||||||||
2639 | cleanupSinglePredPHIs(F); | ||||||||||||
2640 | |||||||||||||
2641 | // Transforms multi-edge PHI Nodes, so that any value feeding into a PHI will | ||||||||||||
2642 | // never has its definition separated from the PHI by the suspend point. | ||||||||||||
2643 | rewritePHIs(F); | ||||||||||||
2644 | |||||||||||||
2645 | // Build suspend crossing info. | ||||||||||||
2646 | SuspendCrossingInfo Checker(F, Shape); | ||||||||||||
2647 | |||||||||||||
2648 | IRBuilder<> Builder(F.getContext()); | ||||||||||||
2649 | FrameDataInfo FrameData; | ||||||||||||
2650 | SmallVector<CoroAllocaAllocInst*, 4> LocalAllocas; | ||||||||||||
2651 | SmallVector<Instruction*, 4> DeadInstructions; | ||||||||||||
2652 | |||||||||||||
2653 | { | ||||||||||||
2654 | SpillInfo Spills; | ||||||||||||
2655 | for (int Repeat = 0; Repeat < 4; ++Repeat) { | ||||||||||||
2656 | // See if there are materializable instructions across suspend points. | ||||||||||||
2657 | for (Instruction &I : instructions(F)) | ||||||||||||
2658 | if (materializable(I)) { | ||||||||||||
2659 | for (User *U : I.users()) | ||||||||||||
2660 | if (Checker.isDefinitionAcrossSuspend(I, U)) | ||||||||||||
2661 | Spills[&I].push_back(cast<Instruction>(U)); | ||||||||||||
2662 | |||||||||||||
2663 | // Manually add dbg.value metadata uses of I. | ||||||||||||
2664 | SmallVector<DbgValueInst *, 16> DVIs; | ||||||||||||
2665 | findDbgValues(DVIs, &I); | ||||||||||||
2666 | for (auto *DVI : DVIs) | ||||||||||||
2667 | if (Checker.isDefinitionAcrossSuspend(I, DVI)) | ||||||||||||
2668 | Spills[&I].push_back(DVI); | ||||||||||||
2669 | } | ||||||||||||
2670 | |||||||||||||
2671 | if (Spills.empty()) | ||||||||||||
2672 | break; | ||||||||||||
2673 | |||||||||||||
2674 | // Rewrite materializable instructions to be materialized at the use | ||||||||||||
2675 | // point. | ||||||||||||
2676 | LLVM_DEBUG(dumpSpills("Materializations", Spills))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dumpSpills("Materializations", Spills); } } while (false); | ||||||||||||
2677 | rewriteMaterializableInstructions(Builder, Spills); | ||||||||||||
2678 | Spills.clear(); | ||||||||||||
2679 | } | ||||||||||||
2680 | } | ||||||||||||
2681 | |||||||||||||
2682 | if (Shape.ABI != coro::ABI::Async && Shape.ABI != coro::ABI::Retcon && | ||||||||||||
2683 | Shape.ABI != coro::ABI::RetconOnce) | ||||||||||||
2684 | sinkLifetimeStartMarkers(F, Shape, Checker); | ||||||||||||
2685 | |||||||||||||
2686 | if (Shape.ABI != coro::ABI::Async || !Shape.CoroSuspends.empty()) | ||||||||||||
2687 | collectFrameAllocas(F, Shape, Checker, FrameData.Allocas); | ||||||||||||
2688 | LLVM_DEBUG(dumpAllocas(FrameData.Allocas))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dumpAllocas(FrameData.Allocas); } } while ( false); | ||||||||||||
2689 | |||||||||||||
2690 | // Collect the spills for arguments and other not-materializable values. | ||||||||||||
2691 | for (Argument &A : F.args()) | ||||||||||||
2692 | for (User *U : A.users()) | ||||||||||||
2693 | if (Checker.isDefinitionAcrossSuspend(A, U)) | ||||||||||||
2694 | FrameData.Spills[&A].push_back(cast<Instruction>(U)); | ||||||||||||
2695 | |||||||||||||
2696 | for (Instruction &I : instructions(F)) { | ||||||||||||
2697 | // Values returned from coroutine structure intrinsics should not be part | ||||||||||||
2698 | // of the Coroutine Frame. | ||||||||||||
2699 | if (isCoroutineStructureIntrinsic(I) || &I == Shape.CoroBegin) | ||||||||||||
2700 | continue; | ||||||||||||
2701 | |||||||||||||
2702 | // The Coroutine Promise always included into coroutine frame, no need to | ||||||||||||
2703 | // check for suspend crossing. | ||||||||||||
2704 | if (Shape.ABI == coro::ABI::Switch && | ||||||||||||
2705 | Shape.SwitchLowering.PromiseAlloca == &I) | ||||||||||||
2706 | continue; | ||||||||||||
2707 | |||||||||||||
2708 | // Handle alloca.alloc specially here. | ||||||||||||
2709 | if (auto AI = dyn_cast<CoroAllocaAllocInst>(&I)) { | ||||||||||||
2710 | // Check whether the alloca's lifetime is bounded by suspend points. | ||||||||||||
2711 | if (isLocalAlloca(AI)) { | ||||||||||||
2712 | LocalAllocas.push_back(AI); | ||||||||||||
2713 | continue; | ||||||||||||
2714 | } | ||||||||||||
2715 | |||||||||||||
2716 | // If not, do a quick rewrite of the alloca and then add spills of | ||||||||||||
2717 | // the rewritten value. The rewrite doesn't invalidate anything in | ||||||||||||
2718 | // Spills because the other alloca intrinsics have no other operands | ||||||||||||
2719 | // besides AI, and it doesn't invalidate the iteration because we delay | ||||||||||||
2720 | // erasing AI. | ||||||||||||
2721 | auto Alloc = lowerNonLocalAlloca(AI, Shape, DeadInstructions); | ||||||||||||
2722 | |||||||||||||
2723 | for (User *U : Alloc->users()) { | ||||||||||||
2724 | if (Checker.isDefinitionAcrossSuspend(*Alloc, U)) | ||||||||||||
2725 | FrameData.Spills[Alloc].push_back(cast<Instruction>(U)); | ||||||||||||
2726 | } | ||||||||||||
2727 | continue; | ||||||||||||
2728 | } | ||||||||||||
2729 | |||||||||||||
2730 | // Ignore alloca.get; we process this as part of coro.alloca.alloc. | ||||||||||||
2731 | if (isa<CoroAllocaGetInst>(I)) | ||||||||||||
2732 | continue; | ||||||||||||
2733 | |||||||||||||
2734 | if (isa<AllocaInst>(I)) | ||||||||||||
2735 | continue; | ||||||||||||
2736 | |||||||||||||
2737 | for (User *U : I.users()) | ||||||||||||
2738 | if (Checker.isDefinitionAcrossSuspend(I, U)) { | ||||||||||||
2739 | // We cannot spill a token. | ||||||||||||
2740 | if (I.getType()->isTokenTy()) | ||||||||||||
2741 | report_fatal_error( | ||||||||||||
2742 | "token definition is separated from the use by a suspend point"); | ||||||||||||
2743 | FrameData.Spills[&I].push_back(cast<Instruction>(U)); | ||||||||||||
2744 | } | ||||||||||||
2745 | } | ||||||||||||
2746 | |||||||||||||
2747 | // We don't want the layout of coroutine frame to be affected | ||||||||||||
2748 | // by debug information. So we only choose to salvage DbgValueInst for | ||||||||||||
2749 | // whose value is already in the frame. | ||||||||||||
2750 | // We would handle the dbg.values for allocas specially | ||||||||||||
2751 | for (auto &Iter : FrameData.Spills) { | ||||||||||||
2752 | auto *V = Iter.first; | ||||||||||||
2753 | SmallVector<DbgValueInst *, 16> DVIs; | ||||||||||||
2754 | findDbgValues(DVIs, V); | ||||||||||||
2755 | llvm::for_each(DVIs, [&](DbgValueInst *DVI) { | ||||||||||||
2756 | if (Checker.isDefinitionAcrossSuspend(*V, DVI)) | ||||||||||||
2757 | FrameData.Spills[V].push_back(DVI); | ||||||||||||
2758 | }); | ||||||||||||
2759 | } | ||||||||||||
2760 | |||||||||||||
2761 | LLVM_DEBUG(dumpSpills("Spills", FrameData.Spills))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("coro-frame")) { dumpSpills("Spills", FrameData.Spills); } } while (false); | ||||||||||||
2762 | if (Shape.ABI == coro::ABI::Retcon || Shape.ABI == coro::ABI::RetconOnce || | ||||||||||||
2763 | Shape.ABI == coro::ABI::Async) | ||||||||||||
2764 | sinkSpillUsesAfterCoroBegin(F, FrameData, Shape.CoroBegin); | ||||||||||||
2765 | Shape.FrameTy = buildFrameType(F, Shape, FrameData); | ||||||||||||
2766 | createFramePtr(Shape); | ||||||||||||
2767 | // For now, this works for C++ programs only. | ||||||||||||
2768 | buildFrameDebugInfo(F, Shape, FrameData); | ||||||||||||
2769 | insertSpills(FrameData, Shape); | ||||||||||||
2770 | lowerLocalAllocas(LocalAllocas, DeadInstructions); | ||||||||||||
2771 | |||||||||||||
2772 | for (auto I : DeadInstructions) | ||||||||||||
2773 | I->eraseFromParent(); | ||||||||||||
2774 | } |
1 | //===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// |
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 | /// /file |
10 | /// This file defines the SmallVector class. |
11 | /// |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_ADT_SMALLVECTOR_H |
15 | #define LLVM_ADT_SMALLVECTOR_H |
16 | |
17 | #include "llvm/Support/Compiler.h" |
18 | #include "llvm/Support/type_traits.h" |
19 | #include <algorithm> |
20 | #include <cassert> |
21 | #include <cstddef> |
22 | #include <cstdlib> |
23 | #include <cstring> |
24 | #include <functional> |
25 | #include <initializer_list> |
26 | #include <iterator> |
27 | #include <limits> |
28 | #include <memory> |
29 | #include <new> |
30 | #include <type_traits> |
31 | #include <utility> |
32 | |
33 | namespace llvm { |
34 | |
35 | template <typename IteratorT> class iterator_range; |
36 | |
37 | /// This is all the stuff common to all SmallVectors. |
38 | /// |
39 | /// The template parameter specifies the type which should be used to hold the |
40 | /// Size and Capacity of the SmallVector, so it can be adjusted. |
41 | /// Using 32 bit size is desirable to shrink the size of the SmallVector. |
42 | /// Using 64 bit size is desirable for cases like SmallVector<char>, where a |
43 | /// 32 bit size would limit the vector to ~4GB. SmallVectors are used for |
44 | /// buffering bitcode output - which can exceed 4GB. |
45 | template <class Size_T> class SmallVectorBase { |
46 | protected: |
47 | void *BeginX; |
48 | Size_T Size = 0, Capacity; |
49 | |
50 | /// The maximum value of the Size_T used. |
51 | static constexpr size_t SizeTypeMax() { |
52 | return std::numeric_limits<Size_T>::max(); |
53 | } |
54 | |
55 | SmallVectorBase() = delete; |
56 | SmallVectorBase(void *FirstEl, size_t TotalCapacity) |
57 | : BeginX(FirstEl), Capacity(TotalCapacity) {} |
58 | |
59 | /// This is a helper for \a grow() that's out of line to reduce code |
60 | /// duplication. This function will report a fatal error if it can't grow at |
61 | /// least to \p MinSize. |
62 | void *mallocForGrow(size_t MinSize, size_t TSize, size_t &NewCapacity); |
63 | |
64 | /// This is an implementation of the grow() method which only works |
65 | /// on POD-like data types and is out of line to reduce code duplication. |
66 | /// This function will report a fatal error if it cannot increase capacity. |
67 | void grow_pod(void *FirstEl, size_t MinSize, size_t TSize); |
68 | |
69 | public: |
70 | size_t size() const { return Size; } |
71 | size_t capacity() const { return Capacity; } |
72 | |
73 | LLVM_NODISCARD[[clang::warn_unused_result]] bool empty() const { return !Size; } |
74 | |
75 | protected: |
76 | /// Set the array size to \p N, which the current array must have enough |
77 | /// capacity for. |
78 | /// |
79 | /// This does not construct or destroy any elements in the vector. |
80 | void set_size(size_t N) { |
81 | assert(N <= capacity())(static_cast <bool> (N <= capacity()) ? void (0) : __assert_fail ("N <= capacity()", "llvm/include/llvm/ADT/SmallVector.h" , 81, __extension__ __PRETTY_FUNCTION__)); |
82 | Size = N; |
83 | } |
84 | }; |
85 | |
86 | template <class T> |
87 | using SmallVectorSizeType = |
88 | typename std::conditional<sizeof(T) < 4 && sizeof(void *) >= 8, uint64_t, |
89 | uint32_t>::type; |
90 | |
91 | /// Figure out the offset of the first element. |
92 | template <class T, typename = void> struct SmallVectorAlignmentAndSize { |
93 | alignas(SmallVectorBase<SmallVectorSizeType<T>>) char Base[sizeof( |
94 | SmallVectorBase<SmallVectorSizeType<T>>)]; |
95 | alignas(T) char FirstEl[sizeof(T)]; |
96 | }; |
97 | |
98 | /// This is the part of SmallVectorTemplateBase which does not depend on whether |
99 | /// the type T is a POD. The extra dummy template argument is used by ArrayRef |
100 | /// to avoid unnecessarily requiring T to be complete. |
101 | template <typename T, typename = void> |
102 | class SmallVectorTemplateCommon |
103 | : public SmallVectorBase<SmallVectorSizeType<T>> { |
104 | using Base = SmallVectorBase<SmallVectorSizeType<T>>; |
105 | |
106 | /// Find the address of the first element. For this pointer math to be valid |
107 | /// with small-size of 0 for T with lots of alignment, it's important that |
108 | /// SmallVectorStorage is properly-aligned even for small-size of 0. |
109 | void *getFirstEl() const { |
110 | return const_cast<void *>(reinterpret_cast<const void *>( |
111 | reinterpret_cast<const char *>(this) + |
112 | offsetof(SmallVectorAlignmentAndSize<T>, FirstEl)__builtin_offsetof(SmallVectorAlignmentAndSize<T>, FirstEl ))); |
113 | } |
114 | // Space after 'FirstEl' is clobbered, do not add any instance vars after it. |
115 | |
116 | protected: |
117 | SmallVectorTemplateCommon(size_t Size) : Base(getFirstEl(), Size) {} |
118 | |
119 | void grow_pod(size_t MinSize, size_t TSize) { |
120 | Base::grow_pod(getFirstEl(), MinSize, TSize); |
121 | } |
122 | |
123 | /// Return true if this is a smallvector which has not had dynamic |
124 | /// memory allocated for it. |
125 | bool isSmall() const { return this->BeginX == getFirstEl(); } |
126 | |
127 | /// Put this vector in a state of being small. |
128 | void resetToSmall() { |
129 | this->BeginX = getFirstEl(); |
130 | this->Size = this->Capacity = 0; // FIXME: Setting Capacity to 0 is suspect. |
131 | } |
132 | |
133 | /// Return true if V is an internal reference to the given range. |
134 | bool isReferenceToRange(const void *V, const void *First, const void *Last) const { |
135 | // Use std::less to avoid UB. |
136 | std::less<> LessThan; |
137 | return !LessThan(V, First) && LessThan(V, Last); |
138 | } |
139 | |
140 | /// Return true if V is an internal reference to this vector. |
141 | bool isReferenceToStorage(const void *V) const { |
142 | return isReferenceToRange(V, this->begin(), this->end()); |
143 | } |
144 | |
145 | /// Return true if First and Last form a valid (possibly empty) range in this |
146 | /// vector's storage. |
147 | bool isRangeInStorage(const void *First, const void *Last) const { |
148 | // Use std::less to avoid UB. |
149 | std::less<> LessThan; |
150 | return !LessThan(First, this->begin()) && !LessThan(Last, First) && |
151 | !LessThan(this->end(), Last); |
152 | } |
153 | |
154 | /// Return true unless Elt will be invalidated by resizing the vector to |
155 | /// NewSize. |
156 | bool isSafeToReferenceAfterResize(const void *Elt, size_t NewSize) { |
157 | // Past the end. |
158 | if (LLVM_LIKELY(!isReferenceToStorage(Elt))__builtin_expect((bool)(!isReferenceToStorage(Elt)), true)) |
159 | return true; |
160 | |
161 | // Return false if Elt will be destroyed by shrinking. |
162 | if (NewSize <= this->size()) |
163 | return Elt < this->begin() + NewSize; |
164 | |
165 | // Return false if we need to grow. |
166 | return NewSize <= this->capacity(); |
167 | } |
168 | |
169 | /// Check whether Elt will be invalidated by resizing the vector to NewSize. |
170 | void assertSafeToReferenceAfterResize(const void *Elt, size_t NewSize) { |
171 | assert(isSafeToReferenceAfterResize(Elt, NewSize) &&(static_cast <bool> (isSafeToReferenceAfterResize(Elt, NewSize ) && "Attempting to reference an element of the vector in an operation " "that invalidates it") ? void (0) : __assert_fail ("isSafeToReferenceAfterResize(Elt, NewSize) && \"Attempting to reference an element of the vector in an operation \" \"that invalidates it\"" , "llvm/include/llvm/ADT/SmallVector.h", 173, __extension__ __PRETTY_FUNCTION__ )) |
172 | "Attempting to reference an element of the vector in an operation "(static_cast <bool> (isSafeToReferenceAfterResize(Elt, NewSize ) && "Attempting to reference an element of the vector in an operation " "that invalidates it") ? void (0) : __assert_fail ("isSafeToReferenceAfterResize(Elt, NewSize) && \"Attempting to reference an element of the vector in an operation \" \"that invalidates it\"" , "llvm/include/llvm/ADT/SmallVector.h", 173, __extension__ __PRETTY_FUNCTION__ )) |
173 | "that invalidates it")(static_cast <bool> (isSafeToReferenceAfterResize(Elt, NewSize ) && "Attempting to reference an element of the vector in an operation " "that invalidates it") ? void (0) : __assert_fail ("isSafeToReferenceAfterResize(Elt, NewSize) && \"Attempting to reference an element of the vector in an operation \" \"that invalidates it\"" , "llvm/include/llvm/ADT/SmallVector.h", 173, __extension__ __PRETTY_FUNCTION__ )); |
174 | } |
175 | |
176 | /// Check whether Elt will be invalidated by increasing the size of the |
177 | /// vector by N. |
178 | void assertSafeToAdd(const void *Elt, size_t N = 1) { |
179 | this->assertSafeToReferenceAfterResize(Elt, this->size() + N); |
180 | } |
181 | |
182 | /// Check whether any part of the range will be invalidated by clearing. |
183 | void assertSafeToReferenceAfterClear(const T *From, const T *To) { |
184 | if (From == To) |
185 | return; |
186 | this->assertSafeToReferenceAfterResize(From, 0); |
187 | this->assertSafeToReferenceAfterResize(To - 1, 0); |
188 | } |
189 | template < |
190 | class ItTy, |
191 | std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>, T *>::value, |
192 | bool> = false> |
193 | void assertSafeToReferenceAfterClear(ItTy, ItTy) {} |
194 | |
195 | /// Check whether any part of the range will be invalidated by growing. |
196 | void assertSafeToAddRange(const T *From, const T *To) { |
197 | if (From == To) |
198 | return; |
199 | this->assertSafeToAdd(From, To - From); |
200 | this->assertSafeToAdd(To - 1, To - From); |
201 | } |
202 | template < |
203 | class ItTy, |
204 | std::enable_if_t<!std::is_same<std::remove_const_t<ItTy>, T *>::value, |
205 | bool> = false> |
206 | void assertSafeToAddRange(ItTy, ItTy) {} |
207 | |
208 | /// Reserve enough space to add one element, and return the updated element |
209 | /// pointer in case it was a reference to the storage. |
210 | template <class U> |
211 | static const T *reserveForParamAndGetAddressImpl(U *This, const T &Elt, |
212 | size_t N) { |
213 | size_t NewSize = This->size() + N; |
214 | if (LLVM_LIKELY(NewSize <= This->capacity())__builtin_expect((bool)(NewSize <= This->capacity()), true )) |
215 | return &Elt; |
216 | |
217 | bool ReferencesStorage = false; |
218 | int64_t Index = -1; |
219 | if (!U::TakesParamByValue) { |
220 | if (LLVM_UNLIKELY(This->isReferenceToStorage(&Elt))__builtin_expect((bool)(This->isReferenceToStorage(&Elt )), false)) { |
221 | ReferencesStorage = true; |
222 | Index = &Elt - This->begin(); |
223 | } |
224 | } |
225 | This->grow(NewSize); |
226 | return ReferencesStorage ? This->begin() + Index : &Elt; |
227 | } |
228 | |
229 | public: |
230 | using size_type = size_t; |
231 | using difference_type = ptrdiff_t; |
232 | using value_type = T; |
233 | using iterator = T *; |
234 | using const_iterator = const T *; |
235 | |
236 | using const_reverse_iterator = std::reverse_iterator<const_iterator>; |
237 | using reverse_iterator = std::reverse_iterator<iterator>; |
238 | |
239 | using reference = T &; |
240 | using const_reference = const T &; |
241 | using pointer = T *; |
242 | using const_pointer = const T *; |
243 | |
244 | using Base::capacity; |
245 | using Base::empty; |
246 | using Base::size; |
247 | |
248 | // forward iterator creation methods. |
249 | iterator begin() { return (iterator)this->BeginX; } |
250 | const_iterator begin() const { return (const_iterator)this->BeginX; } |
251 | iterator end() { return begin() + size(); } |
252 | const_iterator end() const { return begin() + size(); } |
253 | |
254 | // reverse iterator creation methods. |
255 | reverse_iterator rbegin() { return reverse_iterator(end()); } |
256 | const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } |
257 | reverse_iterator rend() { return reverse_iterator(begin()); } |
258 | const_reverse_iterator rend() const { return const_reverse_iterator(begin());} |
259 | |
260 | size_type size_in_bytes() const { return size() * sizeof(T); } |
261 | size_type max_size() const { |
262 | return std::min(this->SizeTypeMax(), size_type(-1) / sizeof(T)); |
263 | } |
264 | |
265 | size_t capacity_in_bytes() const { return capacity() * sizeof(T); } |
266 | |
267 | /// Return a pointer to the vector's buffer, even if empty(). |
268 | pointer data() { return pointer(begin()); } |
269 | /// Return a pointer to the vector's buffer, even if empty(). |
270 | const_pointer data() const { return const_pointer(begin()); } |
271 | |
272 | reference operator[](size_type idx) { |
273 | assert(idx < size())(static_cast <bool> (idx < size()) ? void (0) : __assert_fail ("idx < size()", "llvm/include/llvm/ADT/SmallVector.h", 273 , __extension__ __PRETTY_FUNCTION__)); |
274 | return begin()[idx]; |
275 | } |
276 | const_reference operator[](size_type idx) const { |
277 | assert(idx < size())(static_cast <bool> (idx < size()) ? void (0) : __assert_fail ("idx < size()", "llvm/include/llvm/ADT/SmallVector.h", 277 , __extension__ __PRETTY_FUNCTION__)); |
278 | return begin()[idx]; |
279 | } |
280 | |
281 | reference front() { |
282 | assert(!empty())(static_cast <bool> (!empty()) ? void (0) : __assert_fail ("!empty()", "llvm/include/llvm/ADT/SmallVector.h", 282, __extension__ __PRETTY_FUNCTION__)); |
283 | return begin()[0]; |
284 | } |
285 | const_reference front() const { |
286 | assert(!empty())(static_cast <bool> (!empty()) ? void (0) : __assert_fail ("!empty()", "llvm/include/llvm/ADT/SmallVector.h", 286, __extension__ __PRETTY_FUNCTION__)); |
287 | return begin()[0]; |
288 | } |
289 | |
290 | reference back() { |
291 | assert(!empty())(static_cast <bool> (!empty()) ? void (0) : __assert_fail ("!empty()", "llvm/include/llvm/ADT/SmallVector.h", 291, __extension__ __PRETTY_FUNCTION__)); |
292 | return end()[-1]; |
293 | } |
294 | const_reference back() const { |
295 | assert(!empty())(static_cast <bool> (!empty()) ? void (0) : __assert_fail ("!empty()", "llvm/include/llvm/ADT/SmallVector.h", 295, __extension__ __PRETTY_FUNCTION__)); |
296 | return end()[-1]; |
297 | } |
298 | }; |
299 | |
300 | /// SmallVectorTemplateBase<TriviallyCopyable = false> - This is where we put |
301 | /// method implementations that are designed to work with non-trivial T's. |
302 | /// |
303 | /// We approximate is_trivially_copyable with trivial move/copy construction and |
304 | /// trivial destruction. While the standard doesn't specify that you're allowed |
305 | /// copy these types with memcpy, there is no way for the type to observe this. |
306 | /// This catches the important case of std::pair<POD, POD>, which is not |
307 | /// trivially assignable. |
308 | template <typename T, bool = (is_trivially_copy_constructible<T>::value) && |
309 | (is_trivially_move_constructible<T>::value) && |
310 | std::is_trivially_destructible<T>::value> |
311 | class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> { |
312 | friend class SmallVectorTemplateCommon<T>; |
313 | |
314 | protected: |
315 | static constexpr bool TakesParamByValue = false; |
316 | using ValueParamT = const T &; |
317 | |
318 | SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {} |
319 | |
320 | static void destroy_range(T *S, T *E) { |
321 | while (S != E) { |
322 | --E; |
323 | E->~T(); |
324 | } |
325 | } |
326 | |
327 | /// Move the range [I, E) into the uninitialized memory starting with "Dest", |
328 | /// constructing elements as needed. |
329 | template<typename It1, typename It2> |
330 | static void uninitialized_move(It1 I, It1 E, It2 Dest) { |
331 | std::uninitialized_copy(std::make_move_iterator(I), |
332 | std::make_move_iterator(E), Dest); |
333 | } |
334 | |
335 | /// Copy the range [I, E) onto the uninitialized memory starting with "Dest", |
336 | /// constructing elements as needed. |
337 | template<typename It1, typename It2> |
338 | static void uninitialized_copy(It1 I, It1 E, It2 Dest) { |
339 | std::uninitialized_copy(I, E, Dest); |
340 | } |
341 | |
342 | /// Grow the allocated memory (without initializing new elements), doubling |
343 | /// the size of the allocated memory. Guarantees space for at least one more |
344 | /// element, or MinSize more elements if specified. |
345 | void grow(size_t MinSize = 0); |
346 | |
347 | /// Create a new allocation big enough for \p MinSize and pass back its size |
348 | /// in \p NewCapacity. This is the first section of \a grow(). |
349 | T *mallocForGrow(size_t MinSize, size_t &NewCapacity) { |
350 | return static_cast<T *>( |
351 | SmallVectorBase<SmallVectorSizeType<T>>::mallocForGrow( |
352 | MinSize, sizeof(T), NewCapacity)); |
353 | } |
354 | |
355 | /// Move existing elements over to the new allocation \p NewElts, the middle |
356 | /// section of \a grow(). |
357 | void moveElementsForGrow(T *NewElts); |
358 | |
359 | /// Transfer ownership of the allocation, finishing up \a grow(). |
360 | void takeAllocationForGrow(T *NewElts, size_t NewCapacity); |
361 | |
362 | /// Reserve enough space to add one element, and return the updated element |
363 | /// pointer in case it was a reference to the storage. |
364 | const T *reserveForParamAndGetAddress(const T &Elt, size_t N = 1) { |
365 | return this->reserveForParamAndGetAddressImpl(this, Elt, N); |
366 | } |
367 | |
368 | /// Reserve enough space to add one element, and return the updated element |
369 | /// pointer in case it was a reference to the storage. |
370 | T *reserveForParamAndGetAddress(T &Elt, size_t N = 1) { |
371 | return const_cast<T *>( |
372 | this->reserveForParamAndGetAddressImpl(this, Elt, N)); |
373 | } |
374 | |
375 | static T &&forward_value_param(T &&V) { return std::move(V); } |
376 | static const T &forward_value_param(const T &V) { return V; } |
377 | |
378 | void growAndAssign(size_t NumElts, const T &Elt) { |
379 | // Grow manually in case Elt is an internal reference. |
380 | size_t NewCapacity; |
381 | T *NewElts = mallocForGrow(NumElts, NewCapacity); |
382 | std::uninitialized_fill_n(NewElts, NumElts, Elt); |
383 | this->destroy_range(this->begin(), this->end()); |
384 | takeAllocationForGrow(NewElts, NewCapacity); |
385 | this->set_size(NumElts); |
386 | } |
387 | |
388 | template <typename... ArgTypes> T &growAndEmplaceBack(ArgTypes &&... Args) { |
389 | // Grow manually in case one of Args is an internal reference. |
390 | size_t NewCapacity; |
391 | T *NewElts = mallocForGrow(0, NewCapacity); |
392 | ::new ((void *)(NewElts + this->size())) T(std::forward<ArgTypes>(Args)...); |
393 | moveElementsForGrow(NewElts); |
394 | takeAllocationForGrow(NewElts, NewCapacity); |
395 | this->set_size(this->size() + 1); |
396 | return this->back(); |
397 | } |
398 | |
399 | public: |
400 | void push_back(const T &Elt) { |
401 | const T *EltPtr = reserveForParamAndGetAddress(Elt); |
402 | ::new ((void *)this->end()) T(*EltPtr); |
403 | this->set_size(this->size() + 1); |
404 | } |
405 | |
406 | void push_back(T &&Elt) { |
407 | T *EltPtr = reserveForParamAndGetAddress(Elt); |
408 | ::new ((void *)this->end()) T(::std::move(*EltPtr)); |
409 | this->set_size(this->size() + 1); |
410 | } |
411 | |
412 | void pop_back() { |
413 | this->set_size(this->size() - 1); |
414 | this->end()->~T(); |
415 | } |
416 | }; |
417 | |
418 | // Define this out-of-line to dissuade the C++ compiler from inlining it. |
419 | template <typename T, bool TriviallyCopyable> |
420 | void SmallVectorTemplateBase<T, TriviallyCopyable>::grow(size_t MinSize) { |
421 | size_t NewCapacity; |
422 | T *NewElts = mallocForGrow(MinSize, NewCapacity); |
423 | moveElementsForGrow(NewElts); |
424 | takeAllocationForGrow(NewElts, NewCapacity); |
425 | } |
426 | |
427 | // Define this out-of-line to dissuade the C++ compiler from inlining it. |
428 | template <typename T, bool TriviallyCopyable> |
429 | void SmallVectorTemplateBase<T, TriviallyCopyable>::moveElementsForGrow( |
430 | T *NewElts) { |
431 | // Move the elements over. |
432 | this->uninitialized_move(this->begin(), this->end(), NewElts); |
433 | |
434 | // Destroy the original elements. |
435 | destroy_range(this->begin(), this->end()); |
436 | } |
437 | |
438 | // Define this out-of-line to dissuade the C++ compiler from inlining it. |
439 | template <typename T, bool TriviallyCopyable> |
440 | void SmallVectorTemplateBase<T, TriviallyCopyable>::takeAllocationForGrow( |
441 | T *NewElts, size_t NewCapacity) { |
442 | // If this wasn't grown from the inline copy, deallocate the old space. |
443 | if (!this->isSmall()) |
444 | free(this->begin()); |
445 | |
446 | this->BeginX = NewElts; |
447 | this->Capacity = NewCapacity; |
448 | } |
449 | |
450 | /// SmallVectorTemplateBase<TriviallyCopyable = true> - This is where we put |
451 | /// method implementations that are designed to work with trivially copyable |
452 | /// T's. This allows using memcpy in place of copy/move construction and |
453 | /// skipping destruction. |
454 | template <typename T> |
455 | class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> { |
456 | friend class SmallVectorTemplateCommon<T>; |
457 | |
458 | protected: |
459 | /// True if it's cheap enough to take parameters by value. Doing so avoids |
460 | /// overhead related to mitigations for reference invalidation. |
461 | static constexpr bool TakesParamByValue = sizeof(T) <= 2 * sizeof(void *); |
462 | |
463 | /// Either const T& or T, depending on whether it's cheap enough to take |
464 | /// parameters by value. |
465 | using ValueParamT = |
466 | typename std::conditional<TakesParamByValue, T, const T &>::type; |
467 | |
468 | SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {} |
469 | |
470 | // No need to do a destroy loop for POD's. |
471 | static void destroy_range(T *, T *) {} |
472 | |
473 | /// Move the range [I, E) onto the uninitialized memory |
474 | /// starting with "Dest", constructing elements into it as needed. |
475 | template<typename It1, typename It2> |
476 | static void uninitialized_move(It1 I, It1 E, It2 Dest) { |
477 | // Just do a copy. |
478 | uninitialized_copy(I, E, Dest); |
479 | } |
480 | |
481 | /// Copy the range [I, E) onto the uninitialized memory |
482 | /// starting with "Dest", constructing elements into it as needed. |
483 | template<typename It1, typename It2> |
484 | static void uninitialized_copy(It1 I, It1 E, It2 Dest) { |
485 | // Arbitrary iterator types; just use the basic implementation. |
486 | std::uninitialized_copy(I, E, Dest); |
487 | } |
488 | |
489 | /// Copy the range [I, E) onto the uninitialized memory |
490 | /// starting with "Dest", constructing elements into it as needed. |
491 | template <typename T1, typename T2> |
492 | static void uninitialized_copy( |
493 | T1 *I, T1 *E, T2 *Dest, |
494 | std::enable_if_t<std::is_same<typename std::remove_const<T1>::type, |
495 | T2>::value> * = nullptr) { |
496 | // Use memcpy for PODs iterated by pointers (which includes SmallVector |
497 | // iterators): std::uninitialized_copy optimizes to memmove, but we can |
498 | // use memcpy here. Note that I and E are iterators and thus might be |
499 | // invalid for memcpy if they are equal. |
500 | if (I != E) |
501 | memcpy(reinterpret_cast<void *>(Dest), I, (E - I) * sizeof(T)); |
502 | } |
503 | |
504 | /// Double the size of the allocated memory, guaranteeing space for at |
505 | /// least one more element or MinSize if specified. |
506 | void grow(size_t MinSize = 0) { this->grow_pod(MinSize, sizeof(T)); } |
507 | |
508 | /// Reserve enough space to add one element, and return the updated element |
509 | /// pointer in case it was a reference to the storage. |
510 | const T *reserveForParamAndGetAddress(const T &Elt, size_t N = 1) { |
511 | return this->reserveForParamAndGetAddressImpl(this, Elt, N); |
512 | } |
513 | |
514 | /// Reserve enough space to add one element, and return the updated element |
515 | /// pointer in case it was a reference to the storage. |
516 | T *reserveForParamAndGetAddress(T &Elt, size_t N = 1) { |
517 | return const_cast<T *>( |
518 | this->reserveForParamAndGetAddressImpl(this, Elt, N)); |
519 | } |
520 | |
521 | /// Copy \p V or return a reference, depending on \a ValueParamT. |
522 | static ValueParamT forward_value_param(ValueParamT V) { return V; } |
523 | |
524 | void growAndAssign(size_t NumElts, T Elt) { |
525 | // Elt has been copied in case it's an internal reference, side-stepping |
526 | // reference invalidation problems without losing the realloc optimization. |
527 | this->set_size(0); |
528 | this->grow(NumElts); |
529 | std::uninitialized_fill_n(this->begin(), NumElts, Elt); |
530 | this->set_size(NumElts); |
531 | } |
532 | |
533 | template <typename... ArgTypes> T &growAndEmplaceBack(ArgTypes &&... Args) { |
534 | // Use push_back with a copy in case Args has an internal reference, |
535 | // side-stepping reference invalidation problems without losing the realloc |
536 | // optimization. |
537 | push_back(T(std::forward<ArgTypes>(Args)...)); |
538 | return this->back(); |
539 | } |
540 | |
541 | public: |
542 | void push_back(ValueParamT Elt) { |
543 | const T *EltPtr = reserveForParamAndGetAddress(Elt); |
544 | memcpy(reinterpret_cast<void *>(this->end()), EltPtr, sizeof(T)); |
545 | this->set_size(this->size() + 1); |
546 | } |
547 | |
548 | void pop_back() { this->set_size(this->size() - 1); } |
549 | }; |
550 | |
551 | /// This class consists of common code factored out of the SmallVector class to |
552 | /// reduce code duplication based on the SmallVector 'N' template parameter. |
553 | template <typename T> |
554 | class SmallVectorImpl : public SmallVectorTemplateBase<T> { |
555 | using SuperClass = SmallVectorTemplateBase<T>; |
556 | |
557 | public: |
558 | using iterator = typename SuperClass::iterator; |
559 | using const_iterator = typename SuperClass::const_iterator; |
560 | using reference = typename SuperClass::reference; |
561 | using size_type = typename SuperClass::size_type; |
562 | |
563 | protected: |
564 | using SmallVectorTemplateBase<T>::TakesParamByValue; |
565 | using ValueParamT = typename SuperClass::ValueParamT; |
566 | |
567 | // Default ctor - Initialize to empty. |
568 | explicit SmallVectorImpl(unsigned N) |
569 | : SmallVectorTemplateBase<T>(N) {} |
570 | |
571 | void assignRemote(SmallVectorImpl &&RHS) { |
572 | this->destroy_range(this->begin(), this->end()); |
573 | if (!this->isSmall()) |
574 | free(this->begin()); |
575 | this->BeginX = RHS.BeginX; |
576 | this->Size = RHS.Size; |
577 | this->Capacity = RHS.Capacity; |
578 | RHS.resetToSmall(); |
579 | } |
580 | |
581 | public: |
582 | SmallVectorImpl(const SmallVectorImpl &) = delete; |
583 | |
584 | ~SmallVectorImpl() { |
585 | // Subclass has already destructed this vector's elements. |
586 | // If this wasn't grown from the inline copy, deallocate the old space. |
587 | if (!this->isSmall()) |
588 | free(this->begin()); |
589 | } |
590 | |
591 | void clear() { |
592 | this->destroy_range(this->begin(), this->end()); |
593 | this->Size = 0; |
594 | } |
595 | |
596 | private: |
597 | // Make set_size() private to avoid misuse in subclasses. |
598 | using SuperClass::set_size; |
599 | |
600 | template <bool ForOverwrite> void resizeImpl(size_type N) { |
601 | if (N == this->size()) |
602 | return; |
603 | |
604 | if (N < this->size()) { |
605 | this->truncate(N); |
606 | return; |
607 | } |
608 | |
609 | this->reserve(N); |
610 | for (auto I = this->end(), E = this->begin() + N; I != E; ++I) |
611 | if (ForOverwrite) |
612 | new (&*I) T; |
613 | else |
614 | new (&*I) T(); |
615 | this->set_size(N); |
616 | } |
617 | |
618 | public: |
619 | void resize(size_type N) { resizeImpl<false>(N); } |
620 | |
621 | /// Like resize, but \ref T is POD, the new values won't be initialized. |
622 | void resize_for_overwrite(size_type N) { resizeImpl<true>(N); } |
623 | |
624 | /// Like resize, but requires that \p N is less than \a size(). |
625 | void truncate(size_type N) { |
626 | assert(this->size() >= N && "Cannot increase size with truncate")(static_cast <bool> (this->size() >= N && "Cannot increase size with truncate") ? void (0) : __assert_fail ("this->size() >= N && \"Cannot increase size with truncate\"" , "llvm/include/llvm/ADT/SmallVector.h", 626, __extension__ __PRETTY_FUNCTION__ )); |
627 | this->destroy_range(this->begin() + N, this->end()); |
628 | this->set_size(N); |
629 | } |
630 | |
631 | void resize(size_type N, ValueParamT NV) { |
632 | if (N == this->size()) |
633 | return; |
634 | |
635 | if (N < this->size()) { |
636 | this->truncate(N); |
637 | return; |
638 | } |
639 | |
640 | // N > this->size(). Defer to append. |
641 | this->append(N - this->size(), NV); |
642 | } |
643 | |
644 | void reserve(size_type N) { |
645 | if (this->capacity() < N) |
646 | this->grow(N); |
647 | } |
648 | |
649 | void pop_back_n(size_type NumItems) { |
650 | assert(this->size() >= NumItems)(static_cast <bool> (this->size() >= NumItems) ? void (0) : __assert_fail ("this->size() >= NumItems", "llvm/include/llvm/ADT/SmallVector.h" , 650, __extension__ __PRETTY_FUNCTION__)); |
651 | truncate(this->size() - NumItems); |
652 | } |
653 | |
654 | LLVM_NODISCARD[[clang::warn_unused_result]] T pop_back_val() { |
655 | T Result = ::std::move(this->back()); |
656 | this->pop_back(); |
657 | return Result; |
658 | } |
659 | |
660 | void swap(SmallVectorImpl &RHS); |
661 | |
662 | /// Add the specified range to the end of the SmallVector. |
663 | template <typename in_iter, |
664 | typename = std::enable_if_t<std::is_convertible< |
665 | typename std::iterator_traits<in_iter>::iterator_category, |
666 | std::input_iterator_tag>::value>> |
667 | void append(in_iter in_start, in_iter in_end) { |
668 | this->assertSafeToAddRange(in_start, in_end); |
669 | size_type NumInputs = std::distance(in_start, in_end); |
670 | this->reserve(this->size() + NumInputs); |
671 | this->uninitialized_copy(in_start, in_end, this->end()); |
672 | this->set_size(this->size() + NumInputs); |
673 | } |
674 | |
675 | /// Append \p NumInputs copies of \p Elt to the end. |
676 | void append(size_type NumInputs, ValueParamT Elt) { |
677 | const T *EltPtr = this->reserveForParamAndGetAddress(Elt, NumInputs); |
678 | std::uninitialized_fill_n(this->end(), NumInputs, *EltPtr); |
679 | this->set_size(this->size() + NumInputs); |
680 | } |
681 | |
682 | void append(std::initializer_list<T> IL) { |
683 | append(IL.begin(), IL.end()); |
684 | } |
685 | |
686 | void append(const SmallVectorImpl &RHS) { append(RHS.begin(), RHS.end()); } |
687 | |
688 | void assign(size_type NumElts, ValueParamT Elt) { |
689 | // Note that Elt could be an internal reference. |
690 | if (NumElts > this->capacity()) { |
691 | this->growAndAssign(NumElts, Elt); |
692 | return; |
693 | } |
694 | |
695 | // Assign over existing elements. |
696 | std::fill_n(this->begin(), std::min(NumElts, this->size()), Elt); |
697 | if (NumElts > this->size()) |
698 | std::uninitialized_fill_n(this->end(), NumElts - this->size(), Elt); |
699 | else if (NumElts < this->size()) |
700 | this->destroy_range(this->begin() + NumElts, this->end()); |
701 | this->set_size(NumElts); |
702 | } |
703 | |
704 | // FIXME: Consider assigning over existing elements, rather than clearing & |
705 | // re-initializing them - for all assign(...) variants. |
706 | |
707 | template <typename in_iter, |
708 | typename = std::enable_if_t<std::is_convertible< |
709 | typename std::iterator_traits<in_iter>::iterator_category, |
710 | std::input_iterator_tag>::value>> |
711 | void assign(in_iter in_start, in_iter in_end) { |
712 | this->assertSafeToReferenceAfterClear(in_start, in_end); |
713 | clear(); |
714 | append(in_start, in_end); |
715 | } |
716 | |
717 | void assign(std::initializer_list<T> IL) { |
718 | clear(); |
719 | append(IL); |
720 | } |
721 | |
722 | void assign(const SmallVectorImpl &RHS) { assign(RHS.begin(), RHS.end()); } |
723 | |
724 | iterator erase(const_iterator CI) { |
725 | // Just cast away constness because this is a non-const member function. |
726 | iterator I = const_cast<iterator>(CI); |
727 | |
728 | assert(this->isReferenceToStorage(CI) && "Iterator to erase is out of bounds.")(static_cast <bool> (this->isReferenceToStorage(CI) && "Iterator to erase is out of bounds.") ? void (0) : __assert_fail ("this->isReferenceToStorage(CI) && \"Iterator to erase is out of bounds.\"" , "llvm/include/llvm/ADT/SmallVector.h", 728, __extension__ __PRETTY_FUNCTION__ )); |
729 | |
730 | iterator N = I; |
731 | // Shift all elts down one. |
732 | std::move(I+1, this->end(), I); |
733 | // Drop the last elt. |
734 | this->pop_back(); |
735 | return(N); |
736 | } |
737 | |
738 | iterator erase(const_iterator CS, const_iterator CE) { |
739 | // Just cast away constness because this is a non-const member function. |
740 | iterator S = const_cast<iterator>(CS); |
741 | iterator E = const_cast<iterator>(CE); |
742 | |
743 | assert(this->isRangeInStorage(S, E) && "Range to erase is out of bounds.")(static_cast <bool> (this->isRangeInStorage(S, E) && "Range to erase is out of bounds.") ? void (0) : __assert_fail ("this->isRangeInStorage(S, E) && \"Range to erase is out of bounds.\"" , "llvm/include/llvm/ADT/SmallVector.h", 743, __extension__ __PRETTY_FUNCTION__ )); |
744 | |
745 | iterator N = S; |
746 | // Shift all elts down. |
747 | iterator I = std::move(E, this->end(), S); |
748 | // Drop the last elts. |
749 | this->destroy_range(I, this->end()); |
750 | this->set_size(I - this->begin()); |
751 | return(N); |
752 | } |
753 | |
754 | private: |
755 | template <class ArgType> iterator insert_one_impl(iterator I, ArgType &&Elt) { |
756 | // Callers ensure that ArgType is derived from T. |
757 | static_assert( |
758 | std::is_same<std::remove_const_t<std::remove_reference_t<ArgType>>, |
759 | T>::value, |
760 | "ArgType must be derived from T!"); |
761 | |
762 | if (I == this->end()) { // Important special case for empty vector. |
763 | this->push_back(::std::forward<ArgType>(Elt)); |
764 | return this->end()-1; |
765 | } |
766 | |
767 | assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.")(static_cast <bool> (this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.") ? void (0) : __assert_fail ("this->isReferenceToStorage(I) && \"Insertion iterator is out of bounds.\"" , "llvm/include/llvm/ADT/SmallVector.h", 767, __extension__ __PRETTY_FUNCTION__ )); |
768 | |
769 | // Grow if necessary. |
770 | size_t Index = I - this->begin(); |
771 | std::remove_reference_t<ArgType> *EltPtr = |
772 | this->reserveForParamAndGetAddress(Elt); |
773 | I = this->begin() + Index; |
774 | |
775 | ::new ((void*) this->end()) T(::std::move(this->back())); |
776 | // Push everything else over. |
777 | std::move_backward(I, this->end()-1, this->end()); |
778 | this->set_size(this->size() + 1); |
779 | |
780 | // If we just moved the element we're inserting, be sure to update |
781 | // the reference (never happens if TakesParamByValue). |
782 | static_assert(!TakesParamByValue || std::is_same<ArgType, T>::value, |
783 | "ArgType must be 'T' when taking by value!"); |
784 | if (!TakesParamByValue && this->isReferenceToRange(EltPtr, I, this->end())) |
785 | ++EltPtr; |
786 | |
787 | *I = ::std::forward<ArgType>(*EltPtr); |
788 | return I; |
789 | } |
790 | |
791 | public: |
792 | iterator insert(iterator I, T &&Elt) { |
793 | return insert_one_impl(I, this->forward_value_param(std::move(Elt))); |
794 | } |
795 | |
796 | iterator insert(iterator I, const T &Elt) { |
797 | return insert_one_impl(I, this->forward_value_param(Elt)); |
798 | } |
799 | |
800 | iterator insert(iterator I, size_type NumToInsert, ValueParamT Elt) { |
801 | // Convert iterator to elt# to avoid invalidating iterator when we reserve() |
802 | size_t InsertElt = I - this->begin(); |
803 | |
804 | if (I == this->end()) { // Important special case for empty vector. |
805 | append(NumToInsert, Elt); |
806 | return this->begin()+InsertElt; |
807 | } |
808 | |
809 | assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.")(static_cast <bool> (this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.") ? void (0) : __assert_fail ("this->isReferenceToStorage(I) && \"Insertion iterator is out of bounds.\"" , "llvm/include/llvm/ADT/SmallVector.h", 809, __extension__ __PRETTY_FUNCTION__ )); |
810 | |
811 | // Ensure there is enough space, and get the (maybe updated) address of |
812 | // Elt. |
813 | const T *EltPtr = this->reserveForParamAndGetAddress(Elt, NumToInsert); |
814 | |
815 | // Uninvalidate the iterator. |
816 | I = this->begin()+InsertElt; |
817 | |
818 | // If there are more elements between the insertion point and the end of the |
819 | // range than there are being inserted, we can use a simple approach to |
820 | // insertion. Since we already reserved space, we know that this won't |
821 | // reallocate the vector. |
822 | if (size_t(this->end()-I) >= NumToInsert) { |
823 | T *OldEnd = this->end(); |
824 | append(std::move_iterator<iterator>(this->end() - NumToInsert), |
825 | std::move_iterator<iterator>(this->end())); |
826 | |
827 | // Copy the existing elements that get replaced. |
828 | std::move_backward(I, OldEnd-NumToInsert, OldEnd); |
829 | |
830 | // If we just moved the element we're inserting, be sure to update |
831 | // the reference (never happens if TakesParamByValue). |
832 | if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end()) |
833 | EltPtr += NumToInsert; |
834 | |
835 | std::fill_n(I, NumToInsert, *EltPtr); |
836 | return I; |
837 | } |
838 | |
839 | // Otherwise, we're inserting more elements than exist already, and we're |
840 | // not inserting at the end. |
841 | |
842 | // Move over the elements that we're about to overwrite. |
843 | T *OldEnd = this->end(); |
844 | this->set_size(this->size() + NumToInsert); |
845 | size_t NumOverwritten = OldEnd-I; |
846 | this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); |
847 | |
848 | // If we just moved the element we're inserting, be sure to update |
849 | // the reference (never happens if TakesParamByValue). |
850 | if (!TakesParamByValue && I <= EltPtr && EltPtr < this->end()) |
851 | EltPtr += NumToInsert; |
852 | |
853 | // Replace the overwritten part. |
854 | std::fill_n(I, NumOverwritten, *EltPtr); |
855 | |
856 | // Insert the non-overwritten middle part. |
857 | std::uninitialized_fill_n(OldEnd, NumToInsert - NumOverwritten, *EltPtr); |
858 | return I; |
859 | } |
860 | |
861 | template <typename ItTy, |
862 | typename = std::enable_if_t<std::is_convertible< |
863 | typename std::iterator_traits<ItTy>::iterator_category, |
864 | std::input_iterator_tag>::value>> |
865 | iterator insert(iterator I, ItTy From, ItTy To) { |
866 | // Convert iterator to elt# to avoid invalidating iterator when we reserve() |
867 | size_t InsertElt = I - this->begin(); |
868 | |
869 | if (I == this->end()) { // Important special case for empty vector. |
870 | append(From, To); |
871 | return this->begin()+InsertElt; |
872 | } |
873 | |
874 | assert(this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.")(static_cast <bool> (this->isReferenceToStorage(I) && "Insertion iterator is out of bounds.") ? void (0) : __assert_fail ("this->isReferenceToStorage(I) && \"Insertion iterator is out of bounds.\"" , "llvm/include/llvm/ADT/SmallVector.h", 874, __extension__ __PRETTY_FUNCTION__ )); |
875 | |
876 | // Check that the reserve that follows doesn't invalidate the iterators. |
877 | this->assertSafeToAddRange(From, To); |
878 | |
879 | size_t NumToInsert = std::distance(From, To); |
880 | |
881 | // Ensure there is enough space. |
882 | reserve(this->size() + NumToInsert); |
883 | |
884 | // Uninvalidate the iterator. |
885 | I = this->begin()+InsertElt; |
886 | |
887 | // If there are more elements between the insertion point and the end of the |
888 | // range than there are being inserted, we can use a simple approach to |
889 | // insertion. Since we already reserved space, we know that this won't |
890 | // reallocate the vector. |
891 | if (size_t(this->end()-I) >= NumToInsert) { |
892 | T *OldEnd = this->end(); |
893 | append(std::move_iterator<iterator>(this->end() - NumToInsert), |
894 | std::move_iterator<iterator>(this->end())); |
895 | |
896 | // Copy the existing elements that get replaced. |
897 | std::move_backward(I, OldEnd-NumToInsert, OldEnd); |
898 | |
899 | std::copy(From, To, I); |
900 | return I; |
901 | } |
902 | |
903 | // Otherwise, we're inserting more elements than exist already, and we're |
904 | // not inserting at the end. |
905 | |
906 | // Move over the elements that we're about to overwrite. |
907 | T *OldEnd = this->end(); |
908 | this->set_size(this->size() + NumToInsert); |
909 | size_t NumOverwritten = OldEnd-I; |
910 | this->uninitialized_move(I, OldEnd, this->end()-NumOverwritten); |
911 | |
912 | // Replace the overwritten part. |
913 | for (T *J = I; NumOverwritten > 0; --NumOverwritten) { |
914 | *J = *From; |
915 | ++J; ++From; |
916 | } |
917 | |
918 | // Insert the non-overwritten middle part. |
919 | this->uninitialized_copy(From, To, OldEnd); |
920 | return I; |
921 | } |
922 | |
923 | void insert(iterator I, std::initializer_list<T> IL) { |
924 | insert(I, IL.begin(), IL.end()); |
925 | } |
926 | |
927 | template <typename... ArgTypes> reference emplace_back(ArgTypes &&... Args) { |
928 | if (LLVM_UNLIKELY(this->size() >= this->capacity())__builtin_expect((bool)(this->size() >= this->capacity ()), false)) |
929 | return this->growAndEmplaceBack(std::forward<ArgTypes>(Args)...); |
930 | |
931 | ::new ((void *)this->end()) T(std::forward<ArgTypes>(Args)...); |
932 | this->set_size(this->size() + 1); |
933 | return this->back(); |
934 | } |
935 | |
936 | SmallVectorImpl &operator=(const SmallVectorImpl &RHS); |
937 | |
938 | SmallVectorImpl &operator=(SmallVectorImpl &&RHS); |
939 | |
940 | bool operator==(const SmallVectorImpl &RHS) const { |
941 | if (this->size() != RHS.size()) return false; |
942 | return std::equal(this->begin(), this->end(), RHS.begin()); |
943 | } |
944 | bool operator!=(const SmallVectorImpl &RHS) const { |
945 | return !(*this == RHS); |
946 | } |
947 | |
948 | bool operator<(const SmallVectorImpl &RHS) const { |
949 | return std::lexicographical_compare(this->begin(), this->end(), |
950 | RHS.begin(), RHS.end()); |
951 | } |
952 | }; |
953 | |
954 | template <typename T> |
955 | void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) { |
956 | if (this == &RHS) return; |
957 | |
958 | // We can only avoid copying elements if neither vector is small. |
959 | if (!this->isSmall() && !RHS.isSmall()) { |
960 | std::swap(this->BeginX, RHS.BeginX); |
961 | std::swap(this->Size, RHS.Size); |
962 | std::swap(this->Capacity, RHS.Capacity); |
963 | return; |
964 | } |
965 | this->reserve(RHS.size()); |
966 | RHS.reserve(this->size()); |
967 | |
968 | // Swap the shared elements. |
969 | size_t NumShared = this->size(); |
970 | if (NumShared > RHS.size()) NumShared = RHS.size(); |
971 | for (size_type i = 0; i != NumShared; ++i) |
972 | std::swap((*this)[i], RHS[i]); |
973 | |
974 | // Copy over the extra elts. |
975 | if (this->size() > RHS.size()) { |
976 | size_t EltDiff = this->size() - RHS.size(); |
977 | this->uninitialized_copy(this->begin()+NumShared, this->end(), RHS.end()); |
978 | RHS.set_size(RHS.size() + EltDiff); |
979 | this->destroy_range(this->begin()+NumShared, this->end()); |
980 | this->set_size(NumShared); |
981 | } else if (RHS.size() > this->size()) { |
982 | size_t EltDiff = RHS.size() - this->size(); |
983 | this->uninitialized_copy(RHS.begin()+NumShared, RHS.end(), this->end()); |
984 | this->set_size(this->size() + EltDiff); |
985 | this->destroy_range(RHS.begin()+NumShared, RHS.end()); |
986 | RHS.set_size(NumShared); |
987 | } |
988 | } |
989 | |
990 | template <typename T> |
991 | SmallVectorImpl<T> &SmallVectorImpl<T>:: |
992 | operator=(const SmallVectorImpl<T> &RHS) { |
993 | // Avoid self-assignment. |
994 | if (this == &RHS) return *this; |
995 | |
996 | // If we already have sufficient space, assign the common elements, then |
997 | // destroy any excess. |
998 | size_t RHSSize = RHS.size(); |
999 | size_t CurSize = this->size(); |
1000 | if (CurSize >= RHSSize) { |
1001 | // Assign common elements. |
1002 | iterator NewEnd; |
1003 | if (RHSSize) |
1004 | NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, this->begin()); |
1005 | else |
1006 | NewEnd = this->begin(); |
1007 | |
1008 | // Destroy excess elements. |
1009 | this->destroy_range(NewEnd, this->end()); |
1010 | |
1011 | // Trim. |
1012 | this->set_size(RHSSize); |
1013 | return *this; |
1014 | } |
1015 | |
1016 | // If we have to grow to have enough elements, destroy the current elements. |
1017 | // This allows us to avoid copying them during the grow. |
1018 | // FIXME: don't do this if they're efficiently moveable. |
1019 | if (this->capacity() < RHSSize) { |
1020 | // Destroy current elements. |
1021 | this->clear(); |
1022 | CurSize = 0; |
1023 | this->grow(RHSSize); |
1024 | } else if (CurSize) { |
1025 | // Otherwise, use assignment for the already-constructed elements. |
1026 | std::copy(RHS.begin(), RHS.begin()+CurSize, this->begin()); |
1027 | } |
1028 | |
1029 | // Copy construct the new elements in place. |
1030 | this->uninitialized_copy(RHS.begin()+CurSize, RHS.end(), |
1031 | this->begin()+CurSize); |
1032 | |
1033 | // Set end. |
1034 | this->set_size(RHSSize); |
1035 | return *this; |
1036 | } |
1037 | |
1038 | template <typename T> |
1039 | SmallVectorImpl<T> &SmallVectorImpl<T>::operator=(SmallVectorImpl<T> &&RHS) { |
1040 | // Avoid self-assignment. |
1041 | if (this == &RHS) return *this; |
1042 | |
1043 | // If the RHS isn't small, clear this vector and then steal its buffer. |
1044 | if (!RHS.isSmall()) { |
1045 | this->assignRemote(std::move(RHS)); |
1046 | return *this; |
1047 | } |
1048 | |
1049 | // If we already have sufficient space, assign the common elements, then |
1050 | // destroy any excess. |
1051 | size_t RHSSize = RHS.size(); |
1052 | size_t CurSize = this->size(); |
1053 | if (CurSize >= RHSSize) { |
1054 | // Assign common elements. |
1055 | iterator NewEnd = this->begin(); |
1056 | if (RHSSize) |
1057 | NewEnd = std::move(RHS.begin(), RHS.end(), NewEnd); |
1058 | |
1059 | // Destroy excess elements and trim the bounds. |
1060 | this->destroy_range(NewEnd, this->end()); |
1061 | this->set_size(RHSSize); |
1062 | |
1063 | // Clear the RHS. |
1064 | RHS.clear(); |
1065 | |
1066 | return *this; |
1067 | } |
1068 | |
1069 | // If we have to grow to have enough elements, destroy the current elements. |
1070 | // This allows us to avoid copying them during the grow. |
1071 | // FIXME: this may not actually make any sense if we can efficiently move |
1072 | // elements. |
1073 | if (this->capacity() < RHSSize) { |
1074 | // Destroy current elements. |
1075 | this->clear(); |
1076 | CurSize = 0; |
1077 | this->grow(RHSSize); |
1078 | } else if (CurSize) { |
1079 | // Otherwise, use assignment for the already-constructed elements. |
1080 | std::move(RHS.begin(), RHS.begin()+CurSize, this->begin()); |
1081 | } |
1082 | |
1083 | // Move-construct the new elements in place. |
1084 | this->uninitialized_move(RHS.begin()+CurSize, RHS.end(), |
1085 | this->begin()+CurSize); |
1086 | |
1087 | // Set end. |
1088 | this->set_size(RHSSize); |
1089 | |
1090 | RHS.clear(); |
1091 | return *this; |
1092 | } |
1093 | |
1094 | /// Storage for the SmallVector elements. This is specialized for the N=0 case |
1095 | /// to avoid allocating unnecessary storage. |
1096 | template <typename T, unsigned N> |
1097 | struct SmallVectorStorage { |
1098 | alignas(T) char InlineElts[N * sizeof(T)]; |
1099 | }; |
1100 | |
1101 | /// We need the storage to be properly aligned even for small-size of 0 so that |
1102 | /// the pointer math in \a SmallVectorTemplateCommon::getFirstEl() is |
1103 | /// well-defined. |
1104 | template <typename T> struct alignas(T) SmallVectorStorage<T, 0> {}; |
1105 | |
1106 | /// Forward declaration of SmallVector so that |
1107 | /// calculateSmallVectorDefaultInlinedElements can reference |
1108 | /// `sizeof(SmallVector<T, 0>)`. |
1109 | template <typename T, unsigned N> class LLVM_GSL_OWNER[[gsl::Owner]] SmallVector; |
1110 | |
1111 | /// Helper class for calculating the default number of inline elements for |
1112 | /// `SmallVector<T>`. |
1113 | /// |
1114 | /// This should be migrated to a constexpr function when our minimum |
1115 | /// compiler support is enough for multi-statement constexpr functions. |
1116 | template <typename T> struct CalculateSmallVectorDefaultInlinedElements { |
1117 | // Parameter controlling the default number of inlined elements |
1118 | // for `SmallVector<T>`. |
1119 | // |
1120 | // The default number of inlined elements ensures that |
1121 | // 1. There is at least one inlined element. |
1122 | // 2. `sizeof(SmallVector<T>) <= kPreferredSmallVectorSizeof` unless |
1123 | // it contradicts 1. |
1124 | static constexpr size_t kPreferredSmallVectorSizeof = 64; |
1125 | |
1126 | // static_assert that sizeof(T) is not "too big". |
1127 | // |
1128 | // Because our policy guarantees at least one inlined element, it is possible |
1129 | // for an arbitrarily large inlined element to allocate an arbitrarily large |
1130 | // amount of inline storage. We generally consider it an antipattern for a |
1131 | // SmallVector to allocate an excessive amount of inline storage, so we want |
1132 | // to call attention to these cases and make sure that users are making an |
1133 | // intentional decision if they request a lot of inline storage. |
1134 | // |
1135 | // We want this assertion to trigger in pathological cases, but otherwise |
1136 | // not be too easy to hit. To accomplish that, the cutoff is actually somewhat |
1137 | // larger than kPreferredSmallVectorSizeof (otherwise, |
1138 | // `SmallVector<SmallVector<T>>` would be one easy way to trip it, and that |
1139 | // pattern seems useful in practice). |
1140 | // |
1141 | // One wrinkle is that this assertion is in theory non-portable, since |
1142 | // sizeof(T) is in general platform-dependent. However, we don't expect this |
1143 | // to be much of an issue, because most LLVM development happens on 64-bit |
1144 | // hosts, and therefore sizeof(T) is expected to *decrease* when compiled for |
1145 | // 32-bit hosts, dodging the issue. The reverse situation, where development |
1146 | // happens on a 32-bit host and then fails due to sizeof(T) *increasing* on a |
1147 | // 64-bit host, is expected to be very rare. |
1148 | static_assert( |
1149 | sizeof(T) <= 256, |
1150 | "You are trying to use a default number of inlined elements for " |
1151 | "`SmallVector<T>` but `sizeof(T)` is really big! Please use an " |
1152 | "explicit number of inlined elements with `SmallVector<T, N>` to make " |
1153 | "sure you really want that much inline storage."); |
1154 | |
1155 | // Discount the size of the header itself when calculating the maximum inline |
1156 | // bytes. |
1157 | static constexpr size_t PreferredInlineBytes = |
1158 | kPreferredSmallVectorSizeof - sizeof(SmallVector<T, 0>); |
1159 | static constexpr size_t NumElementsThatFit = PreferredInlineBytes / sizeof(T); |
1160 | static constexpr size_t value = |
1161 | NumElementsThatFit == 0 ? 1 : NumElementsThatFit; |
1162 | }; |
1163 | |
1164 | /// This is a 'vector' (really, a variable-sized array), optimized |
1165 | /// for the case when the array is small. It contains some number of elements |
1166 | /// in-place, which allows it to avoid heap allocation when the actual number of |
1167 | /// elements is below that threshold. This allows normal "small" cases to be |
1168 | /// fast without losing generality for large inputs. |
1169 | /// |
1170 | /// \note |
1171 | /// In the absence of a well-motivated choice for the number of inlined |
1172 | /// elements \p N, it is recommended to use \c SmallVector<T> (that is, |
1173 | /// omitting the \p N). This will choose a default number of inlined elements |
1174 | /// reasonable for allocation on the stack (for example, trying to keep \c |
1175 | /// sizeof(SmallVector<T>) around 64 bytes). |
1176 | /// |
1177 | /// \warning This does not attempt to be exception safe. |
1178 | /// |
1179 | /// \see https://llvm.org/docs/ProgrammersManual.html#llvm-adt-smallvector-h |
1180 | template <typename T, |
1181 | unsigned N = CalculateSmallVectorDefaultInlinedElements<T>::value> |
1182 | class LLVM_GSL_OWNER[[gsl::Owner]] SmallVector : public SmallVectorImpl<T>, |
1183 | SmallVectorStorage<T, N> { |
1184 | public: |
1185 | SmallVector() : SmallVectorImpl<T>(N) {} |
1186 | |
1187 | ~SmallVector() { |
1188 | // Destroy the constructed elements in the vector. |
1189 | this->destroy_range(this->begin(), this->end()); |
1190 | } |
1191 | |
1192 | explicit SmallVector(size_t Size, const T &Value = T()) |
1193 | : SmallVectorImpl<T>(N) { |
1194 | this->assign(Size, Value); |
1195 | } |
1196 | |
1197 | template <typename ItTy, |
1198 | typename = std::enable_if_t<std::is_convertible< |
1199 | typename std::iterator_traits<ItTy>::iterator_category, |
1200 | std::input_iterator_tag>::value>> |
1201 | SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(N) { |
1202 | this->append(S, E); |
1203 | } |
1204 | |
1205 | template <typename RangeTy> |
1206 | explicit SmallVector(const iterator_range<RangeTy> &R) |
1207 | : SmallVectorImpl<T>(N) { |
1208 | this->append(R.begin(), R.end()); |
1209 | } |
1210 | |
1211 | SmallVector(std::initializer_list<T> IL) : SmallVectorImpl<T>(N) { |
1212 | this->assign(IL); |
1213 | } |
1214 | |
1215 | SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(N) { |
1216 | if (!RHS.empty()) |
1217 | SmallVectorImpl<T>::operator=(RHS); |
1218 | } |
1219 | |
1220 | SmallVector &operator=(const SmallVector &RHS) { |
1221 | SmallVectorImpl<T>::operator=(RHS); |
1222 | return *this; |
1223 | } |
1224 | |
1225 | SmallVector(SmallVector &&RHS) : SmallVectorImpl<T>(N) { |
1226 | if (!RHS.empty()) |
1227 | SmallVectorImpl<T>::operator=(::std::move(RHS)); |
1228 | } |
1229 | |
1230 | SmallVector(SmallVectorImpl<T> &&RHS) : SmallVectorImpl<T>(N) { |
1231 | if (!RHS.empty()) |
1232 | SmallVectorImpl<T>::operator=(::std::move(RHS)); |
1233 | } |
1234 | |
1235 | SmallVector &operator=(SmallVector &&RHS) { |
1236 | if (N) { |
1237 | SmallVectorImpl<T>::operator=(::std::move(RHS)); |
1238 | return *this; |
1239 | } |
1240 | // SmallVectorImpl<T>::operator= does not leverage N==0. Optimize the |
1241 | // case. |
1242 | if (this == &RHS) |
1243 | return *this; |
1244 | if (RHS.empty()) { |
1245 | this->destroy_range(this->begin(), this->end()); |
1246 | this->Size = 0; |
1247 | } else { |
1248 | this->assignRemote(std::move(RHS)); |
1249 | } |
1250 | return *this; |
1251 | } |
1252 | |
1253 | SmallVector &operator=(SmallVectorImpl<T> &&RHS) { |
1254 | SmallVectorImpl<T>::operator=(::std::move(RHS)); |
1255 | return *this; |
1256 | } |
1257 | |
1258 | SmallVector &operator=(std::initializer_list<T> IL) { |
1259 | this->assign(IL); |
1260 | return *this; |
1261 | } |
1262 | }; |
1263 | |
1264 | template <typename T, unsigned N> |
1265 | inline size_t capacity_in_bytes(const SmallVector<T, N> &X) { |
1266 | return X.capacity_in_bytes(); |
1267 | } |
1268 | |
1269 | template <typename RangeType> |
1270 | using ValueTypeFromRangeType = |
1271 | typename std::remove_const<typename std::remove_reference< |
1272 | decltype(*std::begin(std::declval<RangeType &>()))>::type>::type; |
1273 | |
1274 | /// Given a range of type R, iterate the entire range and return a |
1275 | /// SmallVector with elements of the vector. This is useful, for example, |
1276 | /// when you want to iterate a range and then sort the results. |
1277 | template <unsigned Size, typename R> |
1278 | SmallVector<ValueTypeFromRangeType<R>, Size> to_vector(R &&Range) { |
1279 | return {std::begin(Range), std::end(Range)}; |
1280 | } |
1281 | template <typename R> |
1282 | SmallVector<ValueTypeFromRangeType<R>, |
1283 | CalculateSmallVectorDefaultInlinedElements< |
1284 | ValueTypeFromRangeType<R>>::value> |
1285 | to_vector(R &&Range) { |
1286 | return {std::begin(Range), std::end(Range)}; |
1287 | } |
1288 | |
1289 | } // end namespace llvm |
1290 | |
1291 | namespace std { |
1292 | |
1293 | /// Implement std::swap in terms of SmallVector swap. |
1294 | template<typename T> |
1295 | inline void |
1296 | swap(llvm::SmallVectorImpl<T> &LHS, llvm::SmallVectorImpl<T> &RHS) { |
1297 | LHS.swap(RHS); |
1298 | } |
1299 | |
1300 | /// Implement std::swap in terms of SmallVector swap. |
1301 | template<typename T, unsigned N> |
1302 | inline void |
1303 | swap(llvm::SmallVector<T, N> &LHS, llvm::SmallVector<T, N> &RHS) { |
1304 | LHS.swap(RHS); |
1305 | } |
1306 | |
1307 | } // end namespace std |
1308 | |
1309 | #endif // LLVM_ADT_SMALLVECTOR_H |
1 | //===-- llvm/IntrinsicInst.h - Intrinsic Instruction Wrappers ---*- C++ -*-===// | |||
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 file defines classes that make it really easy to deal with intrinsic | |||
10 | // functions with the isa/dyncast family of functions. In particular, this | |||
11 | // allows you to do things like: | |||
12 | // | |||
13 | // if (MemCpyInst *MCI = dyn_cast<MemCpyInst>(Inst)) | |||
14 | // ... MCI->getDest() ... MCI->getSource() ... | |||
15 | // | |||
16 | // All intrinsic function calls are instances of the call instruction, so these | |||
17 | // are all subclasses of the CallInst class. Note that none of these classes | |||
18 | // has state or virtual methods, which is an important part of this gross/neat | |||
19 | // hack working. | |||
20 | // | |||
21 | //===----------------------------------------------------------------------===// | |||
22 | ||||
23 | #ifndef LLVM_IR_INTRINSICINST_H | |||
24 | #define LLVM_IR_INTRINSICINST_H | |||
25 | ||||
26 | #include "llvm/IR/Constants.h" | |||
27 | #include "llvm/IR/DebugInfoMetadata.h" | |||
28 | #include "llvm/IR/DerivedTypes.h" | |||
29 | #include "llvm/IR/FPEnv.h" | |||
30 | #include "llvm/IR/Function.h" | |||
31 | #include "llvm/IR/GlobalVariable.h" | |||
32 | #include "llvm/IR/Instructions.h" | |||
33 | #include "llvm/IR/Intrinsics.h" | |||
34 | #include "llvm/IR/Metadata.h" | |||
35 | #include "llvm/IR/Value.h" | |||
36 | #include "llvm/Support/Casting.h" | |||
37 | #include <cassert> | |||
38 | #include <cstdint> | |||
39 | ||||
40 | namespace llvm { | |||
41 | ||||
42 | /// A wrapper class for inspecting calls to intrinsic functions. | |||
43 | /// This allows the standard isa/dyncast/cast functionality to work with calls | |||
44 | /// to intrinsic functions. | |||
45 | class IntrinsicInst : public CallInst { | |||
46 | public: | |||
47 | IntrinsicInst() = delete; | |||
48 | IntrinsicInst(const IntrinsicInst &) = delete; | |||
49 | IntrinsicInst &operator=(const IntrinsicInst &) = delete; | |||
50 | ||||
51 | /// Return the intrinsic ID of this intrinsic. | |||
52 | Intrinsic::ID getIntrinsicID() const { | |||
53 | return getCalledFunction()->getIntrinsicID(); | |||
54 | } | |||
55 | ||||
56 | /// Return true if swapping the first two arguments to the intrinsic produces | |||
57 | /// the same result. | |||
58 | bool isCommutative() const { | |||
59 | switch (getIntrinsicID()) { | |||
60 | case Intrinsic::maxnum: | |||
61 | case Intrinsic::minnum: | |||
62 | case Intrinsic::maximum: | |||
63 | case Intrinsic::minimum: | |||
64 | case Intrinsic::smax: | |||
65 | case Intrinsic::smin: | |||
66 | case Intrinsic::umax: | |||
67 | case Intrinsic::umin: | |||
68 | case Intrinsic::sadd_sat: | |||
69 | case Intrinsic::uadd_sat: | |||
70 | case Intrinsic::sadd_with_overflow: | |||
71 | case Intrinsic::uadd_with_overflow: | |||
72 | case Intrinsic::smul_with_overflow: | |||
73 | case Intrinsic::umul_with_overflow: | |||
74 | case Intrinsic::smul_fix: | |||
75 | case Intrinsic::umul_fix: | |||
76 | case Intrinsic::smul_fix_sat: | |||
77 | case Intrinsic::umul_fix_sat: | |||
78 | case Intrinsic::fma: | |||
79 | case Intrinsic::fmuladd: | |||
80 | return true; | |||
81 | default: | |||
82 | return false; | |||
83 | } | |||
84 | } | |||
85 | ||||
86 | // Checks if the intrinsic is an annotation. | |||
87 | bool isAssumeLikeIntrinsic() const { | |||
88 | switch (getIntrinsicID()) { | |||
89 | default: break; | |||
90 | case Intrinsic::assume: | |||
91 | case Intrinsic::sideeffect: | |||
92 | case Intrinsic::pseudoprobe: | |||
93 | case Intrinsic::dbg_declare: | |||
94 | case Intrinsic::dbg_value: | |||
95 | case Intrinsic::dbg_label: | |||
96 | case Intrinsic::invariant_start: | |||
97 | case Intrinsic::invariant_end: | |||
98 | case Intrinsic::lifetime_start: | |||
99 | case Intrinsic::lifetime_end: | |||
100 | case Intrinsic::experimental_noalias_scope_decl: | |||
101 | case Intrinsic::objectsize: | |||
102 | case Intrinsic::ptr_annotation: | |||
103 | case Intrinsic::var_annotation: | |||
104 | return true; | |||
105 | } | |||
106 | return false; | |||
107 | } | |||
108 | ||||
109 | // Methods for support type inquiry through isa, cast, and dyn_cast: | |||
110 | static bool classof(const CallInst *I) { | |||
111 | if (const Function *CF = I->getCalledFunction()) | |||
112 | return CF->isIntrinsic(); | |||
113 | return false; | |||
114 | } | |||
115 | static bool classof(const Value *V) { | |||
116 | return isa<CallInst>(V) && classof(cast<CallInst>(V)); | |||
117 | } | |||
118 | }; | |||
119 | ||||
120 | /// Check if \p ID corresponds to a debug info intrinsic. | |||
121 | static inline bool isDbgInfoIntrinsic(Intrinsic::ID ID) { | |||
122 | switch (ID) { | |||
123 | case Intrinsic::dbg_declare: | |||
124 | case Intrinsic::dbg_value: | |||
125 | case Intrinsic::dbg_addr: | |||
126 | case Intrinsic::dbg_label: | |||
127 | return true; | |||
128 | default: | |||
129 | return false; | |||
130 | } | |||
131 | } | |||
132 | ||||
133 | /// This is the common base class for debug info intrinsics. | |||
134 | class DbgInfoIntrinsic : public IntrinsicInst { | |||
135 | public: | |||
136 | /// \name Casting methods | |||
137 | /// @{ | |||
138 | static bool classof(const IntrinsicInst *I) { | |||
139 | return isDbgInfoIntrinsic(I->getIntrinsicID()); | |||
140 | } | |||
141 | static bool classof(const Value *V) { | |||
142 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
143 | } | |||
144 | /// @} | |||
145 | }; | |||
146 | ||||
147 | /// This is the common base class for debug info intrinsics for variables. | |||
148 | class DbgVariableIntrinsic : public DbgInfoIntrinsic { | |||
149 | public: | |||
150 | // Iterator for ValueAsMetadata that internally uses direct pointer iteration | |||
151 | // over either a ValueAsMetadata* or a ValueAsMetadata**, dereferencing to the | |||
152 | // ValueAsMetadata . | |||
153 | class location_op_iterator | |||
154 | : public iterator_facade_base<location_op_iterator, | |||
155 | std::bidirectional_iterator_tag, Value *> { | |||
156 | PointerUnion<ValueAsMetadata *, ValueAsMetadata **> I; | |||
157 | ||||
158 | public: | |||
159 | location_op_iterator(ValueAsMetadata *SingleIter) : I(SingleIter) {} | |||
160 | location_op_iterator(ValueAsMetadata **MultiIter) : I(MultiIter) {} | |||
161 | ||||
162 | location_op_iterator(const location_op_iterator &R) : I(R.I) {} | |||
163 | location_op_iterator &operator=(const location_op_iterator &R) { | |||
164 | I = R.I; | |||
165 | return *this; | |||
166 | } | |||
167 | bool operator==(const location_op_iterator &RHS) const { | |||
168 | return I == RHS.I; | |||
169 | } | |||
170 | const Value *operator*() const { | |||
171 | ValueAsMetadata *VAM = I.is<ValueAsMetadata *>() | |||
172 | ? I.get<ValueAsMetadata *>() | |||
173 | : *I.get<ValueAsMetadata **>(); | |||
174 | return VAM->getValue(); | |||
175 | }; | |||
176 | Value *operator*() { | |||
177 | ValueAsMetadata *VAM = I.is<ValueAsMetadata *>() | |||
178 | ? I.get<ValueAsMetadata *>() | |||
179 | : *I.get<ValueAsMetadata **>(); | |||
180 | return VAM->getValue(); | |||
181 | } | |||
182 | location_op_iterator &operator++() { | |||
183 | if (I.is<ValueAsMetadata *>()) | |||
184 | I = I.get<ValueAsMetadata *>() + 1; | |||
185 | else | |||
186 | I = I.get<ValueAsMetadata **>() + 1; | |||
187 | return *this; | |||
188 | } | |||
189 | location_op_iterator &operator--() { | |||
190 | if (I.is<ValueAsMetadata *>()) | |||
191 | I = I.get<ValueAsMetadata *>() - 1; | |||
192 | else | |||
193 | I = I.get<ValueAsMetadata **>() - 1; | |||
194 | return *this; | |||
195 | } | |||
196 | }; | |||
197 | ||||
198 | /// Get the locations corresponding to the variable referenced by the debug | |||
199 | /// info intrinsic. Depending on the intrinsic, this could be the | |||
200 | /// variable's value or its address. | |||
201 | iterator_range<location_op_iterator> location_ops() const; | |||
202 | ||||
203 | Value *getVariableLocationOp(unsigned OpIdx) const; | |||
204 | ||||
205 | void replaceVariableLocationOp(Value *OldValue, Value *NewValue); | |||
206 | void replaceVariableLocationOp(unsigned OpIdx, Value *NewValue); | |||
207 | /// Adding a new location operand will always result in this intrinsic using | |||
208 | /// an ArgList, and must always be accompanied by a new expression that uses | |||
209 | /// the new operand. | |||
210 | void addVariableLocationOps(ArrayRef<Value *> NewValues, | |||
211 | DIExpression *NewExpr); | |||
212 | ||||
213 | void setVariable(DILocalVariable *NewVar) { | |||
214 | setArgOperand(1, MetadataAsValue::get(NewVar->getContext(), NewVar)); | |||
215 | } | |||
216 | ||||
217 | void setExpression(DIExpression *NewExpr) { | |||
218 | setArgOperand(2, MetadataAsValue::get(NewExpr->getContext(), NewExpr)); | |||
| ||||
219 | } | |||
220 | ||||
221 | unsigned getNumVariableLocationOps() const { | |||
222 | if (hasArgList()) | |||
223 | return cast<DIArgList>(getRawLocation())->getArgs().size(); | |||
224 | return 1; | |||
225 | } | |||
226 | ||||
227 | bool hasArgList() const { return isa<DIArgList>(getRawLocation()); } | |||
228 | ||||
229 | /// Does this describe the address of a local variable. True for dbg.addr | |||
230 | /// and dbg.declare, but not dbg.value, which describes its value. | |||
231 | bool isAddressOfVariable() const { | |||
232 | return getIntrinsicID() != Intrinsic::dbg_value; | |||
233 | } | |||
234 | ||||
235 | void setUndef() { | |||
236 | // TODO: When/if we remove duplicate values from DIArgLists, we don't need | |||
237 | // this set anymore. | |||
238 | SmallPtrSet<Value *, 4> RemovedValues; | |||
239 | for (Value *OldValue : location_ops()) { | |||
240 | if (!RemovedValues.insert(OldValue).second) | |||
241 | continue; | |||
242 | Value *Undef = UndefValue::get(OldValue->getType()); | |||
243 | replaceVariableLocationOp(OldValue, Undef); | |||
244 | } | |||
245 | } | |||
246 | ||||
247 | bool isUndef() const { | |||
248 | return (getNumVariableLocationOps() == 0 && | |||
249 | !getExpression()->isComplex()) || | |||
250 | any_of(location_ops(), [](Value *V) { return isa<UndefValue>(V); }); | |||
251 | } | |||
252 | ||||
253 | DILocalVariable *getVariable() const { | |||
254 | return cast<DILocalVariable>(getRawVariable()); | |||
255 | } | |||
256 | ||||
257 | DIExpression *getExpression() const { | |||
258 | return cast<DIExpression>(getRawExpression()); | |||
259 | } | |||
260 | ||||
261 | Metadata *getRawLocation() const { | |||
262 | return cast<MetadataAsValue>(getArgOperand(0))->getMetadata(); | |||
263 | } | |||
264 | ||||
265 | Metadata *getRawVariable() const { | |||
266 | return cast<MetadataAsValue>(getArgOperand(1))->getMetadata(); | |||
267 | } | |||
268 | ||||
269 | Metadata *getRawExpression() const { | |||
270 | return cast<MetadataAsValue>(getArgOperand(2))->getMetadata(); | |||
271 | } | |||
272 | ||||
273 | /// Use of this should generally be avoided; instead, | |||
274 | /// replaceVariableLocationOp and addVariableLocationOps should be used where | |||
275 | /// possible to avoid creating invalid state. | |||
276 | void setRawLocation(Metadata *Location) { | |||
277 | return setArgOperand(0, MetadataAsValue::get(getContext(), Location)); | |||
278 | } | |||
279 | ||||
280 | /// Get the size (in bits) of the variable, or fragment of the variable that | |||
281 | /// is described. | |||
282 | Optional<uint64_t> getFragmentSizeInBits() const; | |||
283 | ||||
284 | /// \name Casting methods | |||
285 | /// @{ | |||
286 | static bool classof(const IntrinsicInst *I) { | |||
287 | switch (I->getIntrinsicID()) { | |||
288 | case Intrinsic::dbg_declare: | |||
289 | case Intrinsic::dbg_value: | |||
290 | case Intrinsic::dbg_addr: | |||
291 | return true; | |||
292 | default: | |||
293 | return false; | |||
294 | } | |||
295 | } | |||
296 | static bool classof(const Value *V) { | |||
297 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
298 | } | |||
299 | /// @} | |||
300 | private: | |||
301 | void setArgOperand(unsigned i, Value *v) { | |||
302 | DbgInfoIntrinsic::setArgOperand(i, v); | |||
303 | } | |||
304 | void setOperand(unsigned i, Value *v) { DbgInfoIntrinsic::setOperand(i, v); } | |||
305 | }; | |||
306 | ||||
307 | /// This represents the llvm.dbg.declare instruction. | |||
308 | class DbgDeclareInst : public DbgVariableIntrinsic { | |||
309 | public: | |||
310 | Value *getAddress() const { | |||
311 | assert(getNumVariableLocationOps() == 1 &&(static_cast <bool> (getNumVariableLocationOps() == 1 && "dbg.declare must have exactly 1 location operand.") ? void ( 0) : __assert_fail ("getNumVariableLocationOps() == 1 && \"dbg.declare must have exactly 1 location operand.\"" , "llvm/include/llvm/IR/IntrinsicInst.h", 312, __extension__ __PRETTY_FUNCTION__ )) | |||
312 | "dbg.declare must have exactly 1 location operand.")(static_cast <bool> (getNumVariableLocationOps() == 1 && "dbg.declare must have exactly 1 location operand.") ? void ( 0) : __assert_fail ("getNumVariableLocationOps() == 1 && \"dbg.declare must have exactly 1 location operand.\"" , "llvm/include/llvm/IR/IntrinsicInst.h", 312, __extension__ __PRETTY_FUNCTION__ )); | |||
313 | return getVariableLocationOp(0); | |||
314 | } | |||
315 | ||||
316 | /// \name Casting methods | |||
317 | /// @{ | |||
318 | static bool classof(const IntrinsicInst *I) { | |||
319 | return I->getIntrinsicID() == Intrinsic::dbg_declare; | |||
320 | } | |||
321 | static bool classof(const Value *V) { | |||
322 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
323 | } | |||
324 | /// @} | |||
325 | }; | |||
326 | ||||
327 | /// This represents the llvm.dbg.addr instruction. | |||
328 | class DbgAddrIntrinsic : public DbgVariableIntrinsic { | |||
329 | public: | |||
330 | Value *getAddress() const { | |||
331 | assert(getNumVariableLocationOps() == 1 &&(static_cast <bool> (getNumVariableLocationOps() == 1 && "dbg.addr must have exactly 1 location operand.") ? void (0) : __assert_fail ("getNumVariableLocationOps() == 1 && \"dbg.addr must have exactly 1 location operand.\"" , "llvm/include/llvm/IR/IntrinsicInst.h", 332, __extension__ __PRETTY_FUNCTION__ )) | |||
332 | "dbg.addr must have exactly 1 location operand.")(static_cast <bool> (getNumVariableLocationOps() == 1 && "dbg.addr must have exactly 1 location operand.") ? void (0) : __assert_fail ("getNumVariableLocationOps() == 1 && \"dbg.addr must have exactly 1 location operand.\"" , "llvm/include/llvm/IR/IntrinsicInst.h", 332, __extension__ __PRETTY_FUNCTION__ )); | |||
333 | return getVariableLocationOp(0); | |||
334 | } | |||
335 | ||||
336 | /// \name Casting methods | |||
337 | /// @{ | |||
338 | static bool classof(const IntrinsicInst *I) { | |||
339 | return I->getIntrinsicID() == Intrinsic::dbg_addr; | |||
340 | } | |||
341 | static bool classof(const Value *V) { | |||
342 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
343 | } | |||
344 | }; | |||
345 | ||||
346 | /// This represents the llvm.dbg.value instruction. | |||
347 | class DbgValueInst : public DbgVariableIntrinsic { | |||
348 | public: | |||
349 | // The default argument should only be used in ISel, and the default option | |||
350 | // should be removed once ISel support for multiple location ops is complete. | |||
351 | Value *getValue(unsigned OpIdx = 0) const { | |||
352 | return getVariableLocationOp(OpIdx); | |||
353 | } | |||
354 | iterator_range<location_op_iterator> getValues() const { | |||
355 | return location_ops(); | |||
356 | } | |||
357 | ||||
358 | /// \name Casting methods | |||
359 | /// @{ | |||
360 | static bool classof(const IntrinsicInst *I) { | |||
361 | return I->getIntrinsicID() == Intrinsic::dbg_value; | |||
362 | } | |||
363 | static bool classof(const Value *V) { | |||
364 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
365 | } | |||
366 | /// @} | |||
367 | }; | |||
368 | ||||
369 | /// This represents the llvm.dbg.label instruction. | |||
370 | class DbgLabelInst : public DbgInfoIntrinsic { | |||
371 | public: | |||
372 | DILabel *getLabel() const { return cast<DILabel>(getRawLabel()); } | |||
373 | ||||
374 | Metadata *getRawLabel() const { | |||
375 | return cast<MetadataAsValue>(getArgOperand(0))->getMetadata(); | |||
376 | } | |||
377 | ||||
378 | /// Methods for support type inquiry through isa, cast, and dyn_cast: | |||
379 | /// @{ | |||
380 | static bool classof(const IntrinsicInst *I) { | |||
381 | return I->getIntrinsicID() == Intrinsic::dbg_label; | |||
382 | } | |||
383 | static bool classof(const Value *V) { | |||
384 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
385 | } | |||
386 | /// @} | |||
387 | }; | |||
388 | ||||
389 | /// This is the common base class for vector predication intrinsics. | |||
390 | class VPIntrinsic : public IntrinsicInst { | |||
391 | public: | |||
392 | /// \brief Declares a llvm.vp.* intrinsic in \p M that matches the parameters | |||
393 | /// \p Params. Additionally, the load and gather intrinsics require | |||
394 | /// \p ReturnType to be specified. | |||
395 | static Function *getDeclarationForParams(Module *M, Intrinsic::ID, | |||
396 | Type *ReturnType, | |||
397 | ArrayRef<Value *> Params); | |||
398 | ||||
399 | static Optional<unsigned> getMaskParamPos(Intrinsic::ID IntrinsicID); | |||
400 | static Optional<unsigned> getVectorLengthParamPos(Intrinsic::ID IntrinsicID); | |||
401 | ||||
402 | /// The llvm.vp.* intrinsics for this instruction Opcode | |||
403 | static Intrinsic::ID getForOpcode(unsigned OC); | |||
404 | ||||
405 | // Whether \p ID is a VP intrinsic ID. | |||
406 | static bool isVPIntrinsic(Intrinsic::ID); | |||
407 | ||||
408 | /// \return The mask parameter or nullptr. | |||
409 | Value *getMaskParam() const; | |||
410 | void setMaskParam(Value *); | |||
411 | ||||
412 | /// \return The vector length parameter or nullptr. | |||
413 | Value *getVectorLengthParam() const; | |||
414 | void setVectorLengthParam(Value *); | |||
415 | ||||
416 | /// \return Whether the vector length param can be ignored. | |||
417 | bool canIgnoreVectorLengthParam() const; | |||
418 | ||||
419 | /// \return The static element count (vector number of elements) the vector | |||
420 | /// length parameter applies to. | |||
421 | ElementCount getStaticVectorLength() const; | |||
422 | ||||
423 | /// \return The alignment of the pointer used by this load/store/gather or | |||
424 | /// scatter. | |||
425 | MaybeAlign getPointerAlignment() const; | |||
426 | // MaybeAlign setPointerAlignment(Align NewAlign); // TODO | |||
427 | ||||
428 | /// \return The pointer operand of this load,store, gather or scatter. | |||
429 | Value *getMemoryPointerParam() const; | |||
430 | static Optional<unsigned> getMemoryPointerParamPos(Intrinsic::ID); | |||
431 | ||||
432 | /// \return The data (payload) operand of this store or scatter. | |||
433 | Value *getMemoryDataParam() const; | |||
434 | static Optional<unsigned> getMemoryDataParamPos(Intrinsic::ID); | |||
435 | ||||
436 | // Methods for support type inquiry through isa, cast, and dyn_cast: | |||
437 | static bool classof(const IntrinsicInst *I) { | |||
438 | return isVPIntrinsic(I->getIntrinsicID()); | |||
439 | } | |||
440 | static bool classof(const Value *V) { | |||
441 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
442 | } | |||
443 | ||||
444 | // Equivalent non-predicated opcode | |||
445 | Optional<unsigned> getFunctionalOpcode() const { | |||
446 | return getFunctionalOpcodeForVP(getIntrinsicID()); | |||
447 | } | |||
448 | ||||
449 | // Equivalent non-predicated opcode | |||
450 | static Optional<unsigned> getFunctionalOpcodeForVP(Intrinsic::ID ID); | |||
451 | }; | |||
452 | ||||
453 | /// This represents vector predication reduction intrinsics. | |||
454 | class VPReductionIntrinsic : public VPIntrinsic { | |||
455 | public: | |||
456 | static bool isVPReduction(Intrinsic::ID ID); | |||
457 | ||||
458 | unsigned getStartParamPos() const; | |||
459 | unsigned getVectorParamPos() const; | |||
460 | ||||
461 | static Optional<unsigned> getStartParamPos(Intrinsic::ID ID); | |||
462 | static Optional<unsigned> getVectorParamPos(Intrinsic::ID ID); | |||
463 | ||||
464 | /// Methods for support type inquiry through isa, cast, and dyn_cast: | |||
465 | /// @{ | |||
466 | static bool classof(const IntrinsicInst *I) { | |||
467 | return VPReductionIntrinsic::isVPReduction(I->getIntrinsicID()); | |||
468 | } | |||
469 | static bool classof(const Value *V) { | |||
470 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
471 | } | |||
472 | /// @} | |||
473 | }; | |||
474 | ||||
475 | /// This is the common base class for constrained floating point intrinsics. | |||
476 | class ConstrainedFPIntrinsic : public IntrinsicInst { | |||
477 | public: | |||
478 | bool isUnaryOp() const; | |||
479 | bool isTernaryOp() const; | |||
480 | Optional<RoundingMode> getRoundingMode() const; | |||
481 | Optional<fp::ExceptionBehavior> getExceptionBehavior() const; | |||
482 | bool isDefaultFPEnvironment() const; | |||
483 | ||||
484 | // Methods for support type inquiry through isa, cast, and dyn_cast: | |||
485 | static bool classof(const IntrinsicInst *I); | |||
486 | static bool classof(const Value *V) { | |||
487 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
488 | } | |||
489 | }; | |||
490 | ||||
491 | /// Constrained floating point compare intrinsics. | |||
492 | class ConstrainedFPCmpIntrinsic : public ConstrainedFPIntrinsic { | |||
493 | public: | |||
494 | FCmpInst::Predicate getPredicate() const; | |||
495 | bool isSignaling() const { | |||
496 | return getIntrinsicID() == Intrinsic::experimental_constrained_fcmps; | |||
497 | } | |||
498 | ||||
499 | // Methods for support type inquiry through isa, cast, and dyn_cast: | |||
500 | static bool classof(const IntrinsicInst *I) { | |||
501 | switch (I->getIntrinsicID()) { | |||
502 | case Intrinsic::experimental_constrained_fcmp: | |||
503 | case Intrinsic::experimental_constrained_fcmps: | |||
504 | return true; | |||
505 | default: | |||
506 | return false; | |||
507 | } | |||
508 | } | |||
509 | static bool classof(const Value *V) { | |||
510 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
511 | } | |||
512 | }; | |||
513 | ||||
514 | /// This class represents min/max intrinsics. | |||
515 | class MinMaxIntrinsic : public IntrinsicInst { | |||
516 | public: | |||
517 | static bool classof(const IntrinsicInst *I) { | |||
518 | switch (I->getIntrinsicID()) { | |||
519 | case Intrinsic::umin: | |||
520 | case Intrinsic::umax: | |||
521 | case Intrinsic::smin: | |||
522 | case Intrinsic::smax: | |||
523 | return true; | |||
524 | default: | |||
525 | return false; | |||
526 | } | |||
527 | } | |||
528 | static bool classof(const Value *V) { | |||
529 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
530 | } | |||
531 | ||||
532 | Value *getLHS() const { return const_cast<Value *>(getArgOperand(0)); } | |||
533 | Value *getRHS() const { return const_cast<Value *>(getArgOperand(1)); } | |||
534 | ||||
535 | /// Returns the comparison predicate underlying the intrinsic. | |||
536 | static ICmpInst::Predicate getPredicate(Intrinsic::ID ID) { | |||
537 | switch (ID) { | |||
538 | case Intrinsic::umin: | |||
539 | return ICmpInst::Predicate::ICMP_ULT; | |||
540 | case Intrinsic::umax: | |||
541 | return ICmpInst::Predicate::ICMP_UGT; | |||
542 | case Intrinsic::smin: | |||
543 | return ICmpInst::Predicate::ICMP_SLT; | |||
544 | case Intrinsic::smax: | |||
545 | return ICmpInst::Predicate::ICMP_SGT; | |||
546 | default: | |||
547 | llvm_unreachable("Invalid intrinsic")::llvm::llvm_unreachable_internal("Invalid intrinsic", "llvm/include/llvm/IR/IntrinsicInst.h" , 547); | |||
548 | } | |||
549 | } | |||
550 | ||||
551 | /// Returns the comparison predicate underlying the intrinsic. | |||
552 | ICmpInst::Predicate getPredicate() const { | |||
553 | return getPredicate(getIntrinsicID()); | |||
554 | } | |||
555 | ||||
556 | /// Whether the intrinsic is signed or unsigned. | |||
557 | static bool isSigned(Intrinsic::ID ID) { | |||
558 | return ICmpInst::isSigned(getPredicate(ID)); | |||
559 | }; | |||
560 | ||||
561 | /// Whether the intrinsic is signed or unsigned. | |||
562 | bool isSigned() const { return isSigned(getIntrinsicID()); }; | |||
563 | ||||
564 | /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values, | |||
565 | /// so there is a certain threshold value, upon reaching which, | |||
566 | /// their value can no longer change. Return said threshold. | |||
567 | static APInt getSaturationPoint(Intrinsic::ID ID, unsigned numBits) { | |||
568 | switch (ID) { | |||
569 | case Intrinsic::umin: | |||
570 | return APInt::getMinValue(numBits); | |||
571 | case Intrinsic::umax: | |||
572 | return APInt::getMaxValue(numBits); | |||
573 | case Intrinsic::smin: | |||
574 | return APInt::getSignedMinValue(numBits); | |||
575 | case Intrinsic::smax: | |||
576 | return APInt::getSignedMaxValue(numBits); | |||
577 | default: | |||
578 | llvm_unreachable("Invalid intrinsic")::llvm::llvm_unreachable_internal("Invalid intrinsic", "llvm/include/llvm/IR/IntrinsicInst.h" , 578); | |||
579 | } | |||
580 | } | |||
581 | ||||
582 | /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values, | |||
583 | /// so there is a certain threshold value, upon reaching which, | |||
584 | /// their value can no longer change. Return said threshold. | |||
585 | APInt getSaturationPoint(unsigned numBits) const { | |||
586 | return getSaturationPoint(getIntrinsicID(), numBits); | |||
587 | } | |||
588 | ||||
589 | /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values, | |||
590 | /// so there is a certain threshold value, upon reaching which, | |||
591 | /// their value can no longer change. Return said threshold. | |||
592 | static Constant *getSaturationPoint(Intrinsic::ID ID, Type *Ty) { | |||
593 | return Constant::getIntegerValue( | |||
594 | Ty, getSaturationPoint(ID, Ty->getScalarSizeInBits())); | |||
595 | } | |||
596 | ||||
597 | /// Min/max intrinsics are monotonic, they operate on a fixed-bitwidth values, | |||
598 | /// so there is a certain threshold value, upon reaching which, | |||
599 | /// their value can no longer change. Return said threshold. | |||
600 | Constant *getSaturationPoint(Type *Ty) const { | |||
601 | return getSaturationPoint(getIntrinsicID(), Ty); | |||
602 | } | |||
603 | }; | |||
604 | ||||
605 | /// This class represents an intrinsic that is based on a binary operation. | |||
606 | /// This includes op.with.overflow and saturating add/sub intrinsics. | |||
607 | class BinaryOpIntrinsic : public IntrinsicInst { | |||
608 | public: | |||
609 | static bool classof(const IntrinsicInst *I) { | |||
610 | switch (I->getIntrinsicID()) { | |||
611 | case Intrinsic::uadd_with_overflow: | |||
612 | case Intrinsic::sadd_with_overflow: | |||
613 | case Intrinsic::usub_with_overflow: | |||
614 | case Intrinsic::ssub_with_overflow: | |||
615 | case Intrinsic::umul_with_overflow: | |||
616 | case Intrinsic::smul_with_overflow: | |||
617 | case Intrinsic::uadd_sat: | |||
618 | case Intrinsic::sadd_sat: | |||
619 | case Intrinsic::usub_sat: | |||
620 | case Intrinsic::ssub_sat: | |||
621 | return true; | |||
622 | default: | |||
623 | return false; | |||
624 | } | |||
625 | } | |||
626 | static bool classof(const Value *V) { | |||
627 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
628 | } | |||
629 | ||||
630 | Value *getLHS() const { return const_cast<Value *>(getArgOperand(0)); } | |||
631 | Value *getRHS() const { return const_cast<Value *>(getArgOperand(1)); } | |||
632 | ||||
633 | /// Returns the binary operation underlying the intrinsic. | |||
634 | Instruction::BinaryOps getBinaryOp() const; | |||
635 | ||||
636 | /// Whether the intrinsic is signed or unsigned. | |||
637 | bool isSigned() const; | |||
638 | ||||
639 | /// Returns one of OBO::NoSignedWrap or OBO::NoUnsignedWrap. | |||
640 | unsigned getNoWrapKind() const; | |||
641 | }; | |||
642 | ||||
643 | /// Represents an op.with.overflow intrinsic. | |||
644 | class WithOverflowInst : public BinaryOpIntrinsic { | |||
645 | public: | |||
646 | static bool classof(const IntrinsicInst *I) { | |||
647 | switch (I->getIntrinsicID()) { | |||
648 | case Intrinsic::uadd_with_overflow: | |||
649 | case Intrinsic::sadd_with_overflow: | |||
650 | case Intrinsic::usub_with_overflow: | |||
651 | case Intrinsic::ssub_with_overflow: | |||
652 | case Intrinsic::umul_with_overflow: | |||
653 | case Intrinsic::smul_with_overflow: | |||
654 | return true; | |||
655 | default: | |||
656 | return false; | |||
657 | } | |||
658 | } | |||
659 | static bool classof(const Value *V) { | |||
660 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
661 | } | |||
662 | }; | |||
663 | ||||
664 | /// Represents a saturating add/sub intrinsic. | |||
665 | class SaturatingInst : public BinaryOpIntrinsic { | |||
666 | public: | |||
667 | static bool classof(const IntrinsicInst *I) { | |||
668 | switch (I->getIntrinsicID()) { | |||
669 | case Intrinsic::uadd_sat: | |||
670 | case Intrinsic::sadd_sat: | |||
671 | case Intrinsic::usub_sat: | |||
672 | case Intrinsic::ssub_sat: | |||
673 | return true; | |||
674 | default: | |||
675 | return false; | |||
676 | } | |||
677 | } | |||
678 | static bool classof(const Value *V) { | |||
679 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
680 | } | |||
681 | }; | |||
682 | ||||
683 | /// Common base class for all memory intrinsics. Simply provides | |||
684 | /// common methods. | |||
685 | /// Written as CRTP to avoid a common base class amongst the | |||
686 | /// three atomicity hierarchies. | |||
687 | template <typename Derived> class MemIntrinsicBase : public IntrinsicInst { | |||
688 | private: | |||
689 | enum { ARG_DEST = 0, ARG_LENGTH = 2 }; | |||
690 | ||||
691 | public: | |||
692 | Value *getRawDest() const { | |||
693 | return const_cast<Value *>(getArgOperand(ARG_DEST)); | |||
694 | } | |||
695 | const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); } | |||
696 | Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); } | |||
697 | ||||
698 | Value *getLength() const { | |||
699 | return const_cast<Value *>(getArgOperand(ARG_LENGTH)); | |||
700 | } | |||
701 | const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); } | |||
702 | Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); } | |||
703 | ||||
704 | /// This is just like getRawDest, but it strips off any cast | |||
705 | /// instructions (including addrspacecast) that feed it, giving the | |||
706 | /// original input. The returned value is guaranteed to be a pointer. | |||
707 | Value *getDest() const { return getRawDest()->stripPointerCasts(); } | |||
708 | ||||
709 | unsigned getDestAddressSpace() const { | |||
710 | return cast<PointerType>(getRawDest()->getType())->getAddressSpace(); | |||
711 | } | |||
712 | ||||
713 | /// FIXME: Remove this function once transition to Align is over. | |||
714 | /// Use getDestAlign() instead. | |||
715 | unsigned getDestAlignment() const { | |||
716 | if (auto MA = getParamAlign(ARG_DEST)) | |||
717 | return MA->value(); | |||
718 | return 0; | |||
719 | } | |||
720 | MaybeAlign getDestAlign() const { return getParamAlign(ARG_DEST); } | |||
721 | ||||
722 | /// Set the specified arguments of the instruction. | |||
723 | void setDest(Value *Ptr) { | |||
724 | assert(getRawDest()->getType() == Ptr->getType() &&(static_cast <bool> (getRawDest()->getType() == Ptr-> getType() && "setDest called with pointer of wrong type!" ) ? void (0) : __assert_fail ("getRawDest()->getType() == Ptr->getType() && \"setDest called with pointer of wrong type!\"" , "llvm/include/llvm/IR/IntrinsicInst.h", 725, __extension__ __PRETTY_FUNCTION__ )) | |||
725 | "setDest called with pointer of wrong type!")(static_cast <bool> (getRawDest()->getType() == Ptr-> getType() && "setDest called with pointer of wrong type!" ) ? void (0) : __assert_fail ("getRawDest()->getType() == Ptr->getType() && \"setDest called with pointer of wrong type!\"" , "llvm/include/llvm/IR/IntrinsicInst.h", 725, __extension__ __PRETTY_FUNCTION__ )); | |||
726 | setArgOperand(ARG_DEST, Ptr); | |||
727 | } | |||
728 | ||||
729 | /// FIXME: Remove this function once transition to Align is over. | |||
730 | /// Use the version that takes MaybeAlign instead of this one. | |||
731 | void setDestAlignment(unsigned Alignment) { | |||
732 | setDestAlignment(MaybeAlign(Alignment)); | |||
733 | } | |||
734 | void setDestAlignment(MaybeAlign Alignment) { | |||
735 | removeParamAttr(ARG_DEST, Attribute::Alignment); | |||
736 | if (Alignment) | |||
737 | addParamAttr(ARG_DEST, | |||
738 | Attribute::getWithAlignment(getContext(), *Alignment)); | |||
739 | } | |||
740 | void setDestAlignment(Align Alignment) { | |||
741 | removeParamAttr(ARG_DEST, Attribute::Alignment); | |||
742 | addParamAttr(ARG_DEST, | |||
743 | Attribute::getWithAlignment(getContext(), Alignment)); | |||
744 | } | |||
745 | ||||
746 | void setLength(Value *L) { | |||
747 | assert(getLength()->getType() == L->getType() &&(static_cast <bool> (getLength()->getType() == L-> getType() && "setLength called with value of wrong type!" ) ? void (0) : __assert_fail ("getLength()->getType() == L->getType() && \"setLength called with value of wrong type!\"" , "llvm/include/llvm/IR/IntrinsicInst.h", 748, __extension__ __PRETTY_FUNCTION__ )) | |||
748 | "setLength called with value of wrong type!")(static_cast <bool> (getLength()->getType() == L-> getType() && "setLength called with value of wrong type!" ) ? void (0) : __assert_fail ("getLength()->getType() == L->getType() && \"setLength called with value of wrong type!\"" , "llvm/include/llvm/IR/IntrinsicInst.h", 748, __extension__ __PRETTY_FUNCTION__ )); | |||
749 | setArgOperand(ARG_LENGTH, L); | |||
750 | } | |||
751 | }; | |||
752 | ||||
753 | /// Common base class for all memory transfer intrinsics. Simply provides | |||
754 | /// common methods. | |||
755 | template <class BaseCL> class MemTransferBase : public BaseCL { | |||
756 | private: | |||
757 | enum { ARG_SOURCE = 1 }; | |||
758 | ||||
759 | public: | |||
760 | /// Return the arguments to the instruction. | |||
761 | Value *getRawSource() const { | |||
762 | return const_cast<Value *>(BaseCL::getArgOperand(ARG_SOURCE)); | |||
763 | } | |||
764 | const Use &getRawSourceUse() const { | |||
765 | return BaseCL::getArgOperandUse(ARG_SOURCE); | |||
766 | } | |||
767 | Use &getRawSourceUse() { return BaseCL::getArgOperandUse(ARG_SOURCE); } | |||
768 | ||||
769 | /// This is just like getRawSource, but it strips off any cast | |||
770 | /// instructions that feed it, giving the original input. The returned | |||
771 | /// value is guaranteed to be a pointer. | |||
772 | Value *getSource() const { return getRawSource()->stripPointerCasts(); } | |||
773 | ||||
774 | unsigned getSourceAddressSpace() const { | |||
775 | return cast<PointerType>(getRawSource()->getType())->getAddressSpace(); | |||
776 | } | |||
777 | ||||
778 | /// FIXME: Remove this function once transition to Align is over. | |||
779 | /// Use getSourceAlign() instead. | |||
780 | unsigned getSourceAlignment() const { | |||
781 | if (auto MA = BaseCL::getParamAlign(ARG_SOURCE)) | |||
782 | return MA->value(); | |||
783 | return 0; | |||
784 | } | |||
785 | ||||
786 | MaybeAlign getSourceAlign() const { | |||
787 | return BaseCL::getParamAlign(ARG_SOURCE); | |||
788 | } | |||
789 | ||||
790 | void setSource(Value *Ptr) { | |||
791 | assert(getRawSource()->getType() == Ptr->getType() &&(static_cast <bool> (getRawSource()->getType() == Ptr ->getType() && "setSource called with pointer of wrong type!" ) ? void (0) : __assert_fail ("getRawSource()->getType() == Ptr->getType() && \"setSource called with pointer of wrong type!\"" , "llvm/include/llvm/IR/IntrinsicInst.h", 792, __extension__ __PRETTY_FUNCTION__ )) | |||
792 | "setSource called with pointer of wrong type!")(static_cast <bool> (getRawSource()->getType() == Ptr ->getType() && "setSource called with pointer of wrong type!" ) ? void (0) : __assert_fail ("getRawSource()->getType() == Ptr->getType() && \"setSource called with pointer of wrong type!\"" , "llvm/include/llvm/IR/IntrinsicInst.h", 792, __extension__ __PRETTY_FUNCTION__ )); | |||
793 | BaseCL::setArgOperand(ARG_SOURCE, Ptr); | |||
794 | } | |||
795 | ||||
796 | /// FIXME: Remove this function once transition to Align is over. | |||
797 | /// Use the version that takes MaybeAlign instead of this one. | |||
798 | void setSourceAlignment(unsigned Alignment) { | |||
799 | setSourceAlignment(MaybeAlign(Alignment)); | |||
800 | } | |||
801 | void setSourceAlignment(MaybeAlign Alignment) { | |||
802 | BaseCL::removeParamAttr(ARG_SOURCE, Attribute::Alignment); | |||
803 | if (Alignment) | |||
804 | BaseCL::addParamAttr(ARG_SOURCE, Attribute::getWithAlignment( | |||
805 | BaseCL::getContext(), *Alignment)); | |||
806 | } | |||
807 | void setSourceAlignment(Align Alignment) { | |||
808 | BaseCL::removeParamAttr(ARG_SOURCE, Attribute::Alignment); | |||
809 | BaseCL::addParamAttr(ARG_SOURCE, Attribute::getWithAlignment( | |||
810 | BaseCL::getContext(), Alignment)); | |||
811 | } | |||
812 | }; | |||
813 | ||||
814 | /// Common base class for all memset intrinsics. Simply provides | |||
815 | /// common methods. | |||
816 | template <class BaseCL> class MemSetBase : public BaseCL { | |||
817 | private: | |||
818 | enum { ARG_VALUE = 1 }; | |||
819 | ||||
820 | public: | |||
821 | Value *getValue() const { | |||
822 | return const_cast<Value *>(BaseCL::getArgOperand(ARG_VALUE)); | |||
823 | } | |||
824 | const Use &getValueUse() const { return BaseCL::getArgOperandUse(ARG_VALUE); } | |||
825 | Use &getValueUse() { return BaseCL::getArgOperandUse(ARG_VALUE); } | |||
826 | ||||
827 | void setValue(Value *Val) { | |||
828 | assert(getValue()->getType() == Val->getType() &&(static_cast <bool> (getValue()->getType() == Val-> getType() && "setValue called with value of wrong type!" ) ? void (0) : __assert_fail ("getValue()->getType() == Val->getType() && \"setValue called with value of wrong type!\"" , "llvm/include/llvm/IR/IntrinsicInst.h", 829, __extension__ __PRETTY_FUNCTION__ )) | |||
829 | "setValue called with value of wrong type!")(static_cast <bool> (getValue()->getType() == Val-> getType() && "setValue called with value of wrong type!" ) ? void (0) : __assert_fail ("getValue()->getType() == Val->getType() && \"setValue called with value of wrong type!\"" , "llvm/include/llvm/IR/IntrinsicInst.h", 829, __extension__ __PRETTY_FUNCTION__ )); | |||
830 | BaseCL::setArgOperand(ARG_VALUE, Val); | |||
831 | } | |||
832 | }; | |||
833 | ||||
834 | // The common base class for the atomic memset/memmove/memcpy intrinsics | |||
835 | // i.e. llvm.element.unordered.atomic.memset/memcpy/memmove | |||
836 | class AtomicMemIntrinsic : public MemIntrinsicBase<AtomicMemIntrinsic> { | |||
837 | private: | |||
838 | enum { ARG_ELEMENTSIZE = 3 }; | |||
839 | ||||
840 | public: | |||
841 | Value *getRawElementSizeInBytes() const { | |||
842 | return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE)); | |||
843 | } | |||
844 | ||||
845 | ConstantInt *getElementSizeInBytesCst() const { | |||
846 | return cast<ConstantInt>(getRawElementSizeInBytes()); | |||
847 | } | |||
848 | ||||
849 | uint32_t getElementSizeInBytes() const { | |||
850 | return getElementSizeInBytesCst()->getZExtValue(); | |||
851 | } | |||
852 | ||||
853 | void setElementSizeInBytes(Constant *V) { | |||
854 | assert(V->getType() == Type::getInt8Ty(getContext()) &&(static_cast <bool> (V->getType() == Type::getInt8Ty (getContext()) && "setElementSizeInBytes called with value of wrong type!" ) ? void (0) : __assert_fail ("V->getType() == Type::getInt8Ty(getContext()) && \"setElementSizeInBytes called with value of wrong type!\"" , "llvm/include/llvm/IR/IntrinsicInst.h", 855, __extension__ __PRETTY_FUNCTION__ )) | |||
855 | "setElementSizeInBytes called with value of wrong type!")(static_cast <bool> (V->getType() == Type::getInt8Ty (getContext()) && "setElementSizeInBytes called with value of wrong type!" ) ? void (0) : __assert_fail ("V->getType() == Type::getInt8Ty(getContext()) && \"setElementSizeInBytes called with value of wrong type!\"" , "llvm/include/llvm/IR/IntrinsicInst.h", 855, __extension__ __PRETTY_FUNCTION__ )); | |||
856 | setArgOperand(ARG_ELEMENTSIZE, V); | |||
857 | } | |||
858 | ||||
859 | static bool classof(const IntrinsicInst *I) { | |||
860 | switch (I->getIntrinsicID()) { | |||
861 | case Intrinsic::memcpy_element_unordered_atomic: | |||
862 | case Intrinsic::memmove_element_unordered_atomic: | |||
863 | case Intrinsic::memset_element_unordered_atomic: | |||
864 | return true; | |||
865 | default: | |||
866 | return false; | |||
867 | } | |||
868 | } | |||
869 | static bool classof(const Value *V) { | |||
870 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
871 | } | |||
872 | }; | |||
873 | ||||
874 | /// This class represents atomic memset intrinsic | |||
875 | // i.e. llvm.element.unordered.atomic.memset | |||
876 | class AtomicMemSetInst : public MemSetBase<AtomicMemIntrinsic> { | |||
877 | public: | |||
878 | static bool classof(const IntrinsicInst *I) { | |||
879 | return I->getIntrinsicID() == Intrinsic::memset_element_unordered_atomic; | |||
880 | } | |||
881 | static bool classof(const Value *V) { | |||
882 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
883 | } | |||
884 | }; | |||
885 | ||||
886 | // This class wraps the atomic memcpy/memmove intrinsics | |||
887 | // i.e. llvm.element.unordered.atomic.memcpy/memmove | |||
888 | class AtomicMemTransferInst : public MemTransferBase<AtomicMemIntrinsic> { | |||
889 | public: | |||
890 | static bool classof(const IntrinsicInst *I) { | |||
891 | switch (I->getIntrinsicID()) { | |||
892 | case Intrinsic::memcpy_element_unordered_atomic: | |||
893 | case Intrinsic::memmove_element_unordered_atomic: | |||
894 | return true; | |||
895 | default: | |||
896 | return false; | |||
897 | } | |||
898 | } | |||
899 | static bool classof(const Value *V) { | |||
900 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
901 | } | |||
902 | }; | |||
903 | ||||
904 | /// This class represents the atomic memcpy intrinsic | |||
905 | /// i.e. llvm.element.unordered.atomic.memcpy | |||
906 | class AtomicMemCpyInst : public AtomicMemTransferInst { | |||
907 | public: | |||
908 | static bool classof(const IntrinsicInst *I) { | |||
909 | return I->getIntrinsicID() == Intrinsic::memcpy_element_unordered_atomic; | |||
910 | } | |||
911 | static bool classof(const Value *V) { | |||
912 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
913 | } | |||
914 | }; | |||
915 | ||||
916 | /// This class represents the atomic memmove intrinsic | |||
917 | /// i.e. llvm.element.unordered.atomic.memmove | |||
918 | class AtomicMemMoveInst : public AtomicMemTransferInst { | |||
919 | public: | |||
920 | static bool classof(const IntrinsicInst *I) { | |||
921 | return I->getIntrinsicID() == Intrinsic::memmove_element_unordered_atomic; | |||
922 | } | |||
923 | static bool classof(const Value *V) { | |||
924 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
925 | } | |||
926 | }; | |||
927 | ||||
928 | /// This is the common base class for memset/memcpy/memmove. | |||
929 | class MemIntrinsic : public MemIntrinsicBase<MemIntrinsic> { | |||
930 | private: | |||
931 | enum { ARG_VOLATILE = 3 }; | |||
932 | ||||
933 | public: | |||
934 | ConstantInt *getVolatileCst() const { | |||
935 | return cast<ConstantInt>(const_cast<Value *>(getArgOperand(ARG_VOLATILE))); | |||
936 | } | |||
937 | ||||
938 | bool isVolatile() const { return !getVolatileCst()->isZero(); } | |||
939 | ||||
940 | void setVolatile(Constant *V) { setArgOperand(ARG_VOLATILE, V); } | |||
941 | ||||
942 | // Methods for support type inquiry through isa, cast, and dyn_cast: | |||
943 | static bool classof(const IntrinsicInst *I) { | |||
944 | switch (I->getIntrinsicID()) { | |||
945 | case Intrinsic::memcpy: | |||
946 | case Intrinsic::memmove: | |||
947 | case Intrinsic::memset: | |||
948 | case Intrinsic::memcpy_inline: | |||
949 | return true; | |||
950 | default: | |||
951 | return false; | |||
952 | } | |||
953 | } | |||
954 | static bool classof(const Value *V) { | |||
955 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
956 | } | |||
957 | }; | |||
958 | ||||
959 | /// This class wraps the llvm.memset intrinsic. | |||
960 | class MemSetInst : public MemSetBase<MemIntrinsic> { | |||
961 | public: | |||
962 | // Methods for support type inquiry through isa, cast, and dyn_cast: | |||
963 | static bool classof(const IntrinsicInst *I) { | |||
964 | return I->getIntrinsicID() == Intrinsic::memset; | |||
965 | } | |||
966 | static bool classof(const Value *V) { | |||
967 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
968 | } | |||
969 | }; | |||
970 | ||||
971 | /// This class wraps the llvm.memcpy/memmove intrinsics. | |||
972 | class MemTransferInst : public MemTransferBase<MemIntrinsic> { | |||
973 | public: | |||
974 | // Methods for support type inquiry through isa, cast, and dyn_cast: | |||
975 | static bool classof(const IntrinsicInst *I) { | |||
976 | switch (I->getIntrinsicID()) { | |||
977 | case Intrinsic::memcpy: | |||
978 | case Intrinsic::memmove: | |||
979 | case Intrinsic::memcpy_inline: | |||
980 | return true; | |||
981 | default: | |||
982 | return false; | |||
983 | } | |||
984 | } | |||
985 | static bool classof(const Value *V) { | |||
986 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
987 | } | |||
988 | }; | |||
989 | ||||
990 | /// This class wraps the llvm.memcpy intrinsic. | |||
991 | class MemCpyInst : public MemTransferInst { | |||
992 | public: | |||
993 | // Methods for support type inquiry through isa, cast, and dyn_cast: | |||
994 | static bool classof(const IntrinsicInst *I) { | |||
995 | return I->getIntrinsicID() == Intrinsic::memcpy || | |||
996 | I->getIntrinsicID() == Intrinsic::memcpy_inline; | |||
997 | } | |||
998 | static bool classof(const Value *V) { | |||
999 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1000 | } | |||
1001 | }; | |||
1002 | ||||
1003 | /// This class wraps the llvm.memmove intrinsic. | |||
1004 | class MemMoveInst : public MemTransferInst { | |||
1005 | public: | |||
1006 | // Methods for support type inquiry through isa, cast, and dyn_cast: | |||
1007 | static bool classof(const IntrinsicInst *I) { | |||
1008 | return I->getIntrinsicID() == Intrinsic::memmove; | |||
1009 | } | |||
1010 | static bool classof(const Value *V) { | |||
1011 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1012 | } | |||
1013 | }; | |||
1014 | ||||
1015 | /// This class wraps the llvm.memcpy.inline intrinsic. | |||
1016 | class MemCpyInlineInst : public MemCpyInst { | |||
1017 | public: | |||
1018 | ConstantInt *getLength() const { | |||
1019 | return cast<ConstantInt>(MemCpyInst::getLength()); | |||
1020 | } | |||
1021 | // Methods for support type inquiry through isa, cast, and dyn_cast: | |||
1022 | static bool classof(const IntrinsicInst *I) { | |||
1023 | return I->getIntrinsicID() == Intrinsic::memcpy_inline; | |||
1024 | } | |||
1025 | static bool classof(const Value *V) { | |||
1026 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1027 | } | |||
1028 | }; | |||
1029 | ||||
1030 | // The common base class for any memset/memmove/memcpy intrinsics; | |||
1031 | // whether they be atomic or non-atomic. | |||
1032 | // i.e. llvm.element.unordered.atomic.memset/memcpy/memmove | |||
1033 | // and llvm.memset/memcpy/memmove | |||
1034 | class AnyMemIntrinsic : public MemIntrinsicBase<AnyMemIntrinsic> { | |||
1035 | public: | |||
1036 | bool isVolatile() const { | |||
1037 | // Only the non-atomic intrinsics can be volatile | |||
1038 | if (auto *MI = dyn_cast<MemIntrinsic>(this)) | |||
1039 | return MI->isVolatile(); | |||
1040 | return false; | |||
1041 | } | |||
1042 | ||||
1043 | static bool classof(const IntrinsicInst *I) { | |||
1044 | switch (I->getIntrinsicID()) { | |||
1045 | case Intrinsic::memcpy: | |||
1046 | case Intrinsic::memcpy_inline: | |||
1047 | case Intrinsic::memmove: | |||
1048 | case Intrinsic::memset: | |||
1049 | case Intrinsic::memcpy_element_unordered_atomic: | |||
1050 | case Intrinsic::memmove_element_unordered_atomic: | |||
1051 | case Intrinsic::memset_element_unordered_atomic: | |||
1052 | return true; | |||
1053 | default: | |||
1054 | return false; | |||
1055 | } | |||
1056 | } | |||
1057 | static bool classof(const Value *V) { | |||
1058 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1059 | } | |||
1060 | }; | |||
1061 | ||||
1062 | /// This class represents any memset intrinsic | |||
1063 | // i.e. llvm.element.unordered.atomic.memset | |||
1064 | // and llvm.memset | |||
1065 | class AnyMemSetInst : public MemSetBase<AnyMemIntrinsic> { | |||
1066 | public: | |||
1067 | static bool classof(const IntrinsicInst *I) { | |||
1068 | switch (I->getIntrinsicID()) { | |||
1069 | case Intrinsic::memset: | |||
1070 | case Intrinsic::memset_element_unordered_atomic: | |||
1071 | return true; | |||
1072 | default: | |||
1073 | return false; | |||
1074 | } | |||
1075 | } | |||
1076 | static bool classof(const Value *V) { | |||
1077 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1078 | } | |||
1079 | }; | |||
1080 | ||||
1081 | // This class wraps any memcpy/memmove intrinsics | |||
1082 | // i.e. llvm.element.unordered.atomic.memcpy/memmove | |||
1083 | // and llvm.memcpy/memmove | |||
1084 | class AnyMemTransferInst : public MemTransferBase<AnyMemIntrinsic> { | |||
1085 | public: | |||
1086 | static bool classof(const IntrinsicInst *I) { | |||
1087 | switch (I->getIntrinsicID()) { | |||
1088 | case Intrinsic::memcpy: | |||
1089 | case Intrinsic::memcpy_inline: | |||
1090 | case Intrinsic::memmove: | |||
1091 | case Intrinsic::memcpy_element_unordered_atomic: | |||
1092 | case Intrinsic::memmove_element_unordered_atomic: | |||
1093 | return true; | |||
1094 | default: | |||
1095 | return false; | |||
1096 | } | |||
1097 | } | |||
1098 | static bool classof(const Value *V) { | |||
1099 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1100 | } | |||
1101 | }; | |||
1102 | ||||
1103 | /// This class represents any memcpy intrinsic | |||
1104 | /// i.e. llvm.element.unordered.atomic.memcpy | |||
1105 | /// and llvm.memcpy | |||
1106 | class AnyMemCpyInst : public AnyMemTransferInst { | |||
1107 | public: | |||
1108 | static bool classof(const IntrinsicInst *I) { | |||
1109 | switch (I->getIntrinsicID()) { | |||
1110 | case Intrinsic::memcpy: | |||
1111 | case Intrinsic::memcpy_inline: | |||
1112 | case Intrinsic::memcpy_element_unordered_atomic: | |||
1113 | return true; | |||
1114 | default: | |||
1115 | return false; | |||
1116 | } | |||
1117 | } | |||
1118 | static bool classof(const Value *V) { | |||
1119 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1120 | } | |||
1121 | }; | |||
1122 | ||||
1123 | /// This class represents any memmove intrinsic | |||
1124 | /// i.e. llvm.element.unordered.atomic.memmove | |||
1125 | /// and llvm.memmove | |||
1126 | class AnyMemMoveInst : public AnyMemTransferInst { | |||
1127 | public: | |||
1128 | static bool classof(const IntrinsicInst *I) { | |||
1129 | switch (I->getIntrinsicID()) { | |||
1130 | case Intrinsic::memmove: | |||
1131 | case Intrinsic::memmove_element_unordered_atomic: | |||
1132 | return true; | |||
1133 | default: | |||
1134 | return false; | |||
1135 | } | |||
1136 | } | |||
1137 | static bool classof(const Value *V) { | |||
1138 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1139 | } | |||
1140 | }; | |||
1141 | ||||
1142 | /// This represents the llvm.va_start intrinsic. | |||
1143 | class VAStartInst : public IntrinsicInst { | |||
1144 | public: | |||
1145 | static bool classof(const IntrinsicInst *I) { | |||
1146 | return I->getIntrinsicID() == Intrinsic::vastart; | |||
1147 | } | |||
1148 | static bool classof(const Value *V) { | |||
1149 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1150 | } | |||
1151 | ||||
1152 | Value *getArgList() const { return const_cast<Value *>(getArgOperand(0)); } | |||
1153 | }; | |||
1154 | ||||
1155 | /// This represents the llvm.va_end intrinsic. | |||
1156 | class VAEndInst : public IntrinsicInst { | |||
1157 | public: | |||
1158 | static bool classof(const IntrinsicInst *I) { | |||
1159 | return I->getIntrinsicID() == Intrinsic::vaend; | |||
1160 | } | |||
1161 | static bool classof(const Value *V) { | |||
1162 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1163 | } | |||
1164 | ||||
1165 | Value *getArgList() const { return const_cast<Value *>(getArgOperand(0)); } | |||
1166 | }; | |||
1167 | ||||
1168 | /// This represents the llvm.va_copy intrinsic. | |||
1169 | class VACopyInst : public IntrinsicInst { | |||
1170 | public: | |||
1171 | static bool classof(const IntrinsicInst *I) { | |||
1172 | return I->getIntrinsicID() == Intrinsic::vacopy; | |||
1173 | } | |||
1174 | static bool classof(const Value *V) { | |||
1175 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1176 | } | |||
1177 | ||||
1178 | Value *getDest() const { return const_cast<Value *>(getArgOperand(0)); } | |||
1179 | Value *getSrc() const { return const_cast<Value *>(getArgOperand(1)); } | |||
1180 | }; | |||
1181 | ||||
1182 | /// A base class for all instrprof intrinsics. | |||
1183 | class InstrProfInstBase : public IntrinsicInst { | |||
1184 | public: | |||
1185 | // The name of the instrumented function. | |||
1186 | GlobalVariable *getName() const { | |||
1187 | return cast<GlobalVariable>( | |||
1188 | const_cast<Value *>(getArgOperand(0))->stripPointerCasts()); | |||
1189 | } | |||
1190 | // The hash of the CFG for the instrumented function. | |||
1191 | ConstantInt *getHash() const { | |||
1192 | return cast<ConstantInt>(const_cast<Value *>(getArgOperand(1))); | |||
1193 | } | |||
1194 | // The number of counters for the instrumented function. | |||
1195 | ConstantInt *getNumCounters() const; | |||
1196 | // The index of the counter that this instruction acts on. | |||
1197 | ConstantInt *getIndex() const; | |||
1198 | }; | |||
1199 | ||||
1200 | /// This represents the llvm.instrprof.cover intrinsic. | |||
1201 | class InstrProfCoverInst : public InstrProfInstBase { | |||
1202 | public: | |||
1203 | static bool classof(const IntrinsicInst *I) { | |||
1204 | return I->getIntrinsicID() == Intrinsic::instrprof_cover; | |||
1205 | } | |||
1206 | static bool classof(const Value *V) { | |||
1207 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1208 | } | |||
1209 | }; | |||
1210 | ||||
1211 | /// This represents the llvm.instrprof.increment intrinsic. | |||
1212 | class InstrProfIncrementInst : public InstrProfInstBase { | |||
1213 | public: | |||
1214 | static bool classof(const IntrinsicInst *I) { | |||
1215 | return I->getIntrinsicID() == Intrinsic::instrprof_increment; | |||
1216 | } | |||
1217 | static bool classof(const Value *V) { | |||
1218 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1219 | } | |||
1220 | Value *getStep() const; | |||
1221 | }; | |||
1222 | ||||
1223 | /// This represents the llvm.instrprof.increment.step intrinsic. | |||
1224 | class InstrProfIncrementInstStep : public InstrProfIncrementInst { | |||
1225 | public: | |||
1226 | static bool classof(const IntrinsicInst *I) { | |||
1227 | return I->getIntrinsicID() == Intrinsic::instrprof_increment_step; | |||
1228 | } | |||
1229 | static bool classof(const Value *V) { | |||
1230 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1231 | } | |||
1232 | }; | |||
1233 | ||||
1234 | /// This represents the llvm.instrprof.value.profile intrinsic. | |||
1235 | class InstrProfValueProfileInst : public InstrProfInstBase { | |||
1236 | public: | |||
1237 | static bool classof(const IntrinsicInst *I) { | |||
1238 | return I->getIntrinsicID() == Intrinsic::instrprof_value_profile; | |||
1239 | } | |||
1240 | static bool classof(const Value *V) { | |||
1241 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1242 | } | |||
1243 | ||||
1244 | Value *getTargetValue() const { | |||
1245 | return cast<Value>(const_cast<Value *>(getArgOperand(2))); | |||
1246 | } | |||
1247 | ||||
1248 | ConstantInt *getValueKind() const { | |||
1249 | return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3))); | |||
1250 | } | |||
1251 | ||||
1252 | // Returns the value site index. | |||
1253 | ConstantInt *getIndex() const { | |||
1254 | return cast<ConstantInt>(const_cast<Value *>(getArgOperand(4))); | |||
1255 | } | |||
1256 | }; | |||
1257 | ||||
1258 | class PseudoProbeInst : public IntrinsicInst { | |||
1259 | public: | |||
1260 | static bool classof(const IntrinsicInst *I) { | |||
1261 | return I->getIntrinsicID() == Intrinsic::pseudoprobe; | |||
1262 | } | |||
1263 | ||||
1264 | static bool classof(const Value *V) { | |||
1265 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1266 | } | |||
1267 | ||||
1268 | ConstantInt *getFuncGuid() const { | |||
1269 | return cast<ConstantInt>(const_cast<Value *>(getArgOperand(0))); | |||
1270 | } | |||
1271 | ||||
1272 | ConstantInt *getIndex() const { | |||
1273 | return cast<ConstantInt>(const_cast<Value *>(getArgOperand(1))); | |||
1274 | } | |||
1275 | ||||
1276 | ConstantInt *getAttributes() const { | |||
1277 | return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2))); | |||
1278 | } | |||
1279 | ||||
1280 | ConstantInt *getFactor() const { | |||
1281 | return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3))); | |||
1282 | } | |||
1283 | }; | |||
1284 | ||||
1285 | class NoAliasScopeDeclInst : public IntrinsicInst { | |||
1286 | public: | |||
1287 | static bool classof(const IntrinsicInst *I) { | |||
1288 | return I->getIntrinsicID() == Intrinsic::experimental_noalias_scope_decl; | |||
1289 | } | |||
1290 | ||||
1291 | static bool classof(const Value *V) { | |||
1292 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1293 | } | |||
1294 | ||||
1295 | MDNode *getScopeList() const { | |||
1296 | auto *MV = | |||
1297 | cast<MetadataAsValue>(getOperand(Intrinsic::NoAliasScopeDeclScopeArg)); | |||
1298 | return cast<MDNode>(MV->getMetadata()); | |||
1299 | } | |||
1300 | ||||
1301 | void setScopeList(MDNode *ScopeList) { | |||
1302 | setOperand(Intrinsic::NoAliasScopeDeclScopeArg, | |||
1303 | MetadataAsValue::get(getContext(), ScopeList)); | |||
1304 | } | |||
1305 | }; | |||
1306 | ||||
1307 | // Defined in Statepoint.h -- NOT a subclass of IntrinsicInst | |||
1308 | class GCStatepointInst; | |||
1309 | ||||
1310 | /// Common base class for representing values projected from a statepoint. | |||
1311 | /// Currently, the only projections available are gc.result and gc.relocate. | |||
1312 | class GCProjectionInst : public IntrinsicInst { | |||
1313 | public: | |||
1314 | static bool classof(const IntrinsicInst *I) { | |||
1315 | return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate || | |||
1316 | I->getIntrinsicID() == Intrinsic::experimental_gc_result; | |||
1317 | } | |||
1318 | ||||
1319 | static bool classof(const Value *V) { | |||
1320 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1321 | } | |||
1322 | ||||
1323 | /// Return true if this relocate is tied to the invoke statepoint. | |||
1324 | /// This includes relocates which are on the unwinding path. | |||
1325 | bool isTiedToInvoke() const { | |||
1326 | const Value *Token = getArgOperand(0); | |||
1327 | ||||
1328 | return isa<LandingPadInst>(Token) || isa<InvokeInst>(Token); | |||
1329 | } | |||
1330 | ||||
1331 | /// The statepoint with which this gc.relocate is associated. | |||
1332 | const GCStatepointInst *getStatepoint() const; | |||
1333 | }; | |||
1334 | ||||
1335 | /// Represents calls to the gc.relocate intrinsic. | |||
1336 | class GCRelocateInst : public GCProjectionInst { | |||
1337 | public: | |||
1338 | static bool classof(const IntrinsicInst *I) { | |||
1339 | return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate; | |||
1340 | } | |||
1341 | ||||
1342 | static bool classof(const Value *V) { | |||
1343 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1344 | } | |||
1345 | ||||
1346 | /// The index into the associate statepoint's argument list | |||
1347 | /// which contains the base pointer of the pointer whose | |||
1348 | /// relocation this gc.relocate describes. | |||
1349 | unsigned getBasePtrIndex() const { | |||
1350 | return cast<ConstantInt>(getArgOperand(1))->getZExtValue(); | |||
1351 | } | |||
1352 | ||||
1353 | /// The index into the associate statepoint's argument list which | |||
1354 | /// contains the pointer whose relocation this gc.relocate describes. | |||
1355 | unsigned getDerivedPtrIndex() const { | |||
1356 | return cast<ConstantInt>(getArgOperand(2))->getZExtValue(); | |||
1357 | } | |||
1358 | ||||
1359 | Value *getBasePtr() const; | |||
1360 | Value *getDerivedPtr() const; | |||
1361 | }; | |||
1362 | ||||
1363 | /// Represents calls to the gc.result intrinsic. | |||
1364 | class GCResultInst : public GCProjectionInst { | |||
1365 | public: | |||
1366 | static bool classof(const IntrinsicInst *I) { | |||
1367 | return I->getIntrinsicID() == Intrinsic::experimental_gc_result; | |||
1368 | } | |||
1369 | ||||
1370 | static bool classof(const Value *V) { | |||
1371 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1372 | } | |||
1373 | }; | |||
1374 | ||||
1375 | ||||
1376 | /// This represents the llvm.assume intrinsic. | |||
1377 | class AssumeInst : public IntrinsicInst { | |||
1378 | public: | |||
1379 | static bool classof(const IntrinsicInst *I) { | |||
1380 | return I->getIntrinsicID() == Intrinsic::assume; | |||
1381 | } | |||
1382 | static bool classof(const Value *V) { | |||
1383 | return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); | |||
1384 | } | |||
1385 | }; | |||
1386 | ||||
1387 | } // end namespace llvm | |||
1388 | ||||
1389 | #endif // LLVM_IR_INTRINSICINST_H |