1; RUN: opt -function-attrs -S %s | FileCheck %s 2 3define void @mustprogress_readnone() mustprogress { 4; CHECK: Function Attrs: {{.*}} noreturn {{.*}} readnone willreturn 5; CHECK-NEXT: define void @mustprogress_readnone() 6; 7entry: 8 br label %while.body 9 10while.body: 11 br label %while.body 12} 13 14define i32 @mustprogress_load(i32* %ptr) mustprogress { 15; CHECK: Function Attrs: {{.*}} readonly willreturn 16; CHECK-NEXT: define i32 @mustprogress_load( 17; 18entry: 19 br label %while.body 20 21while.body: 22 %r = load i32, i32* %ptr 23 br label %while.body 24} 25 26define void @mustprogress_store(i32* %ptr) mustprogress { 27; CHECK-NOT: Function Attrs: {{.*}} willreturn 28; CHECK: define void @mustprogress_store( 29; 30entry: 31 br label %while.body 32 33while.body: 34 store i32 0, i32* %ptr 35 br label %while.body 36} 37 38declare void @unknown_fn() 39 40define void @mustprogress_call_unknown_fn() mustprogress { 41; CHECK-NOT: Function Attrs: {{.*}} willreturn 42; CHECK: define void @mustprogress_call_unknown_fn( 43; 44 call void @unknown_fn() 45 ret void 46} 47 48define i32 @mustprogress_call_known_functions(i32* %ptr) mustprogress { 49; CHECK: Function Attrs: {{.*}} readonly willreturn 50; CHECK-NEXT: define i32 @mustprogress_call_known_functions( 51; 52 call void @mustprogress_readnone() 53 %r = call i32 @mustprogress_load(i32* %ptr) 54 ret i32 %r 55} 56 57declare i32 @__gxx_personality_v0(...) 58 59define i64 @mustprogress_mayunwind() mustprogress personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { 60; CHECK: Function Attrs: {{.*}} readnone willreturn 61; CHECK-NEXT: define i64 @mustprogress_mayunwind( 62; 63 %a = invoke i64 @fn_noread() 64 to label %A unwind label %B 65A: 66 ret i64 10 67 68B: 69 %val = landingpad { i8*, i32 } 70 catch i8* null 71 ret i64 0 72} 73 74; Function without loops or non-willreturn calls will return. 75define void @willreturn_no_loop(i1 %c, i32* %p) { 76; CHECK: Function Attrs: mustprogress willreturn 77; CHECK-NEXT: define void @willreturn_no_loop( 78; 79 br i1 %c, label %if, label %else 80 81if: 82 load atomic i32, i32* %p seq_cst, align 4 83 call void @fn_willreturn() 84 br label %end 85 86else: 87 store atomic i32 0, i32* %p seq_cst, align 4 88 br label %end 89 90end: 91 ret void 92} 93 94; Calls a function that is not guaranteed to return, not willreturn. 95define void @willreturn_non_returning_function(i1 %c, i32* %p) { 96; CHECK-NOT: Function Attrs: {{.*}}willreturn 97; CHECK: define void @willreturn_non_returning_function( 98; 99 call void @unknown_fn() 100 ret void 101} 102 103; Infinite loop without mustprogress, will not return. 104define void @willreturn_loop() { 105; CHECK-NOT: Function Attrs: {{.*}}willreturn 106; CHECK: define void @willreturn_loop( 107; 108 br label %loop 109 110loop: 111 br label %loop 112} 113 114; Finite loop. Could be willreturn but not detected. 115; FIXME 116define void @willreturn_finite_loop() { 117; CHECK-NOT: Function Attrs: {{.*}}willreturn 118; CHECK: define void @willreturn_finite_loop( 119; 120entry: 121 br label %loop 122 123loop: 124 %i = phi i32 [ 0, %entry], [ %i.inc, %loop ] 125 %i.inc = add nuw i32 %i, 1 126 %c = icmp ne i32 %i.inc, 100 127 br i1 %c, label %loop, label %end 128 129end: 130 ret void 131} 132 133; Infinite recursion without mustprogress, will not return. 134define void @willreturn_recursion() { 135; CHECK-NOT: Function Attrs: {{.*}}willreturn 136; CHECK: define void @willreturn_recursion( 137; 138 tail call void @willreturn_recursion() 139 ret void 140} 141 142; Irreducible infinite loop, will not return. 143define void @willreturn_irreducible(i1 %c) { 144; CHECK-NOT: Function Attrs: {{.*}}willreturn 145; CHECK: define void @willreturn_irreducible( 146; 147 br i1 %c, label %bb1, label %bb2 148 149bb1: 150 br label %bb2 151 152bb2: 153 br label %bb1 154} 155 156define linkonce i32 @square(i32) { 157; CHECK-NOT: Function Attrs: {{.*}}willreturn 158; CHECK: define linkonce i32 @square( 159 %2 = mul nsw i32 %0, %0 160 ret i32 %2 161} 162 163declare i64 @fn_noread() readnone 164declare void @fn_willreturn() willreturn 165