1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes 2; RUN: opt -passes=function-attrs -S < %s | FileCheck --check-prefixes=COMMON,FNATTRS %s 3; RUN: opt -passes=attributor-light -S < %s | FileCheck --check-prefixes=COMMON,ATTRIBUTOR %s 4 5; TEST 1 6define i32 @foo1() { 7; COMMON: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 8; COMMON-LABEL: define {{[^@]+}}@foo1 9; COMMON-SAME: () #[[ATTR0:[0-9]+]] { 10; COMMON-NEXT: ret i32 1 11; 12 ret i32 1 13} 14 15; TEST 2 16define i32 @scc1_foo() { 17; FNATTRS: Function Attrs: nofree nosync nounwind memory(none) 18; FNATTRS-LABEL: define {{[^@]+}}@scc1_foo 19; FNATTRS-SAME: () #[[ATTR1:[0-9]+]] { 20; FNATTRS-NEXT: [[TMP1:%.*]] = call i32 @scc1_bar() 21; FNATTRS-NEXT: ret i32 1 22; 23; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(none) 24; ATTRIBUTOR-LABEL: define {{[^@]+}}@scc1_foo 25; ATTRIBUTOR-SAME: () #[[ATTR1:[0-9]+]] { 26; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = call i32 @scc1_bar() #[[ATTR1]] 27; ATTRIBUTOR-NEXT: ret i32 1 28; 29 %1 = call i32 @scc1_bar() 30 ret i32 1 31} 32 33 34; TEST 3 35define i32 @scc1_bar() { 36; FNATTRS: Function Attrs: nofree nosync nounwind memory(none) 37; FNATTRS-LABEL: define {{[^@]+}}@scc1_bar 38; FNATTRS-SAME: () #[[ATTR1]] { 39; FNATTRS-NEXT: [[TMP1:%.*]] = call i32 @scc1_foo() 40; FNATTRS-NEXT: ret i32 1 41; 42; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(none) 43; ATTRIBUTOR-LABEL: define {{[^@]+}}@scc1_bar 44; ATTRIBUTOR-SAME: () #[[ATTR1]] { 45; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = call i32 @scc1_foo() #[[ATTR1]] 46; ATTRIBUTOR-NEXT: ret i32 1 47; 48 %1 = call i32 @scc1_foo() 49 ret i32 1 50} 51 52declare i32 @non_nounwind() 53 54; TEST 4 55define void @call_non_nounwind(){ 56; COMMON-LABEL: define {{[^@]+}}@call_non_nounwind() { 57; COMMON-NEXT: [[TMP1:%.*]] = tail call i32 @non_nounwind() 58; COMMON-NEXT: ret void 59; 60 tail call i32 @non_nounwind() 61 ret void 62} 63 64; TEST 5 - throw 65; int maybe_throw(bool canThrow) { 66; if (canThrow) 67; throw; 68; else 69; return -1; 70; } 71 72define i32 @maybe_throw(i1 zeroext %0) { 73; COMMON-LABEL: define {{[^@]+}}@maybe_throw 74; COMMON-SAME: (i1 zeroext [[TMP0:%.*]]) { 75; COMMON-NEXT: br i1 [[TMP0]], label [[TMP2:%.*]], label [[TMP3:%.*]] 76; COMMON: 2: 77; COMMON-NEXT: tail call void @__cxa_rethrow() 78; COMMON-NEXT: unreachable 79; COMMON: 3: 80; COMMON-NEXT: ret i32 -1 81; 82 br i1 %0, label %2, label %3 83 842: ; preds = %1 85 tail call void @__cxa_rethrow() #1 86 unreachable 87 883: ; preds = %1 89 ret i32 -1 90} 91 92declare void @__cxa_rethrow() 93 94; TEST 6 - catch 95; int catch_thing() { 96; try { 97; int a = doThing(true); 98; } 99; catch(...) { return -1; } 100; return 1; 101; } 102 103define i32 @catch_thing() personality ptr @__gxx_personality_v0 { 104; COMMON-LABEL: define {{[^@]+}}@catch_thing() personality ptr @__gxx_personality_v0 { 105; COMMON-NEXT: invoke void @__cxa_rethrow() 106; COMMON-NEXT: to label [[TMP1:%.*]] unwind label [[TMP2:%.*]] 107; COMMON: 1: 108; COMMON-NEXT: unreachable 109; COMMON: 2: 110; COMMON-NEXT: [[TMP3:%.*]] = landingpad { ptr, i32 } 111; COMMON-NEXT: catch ptr null 112; COMMON-NEXT: [[TMP4:%.*]] = extractvalue { ptr, i32 } [[TMP3]], 0 113; COMMON-NEXT: [[TMP5:%.*]] = tail call ptr @__cxa_begin_catch(ptr [[TMP4]]) 114; COMMON-NEXT: tail call void @__cxa_end_catch() 115; COMMON-NEXT: ret i32 -1 116; 117 invoke void @__cxa_rethrow() #1 118 to label %1 unwind label %2 119 1201: ; preds = %0 121 unreachable 122 1232: ; preds = %0 124 %3 = landingpad { ptr, i32 } 125 catch ptr null 126 %4 = extractvalue { ptr, i32 } %3, 0 127 %5 = tail call ptr @__cxa_begin_catch(ptr %4) #2 128 tail call void @__cxa_end_catch() 129 ret i32 -1 130} 131 132define i32 @catch_thing_user() { 133; COMMON-LABEL: define {{[^@]+}}@catch_thing_user() { 134; COMMON-NEXT: [[CATCH_THING_CALL:%.*]] = call i32 @catch_thing() 135; COMMON-NEXT: ret i32 [[CATCH_THING_CALL]] 136; 137 %catch_thing_call = call i32 @catch_thing() 138 ret i32 %catch_thing_call 139} 140 141declare void @do_throw() 142declare void @abort() nounwind 143@catch_ty = external global ptr 144 145define void @catch_specific_landingpad() personality ptr @__gxx_personality_v0 { 146; COMMON: Function Attrs: noreturn 147; COMMON-LABEL: define {{[^@]+}}@catch_specific_landingpad 148; COMMON-SAME: () #[[ATTR3:[0-9]+]] personality ptr @__gxx_personality_v0 { 149; COMMON-NEXT: invoke void @do_throw() 150; COMMON-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]] 151; COMMON: lpad: 152; COMMON-NEXT: [[LP:%.*]] = landingpad { ptr, i32 } 153; COMMON-NEXT: catch ptr @catch_ty 154; COMMON-NEXT: call void @abort() 155; COMMON-NEXT: unreachable 156; COMMON: unreachable: 157; COMMON-NEXT: unreachable 158; 159 invoke void @do_throw() 160 to label %unreachable unwind label %lpad 161 162lpad: 163 %lp = landingpad { ptr, i32 } 164 catch ptr @catch_ty 165 call void @abort() 166 unreachable 167 168unreachable: 169 unreachable 170} 171 172define void @catch_all_landingpad() personality ptr @__gxx_personality_v0 { 173; COMMON: Function Attrs: noreturn nounwind 174; COMMON-LABEL: define {{[^@]+}}@catch_all_landingpad 175; COMMON-SAME: () #[[ATTR4:[0-9]+]] personality ptr @__gxx_personality_v0 { 176; COMMON-NEXT: invoke void @do_throw() 177; COMMON-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]] 178; COMMON: lpad: 179; COMMON-NEXT: [[LP:%.*]] = landingpad { ptr, i32 } 180; COMMON-NEXT: catch ptr null 181; COMMON-NEXT: call void @abort() 182; COMMON-NEXT: unreachable 183; COMMON: unreachable: 184; COMMON-NEXT: unreachable 185; 186 invoke void @do_throw() 187 to label %unreachable unwind label %lpad 188 189lpad: 190 %lp = landingpad { ptr, i32 } 191 catch ptr null 192 call void @abort() 193 unreachable 194 195unreachable: 196 unreachable 197} 198 199define void @filter_specific_landingpad() personality ptr @__gxx_personality_v0 { 200; COMMON: Function Attrs: noreturn 201; COMMON-LABEL: define {{[^@]+}}@filter_specific_landingpad 202; COMMON-SAME: () #[[ATTR3]] personality ptr @__gxx_personality_v0 { 203; COMMON-NEXT: invoke void @do_throw() 204; COMMON-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]] 205; COMMON: lpad: 206; COMMON-NEXT: [[LP:%.*]] = landingpad { ptr, i32 } 207; COMMON-NEXT: filter [1 x ptr] [ptr @catch_ty] 208; COMMON-NEXT: call void @abort() 209; COMMON-NEXT: unreachable 210; COMMON: unreachable: 211; COMMON-NEXT: unreachable 212; 213 invoke void @do_throw() 214 to label %unreachable unwind label %lpad 215 216lpad: 217 %lp = landingpad { ptr, i32 } 218 filter [1 x ptr] [ptr @catch_ty] 219 call void @abort() 220 unreachable 221 222unreachable: 223 unreachable 224} 225 226define void @filter_none_landingpad() personality ptr @__gxx_personality_v0 { 227; COMMON: Function Attrs: noreturn nounwind 228; COMMON-LABEL: define {{[^@]+}}@filter_none_landingpad 229; COMMON-SAME: () #[[ATTR4]] personality ptr @__gxx_personality_v0 { 230; COMMON-NEXT: invoke void @do_throw() 231; COMMON-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]] 232; COMMON: lpad: 233; COMMON-NEXT: [[LP:%.*]] = landingpad { ptr, i32 } 234; COMMON-NEXT: filter [0 x ptr] zeroinitializer 235; COMMON-NEXT: call void @abort() 236; COMMON-NEXT: unreachable 237; COMMON: unreachable: 238; COMMON-NEXT: unreachable 239; 240 invoke void @do_throw() 241 to label %unreachable unwind label %lpad 242 243lpad: 244 %lp = landingpad { ptr, i32 } 245 filter [0 x ptr] zeroinitializer 246 call void @abort() 247 unreachable 248 249unreachable: 250 unreachable 251} 252 253define void @cleanup_landingpad() personality ptr @__gxx_personality_v0 { 254; COMMON: Function Attrs: noreturn 255; COMMON-LABEL: define {{[^@]+}}@cleanup_landingpad 256; COMMON-SAME: () #[[ATTR3]] personality ptr @__gxx_personality_v0 { 257; COMMON-NEXT: invoke void @do_throw() 258; COMMON-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[LPAD:%.*]] 259; COMMON: lpad: 260; COMMON-NEXT: [[LP:%.*]] = landingpad { ptr, i32 } 261; COMMON-NEXT: cleanup 262; COMMON-NEXT: call void @abort() 263; COMMON-NEXT: unreachable 264; COMMON: unreachable: 265; COMMON-NEXT: unreachable 266; 267 invoke void @do_throw() 268 to label %unreachable unwind label %lpad 269 270lpad: 271 %lp = landingpad { ptr, i32 } 272 cleanup 273 call void @abort() 274 unreachable 275 276unreachable: 277 unreachable 278} 279 280define void @cleanuppad() personality ptr @__gxx_personality_v0 { 281; FNATTRS: Function Attrs: noreturn 282; FNATTRS-LABEL: define {{[^@]+}}@cleanuppad 283; FNATTRS-SAME: () #[[ATTR3]] personality ptr @__gxx_personality_v0 { 284; FNATTRS-NEXT: invoke void @do_throw() 285; FNATTRS-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[CPAD:%.*]] 286; FNATTRS: cpad: 287; FNATTRS-NEXT: [[CP:%.*]] = cleanuppad within none [] 288; FNATTRS-NEXT: call void @abort() 289; FNATTRS-NEXT: unreachable 290; FNATTRS: unreachable: 291; FNATTRS-NEXT: unreachable 292; 293; ATTRIBUTOR: Function Attrs: noreturn nounwind 294; ATTRIBUTOR-LABEL: define {{[^@]+}}@cleanuppad 295; ATTRIBUTOR-SAME: () #[[ATTR4]] personality ptr @__gxx_personality_v0 { 296; ATTRIBUTOR-NEXT: invoke void @do_throw() 297; ATTRIBUTOR-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[CPAD:%.*]] 298; ATTRIBUTOR: cpad: 299; ATTRIBUTOR-NEXT: [[CP:%.*]] = cleanuppad within none [] 300; ATTRIBUTOR-NEXT: call void @abort() 301; ATTRIBUTOR-NEXT: unreachable 302; ATTRIBUTOR: unreachable: 303; ATTRIBUTOR-NEXT: unreachable 304; 305 invoke void @do_throw() 306 to label %unreachable unwind label %cpad 307 308cpad: 309 %cp = cleanuppad within none [] 310 call void @abort() 311 unreachable 312 313unreachable: 314 unreachable 315} 316 317define void @catchswitch_cleanuppad() personality ptr @__gxx_personality_v0 { 318; FNATTRS: Function Attrs: noreturn 319; FNATTRS-LABEL: define {{[^@]+}}@catchswitch_cleanuppad 320; FNATTRS-SAME: () #[[ATTR3]] personality ptr @__gxx_personality_v0 { 321; FNATTRS-NEXT: invoke void @do_throw() 322; FNATTRS-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[CS:%.*]] 323; FNATTRS: cs: 324; FNATTRS-NEXT: [[TOK:%.*]] = catchswitch within none [label %catch] unwind label [[CPAD:%.*]] 325; FNATTRS: catch: 326; FNATTRS-NEXT: [[C:%.*]] = catchpad within [[TOK]] [ptr @catch_ty, i32 0, ptr null] 327; FNATTRS-NEXT: call void @abort() 328; FNATTRS-NEXT: unreachable 329; FNATTRS: cpad: 330; FNATTRS-NEXT: [[CP:%.*]] = cleanuppad within none [] 331; FNATTRS-NEXT: call void @abort() 332; FNATTRS-NEXT: unreachable 333; FNATTRS: unreachable: 334; FNATTRS-NEXT: unreachable 335; 336; ATTRIBUTOR: Function Attrs: noreturn nounwind 337; ATTRIBUTOR-LABEL: define {{[^@]+}}@catchswitch_cleanuppad 338; ATTRIBUTOR-SAME: () #[[ATTR4]] personality ptr @__gxx_personality_v0 { 339; ATTRIBUTOR-NEXT: invoke void @do_throw() 340; ATTRIBUTOR-NEXT: to label [[UNREACHABLE:%.*]] unwind label [[CS:%.*]] 341; ATTRIBUTOR: cs: 342; ATTRIBUTOR-NEXT: [[TOK:%.*]] = catchswitch within none [label %catch] unwind label [[CPAD:%.*]] 343; ATTRIBUTOR: catch: 344; ATTRIBUTOR-NEXT: [[C:%.*]] = catchpad within [[TOK]] [ptr @catch_ty, i32 0, ptr null] 345; ATTRIBUTOR-NEXT: call void @abort() 346; ATTRIBUTOR-NEXT: unreachable 347; ATTRIBUTOR: cpad: 348; ATTRIBUTOR-NEXT: [[CP:%.*]] = cleanuppad within none [] 349; ATTRIBUTOR-NEXT: call void @abort() 350; ATTRIBUTOR-NEXT: unreachable 351; ATTRIBUTOR: unreachable: 352; ATTRIBUTOR-NEXT: unreachable 353; 354 invoke void @do_throw() 355 to label %unreachable unwind label %cs 356 357cs: 358 %tok = catchswitch within none [label %catch] unwind label %cpad 359 360catch: 361 %c = catchpad within %tok [ptr @catch_ty, i32 0, ptr null] 362 call void @abort() 363 unreachable 364 365cpad: 366 %cp = cleanuppad within none [] 367 call void @abort() 368 unreachable 369 370unreachable: 371 unreachable 372} 373 374declare i32 @__gxx_personality_v0(...) 375 376declare ptr @__cxa_begin_catch(ptr) 377 378declare void @__cxa_end_catch() 379