1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
3 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
7 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
8 ; CHECK-LABEL: define {{[^@]+}}@foo1
9 ; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
10 ; CHECK-NEXT: ret i32 1
15 declare void @unknown()
16 define void @foo2() nounwind {
17 ; CHECK: Function Attrs: nounwind
18 ; CHECK-LABEL: define {{[^@]+}}@foo2
19 ; CHECK-SAME: () #[[ATTR1:[0-9]+]] {
20 ; CHECK-NEXT: call void @unknown()
21 ; CHECK-NEXT: ret void
28 define i32 @scc1_foo() {
29 ; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
30 ; TUNIT-LABEL: define {{[^@]+}}@scc1_foo
31 ; TUNIT-SAME: () #[[ATTR2:[0-9]+]] {
32 ; TUNIT-NEXT: ret i32 1
34 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
35 ; CGSCC-LABEL: define {{[^@]+}}@scc1_foo
36 ; CGSCC-SAME: () #[[ATTR0]] {
37 ; CGSCC-NEXT: ret i32 1
39 %1 = call i32 @scc1_bar()
45 define i32 @scc1_bar() {
46 ; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
47 ; TUNIT-LABEL: define {{[^@]+}}@scc1_bar
48 ; TUNIT-SAME: () #[[ATTR2]] {
49 ; TUNIT-NEXT: ret i32 1
51 ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
52 ; CGSCC-LABEL: define {{[^@]+}}@scc1_bar
53 ; CGSCC-SAME: () #[[ATTR0]] {
54 ; CGSCC-NEXT: ret i32 1
56 %1 = call i32 @scc1_foo()
60 declare i32 @non_nounwind()
63 define void @call_non_nounwind(){
64 ; CHECK-LABEL: define {{[^@]+}}@call_non_nounwind() {
65 ; CHECK-NEXT: [[TMP1:%.*]] = tail call i32 @non_nounwind()
66 ; CHECK-NEXT: ret void
68 tail call i32 @non_nounwind()
73 ; int maybe_throw(bool canThrow) {
80 define i32 @maybe_throw(i1 zeroext %0) {
81 ; CHECK-LABEL: define {{[^@]+}}@maybe_throw
82 ; CHECK-SAME: (i1 noundef zeroext [[TMP0:%.*]]) {
83 ; CHECK-NEXT: br i1 [[TMP0]], label [[TMP2:%.*]], label [[TMP3:%.*]]
85 ; CHECK-NEXT: tail call void @__cxa_rethrow()
86 ; CHECK-NEXT: unreachable
88 ; CHECK-NEXT: ret i32 -1
90 br i1 %0, label %2, label %3
93 tail call void @__cxa_rethrow() #1
100 declare void @__cxa_rethrow()
103 ; int catch_thing() {
105 ; int a = doThing(true);
107 ; catch(...) { return -1; }
111 define i32 @catch_thing() personality ptr @__gxx_personality_v0 {
112 ; CHECK-LABEL: define {{[^@]+}}@catch_thing() personality ptr @__gxx_personality_v0 {
113 ; CHECK-NEXT: invoke void @__cxa_rethrow()
114 ; CHECK-NEXT: to label [[TMP1:%.*]] unwind label [[TMP2:%.*]]
116 ; CHECK-NEXT: unreachable
118 ; CHECK-NEXT: [[TMP3:%.*]] = landingpad { ptr, i32 }
119 ; CHECK-NEXT: catch ptr null
120 ; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { ptr, i32 } [[TMP3]], 0
121 ; CHECK-NEXT: [[TMP5:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[TMP4]])
122 ; CHECK-NEXT: tail call void @__cxa_end_catch()
123 ; CHECK-NEXT: ret i32 -1
125 invoke void @__cxa_rethrow() #1
126 to label %1 unwind label %2
132 %3 = landingpad { ptr, i32 }
134 %4 = extractvalue { ptr, i32 } %3, 0
135 %5 = tail call ptr @__cxa_begin_catch(ptr %4) #2
136 tail call void @__cxa_end_catch()
140 define i32 @catch_thing_user() {
141 ; TUNIT-LABEL: define {{[^@]+}}@catch_thing_user() {
142 ; TUNIT-NEXT: [[CATCH_THING_CALL:%.*]] = call i32 @catch_thing()
143 ; TUNIT-NEXT: ret i32 -1
145 ; CGSCC-LABEL: define {{[^@]+}}@catch_thing_user() {
146 ; CGSCC-NEXT: [[CATCH_THING_CALL:%.*]] = call noundef i32 @catch_thing()
147 ; CGSCC-NEXT: ret i32 [[CATCH_THING_CALL]]
149 %catch_thing_call = call i32 @catch_thing()
150 ret i32 %catch_thing_call
153 define void @two_potential_callees_pos1(i1 %c) {
154 ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
155 ; TUNIT-LABEL: define {{[^@]+}}@two_potential_callees_pos1
156 ; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
157 ; TUNIT-NEXT: ret void
159 ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn
160 ; CGSCC-LABEL: define {{[^@]+}}@two_potential_callees_pos1
161 ; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR2:[0-9]+]] {
162 ; CGSCC-NEXT: [[FP:%.*]] = select i1 [[C]], ptr @foo1, ptr @scc1_foo
163 ; CGSCC-NEXT: [[TMP1:%.*]] = icmp eq ptr [[FP]], @scc1_foo
164 ; CGSCC-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
166 ; CGSCC-NEXT: call void @scc1_foo()
167 ; CGSCC-NEXT: br label [[TMP6:%.*]]
169 ; CGSCC-NEXT: br i1 true, label [[TMP4:%.*]], label [[TMP5:%.*]]
171 ; CGSCC-NEXT: call void @foo1()
172 ; CGSCC-NEXT: br label [[TMP6]]
174 ; CGSCC-NEXT: unreachable
176 ; CGSCC-NEXT: ret void
178 %fp = select i1 %c, ptr @foo1, ptr @scc1_foo
182 define void @two_potential_callees_pos2(i1 %c) {
183 ; CHECK: Function Attrs: nounwind
184 ; CHECK-LABEL: define {{[^@]+}}@two_potential_callees_pos2
185 ; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
186 ; CHECK-NEXT: [[FP:%.*]] = select i1 [[C]], ptr @foo2, ptr @scc1_foo
187 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[FP]], @scc1_foo
188 ; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
190 ; CHECK-NEXT: call void @scc1_foo()
191 ; CHECK-NEXT: br label [[TMP6:%.*]]
193 ; CHECK-NEXT: br i1 true, label [[TMP4:%.*]], label [[TMP5:%.*]]
195 ; CHECK-NEXT: call void @foo2()
196 ; CHECK-NEXT: br label [[TMP6]]
198 ; CHECK-NEXT: unreachable
200 ; CHECK-NEXT: ret void
202 %fp = select i1 %c, ptr @foo2, ptr @scc1_foo
206 define void @two_potential_callees_neg(i1 %c) {
207 ; CHECK-LABEL: define {{[^@]+}}@two_potential_callees_neg
208 ; CHECK-SAME: (i1 [[C:%.*]]) {
209 ; CHECK-NEXT: [[FP:%.*]] = select i1 [[C]], ptr @foo1, ptr @non_nounwind
210 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[FP]], @non_nounwind
211 ; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
213 ; CHECK-NEXT: call void @non_nounwind()
214 ; CHECK-NEXT: br label [[TMP6:%.*]]
216 ; CHECK-NEXT: br i1 true, label [[TMP4:%.*]], label [[TMP5:%.*]]
218 ; CHECK-NEXT: call void @foo1()
219 ; CHECK-NEXT: br label [[TMP6]]
221 ; CHECK-NEXT: unreachable
223 ; CHECK-NEXT: ret void
225 %fp = select i1 %c, ptr @foo1, ptr @non_nounwind
230 declare i32 @__gxx_personality_v0(...)
232 declare ptr @__cxa_begin_catch(ptr)
234 declare void @__cxa_end_catch()
236 ; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
237 ; TUNIT: attributes #[[ATTR1]] = { nounwind }
238 ; TUNIT: attributes #[[ATTR2]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
240 ; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
241 ; CGSCC: attributes #[[ATTR1]] = { nounwind }
242 ; CGSCC: attributes #[[ATTR2]] = { mustprogress nofree nosync nounwind willreturn }