llvm.org GIT mirror llvm / 2897582
[Attributor] Deduce "willreturn" function attribute Summary: Deduce the "willreturn" attribute for functions. For now, intrinsics are not willreturn. More annotation will be done in another patch. Reviewers: jdoerfert Subscribers: jvesely, nhaehnle, nicholas, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63046 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366335 91177308-0d34-0410-b5e6-96231b3b80d8 Hideto Ueno a month ago
8 changed file(s) with 274 addition(s) and 9 deletion(s). Raw diff Collapse all Expand all
9292 }
9393
9494 def IntrNoReturn : IntrinsicProperty;
95
96 def IntrWillReturn : IntrinsicProperty;
9597
9698 // IntrCold - Calls to this intrinsic are cold.
9799 // Parallels the cold attribute on LLVM IR functions.
739739 /// The identifier used by the Attributor for this class of attributes.
740740 static constexpr Attribute::AttrKind ID = Attribute::NonNull;
741741 };
742
743 /// An abstract attribute for norecurse.
744 struct AANoRecurse : public AbstractAttribute {
745
746 /// See AbstractAttribute::AbstractAttribute(...).
747 AANoRecurse(Value &V, InformationCache &InfoCache)
748 : AbstractAttribute(V, InfoCache) {}
749
750 /// See AbstractAttribute::getAttrKind()
751 virtual Attribute::AttrKind getAttrKind() const override {
752 return Attribute::NoRecurse;
753 }
754
755 /// Return true if "norecurse" is known.
756 virtual bool isKnownNoRecurse() const = 0;
757
758 /// Return true if "norecurse" is assumed.
759 virtual bool isAssumedNoRecurse() const = 0;
760
761 /// The identifier used by the Attributor for this class of attributes.
762 static constexpr Attribute::AttrKind ID = Attribute::NoRecurse;
763 };
764
765 /// An abstract attribute for willreturn.
766 struct AAWillReturn : public AbstractAttribute {
767
768 /// See AbstractAttribute::AbstractAttribute(...).
769 AAWillReturn(Value &V, InformationCache &InfoCache)
770 : AbstractAttribute(V, InfoCache) {}
771
772 /// See AbstractAttribute::getAttrKind()
773 virtual Attribute::AttrKind getAttrKind() const override {
774 return Attribute::WillReturn;
775 }
776
777 /// Return true if "willreturn" is known.
778 virtual bool isKnownWillReturn() const = 0;
779
780 /// Return true if "willreturn" is assumed.
781 virtual bool isAssumedWillReturn() const = 0;
782
783 /// The identifier used by the Attributor for this class of attributes.
784 static constexpr Attribute::AttrKind ID = Attribute::WillReturn;
785 };
742786 } // end namespace llvm
743787
744788 #endif // LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H
1414
1515 #include "llvm/Transforms/IPO/Attributor.h"
1616
17 #include "llvm/ADT/DepthFirstIterator.h"
1718 #include "llvm/ADT/SetVector.h"
1819 #include "llvm/ADT/SmallPtrSet.h"
1920 #include "llvm/ADT/SmallVector.h"
2223 #include "llvm/Analysis/ValueTracking.h"
2324 #include "llvm/IR/Argument.h"
2425 #include "llvm/IR/Attributes.h"
26 #include "llvm/IR/CFG.h"
2527 #include "llvm/IR/InstIterator.h"
2628 #include "llvm/IR/IntrinsicInst.h"
2729 #include "llvm/Support/CommandLine.h"
5557 "Number of function return values marked nonnull");
5658 STATISTIC(NumFnArgumentNonNull, "Number of function arguments marked nonnull");
5759 STATISTIC(NumCSArgumentNonNull, "Number of call site arguments marked nonnull");
60 STATISTIC(NumFnWillReturn, "Number of functions marked willreturn");
5861
5962 // TODO: Determine a good default value.
6063 //
127130 break;
128131 }
129132 break;
133 case Attribute::WillReturn:
134 NumFnWillReturn++;
135 break;
130136 default:
131137 return;
132138 }
11931199 return ChangeStatus::UNCHANGED;
11941200 }
11951201
1202 /// ------------------------ Will-Return Attributes ----------------------------
1203
1204 struct AAWillReturnImpl : public AAWillReturn, BooleanState {
1205
1206 /// See AbstractAttribute::AbstractAttribute(...).
1207 AAWillReturnImpl(Function &F, InformationCache &InfoCache)
1208 : AAWillReturn(F, InfoCache) {}
1209
1210 /// See AAWillReturn::isKnownWillReturn().
1211 bool isKnownWillReturn() const override { return getKnown(); }
1212
1213 /// See AAWillReturn::isAssumedWillReturn().
1214 bool isAssumedWillReturn() const override { return getAssumed(); }
1215
1216 /// See AbstractAttribute::getState(...).
1217 AbstractState &getState() override { return *this; }
1218
1219 /// See AbstractAttribute::getState(...).
1220 const AbstractState &getState() const override { return *this; }
1221
1222 /// See AbstractAttribute::getAsStr()
1223 const std::string getAsStr() const override {
1224 return getAssumed() ? "willreturn" : "may-noreturn";
1225 }
1226 };
1227
1228 struct AAWillReturnFunction final : AAWillReturnImpl {
1229
1230 /// See AbstractAttribute::AbstractAttribute(...).
1231 AAWillReturnFunction(Function &F, InformationCache &InfoCache)
1232 : AAWillReturnImpl(F, InfoCache) {}
1233
1234 /// See AbstractAttribute::getManifestPosition().
1235 ManifestPosition getManifestPosition() const override {
1236 return MP_FUNCTION;
1237 }
1238
1239 /// See AbstractAttribute::initialize(...).
1240 void initialize(Attributor &A) override;
1241
1242 /// See AbstractAttribute::updateImpl(...).
1243 ChangeStatus updateImpl(Attributor &A) override;
1244 };
1245
1246 // Helper function that checks whether a function has any cycle.
1247 // TODO: Replace with more efficent code
1248 bool containsCycle(Function &F) {
1249 SmallPtrSet Visited;
1250
1251 // Traverse BB by dfs and check whether successor is already visited.
1252 for (BasicBlock *BB : depth_first(&F)) {
1253 Visited.insert(BB);
1254 for (auto *SuccBB : successors(BB)) {
1255 if (Visited.count(SuccBB))
1256 return true;
1257 }
1258 }
1259 return false;
1260 }
1261
1262 // Helper function that checks the function have a loop which might become an
1263 // endless loop
1264 // FIXME: Any cycle is regarded as endless loop for now.
1265 // We have to allow some patterns.
1266 bool containsPossiblyEndlessLoop(Function &F) { return containsCycle(F); }
1267
1268 void AAWillReturnFunction::initialize(Attributor &A) {
1269 Function &F = getAnchorScope();
1270
1271 if (containsPossiblyEndlessLoop(F))
1272 indicatePessimisticFixpoint();
1273 }
1274
1275 ChangeStatus AAWillReturnFunction::updateImpl(Attributor &A) {
1276 Function &F = getAnchorScope();
1277
1278 // The map from instruction opcodes to those instructions in the function.
1279 auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
1280
1281 for (unsigned Opcode :
1282 {(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
1283 (unsigned)Instruction::Call}) {
1284 for (Instruction *I : OpcodeInstMap[Opcode]) {
1285 auto ICS = ImmutableCallSite(I);
1286
1287 if (ICS.hasFnAttr(Attribute::WillReturn))
1288 continue;
1289
1290 auto *WillReturnAA = A.getAAFor(*this, *I);
1291 if (!WillReturnAA || !WillReturnAA->isAssumedWillReturn()) {
1292 indicatePessimisticFixpoint();
1293 return ChangeStatus::CHANGED;
1294 }
1295
1296 auto *NoRecurseAA = A.getAAFor(*this, *I);
1297
1298 // FIXME: (i) Prohibit any recursion for now.
1299 // (ii) AANoRecurse isn't implemented yet so currently any call is
1300 // regarded as having recursion.
1301 // Code below should be
1302 // if ((!NoRecurseAA || !NoRecurseAA->isAssumedNoRecurse()) &&
1303 if (!NoRecurseAA && !ICS.hasFnAttr(Attribute::NoRecurse)) {
1304 indicatePessimisticFixpoint();
1305 return ChangeStatus::CHANGED;
1306 }
1307 }
1308 }
1309
1310 return ChangeStatus::UNCHANGED;
1311 }
1312
11961313 /// ----------------------------------------------------------------------------
11971314 /// Attributor
11981315 /// ----------------------------------------------------------------------------
14011518 if (Arg.getType()->isPointerTy())
14021519 registerAA(*new AANonNullArgument(Arg, InfoCache));
14031520 }
1521
1522 // Every function might be "will-return".
1523 registerAA(*new AAWillReturnFunction(F, InfoCache));
14041524
14051525 // Walk all instructions to find more attribute opportunities and also
14061526 // interesting instructions that might be queried by abstract attributes
743743 attributes #0 = { noinline nounwind uwtable }
744744
745745 ; BOTH-NOT: attributes #
746 ; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline norecurse nosync nounwind readnone uwtable }
746 ; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline norecurse nosync nounwind readnone uwtable willreturn }
747747 ; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline nosync nounwind readnone uwtable }
748748 ; BOTH-DAG: attributes #{{[0-9]*}} = { nofree noinline nosync nounwind readonly uwtable }
749749 ; BOTH-DAG: attributes #{{[0-9]*}} = { noinline nounwind uwtable }
0 ; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefix=FNATTR
1 ; RUN: opt -attributor --attributor-disable=false -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR
2
13
24 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
35
68
79
810 ; TEST 1 (positive case)
9 ; FIXME: missing willreturn
1011 ; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
1112 ; FNATTR-NEXT: define void @only_return()
13 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable willreturn
14 ; ATTRIBUTOR-NEXT: define void @only_return()
1215 define void @only_return() #0 {
1316 ret void
1417 }
2124 ; return n<=1? n : fib(n-1) + fib(n-2);
2225 ; }
2326
24 ; FIXME: missing willreturn
2527 ; FNATTR: Function Attrs: noinline nounwind readnone uwtable
2628 ; FNATTR-NEXT: define i32 @fib(i32)
29 ; FIXME: missing willreturn
30 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
31 ; ATTRIBUTOR-NEXT: define i32 @fib(i32) local_unnamed_addr
2732 define i32 @fib(i32) local_unnamed_addr #0 {
2833 %2 = icmp slt i32 %0, 2
2934 br i1 %2, label %9, label %3
5358 ; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
5459 ; FNATTR-NOT: willreturn
5560 ; FNATTR-NEXT: define i32 @fact_maybe_not_halt(i32) local_unnamed_addr
61 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
62 ; ATTRIBUTOR-NOT: willreturn
63 ; ATTRIBUTOR-NEXT: define i32 @fact_maybe_not_halt(i32) local_unnamed_addr
5664 define i32 @fact_maybe_not_halt(i32) local_unnamed_addr #0 {
5765 %2 = icmp eq i32 %0, 0
5866 br i1 %2, label %11, label %3
8694 ; FIXME: missing willreturn
8795 ; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
8896 ; FNATTR-NEXT: define i32 @fact_loop(i32)
97 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
98 ; ATTRIBUTOR-NEXT: define i32 @fact_loop(i32) local_unnamed_addr
8999 define i32 @fact_loop(i32) local_unnamed_addr #0 {
90100 %2 = icmp slt i32 %0, 1
91101 br i1 %2, label %3, label %5
115125 ; FNATTR: Function Attrs: noinline nounwind readnone uwtable
116126 ; FNATTR-NOT: willreturn
117127 ; FNATTR-NEXT: define void @mutual_recursion1()
128 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
129 ; ATTRIBUTOR-NOT: willreturn
130 ; ATTRIBUTOR-NEXT: define void @mutual_recursion1()
118131 define void @mutual_recursion1() #0 {
119132 call void @mutual_recursion2()
120133 ret void
124137 ; FNATTR: Function Attrs: noinline nounwind readnone uwtable
125138 ; FNATTR-NOT: willreturn
126139 ; FNATTR-NEXT: define void @mutual_recursion2()
140 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
141 ; ATTRIBUTOR-NOT: willreturn
142 ; ATTRIBUTOR-NEXT: define void @mutual_recursion2()
127143 define void @mutual_recursion2() #0 {
128144 call void @mutual_recursion1()
129145 ret void
134150 ; call exit/abort (has noreturn attribute)
135151 ; FNATTR: Function Attrs: noreturn
136152 ; FNATTR-NEXT: declare void @exit(i32) local_unnamed_addr
153 ; ATTRIBUTOR: Function Attrs: noreturn
154 ; ATTRIBUTOR-NEXT: declare void @exit(i32) local_unnamed_add
137155 declare void @exit(i32) local_unnamed_addr noreturn
138156
139157 ; FNATTR: Function Attrs: noinline nounwind uwtable
140158 ; FNATTR-NOT: willreturn
141159 ; FNATTR-NEXT: define void @only_exit()
160 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
161 ; ATTRIBUTOR-NOT: willreturn
162 ; ATTRIBUTOR-NEXT: define void @only_exit() local_unnamed_addr
142163 define void @only_exit() local_unnamed_addr #0 {
143164 tail call void @exit(i32 0)
144165 unreachable
157178 ; FNATTR: Function Attrs: noinline nounwind uwtable
158179 ; FNATTR-NOT: willreturn
159180 ; FNATTR-NEXT: define void @conditional_exit(i32, i32* nocapture readonly) local_unnamed_addr
181 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
182 ; ATTRIBUTOR-NOT: willreturn
183 ; ATTRIBUTOR-NEXT: define void @conditional_exit(i32, i32* nocapture readonly) local_unnamed_addr
160184 define void @conditional_exit(i32, i32* nocapture readonly) local_unnamed_addr #0 {
161185 %3 = icmp eq i32 %0, 0
162186 br i1 %3, label %5, label %4
180204
181205 ; TEST 6 (positive case)
182206 ; Call intrinsic function
207 ; FIXME: missing willreturn
183208 ; FNATTRS: Function Attrs: noinline readnone speculatable
184209 ; FNATTRS-NEXT: declare float @llvm.floor.f32(float)
210 ; ATTRIBUTOR: Function Attrs: nounwind readnone speculatable
211 ; ATTRIBUTOR-NEXT: declare float @llvm.floor.f32(float)
185212 declare float @llvm.floor.f32(float)
186213
187 ; FIXME: missing willreturn
188214 ; FNATTRS: Function Attrs: noinline nounwind uwtable
189215 ; FNATTRS-NEXT: define void @call_floor(float %a)
216 ; FIXME: missing willreturn
217 ; ATTRIBUTOR: Function Attrs: noinline nosync nounwind uwtable
218 ; ATTRIBUTOR-NEXT: define void @call_floor(float %a)
190219 define void @call_floor(float %a) #0 {
191220 tail call float @llvm.floor.f32(float %a)
192221 ret void
199228 ; FNATTR: Function Attrs: noinline nounwind uwtable
200229 ; FNATTR-NOT: willreturn
201230 ; FNATTR-NEXT: declare void @maybe_noreturn()
231 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
232 ; ATTRIBUTOR-NOT: willreturn
233 ; ATTRIBUTOR-NEXT: declare void @maybe_noreturn()
202234 declare void @maybe_noreturn() #0
203235
204236 ; FNATTR: Function Attrs: noinline nounwind uwtable
205237 ; FNATTR-NOT: willreturn
206238 ; FNATTR-NEXT: define void @call_maybe_noreturn()
239 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
240 ; ATTRIBUTOR-NOT: willreturn
241 ; ATTRIBUTOR-NEXT: define void @call_maybe_noreturn()
207242 define void @call_maybe_noreturn() #0 {
208243 tail call void @maybe_noreturn()
209244 ret void
215250
216251 ; FNATTR: Function Attrs: willreturn
217252 ; FNATTR-NEXT: declare void @will_return()
253 ; ATTRIBUTOR: Function Attrs: willreturn
254 ; ATTRIBUTOR-NEXT: declare void @will_return()
218255 declare void @will_return() willreturn
219256
220257 ; FIXME: missing willreturn
221258 ; FNATTR: Function Attrs: noinline nounwind uwtable
222259 ; FNATTR-NEXT: define void @f1()
260 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
261 ; ATTRIBUTOR-NEXT: define void @f1()
223262 define void @f1() #0 {
224263 tail call void @will_return()
225264 ret void
228267 ; FIXME: missing willreturn
229268 ; FNATTR: Function Attrs: noinline nounwind uwtable
230269 ; FNATTR-NEXT: define void @f2()
270 ; FIXME: missing willreturn
271 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
272 ; ATTRIBUTOR-NEXT: define void @f2()
231273 define void @f2() #0 {
232274 tail call void @f1()
233275 ret void
240282 ; FNATTR: Function Attrs: noinline nounwind uwtable
241283 ; FNATTR-NOT: willreturn
242284 ; FNATTR-NEXT: define void @call_will_return_but_has_loop()
285 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
286 ; ATTRIBUTOR-NOT: willreturn
287 ; ATTRIBUTOR-NEXT: define void @call_will_return_but_has_loop()
243288 define void @call_will_return_but_has_loop() #0 {
244289 br label %label1
245290 label1:
255300
256301 ; FNATTR: Function Attrs: noinline uwtable willreturn
257302 ; FNATTR-NEXT: declare i1 @maybe_raise_exception()
303 ; ATTRIBUTOR: Function Attrs: noinline uwtable willreturn
304 ; ATTRIBUTOR-NEXT: declare i1 @maybe_raise_exception()
258305 declare i1 @maybe_raise_exception() #1 willreturn
259306
260 ; FIXME: missing willreturn
261307 ; FNATTR: Function Attrs: nounwind
262308 ; FNATTR-NEXT: define void @invoke_test()
309 ; ATTRIBUTOR: Function Attrs: nounwind willreturn
310 ; ATTRIBUTOR-NEXT: define void @invoke_test()
263311 define void @invoke_test() personality i32 (...)* @__gxx_personality_v0 {
264312 invoke i1 @maybe_raise_exception()
265 to label %N unwind label %F
313 to label %N unwind label %F
266314 N:
267315 ret void
268316 F:
287335 ; FIXME: missing willreturn
288336 ; FNATTR: Function Attrs: noinline norecurse nounwind readonly uwtable
289337 ; FNATTR-NEXT: define i32 @loop_constant_trip_count(i32* nocapture readonly)
338 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
339 ; ATTRIBUTOR-NEXT: define i32 @loop_constant_trip_count(i32* nocapture readonly)
290340 define i32 @loop_constant_trip_count(i32* nocapture readonly) #0 {
291341 br label %3
292342
318368 ; FNATTR: Function Attrs: noinline norecurse nounwind readonly uwtable
319369 ; FNATTR-NOT: willreturn
320370 ; FNATTR-NEXT: define i32 @loop_trip_count_unbound(i32, i32, i32* nocapture readonly, i32) local_unnamed_addr
371 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
372 ; ATTRIBUTOR-NOT: willreturn
373 ; ATTRIBUTOR-NEXT: define i32 @loop_trip_count_unbound(i32, i32, i32* nocapture readonly, i32) local_unnamed_addr
321374 define i32 @loop_trip_count_unbound(i32, i32, i32* nocapture readonly, i32) local_unnamed_addr #0 {
322375 %5 = icmp eq i32 %0, %1
323376 br i1 %5, label %6, label %8
353406 ; FIXME: missing willreturn
354407 ; FNATTR: Function Attrs: noinline norecurse nounwind readonly uwtable
355408 ; FNATTR-NEXT: define i32 @loop_trip_dec(i32, i32* nocapture readonly)
409 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable
410 ; ATTRIBUTOR-NEXT: define i32 @loop_trip_dec(i32, i32* nocapture readonly) local_unnamed_addr
356411
357412 define i32 @loop_trip_dec(i32, i32* nocapture readonly) local_unnamed_addr #0 {
358413 %3 = icmp sgt i32 %0, -1
380435 ; TEST 14 (positive case)
381436 ; multiple return
382437
383 ; FIXME: missing willreturn
384438 ; FNATTR: Function Attrs: noinline norecurse nounwind readnone uwtable
385439 ; FNATTR-NEXT: define i32 @multiple_return(i32 %a)
440 ; ATTRIBUTOR: Function Attrs: nofree noinline nosync nounwind uwtable willreturn
441 ; ATTRIBUTOR-NEXT: define i32 @multiple_return(i32 %a)
386442 define i32 @multiple_return(i32 %a) #0 {
387443 %b = icmp eq i32 %a, 0
388444 br i1 %b, label %t, label %f
400456 ; FIXME: missing willreturn
401457 ; FNATTR: Function Attrs: noinline nounwind uwtable
402458 ; FNATTR-NEXT: define void @unreachable_exit_positive1()
459 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
460 ; ATTRIBUTOR-NEXT: define void @unreachable_exit_positive1()
403461 define void @unreachable_exit_positive1() #0 {
404462 tail call void @will_return()
405463 ret void
412470 ; FIXME: missing willreturn
413471 ; FNATTR: Function Attrs: noinline nounwind uwtable
414472 ; FNATTR-NEXT: define i32 @unreachable_exit_positive2(i32)
473 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
474 ; ATTRIBUTOR-NEXT: define i32 @unreachable_exit_positive2(i32)
415475 define i32 @unreachable_exit_positive2(i32) local_unnamed_addr #0 {
416476 %2 = icmp slt i32 %0, 1
417477 br i1 %2, label %3, label %5
439499 ; FNATTR: Function Attrs: noinline nounwind uwtable
440500 ; FNATTR-NOT: willreturn
441501 ; FNATTR-NEXT: define void @unreachable_exit_negative1()
502 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
503 ; ATTRIBUTOR-NOT: willreturn
504 ; ATTRIBUTOR-NEXT: define void @unreachable_exit_negative1()
442505 define void @unreachable_exit_negative1() #0 {
443506 tail call void @exit(i32 0)
444507 ret void
451514 ; FNATTR: Function Attrs: noinline nounwind uwtable
452515 ; FNATTR-NOT: willreturn
453516 ; FNATTR-NEXT: define void @unreachable_exit_negative2()
517 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
518 ; ATTRIBUTOR-NOT: willreturn
519 ; ATTRIBUTOR-NEXT: define void @unreachable_exit_negative2()
454520 define void @unreachable_exit_negative2() #0 {
455521
456522 br label %L1
464530 unreachable
465531 }
466532
533 ; FNATTR: Function Attrs: noreturn nounwind
534 ; FNATTR-NEXT: declare void @llvm.eh.sjlj.longjmp(i8*)
535 ; ATTRIBUTOR: Function Attrs: noreturn nounwind
536 ; ATTRIBUTOR-NEXT: declare void @llvm.eh.sjlj.longjmp(i8*)
537 declare void @llvm.eh.sjlj.longjmp(i8*)
538
539 ; FNATTR: Function Attrs: noinline nounwind uwtable
540 ; FNATTR-NOT: willreturn
541 ; FNATTR-NEXT: define void @call_longjmp(i8* nocapture readnone) local_unnamed_addr #3 {
542 ; ATTRIBUTOR: Function Attrs: noinline nounwind uwtable
543 ; ATTRIBUTOR-NOT: willreturn
544 ; ATTRIBUTOR-NEXT: define void @call_longjmp(i8* nocapture readnone) local_unnamed_addr
545 define void @call_longjmp(i8* nocapture readnone) local_unnamed_addr #0 {
546 tail call void @llvm.eh.sjlj.longjmp(i8* %0)
547 ret void
548 }
549
467550
468551 attributes #0 = { nounwind uwtable noinline }
469552 attributes #1 = { uwtable noinline }
122122 /// True if the intrinsic is no-return.
123123 bool isNoReturn;
124124
125 /// True if the intrinsic is will-return.
126 bool isWillReturn;
127
125128 /// True if the intrinsic is cold.
126129 bool isCold;
127130
556556 isCommutative = false;
557557 canThrow = false;
558558 isNoReturn = false;
559 isWillReturn = false;
559560 isCold = false;
560561 isNoDuplicate = false;
561562 isConvergent = false;
720721 isConvergent = true;
721722 else if (Property->getName() == "IntrNoReturn")
722723 isNoReturn = true;
724 else if (Property->getName() == "IntrWillReturn")
725 isWillReturn = true;
723726 else if (Property->getName() == "IntrCold")
724727 isCold = true;
725728 else if (Property->getName() == "IntrSpeculatable")
543543
544544 if (L->isNoReturn != R->isNoReturn)
545545 return R->isNoReturn;
546
547 if (L->isWillReturn != R->isWillReturn)
548 return R->isWillReturn;
546549
547550 if (L->isCold != R->isCold)
548551 return R->isCold;
685688
686689 if (!intrinsic.canThrow ||
687690 (intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem && !intrinsic.hasSideEffects) ||
688 intrinsic.isNoReturn || intrinsic.isCold || intrinsic.isNoDuplicate ||
689 intrinsic.isConvergent || intrinsic.isSpeculatable) {
691 intrinsic.isNoReturn || intrinsic.isWillReturn || intrinsic.isCold ||
692 intrinsic.isNoDuplicate || intrinsic.isConvergent ||
693 intrinsic.isSpeculatable) {
690694 OS << " const Attribute::AttrKind Atts[] = {";
691695 bool addComma = false;
692696 if (!intrinsic.canThrow) {
697701 if (addComma)
698702 OS << ",";
699703 OS << "Attribute::NoReturn";
704 addComma = true;
705 }
706 if (intrinsic.isWillReturn) {
707 if (addComma)
708 OS << ",";
709 OS << "Attribute::WillReturn";
700710 addComma = true;
701711 }
702712 if (intrinsic.isCold) {