llvm.org GIT mirror llvm / f0c3354
When inlining through an 'nounwind' call, mark inlined calls 'nounwind'. It is important for correct C++ exception handling that nounwind markings do not get lost, so this transformation is actually needed for correctness. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45218 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan Sands 11 years ago
9 changed file(s) with 118 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
947947 bool doesNotThrow() const {
948948 return paramHasAttr(0, ParamAttr::NoUnwind);
949949 }
950 void setDoesNotThrow(bool doesNotThrow = true);
950951
951952 /// @brief Determine if the call returns a structure.
952953 bool isStructReturn() const {
17511752 bool doesNotThrow() const {
17521753 return paramHasAttr(0, ParamAttr::NoUnwind);
17531754 }
1755 void setDoesNotThrow(bool doesNotThrow = true);
17541756
17551757 /// @brief Determine if the call returns a structure.
17561758 bool isStructReturn() const {
148148 static const ParamAttrsList *getModified(const ParamAttrsList *PAL,
149149 const ParamAttrsVector &modVec);
150150
151 /// @brief Add the specified attributes to those in PAL at index idx.
152 static const ParamAttrsList *includeAttrs(const ParamAttrsList *PAL,
153 uint16_t idx, uint16_t attrs);
154
155 /// @brief Remove the specified attributes from those in PAL at index idx.
156 static const ParamAttrsList *excludeAttrs(const ParamAttrsList *PAL,
157 uint16_t idx, uint16_t attrs);
158
151159 /// Returns whether each of the specified lists of attributes can be safely
152160 /// replaced with the other in a function or a function call.
153161 /// @brief Whether one attribute list can safely replace the other.
7474
7575 /// @brief Determine if the call cannot unwind.
7676 bool doesNotThrow() const;
77 void setDoesNotThrow(bool doesNotThrow = true);
7778
7879 /// getType - Return the type of the instruction that generated this call site
7980 ///
121121 // If the SCC doesn't unwind or doesn't throw, note this fact.
122122 if (!SCCMightUnwind || !SCCMightReturn)
123123 for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
124 uint16_t NewAttributes = ParamAttr::None;
125
126 if (!SCCMightUnwind)
127 NewAttributes |= ParamAttr::NoUnwind;
128 if (!SCCMightReturn)
129 NewAttributes |= ParamAttr::NoReturn;
130
124131 const ParamAttrsList *PAL = SCC[i]->getFunction()->getParamAttrs();
125 uint16_t RAttributes = PAL ? PAL->getParamAttrs(0) : 0;
126
127 if (!SCCMightUnwind)
128 RAttributes |= ParamAttr::NoUnwind;
129 if (!SCCMightReturn)
130 RAttributes |= ParamAttr::NoReturn;
131
132 ParamAttrsVector modVec;
133 modVec.push_back(ParamAttrsWithIndex::get(0, RAttributes));
134 PAL = ParamAttrsList::getModified(PAL, modVec);
132 PAL = ParamAttrsList::includeAttrs(PAL, 0, NewAttributes);
135133 SCC[i]->getFunction()->setParamAttrs(PAL);
136134 }
137135
80258025 }
80268026 }
80278027
8028 if (isa(Callee) && !CS.paramHasAttr(0, ParamAttr::NoUnwind)) {
8028 if (isa(Callee) && !CS.doesNotThrow()) {
80298029 // Inline asm calls cannot throw - mark them 'nounwind'.
8030 const ParamAttrsList *PAL = CS.getParamAttrs();
8031 uint16_t RAttributes = PAL ? PAL->getParamAttrs(0) : 0;
8032 RAttributes |= ParamAttr::NoUnwind;
8033
8034 ParamAttrsVector modVec;
8035 modVec.push_back(ParamAttrsWithIndex::get(0, RAttributes));
8036 PAL = ParamAttrsList::getModified(PAL, modVec);
8037 CS.setParamAttrs(PAL);
8030 CS.setDoesNotThrow();
80388031 Changed = true;
80398032 }
80408033
193193 bool MustClearTailCallFlags =
194194 isa(TheCall) && !cast(TheCall)->isTailCall();
195195
196 // If the call to the callee cannot throw, set the 'nounwind' flag on any
197 // calls that we inline.
198 bool MarkNoUnwind = CS.doesNotThrow();
199
196200 BasicBlock *OrigBB = TheCall->getParent();
197201 Function *Caller = OrigBB->getParent();
198202
206210 std::vector Returns;
207211 ClonedCodeInfo InlinedFunctionInfo;
208212 Function::iterator FirstNewBlock;
209
213
210214 { // Scope to destroy ValueMap after cloning.
211215 DenseMap ValueMap;
212216
322326
323327 // If we are inlining tail call instruction through a call site that isn't
324328 // marked 'tail', we must remove the tail marker for any calls in the inlined
325 // code.
326 if (MustClearTailCallFlags && InlinedFunctionInfo.ContainsCalls) {
329 // code. Also, calls inlined through a 'nounwind' call site should be marked
330 // 'nounwind'.
331 if (InlinedFunctionInfo.ContainsCalls &&
332 (MustClearTailCallFlags || MarkNoUnwind)) {
327333 for (Function::iterator BB = FirstNewBlock, E = Caller->end();
328334 BB != E; ++BB)
329335 for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
330 if (CallInst *CI = dyn_cast(I))
331 CI->setTailCall(false);
332 }
336 if (CallInst *CI = dyn_cast(I)) {
337 if (MustClearTailCallFlags)
338 CI->setTailCall(false);
339 if (MarkNoUnwind)
340 CI->setDoesNotThrow();
341 }
342 }
343
344 // If we are inlining through a 'nounwind' call site then any inlined 'unwind'
345 // instructions are unreachable.
346 if (InlinedFunctionInfo.ContainsUnwinds && MarkNoUnwind)
347 for (Function::iterator BB = FirstNewBlock, E = Caller->end();
348 BB != E; ++BB) {
349 TerminatorInst *Term = BB->getTerminator();
350 if (isa(Term)) {
351 new UnreachableInst(Term);
352 BB->getInstList().erase(Term);
353 }
354 }
333355
334356 // If we are inlining for an invoke instruction, we must make sure to rewrite
335357 // any inlined 'unwind' instructions into branches to the invoke exception
260260 return get(newVec);
261261 }
262262
263 const ParamAttrsList *
264 ParamAttrsList::includeAttrs(const ParamAttrsList *PAL,
265 uint16_t idx, uint16_t attrs) {
266 uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
267 uint16_t NewAttrs = OldAttrs | attrs;
268 if (NewAttrs == OldAttrs)
269 return PAL;
270
271 ParamAttrsVector modVec;
272 modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
273 return getModified(PAL, modVec);
274 }
275
276 const ParamAttrsList *
277 ParamAttrsList::excludeAttrs(const ParamAttrsList *PAL,
278 uint16_t idx, uint16_t attrs) {
279 uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
280 uint16_t NewAttrs = OldAttrs & ~attrs;
281 if (NewAttrs == OldAttrs)
282 return PAL;
283
284 ParamAttrsVector modVec;
285 modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
286 return getModified(PAL, modVec);
287 }
288
263289 ParamAttrsList::~ParamAttrsList() {
264290 ParamAttrsLists->RemoveNode(this);
265291 }
6969 return CI->doesNotThrow();
7070 else
7171 return cast(I)->doesNotThrow();
72 }
73 void CallSite::setDoesNotThrow(bool doesNotThrow) {
74 if (CallInst *CI = dyn_cast(I))
75 CI->setDoesNotThrow(doesNotThrow);
76 else
77 cast(I)->setDoesNotThrow(doesNotThrow);
7278 }
7379
7480 //===----------------------------------------------------------------------===//
404410 return false;
405411 }
406412
413 void CallInst::setDoesNotThrow(bool doesNotThrow) {
414 const ParamAttrsList *PAL = getParamAttrs();
415 if (doesNotThrow)
416 PAL = ParamAttrsList::includeAttrs(PAL, 0, ParamAttr::NoUnwind);
417 else
418 PAL = ParamAttrsList::excludeAttrs(PAL, 0, ParamAttr::NoUnwind);
419 setParamAttrs(PAL);
420 }
421
407422
408423 //===----------------------------------------------------------------------===//
409424 // InvokeInst Implementation
480495 if (const Function *F = getCalledFunction())
481496 return F->paramHasAttr(i, attr);
482497 return false;
498 }
499
500 void InvokeInst::setDoesNotThrow(bool doesNotThrow) {
501 const ParamAttrsList *PAL = getParamAttrs();
502 if (doesNotThrow)
503 PAL = ParamAttrsList::includeAttrs(PAL, 0, ParamAttr::NoUnwind);
504 else
505 PAL = ParamAttrsList::excludeAttrs(PAL, 0, ParamAttr::NoUnwind);
506 setParamAttrs(PAL);
483507 }
484508
485509
0 ; RUN: llvm-as < %s -o - | opt -inline | llvm-dis | grep nounwind
1 ; RUN: llvm-as < %s -o - | opt -inline | llvm-dis | grep unreachable
2
3 declare i1 @extern()
4
5 define internal i32 @test() {
6 entry:
7 %n = call i1 @extern( )
8 br i1 %n, label %r, label %u
9 r:
10 ret i32 0;
11 u:
12 unwind
13 }
14
15 define i32 @caller() {
16 %X = call i32 @test( ) nounwind
17 ret i32 %X
18 }