1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals 2; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM 3; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM 4; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM 5; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM 6target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 7 8; Test cases designed for the nosync function attribute. 9; FIXME's are used to indicate problems and missing attributes. 10 11; struct RT { 12; char A; 13; int B[10][20]; 14; char C; 15; }; 16; struct ST { 17; int X; 18; double Y; 19; struct RT Z; 20; }; 21; 22; int *foo(struct ST *s) { 23; return &s[1].Z.B[5][13]; 24; } 25 26; TEST 1 27; non-convergent and readnone implies nosync 28%struct.RT = type { i8, [10 x [20 x i32]], i8 } 29%struct.ST = type { i32, double, %struct.RT } 30 31;. 32; CHECK: @[[A:[a-zA-Z0-9_$"\\.-]+]] = common global i32 0, align 4 33;. 34define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp { 35; CHECK: Function Attrs: nofree norecurse nosync nounwind optsize readnone ssp willreturn uwtable 36; CHECK-LABEL: define {{[^@]+}}@foo 37; CHECK-SAME: (%struct.ST* nofree readnone "no-capture-maybe-returned" [[S:%.*]]) #[[ATTR0:[0-9]+]] { 38; CHECK-NEXT: entry: 39; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ST:%.*]], %struct.ST* [[S]], i64 1, i32 2, i32 1, i64 5, i64 13 40; CHECK-NEXT: ret i32* [[ARRAYIDX]] 41; 42entry: 43 %arrayidx = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 1, i32 2, i32 1, i64 5, i64 13 44 ret i32* %arrayidx 45} 46 47; TEST 2 48; atomic load with monotonic ordering 49; int load_monotonic(_Atomic int *num) { 50; int n = atomic_load_explicit(num, memory_order_relaxed); 51; return n; 52; } 53 54define i32 @load_monotonic(i32* nocapture readonly %0) norecurse nounwind uwtable { 55; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn uwtable 56; CHECK-LABEL: define {{[^@]+}}@load_monotonic 57; CHECK-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[TMP0:%.*]]) #[[ATTR1:[0-9]+]] { 58; CHECK-NEXT: [[TMP2:%.*]] = load atomic i32, i32* [[TMP0]] monotonic, align 4 59; CHECK-NEXT: ret i32 [[TMP2]] 60; 61 %2 = load atomic i32, i32* %0 monotonic, align 4 62 ret i32 %2 63} 64 65 66; TEST 3 67; atomic store with monotonic ordering. 68; void store_monotonic(_Atomic int *num) { 69; atomic_load_explicit(num, memory_order_relaxed); 70; } 71 72define void @store_monotonic(i32* nocapture %0) norecurse nounwind uwtable { 73; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn uwtable 74; CHECK-LABEL: define {{[^@]+}}@store_monotonic 75; CHECK-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]]) #[[ATTR1]] { 76; CHECK-NEXT: store atomic i32 10, i32* [[TMP0]] monotonic, align 4 77; CHECK-NEXT: ret void 78; 79 store atomic i32 10, i32* %0 monotonic, align 4 80 ret void 81} 82 83; TEST 4 - negative, should not deduce nosync 84; atomic load with acquire ordering. 85; int load_acquire(_Atomic int *num) { 86; int n = atomic_load_explicit(num, memory_order_acquire); 87; return n; 88; } 89 90define i32 @load_acquire(i32* nocapture readonly %0) norecurse nounwind uwtable { 91; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn uwtable 92; CHECK-LABEL: define {{[^@]+}}@load_acquire 93; CHECK-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[TMP0:%.*]]) #[[ATTR2:[0-9]+]] { 94; CHECK-NEXT: [[TMP2:%.*]] = load atomic i32, i32* [[TMP0]] acquire, align 4 95; CHECK-NEXT: ret i32 [[TMP2]] 96; 97 %2 = load atomic i32, i32* %0 acquire, align 4 98 ret i32 %2 99} 100 101; TEST 5 - negative, should not deduce nosync 102; atomic load with release ordering 103; void load_release(_Atomic int *num) { 104; atomic_store_explicit(num, 10, memory_order_release); 105; } 106 107define void @load_release(i32* nocapture %0) norecurse nounwind uwtable { 108; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn uwtable 109; CHECK-LABEL: define {{[^@]+}}@load_release 110; CHECK-SAME: (i32* nocapture nofree noundef writeonly align 4 [[TMP0:%.*]]) #[[ATTR2]] { 111; CHECK-NEXT: store atomic volatile i32 10, i32* [[TMP0]] release, align 4 112; CHECK-NEXT: ret void 113; 114 store atomic volatile i32 10, i32* %0 release, align 4 115 ret void 116} 117 118; TEST 6 - negative volatile, relaxed atomic 119 120define void @load_volatile_release(i32* nocapture %0) norecurse nounwind uwtable { 121; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn uwtable 122; CHECK-LABEL: define {{[^@]+}}@load_volatile_release 123; CHECK-SAME: (i32* nocapture nofree noundef writeonly align 4 [[TMP0:%.*]]) #[[ATTR2]] { 124; CHECK-NEXT: store atomic volatile i32 10, i32* [[TMP0]] release, align 4 125; CHECK-NEXT: ret void 126; 127 store atomic volatile i32 10, i32* %0 release, align 4 128 ret void 129} 130 131; TEST 7 - negative, should not deduce nosync 132; volatile store. 133; void volatile_store(volatile int *num) { 134; *num = 14; 135; } 136 137define void @volatile_store(i32* %0) norecurse nounwind uwtable { 138; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn uwtable 139; CHECK-LABEL: define {{[^@]+}}@volatile_store 140; CHECK-SAME: (i32* nofree noundef align 4 [[TMP0:%.*]]) #[[ATTR2]] { 141; CHECK-NEXT: store volatile i32 14, i32* [[TMP0]], align 4 142; CHECK-NEXT: ret void 143; 144 store volatile i32 14, i32* %0, align 4 145 ret void 146} 147 148; TEST 8 - negative, should not deduce nosync 149; volatile load. 150; int volatile_load(volatile int *num) { 151; int n = *num; 152; return n; 153; } 154 155define i32 @volatile_load(i32* %0) norecurse nounwind uwtable { 156; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn uwtable 157; CHECK-LABEL: define {{[^@]+}}@volatile_load 158; CHECK-SAME: (i32* nofree noundef align 4 [[TMP0:%.*]]) #[[ATTR2]] { 159; CHECK-NEXT: [[TMP2:%.*]] = load volatile i32, i32* [[TMP0]], align 4 160; CHECK-NEXT: ret i32 [[TMP2]] 161; 162 %2 = load volatile i32, i32* %0, align 4 163 ret i32 %2 164} 165 166; TEST 9 167 168; CHECK: Function Attrs: noinline nosync nounwind uwtable 169; CHECK-NEXT: declare void @nosync_function() 170declare void @nosync_function() noinline nounwind uwtable nosync 171 172define void @call_nosync_function() nounwind uwtable noinline { 173; CHECK: Function Attrs: noinline nosync nounwind uwtable 174; CHECK-LABEL: define {{[^@]+}}@call_nosync_function 175; CHECK-SAME: () #[[ATTR3:[0-9]+]] { 176; CHECK-NEXT: tail call void @nosync_function() #[[ATTR4:[0-9]+]] 177; CHECK-NEXT: ret void 178; 179 tail call void @nosync_function() noinline nounwind uwtable 180 ret void 181} 182 183; TEST 10 - negative, should not deduce nosync 184 185; CHECK: Function Attrs: noinline nounwind uwtable 186; CHECK-NEXT: declare void @might_sync() 187declare void @might_sync() noinline nounwind uwtable 188 189define void @call_might_sync() nounwind uwtable noinline { 190; CHECK: Function Attrs: noinline nounwind uwtable 191; CHECK-LABEL: define {{[^@]+}}@call_might_sync 192; CHECK-SAME: () #[[ATTR4]] { 193; CHECK-NEXT: tail call void @might_sync() #[[ATTR4]] 194; CHECK-NEXT: ret void 195; 196 tail call void @might_sync() noinline nounwind uwtable 197 ret void 198} 199 200; TEST 11 - positive, should deduce nosync 201; volatile operation in same scc but dead. Call volatile_load defined in TEST 8. 202 203define i32 @scc1(i32* %0) noinline nounwind uwtable { 204; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nounwind uwtable 205; IS__TUNIT____-LABEL: define {{[^@]+}}@scc1 206; IS__TUNIT____-SAME: (i32* nofree [[TMP0:%.*]]) #[[ATTR5:[0-9]+]] { 207; IS__TUNIT____-NEXT: tail call void @scc2(i32* nofree [[TMP0]]) #[[ATTR19:[0-9]+]] 208; IS__TUNIT____-NEXT: [[VAL:%.*]] = tail call i32 @volatile_load(i32* nofree align 4 [[TMP0]]) #[[ATTR19]] 209; IS__TUNIT____-NEXT: ret i32 [[VAL]] 210; 211; IS__CGSCC_OPM: Function Attrs: argmemonly nofree noinline nounwind uwtable 212; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@scc1 213; IS__CGSCC_OPM-SAME: (i32* nofree [[TMP0:%.*]]) #[[ATTR5:[0-9]+]] { 214; IS__CGSCC_OPM-NEXT: tail call void @scc2(i32* nofree [[TMP0]]) #[[ATTR19:[0-9]+]] 215; IS__CGSCC_OPM-NEXT: [[VAL:%.*]] = tail call i32 @volatile_load(i32* nofree noundef align 4 [[TMP0]]) #[[ATTR20:[0-9]+]] 216; IS__CGSCC_OPM-NEXT: ret i32 [[VAL]] 217; 218; IS__CGSCC_NPM: Function Attrs: argmemonly nofree noinline nounwind uwtable 219; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@scc1 220; IS__CGSCC_NPM-SAME: (i32* nofree [[TMP0:%.*]]) #[[ATTR5:[0-9]+]] { 221; IS__CGSCC_NPM-NEXT: tail call void @scc2(i32* nofree [[TMP0]]) #[[ATTR19:[0-9]+]] 222; IS__CGSCC_NPM-NEXT: [[VAL:%.*]] = tail call i32 @volatile_load(i32* nofree noundef align 4 [[TMP0]]) #[[ATTR14:[0-9]+]] 223; IS__CGSCC_NPM-NEXT: ret i32 [[VAL]] 224; 225 tail call void @scc2(i32* %0); 226 %val = tail call i32 @volatile_load(i32* %0); 227 ret i32 %val; 228} 229 230define void @scc2(i32* %0) noinline nounwind uwtable { 231; CHECK: Function Attrs: argmemonly nofree noinline nounwind uwtable 232; CHECK-LABEL: define {{[^@]+}}@scc2 233; CHECK-SAME: (i32* nofree [[TMP0:%.*]]) #[[ATTR5:[0-9]+]] { 234; CHECK-NEXT: [[TMP2:%.*]] = tail call i32 @scc1(i32* nofree [[TMP0]]) #[[ATTR19:[0-9]+]] 235; CHECK-NEXT: ret void 236; 237 tail call i32 @scc1(i32* %0); 238 ret void; 239} 240 241; TEST 12 - fences, negative 242; 243; void foo1(int *a, std::atomic<bool> flag){ 244; *a = 100; 245; atomic_thread_fence(std::memory_order_release); 246; flag.store(true, std::memory_order_relaxed); 247; } 248; 249; void bar(int *a, std::atomic<bool> flag){ 250; while(!flag.load(std::memory_order_relaxed)) 251; ; 252; 253; atomic_thread_fence(std::memory_order_acquire); 254; int b = *a; 255; } 256 257%"struct.std::atomic" = type { %"struct.std::__atomic_base" } 258%"struct.std::__atomic_base" = type { i8 } 259 260define void @foo1(i32* %0, %"struct.std::atomic"* %1) { 261; CHECK: Function Attrs: nofree norecurse nounwind willreturn 262; CHECK-LABEL: define {{[^@]+}}@foo1 263; CHECK-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull writeonly dereferenceable(1) [[TMP1:%.*]]) #[[ATTR6:[0-9]+]] { 264; CHECK-NEXT: store i32 100, i32* [[TMP0]], align 4 265; CHECK-NEXT: fence release 266; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 267; CHECK-NEXT: store atomic i8 1, i8* [[TMP3]] monotonic, align 1 268; CHECK-NEXT: ret void 269; 270 store i32 100, i32* %0, align 4 271 fence release 272 %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0 273 store atomic i8 1, i8* %3 monotonic, align 1 274 ret void 275} 276 277define void @bar(i32* %0, %"struct.std::atomic"* %1) { 278; CHECK: Function Attrs: nofree norecurse nounwind 279; CHECK-LABEL: define {{[^@]+}}@bar 280; CHECK-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]]) #[[ATTR7:[0-9]+]] { 281; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 282; CHECK-NEXT: br label [[TMP4:%.*]] 283; CHECK: 4: 284; CHECK-NEXT: [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1 285; CHECK-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 1 286; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0 287; CHECK-NEXT: br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]] 288; CHECK: 8: 289; CHECK-NEXT: fence acquire 290; CHECK-NEXT: ret void 291; 292 %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0 293 br label %4 294 2954: ; preds = %4, %2 296 %5 = load atomic i8, i8* %3 monotonic, align 1 297 %6 = and i8 %5, 1 298 %7 = icmp eq i8 %6, 0 299 br i1 %7, label %4, label %8 300 3018: ; preds = %4 302 fence acquire 303 ret void 304} 305 306; TEST 13 - Fence syncscope("singlethread") seq_cst 307define void @foo1_singlethread(i32* %0, %"struct.std::atomic"* %1) { 308; CHECK: Function Attrs: nofree norecurse nosync nounwind willreturn 309; CHECK-LABEL: define {{[^@]+}}@foo1_singlethread 310; CHECK-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull writeonly dereferenceable(1) [[TMP1:%.*]]) #[[ATTR8:[0-9]+]] { 311; CHECK-NEXT: store i32 100, i32* [[TMP0]], align 4 312; CHECK-NEXT: fence syncscope("singlethread") release 313; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 314; CHECK-NEXT: store atomic i8 1, i8* [[TMP3]] monotonic, align 1 315; CHECK-NEXT: ret void 316; 317 store i32 100, i32* %0, align 4 318 fence syncscope("singlethread") release 319 %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0 320 store atomic i8 1, i8* %3 monotonic, align 1 321 ret void 322} 323 324define void @bar_singlethread(i32* %0, %"struct.std::atomic"* %1) { 325; CHECK: Function Attrs: nofree norecurse nosync nounwind 326; CHECK-LABEL: define {{[^@]+}}@bar_singlethread 327; CHECK-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]]) #[[ATTR9:[0-9]+]] { 328; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 329; CHECK-NEXT: br label [[TMP4:%.*]] 330; CHECK: 4: 331; CHECK-NEXT: [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1 332; CHECK-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 1 333; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0 334; CHECK-NEXT: br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]] 335; CHECK: 8: 336; CHECK-NEXT: fence syncscope("singlethread") acquire 337; CHECK-NEXT: ret void 338; 339 %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0 340 br label %4 341 3424: ; preds = %4, %2 343 %5 = load atomic i8, i8* %3 monotonic, align 1 344 %6 = and i8 %5, 1 345 %7 = icmp eq i8 %6, 0 346 br i1 %7, label %4, label %8 347 3488: ; preds = %4 349 fence syncscope("singlethread") acquire 350 ret void 351} 352 353declare void @llvm.memcpy(i8* %dest, i8* %src, i32 %len, i1 %isvolatile) 354declare void @llvm.memset(i8* %dest, i8 %val, i32 %len, i1 %isvolatile) 355 356; TEST 14 - negative, checking volatile intrinsics. 357 358; It is odd to add nocapture but a result of the llvm.memcpy nocapture. 359; 360define i32 @memcpy_volatile(i8* %ptr1, i8* %ptr2) { 361; NOT_CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nounwind willreturn 362; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@memcpy_volatile 363; NOT_CGSCC_OPM-SAME: (i8* nocapture nofree writeonly [[PTR1:%.*]], i8* nocapture nofree readonly [[PTR2:%.*]]) #[[ATTR10:[0-9]+]] { 364; NOT_CGSCC_OPM-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture nofree writeonly [[PTR1]], i8* noalias nocapture nofree readonly [[PTR2]], i32 noundef 8, i1 noundef true) #[[ATTR20:[0-9]+]] 365; NOT_CGSCC_OPM-NEXT: ret i32 4 366; 367; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nounwind willreturn 368; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@memcpy_volatile 369; IS__CGSCC_OPM-SAME: (i8* nocapture nofree writeonly [[PTR1:%.*]], i8* nocapture nofree readonly [[PTR2:%.*]]) #[[ATTR10:[0-9]+]] { 370; IS__CGSCC_OPM-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture nofree writeonly [[PTR1]], i8* noalias nocapture nofree readonly [[PTR2]], i32 noundef 8, i1 noundef true) #[[ATTR21:[0-9]+]] 371; IS__CGSCC_OPM-NEXT: ret i32 4 372; 373 call void @llvm.memcpy(i8* %ptr1, i8* %ptr2, i32 8, i1 1) 374 ret i32 4 375} 376 377; TEST 15 - positive, non-volatile intrinsic. 378 379; It is odd to add nocapture but a result of the llvm.memset nocapture. 380; 381define i32 @memset_non_volatile(i8* %ptr1, i8 %val) { 382; NOT_CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly 383; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@memset_non_volatile 384; NOT_CGSCC_OPM-SAME: (i8* nocapture nofree writeonly [[PTR1:%.*]], i8 [[VAL:%.*]]) #[[ATTR11:[0-9]+]] { 385; NOT_CGSCC_OPM-NEXT: call void @llvm.memset.p0i8.i32(i8* nocapture nofree writeonly [[PTR1]], i8 [[VAL]], i32 noundef 8, i1 noundef false) #[[ATTR21:[0-9]+]] 386; NOT_CGSCC_OPM-NEXT: ret i32 4 387; 388; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly 389; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@memset_non_volatile 390; IS__CGSCC_OPM-SAME: (i8* nocapture nofree writeonly [[PTR1:%.*]], i8 [[VAL:%.*]]) #[[ATTR11:[0-9]+]] { 391; IS__CGSCC_OPM-NEXT: call void @llvm.memset.p0i8.i32(i8* nocapture nofree writeonly [[PTR1]], i8 [[VAL]], i32 noundef 8, i1 noundef false) #[[ATTR22:[0-9]+]] 392; IS__CGSCC_OPM-NEXT: ret i32 4 393; 394 call void @llvm.memset(i8* %ptr1, i8 %val, i32 8, i1 0) 395 ret i32 4 396} 397 398; TEST 16 - negative, inline assembly. 399 400define i32 @inline_asm_test(i32 %x) { 401; CHECK-LABEL: define {{[^@]+}}@inline_asm_test 402; CHECK-SAME: (i32 [[X:%.*]]) { 403; CHECK-NEXT: [[TMP1:%.*]] = call i32 asm "bswap $0", "=r,r"(i32 [[X]]) 404; CHECK-NEXT: ret i32 4 405; 406 call i32 asm "bswap $0", "=r,r"(i32 %x) 407 ret i32 4 408} 409 410declare void @readnone_test() convergent readnone 411 412; TEST 17 - negative. Convergent 413define void @convergent_readnone(){ 414; CHECK: Function Attrs: readnone 415; CHECK-LABEL: define {{[^@]+}}@convergent_readnone 416; CHECK-SAME: () #[[ATTR13:[0-9]+]] { 417; CHECK-NEXT: call void @readnone_test() 418; CHECK-NEXT: ret void 419; 420 call void @readnone_test() 421 ret void 422} 423 424; CHECK: Function Attrs: nounwind 425; CHECK-NEXT: declare void @llvm.x86.sse2.clflush(i8*) 426declare void @llvm.x86.sse2.clflush(i8*) 427@a = common global i32 0, align 4 428 429; TEST 18 - negative. Synchronizing intrinsic 430 431define void @i_totally_sync() { 432; CHECK: Function Attrs: nounwind 433; CHECK-LABEL: define {{[^@]+}}@i_totally_sync 434; CHECK-SAME: () #[[ATTR14:[0-9]+]] { 435; CHECK-NEXT: tail call void @llvm.x86.sse2.clflush(i8* noundef nonnull align 4 dereferenceable(4) bitcast (i32* @a to i8*)) 436; CHECK-NEXT: ret void 437; 438 tail call void @llvm.x86.sse2.clflush(i8* bitcast (i32* @a to i8*)) 439 ret void 440} 441 442declare float @llvm.cos(float %val) readnone 443 444; TEST 19 - positive, readnone & non-convergent intrinsic. 445 446define i32 @cos_test(float %x) { 447; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 448; CHECK-LABEL: define {{[^@]+}}@cos_test 449; CHECK-SAME: (float [[X:%.*]]) #[[ATTR15:[0-9]+]] { 450; CHECK-NEXT: ret i32 4 451; 452 call float @llvm.cos(float %x) 453 ret i32 4 454} 455 456define float @cos_test2(float %x) { 457; NOT_CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 458; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@cos_test2 459; NOT_CGSCC_OPM-SAME: (float [[X:%.*]]) #[[ATTR15]] { 460; NOT_CGSCC_OPM-NEXT: [[C:%.*]] = call float @llvm.cos.f32(float [[X]]) #[[ATTR22:[0-9]+]] 461; NOT_CGSCC_OPM-NEXT: ret float [[C]] 462; 463; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 464; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@cos_test2 465; IS__CGSCC_OPM-SAME: (float [[X:%.*]]) #[[ATTR15]] { 466; IS__CGSCC_OPM-NEXT: [[C:%.*]] = call float @llvm.cos.f32(float [[X]]) #[[ATTR23:[0-9]+]] 467; IS__CGSCC_OPM-NEXT: ret float [[C]] 468; 469 %c = call float @llvm.cos(float %x) 470 ret float %c 471} 472;. 473; NOT_CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind optsize readnone ssp willreturn uwtable } 474; NOT_CGSCC_OPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind willreturn uwtable } 475; NOT_CGSCC_OPM: attributes #[[ATTR2]] = { argmemonly nofree norecurse nounwind willreturn uwtable } 476; NOT_CGSCC_OPM: attributes #[[ATTR3]] = { noinline nosync nounwind uwtable } 477; NOT_CGSCC_OPM: attributes #[[ATTR4]] = { noinline nounwind uwtable } 478; NOT_CGSCC_OPM: attributes #[[ATTR5]] = { argmemonly nofree noinline nounwind uwtable } 479; NOT_CGSCC_OPM: attributes #[[ATTR6]] = { nofree norecurse nounwind willreturn } 480; NOT_CGSCC_OPM: attributes #[[ATTR7]] = { nofree norecurse nounwind } 481; NOT_CGSCC_OPM: attributes #[[ATTR8]] = { nofree norecurse nosync nounwind willreturn } 482; NOT_CGSCC_OPM: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind } 483; NOT_CGSCC_OPM: attributes #[[ATTR10]] = { argmemonly nofree norecurse nounwind willreturn } 484; NOT_CGSCC_OPM: attributes #[[ATTR11]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } 485; NOT_CGSCC_OPM: attributes #[[ATTR12:[0-9]+]] = { convergent readnone } 486; NOT_CGSCC_OPM: attributes #[[ATTR13]] = { readnone } 487; NOT_CGSCC_OPM: attributes #[[ATTR14]] = { nounwind } 488; NOT_CGSCC_OPM: attributes #[[ATTR15]] = { nofree norecurse nosync nounwind readnone willreturn } 489; NOT_CGSCC_OPM: attributes #[[ATTR16:[0-9]+]] = { argmemonly nocallback nofree nounwind willreturn } 490; NOT_CGSCC_OPM: attributes #[[ATTR17:[0-9]+]] = { argmemonly nocallback nofree nounwind willreturn writeonly } 491; NOT_CGSCC_OPM: attributes #[[ATTR18:[0-9]+]] = { nocallback nofree nosync nounwind readnone speculatable willreturn } 492; NOT_CGSCC_OPM: attributes #[[ATTR19]] = { nofree nounwind } 493; NOT_CGSCC_OPM: attributes #[[ATTR20]] = { willreturn } 494; NOT_CGSCC_OPM: attributes #[[ATTR21]] = { willreturn writeonly } 495; NOT_CGSCC_OPM: attributes #[[ATTR22]] = { readnone willreturn } 496;. 497; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind optsize readnone ssp willreturn uwtable } 498; IS__CGSCC_OPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind willreturn uwtable } 499; IS__CGSCC_OPM: attributes #[[ATTR2]] = { argmemonly nofree norecurse nounwind willreturn uwtable } 500; IS__CGSCC_OPM: attributes #[[ATTR3]] = { noinline nosync nounwind uwtable } 501; IS__CGSCC_OPM: attributes #[[ATTR4]] = { noinline nounwind uwtable } 502; IS__CGSCC_OPM: attributes #[[ATTR5]] = { argmemonly nofree noinline nounwind uwtable } 503; IS__CGSCC_OPM: attributes #[[ATTR6]] = { nofree norecurse nounwind willreturn } 504; IS__CGSCC_OPM: attributes #[[ATTR7]] = { nofree norecurse nounwind } 505; IS__CGSCC_OPM: attributes #[[ATTR8]] = { nofree norecurse nosync nounwind willreturn } 506; IS__CGSCC_OPM: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind } 507; IS__CGSCC_OPM: attributes #[[ATTR10]] = { argmemonly nofree norecurse nounwind willreturn } 508; IS__CGSCC_OPM: attributes #[[ATTR11]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly } 509; IS__CGSCC_OPM: attributes #[[ATTR12:[0-9]+]] = { convergent readnone } 510; IS__CGSCC_OPM: attributes #[[ATTR13]] = { readnone } 511; IS__CGSCC_OPM: attributes #[[ATTR14]] = { nounwind } 512; IS__CGSCC_OPM: attributes #[[ATTR15]] = { nofree norecurse nosync nounwind readnone willreturn } 513; IS__CGSCC_OPM: attributes #[[ATTR16:[0-9]+]] = { argmemonly nocallback nofree nounwind willreturn } 514; IS__CGSCC_OPM: attributes #[[ATTR17:[0-9]+]] = { argmemonly nocallback nofree nounwind willreturn writeonly } 515; IS__CGSCC_OPM: attributes #[[ATTR18:[0-9]+]] = { nocallback nofree nosync nounwind readnone speculatable willreturn } 516; IS__CGSCC_OPM: attributes #[[ATTR19]] = { nofree nounwind } 517; IS__CGSCC_OPM: attributes #[[ATTR20]] = { nounwind willreturn } 518; IS__CGSCC_OPM: attributes #[[ATTR21]] = { willreturn } 519; IS__CGSCC_OPM: attributes #[[ATTR22]] = { willreturn writeonly } 520; IS__CGSCC_OPM: attributes #[[ATTR23]] = { readnone willreturn } 521;. 522