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 4 5define i32 @defined() convergent { 6; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 7; CHECK-LABEL: define {{[^@]+}}@defined 8; CHECK-SAME: () #[[ATTR0:[0-9]+]] { 9; CHECK-NEXT: ret i32 1 10; 11 ret i32 1 12} 13 14define i32 @calls_defined() convergent { 15; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 16; TUNIT-LABEL: define {{[^@]+}}@calls_defined 17; TUNIT-SAME: () #[[ATTR0]] { 18; TUNIT-NEXT: ret i32 1 19; 20; CGSCC: Function Attrs: convergent mustprogress nofree nosync nounwind willreturn memory(none) 21; CGSCC-LABEL: define {{[^@]+}}@calls_defined 22; CGSCC-SAME: () #[[ATTR1:[0-9]+]] { 23; CGSCC-NEXT: [[A:%.*]] = call noundef i32 @defined() #[[ATTR6:[0-9]+]] 24; CGSCC-NEXT: ret i32 [[A]] 25; 26 %a = call i32 @defined() 27 ret i32 %a 28} 29 30declare void @declared_non_convergent() 31 32define void @calls_declared_non_convergent() convergent { 33; CHECK-LABEL: define {{[^@]+}}@calls_declared_non_convergent() { 34; CHECK-NEXT: call void @declared_non_convergent() 35; CHECK-NEXT: ret void 36; 37 call void @declared_non_convergent() 38 ret void 39} 40 41; CHECK: Function Attrs: convergent 42declare i32 @declared_convergent() convergent 43 44define i32 @calls_declared_convergent() convergent { 45; TUNIT: Function Attrs: convergent 46; TUNIT-LABEL: define {{[^@]+}}@calls_declared_convergent 47; TUNIT-SAME: () #[[ATTR1:[0-9]+]] { 48; TUNIT-NEXT: [[A:%.*]] = call i32 @declared_convergent() 49; TUNIT-NEXT: ret i32 [[A]] 50; 51; CGSCC: Function Attrs: convergent 52; CGSCC-LABEL: define {{[^@]+}}@calls_declared_convergent 53; CGSCC-SAME: () #[[ATTR2:[0-9]+]] { 54; CGSCC-NEXT: [[A:%.*]] = call i32 @declared_convergent() 55; CGSCC-NEXT: ret i32 [[A]] 56; 57 %a = call i32 @declared_convergent() 58 ret i32 %a 59} 60 61define i32 @defined_with_asm(i32 %a, i32 %b) { 62; CHECK-LABEL: define {{[^@]+}}@defined_with_asm 63; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) { 64; CHECK-NEXT: [[RESULT:%.*]] = add i32 [[A]], [[B]] 65; CHECK-NEXT: [[ASM_RESULT:%.*]] = call i32 asm sideeffect "addl $1, $0", "=r,r"(i32 [[RESULT]]) 66; CHECK-NEXT: ret i32 [[ASM_RESULT]] 67; 68 %result = add i32 %a, %b 69 %asm_result = call i32 asm sideeffect "addl $1, $0", "=r,r"(i32 %result) 70 ret i32 %asm_result 71} 72 73define i32 @calls_defined_with_asm(i32 %a, i32 %b) convergent { 74; TUNIT: Function Attrs: convergent 75; TUNIT-LABEL: define {{[^@]+}}@calls_defined_with_asm 76; TUNIT-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR1]] { 77; TUNIT-NEXT: [[C:%.*]] = call i32 @defined_with_asm(i32 [[A]], i32 [[B]]) 78; TUNIT-NEXT: ret i32 [[C]] 79; 80; CGSCC: Function Attrs: convergent 81; CGSCC-LABEL: define {{[^@]+}}@calls_defined_with_asm 82; CGSCC-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) #[[ATTR2]] { 83; CGSCC-NEXT: [[C:%.*]] = call i32 @defined_with_asm(i32 [[A]], i32 [[B]]) 84; CGSCC-NEXT: ret i32 [[C]] 85; 86 %c = call i32 @defined_with_asm(i32 %a, i32 %b) 87 ret i32 %c 88} 89 90declare void @llvm.convergent.copy.p0.p0.i64(ptr %dest, ptr %src, i64 %size, i1 %isVolatile) #0 91 92define void @calls_convergent_intrinsic(ptr %dest, ptr %src, i64 %size) convergent { 93; TUNIT: Function Attrs: convergent mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite) 94; TUNIT-LABEL: define {{[^@]+}}@calls_convergent_intrinsic 95; TUNIT-SAME: (ptr nofree [[DEST:%.*]], ptr nofree [[SRC:%.*]], i64 [[SIZE:%.*]]) #[[ATTR3:[0-9]+]] { 96; TUNIT-NEXT: call void @llvm.convergent.copy.p0.p0.i64(ptr nofree [[DEST]], ptr nofree [[SRC]], i64 [[SIZE]], i1 noundef false) #[[ATTR5:[0-9]+]] 97; TUNIT-NEXT: ret void 98; 99; CGSCC: Function Attrs: convergent mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite) 100; CGSCC-LABEL: define {{[^@]+}}@calls_convergent_intrinsic 101; CGSCC-SAME: (ptr nofree [[DEST:%.*]], ptr nofree [[SRC:%.*]], i64 [[SIZE:%.*]]) #[[ATTR4:[0-9]+]] { 102; CGSCC-NEXT: call void @llvm.convergent.copy.p0.p0.i64(ptr nofree [[DEST]], ptr nofree [[SRC]], i64 [[SIZE]], i1 noundef false) #[[ATTR7:[0-9]+]] 103; CGSCC-NEXT: ret void 104; 105 call void @llvm.convergent.copy.p0.p0.i64(ptr %dest, ptr %src, i64 %size, i1 false) 106 ret void 107} 108 109declare void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 %size, i1 %isVolatile) #0 110 111define void @calls_intrinsic(ptr %dest, ptr %src, i64 %size) convergent { 112; TUNIT: Function Attrs: convergent mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) 113; TUNIT-LABEL: define {{[^@]+}}@calls_intrinsic 114; TUNIT-SAME: (ptr nofree writeonly captures(none) [[DEST:%.*]], ptr nofree readonly captures(none) [[SRC:%.*]], i64 [[SIZE:%.*]]) #[[ATTR2:[0-9]+]] { 115; TUNIT-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr nofree writeonly captures(none) [[DEST]], ptr nofree readonly captures(none) [[SRC]], i64 [[SIZE]], i1 noundef false) #[[ATTR5]] 116; TUNIT-NEXT: ret void 117; 118; CGSCC: Function Attrs: convergent mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) 119; CGSCC-LABEL: define {{[^@]+}}@calls_intrinsic 120; CGSCC-SAME: (ptr nofree writeonly captures(none) [[DEST:%.*]], ptr nofree readonly captures(none) [[SRC:%.*]], i64 [[SIZE:%.*]]) #[[ATTR3:[0-9]+]] { 121; CGSCC-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr nofree writeonly captures(none) [[DEST]], ptr nofree readonly captures(none) [[SRC]], i64 [[SIZE]], i1 noundef false) #[[ATTR7]] 122; CGSCC-NEXT: ret void 123; 124 call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 %size, i1 false) 125 ret void 126} 127 128attributes #0 = { convergent mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) } 129 130;. 131; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } 132; TUNIT: attributes #[[ATTR1]] = { convergent } 133; TUNIT: attributes #[[ATTR2]] = { convergent mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) } 134; TUNIT: attributes #[[ATTR3]] = { convergent mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite) } 135; TUNIT: attributes #[[ATTR4:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } 136; TUNIT: attributes #[[ATTR5]] = { nofree willreturn } 137;. 138; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } 139; CGSCC: attributes #[[ATTR1]] = { convergent mustprogress nofree nosync nounwind willreturn memory(none) } 140; CGSCC: attributes #[[ATTR2]] = { convergent } 141; CGSCC: attributes #[[ATTR3]] = { convergent mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) } 142; CGSCC: attributes #[[ATTR4]] = { convergent mustprogress nofree nosync nounwind willreturn memory(argmem: readwrite) } 143; CGSCC: attributes #[[ATTR5:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) } 144; CGSCC: attributes #[[ATTR6]] = { nofree nosync willreturn } 145; CGSCC: attributes #[[ATTR7]] = { nofree willreturn } 146;. 147