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=2 -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=2 -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; IS__TUNIT____: Function Attrs: nofree nosync nounwind optsize readnone ssp uwtable willreturn 36; IS__TUNIT____-LABEL: define {{[^@]+}}@foo 37; IS__TUNIT____-SAME: (%struct.ST* nofree readnone "no-capture-maybe-returned" [[S:%.*]]) #[[ATTR0:[0-9]+]] { 38; IS__TUNIT____-NEXT: entry: 39; IS__TUNIT____-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ST:%.*]], %struct.ST* [[S]], i64 1, i32 2, i32 1, i64 5, i64 13 40; IS__TUNIT____-NEXT: ret i32* [[ARRAYIDX]] 41; 42; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind optsize readnone ssp uwtable willreturn 43; IS__CGSCC____-LABEL: define {{[^@]+}}@foo 44; IS__CGSCC____-SAME: (%struct.ST* nofree readnone "no-capture-maybe-returned" [[S:%.*]]) #[[ATTR0:[0-9]+]] { 45; IS__CGSCC____-NEXT: entry: 46; IS__CGSCC____-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ST:%.*]], %struct.ST* [[S]], i64 1, i32 2, i32 1, i64 5, i64 13 47; IS__CGSCC____-NEXT: ret i32* [[ARRAYIDX]] 48; 49entry: 50 %arrayidx = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 1, i32 2, i32 1, i64 5, i64 13 51 ret i32* %arrayidx 52} 53 54; TEST 2 55; atomic load with monotonic ordering 56; int load_monotonic(_Atomic int *num) { 57; int n = atomic_load_explicit(num, memory_order_relaxed); 58; return n; 59; } 60 61define i32 @load_monotonic(i32* nocapture readonly %0) norecurse nounwind uwtable { 62; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind uwtable willreturn 63; CHECK-LABEL: define {{[^@]+}}@load_monotonic 64; CHECK-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[TMP0:%.*]]) #[[ATTR1:[0-9]+]] { 65; CHECK-NEXT: [[TMP2:%.*]] = load atomic i32, i32* [[TMP0]] monotonic, align 4 66; CHECK-NEXT: ret i32 [[TMP2]] 67; 68 %2 = load atomic i32, i32* %0 monotonic, align 4 69 ret i32 %2 70} 71 72 73; TEST 3 74; atomic store with monotonic ordering. 75; void store_monotonic(_Atomic int *num) { 76; atomic_load_explicit(num, memory_order_relaxed); 77; } 78 79define void @store_monotonic(i32* nocapture %0) norecurse nounwind uwtable { 80; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind uwtable willreturn 81; CHECK-LABEL: define {{[^@]+}}@store_monotonic 82; CHECK-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]]) #[[ATTR1]] { 83; CHECK-NEXT: store atomic i32 10, i32* [[TMP0]] monotonic, align 4 84; CHECK-NEXT: ret void 85; 86 store atomic i32 10, i32* %0 monotonic, align 4 87 ret void 88} 89 90; TEST 4 - negative, should not deduce nosync 91; atomic load with acquire ordering. 92; int load_acquire(_Atomic int *num) { 93; int n = atomic_load_explicit(num, memory_order_acquire); 94; return n; 95; } 96 97define i32 @load_acquire(i32* nocapture readonly %0) norecurse nounwind uwtable { 98; CHECK: Function Attrs: argmemonly nofree norecurse nounwind uwtable willreturn 99; CHECK-LABEL: define {{[^@]+}}@load_acquire 100; CHECK-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[TMP0:%.*]]) #[[ATTR2:[0-9]+]] { 101; CHECK-NEXT: [[TMP2:%.*]] = load atomic i32, i32* [[TMP0]] acquire, align 4 102; CHECK-NEXT: ret i32 [[TMP2]] 103; 104 %2 = load atomic i32, i32* %0 acquire, align 4 105 ret i32 %2 106} 107 108; TEST 5 - negative, should not deduce nosync 109; atomic load with release ordering 110; void load_release(_Atomic int *num) { 111; atomic_store_explicit(num, 10, memory_order_release); 112; } 113 114define void @load_release(i32* nocapture %0) norecurse nounwind uwtable { 115; CHECK: Function Attrs: argmemonly nofree norecurse nounwind uwtable willreturn 116; CHECK-LABEL: define {{[^@]+}}@load_release 117; CHECK-SAME: (i32* nocapture nofree noundef writeonly align 4 [[TMP0:%.*]]) #[[ATTR2]] { 118; CHECK-NEXT: store atomic volatile i32 10, i32* [[TMP0]] release, align 4 119; CHECK-NEXT: ret void 120; 121 store atomic volatile i32 10, i32* %0 release, align 4 122 ret void 123} 124 125; TEST 6 - negative volatile, relaxed atomic 126 127define void @load_volatile_release(i32* nocapture %0) norecurse nounwind uwtable { 128; CHECK: Function Attrs: argmemonly nofree norecurse nounwind uwtable willreturn 129; CHECK-LABEL: define {{[^@]+}}@load_volatile_release 130; CHECK-SAME: (i32* nocapture nofree noundef writeonly align 4 [[TMP0:%.*]]) #[[ATTR2]] { 131; CHECK-NEXT: store atomic volatile i32 10, i32* [[TMP0]] release, align 4 132; CHECK-NEXT: ret void 133; 134 store atomic volatile i32 10, i32* %0 release, align 4 135 ret void 136} 137 138; TEST 7 - negative, should not deduce nosync 139; volatile store. 140; void volatile_store(volatile int *num) { 141; *num = 14; 142; } 143 144define void @volatile_store(i32* %0) norecurse nounwind uwtable { 145; CHECK: Function Attrs: argmemonly nofree norecurse nounwind uwtable willreturn 146; CHECK-LABEL: define {{[^@]+}}@volatile_store 147; CHECK-SAME: (i32* nofree noundef align 4 [[TMP0:%.*]]) #[[ATTR2]] { 148; CHECK-NEXT: store volatile i32 14, i32* [[TMP0]], align 4 149; CHECK-NEXT: ret void 150; 151 store volatile i32 14, i32* %0, align 4 152 ret void 153} 154 155; TEST 8 - negative, should not deduce nosync 156; volatile load. 157; int volatile_load(volatile int *num) { 158; int n = *num; 159; return n; 160; } 161 162define i32 @volatile_load(i32* %0) norecurse nounwind uwtable { 163; CHECK: Function Attrs: argmemonly nofree norecurse nounwind uwtable willreturn 164; CHECK-LABEL: define {{[^@]+}}@volatile_load 165; CHECK-SAME: (i32* nofree align 4 [[TMP0:%.*]]) #[[ATTR2]] { 166; CHECK-NEXT: [[TMP2:%.*]] = load volatile i32, i32* [[TMP0]], align 4 167; CHECK-NEXT: ret i32 [[TMP2]] 168; 169 %2 = load volatile i32, i32* %0, align 4 170 ret i32 %2 171} 172 173; TEST 9 174 175; CHECK: Function Attrs: noinline nosync nounwind uwtable 176; CHECK-NEXT: declare void @nosync_function() 177declare void @nosync_function() noinline nounwind uwtable nosync 178 179define void @call_nosync_function() nounwind uwtable noinline { 180; CHECK: Function Attrs: noinline nosync nounwind uwtable 181; CHECK-LABEL: define {{[^@]+}}@call_nosync_function 182; CHECK-SAME: () #[[ATTR3:[0-9]+]] { 183; CHECK-NEXT: tail call void @nosync_function() #[[ATTR4:[0-9]+]] 184; CHECK-NEXT: ret void 185; 186 tail call void @nosync_function() noinline nounwind uwtable 187 ret void 188} 189 190; TEST 10 - negative, should not deduce nosync 191 192; CHECK: Function Attrs: noinline nounwind uwtable 193; CHECK-NEXT: declare void @might_sync() 194declare void @might_sync() noinline nounwind uwtable 195 196define void @call_might_sync() nounwind uwtable noinline { 197; CHECK: Function Attrs: noinline nounwind uwtable 198; CHECK-LABEL: define {{[^@]+}}@call_might_sync 199; CHECK-SAME: () #[[ATTR4]] { 200; CHECK-NEXT: tail call void @might_sync() #[[ATTR4]] 201; CHECK-NEXT: ret void 202; 203 tail call void @might_sync() noinline nounwind uwtable 204 ret void 205} 206 207; TEST 11 - positive, should deduce nosync 208; volatile operation in same scc but dead. Call volatile_load defined in TEST 8. 209 210define i32 @scc1(i32* %0) noinline nounwind uwtable { 211; NOT_CGSCC_NPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable willreturn 212; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@scc1 213; NOT_CGSCC_NPM-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]]) #[[ATTR5:[0-9]+]] { 214; NOT_CGSCC_NPM-NEXT: unreachable 215; 216; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn 217; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@scc1 218; IS__CGSCC_NPM-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]]) #[[ATTR5:[0-9]+]] { 219; IS__CGSCC_NPM-NEXT: unreachable 220; 221 tail call void @scc2(i32* %0); 222 %val = tail call i32 @volatile_load(i32* %0); 223 ret i32 %val; 224} 225 226define void @scc2(i32* %0) noinline nounwind uwtable { 227; NOT_CGSCC_NPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable willreturn 228; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@scc2 229; NOT_CGSCC_NPM-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]]) #[[ATTR5]] { 230; NOT_CGSCC_NPM-NEXT: unreachable 231; 232; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn 233; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@scc2 234; IS__CGSCC_NPM-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]]) #[[ATTR5]] { 235; IS__CGSCC_NPM-NEXT: unreachable 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; IS__TUNIT____: Function Attrs: nofree nounwind willreturn 262; IS__TUNIT____-LABEL: define {{[^@]+}}@foo1 263; IS__TUNIT____-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; IS__TUNIT____-NEXT: store i32 100, i32* [[TMP0]], align 4 265; IS__TUNIT____-NEXT: fence release 266; IS__TUNIT____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 267; IS__TUNIT____-NEXT: store atomic i8 1, i8* [[TMP3]] monotonic, align 1 268; IS__TUNIT____-NEXT: ret void 269; 270; IS__CGSCC____: Function Attrs: nofree norecurse nounwind willreturn 271; IS__CGSCC____-LABEL: define {{[^@]+}}@foo1 272; IS__CGSCC____-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]+]] { 273; IS__CGSCC____-NEXT: store i32 100, i32* [[TMP0]], align 4 274; IS__CGSCC____-NEXT: fence release 275; IS__CGSCC____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 276; IS__CGSCC____-NEXT: store atomic i8 1, i8* [[TMP3]] monotonic, align 1 277; IS__CGSCC____-NEXT: ret void 278; 279 store i32 100, i32* %0, align 4 280 fence release 281 %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0 282 store atomic i8 1, i8* %3 monotonic, align 1 283 ret void 284} 285 286define void @bar(i32* %0, %"struct.std::atomic"* %1) { 287; IS__TUNIT____: Function Attrs: nofree nounwind 288; IS__TUNIT____-LABEL: define {{[^@]+}}@bar 289; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]]) #[[ATTR7:[0-9]+]] { 290; IS__TUNIT____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 291; IS__TUNIT____-NEXT: br label [[TMP4:%.*]] 292; IS__TUNIT____: 4: 293; IS__TUNIT____-NEXT: [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1 294; IS__TUNIT____-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 1 295; IS__TUNIT____-NEXT: [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0 296; IS__TUNIT____-NEXT: br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]] 297; IS__TUNIT____: 8: 298; IS__TUNIT____-NEXT: fence acquire 299; IS__TUNIT____-NEXT: ret void 300; 301; IS__CGSCC____: Function Attrs: nofree norecurse nounwind 302; IS__CGSCC____-LABEL: define {{[^@]+}}@bar 303; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]]) #[[ATTR7:[0-9]+]] { 304; IS__CGSCC____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 305; IS__CGSCC____-NEXT: br label [[TMP4:%.*]] 306; IS__CGSCC____: 4: 307; IS__CGSCC____-NEXT: [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1 308; IS__CGSCC____-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 1 309; IS__CGSCC____-NEXT: [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0 310; IS__CGSCC____-NEXT: br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]] 311; IS__CGSCC____: 8: 312; IS__CGSCC____-NEXT: fence acquire 313; IS__CGSCC____-NEXT: ret void 314; 315 %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0 316 br label %4 317 3184: ; preds = %4, %2 319 %5 = load atomic i8, i8* %3 monotonic, align 1 320 %6 = and i8 %5, 1 321 %7 = icmp eq i8 %6, 0 322 br i1 %7, label %4, label %8 323 3248: ; preds = %4 325 fence acquire 326 ret void 327} 328 329; TEST 13 - Fence syncscope("singlethread") seq_cst 330define void @foo1_singlethread(i32* %0, %"struct.std::atomic"* %1) { 331; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn 332; IS__TUNIT____-LABEL: define {{[^@]+}}@foo1_singlethread 333; IS__TUNIT____-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]+]] { 334; IS__TUNIT____-NEXT: store i32 100, i32* [[TMP0]], align 4 335; IS__TUNIT____-NEXT: fence syncscope("singlethread") release 336; IS__TUNIT____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 337; IS__TUNIT____-NEXT: store atomic i8 1, i8* [[TMP3]] monotonic, align 1 338; IS__TUNIT____-NEXT: ret void 339; 340; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn 341; IS__CGSCC____-LABEL: define {{[^@]+}}@foo1_singlethread 342; IS__CGSCC____-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]+]] { 343; IS__CGSCC____-NEXT: store i32 100, i32* [[TMP0]], align 4 344; IS__CGSCC____-NEXT: fence syncscope("singlethread") release 345; IS__CGSCC____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 346; IS__CGSCC____-NEXT: store atomic i8 1, i8* [[TMP3]] monotonic, align 1 347; IS__CGSCC____-NEXT: ret void 348; 349 store i32 100, i32* %0, align 4 350 fence syncscope("singlethread") release 351 %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0 352 store atomic i8 1, i8* %3 monotonic, align 1 353 ret void 354} 355 356define void @bar_singlethread(i32* %0, %"struct.std::atomic"* %1) { 357; IS__TUNIT____: Function Attrs: nofree nosync nounwind 358; IS__TUNIT____-LABEL: define {{[^@]+}}@bar_singlethread 359; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]]) #[[ATTR9:[0-9]+]] { 360; IS__TUNIT____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 361; IS__TUNIT____-NEXT: br label [[TMP4:%.*]] 362; IS__TUNIT____: 4: 363; IS__TUNIT____-NEXT: [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1 364; IS__TUNIT____-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 1 365; IS__TUNIT____-NEXT: [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0 366; IS__TUNIT____-NEXT: br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]] 367; IS__TUNIT____: 8: 368; IS__TUNIT____-NEXT: fence syncscope("singlethread") acquire 369; IS__TUNIT____-NEXT: ret void 370; 371; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind 372; IS__CGSCC____-LABEL: define {{[^@]+}}@bar_singlethread 373; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]]) #[[ATTR9:[0-9]+]] { 374; IS__CGSCC____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 375; IS__CGSCC____-NEXT: br label [[TMP4:%.*]] 376; IS__CGSCC____: 4: 377; IS__CGSCC____-NEXT: [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1 378; IS__CGSCC____-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 1 379; IS__CGSCC____-NEXT: [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0 380; IS__CGSCC____-NEXT: br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]] 381; IS__CGSCC____: 8: 382; IS__CGSCC____-NEXT: fence syncscope("singlethread") acquire 383; IS__CGSCC____-NEXT: ret void 384; 385 %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0 386 br label %4 387 3884: ; preds = %4, %2 389 %5 = load atomic i8, i8* %3 monotonic, align 1 390 %6 = and i8 %5, 1 391 %7 = icmp eq i8 %6, 0 392 br i1 %7, label %4, label %8 393 3948: ; preds = %4 395 fence syncscope("singlethread") acquire 396 ret void 397} 398 399declare void @llvm.memcpy(i8* %dest, i8* %src, i32 %len, i1 %isvolatile) 400declare void @llvm.memset(i8* %dest, i8 %val, i32 %len, i1 %isvolatile) 401 402; TEST 14 - negative, checking volatile intrinsics. 403 404; It is odd to add nocapture but a result of the llvm.memcpy nocapture. 405; 406define i32 @memcpy_volatile(i8* %ptr1, i8* %ptr2) { 407; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn 408; IS__TUNIT____-LABEL: define {{[^@]+}}@memcpy_volatile 409; IS__TUNIT____-SAME: (i8* nocapture nofree writeonly [[PTR1:%.*]], i8* nocapture nofree readonly [[PTR2:%.*]]) #[[ATTR10:[0-9]+]] { 410; IS__TUNIT____-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) #[[ATTR17:[0-9]+]] 411; IS__TUNIT____-NEXT: ret i32 4 412; 413; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind willreturn 414; IS__CGSCC____-LABEL: define {{[^@]+}}@memcpy_volatile 415; IS__CGSCC____-SAME: (i8* nocapture nofree writeonly [[PTR1:%.*]], i8* nocapture nofree readonly [[PTR2:%.*]]) #[[ATTR10:[0-9]+]] { 416; IS__CGSCC____-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) #[[ATTR18:[0-9]+]] 417; IS__CGSCC____-NEXT: ret i32 4 418; 419 call void @llvm.memcpy(i8* %ptr1, i8* %ptr2, i32 8, i1 1) 420 ret i32 4 421} 422 423; TEST 15 - positive, non-volatile intrinsic. 424 425; It is odd to add nocapture but a result of the llvm.memset nocapture. 426; 427define i32 @memset_non_volatile(i8* %ptr1, i8 %val) { 428; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly 429; IS__TUNIT____-LABEL: define {{[^@]+}}@memset_non_volatile 430; IS__TUNIT____-SAME: (i8* nocapture nofree writeonly [[PTR1:%.*]], i8 [[VAL:%.*]]) #[[ATTR11:[0-9]+]] { 431; IS__TUNIT____-NEXT: call void @llvm.memset.p0i8.i32(i8* nocapture nofree writeonly [[PTR1]], i8 [[VAL]], i32 noundef 8, i1 noundef false) #[[ATTR18:[0-9]+]] 432; IS__TUNIT____-NEXT: ret i32 4 433; 434; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly 435; IS__CGSCC____-LABEL: define {{[^@]+}}@memset_non_volatile 436; IS__CGSCC____-SAME: (i8* nocapture nofree writeonly [[PTR1:%.*]], i8 [[VAL:%.*]]) #[[ATTR11:[0-9]+]] { 437; IS__CGSCC____-NEXT: call void @llvm.memset.p0i8.i32(i8* nocapture nofree writeonly [[PTR1]], i8 [[VAL]], i32 noundef 8, i1 noundef false) #[[ATTR19:[0-9]+]] 438; IS__CGSCC____-NEXT: ret i32 4 439; 440 call void @llvm.memset(i8* %ptr1, i8 %val, i32 8, i1 0) 441 ret i32 4 442} 443 444; TEST 16 - negative, inline assembly. 445 446define i32 @inline_asm_test(i32 %x) { 447; CHECK-LABEL: define {{[^@]+}}@inline_asm_test 448; CHECK-SAME: (i32 [[X:%.*]]) { 449; CHECK-NEXT: [[TMP1:%.*]] = call i32 asm "bswap $0", "=r,r"(i32 [[X]]) 450; CHECK-NEXT: ret i32 4 451; 452 call i32 asm "bswap $0", "=r,r"(i32 %x) 453 ret i32 4 454} 455 456declare void @readnone_test() convergent readnone 457 458; TEST 17 - negative. Convergent 459define void @convergent_readnone(){ 460; CHECK: Function Attrs: readnone 461; CHECK-LABEL: define {{[^@]+}}@convergent_readnone 462; CHECK-SAME: () #[[ATTR13:[0-9]+]] { 463; CHECK-NEXT: call void @readnone_test() 464; CHECK-NEXT: ret void 465; 466 call void @readnone_test() 467 ret void 468} 469 470; CHECK: Function Attrs: nounwind 471; CHECK-NEXT: declare void @llvm.x86.sse2.clflush(i8*) 472declare void @llvm.x86.sse2.clflush(i8*) 473@a = common global i32 0, align 4 474 475; TEST 18 - negative. Synchronizing intrinsic 476 477define void @i_totally_sync() { 478; CHECK: Function Attrs: nounwind 479; CHECK-LABEL: define {{[^@]+}}@i_totally_sync 480; CHECK-SAME: () #[[ATTR14:[0-9]+]] { 481; CHECK-NEXT: tail call void @llvm.x86.sse2.clflush(i8* noundef nonnull align 4 dereferenceable(4) bitcast (i32* @a to i8*)) 482; CHECK-NEXT: ret void 483; 484 tail call void @llvm.x86.sse2.clflush(i8* bitcast (i32* @a to i8*)) 485 ret void 486} 487 488declare float @llvm.cos(float %val) readnone 489 490; TEST 19 - positive, readnone & non-convergent intrinsic. 491 492define i32 @cos_test(float %x) { 493; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 494; IS__TUNIT____-LABEL: define {{[^@]+}}@cos_test 495; IS__TUNIT____-SAME: (float [[X:%.*]]) #[[ATTR15:[0-9]+]] { 496; IS__TUNIT____-NEXT: ret i32 4 497; 498; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 499; IS__CGSCC____-LABEL: define {{[^@]+}}@cos_test 500; IS__CGSCC____-SAME: (float [[X:%.*]]) #[[ATTR15:[0-9]+]] { 501; IS__CGSCC____-NEXT: ret i32 4 502; 503 call float @llvm.cos(float %x) 504 ret i32 4 505} 506 507define float @cos_test2(float %x) { 508; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn 509; IS__TUNIT____-LABEL: define {{[^@]+}}@cos_test2 510; IS__TUNIT____-SAME: (float [[X:%.*]]) #[[ATTR15]] { 511; IS__TUNIT____-NEXT: [[C:%.*]] = call float @llvm.cos.f32(float [[X]]) #[[ATTR19:[0-9]+]] 512; IS__TUNIT____-NEXT: ret float [[C]] 513; 514; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn 515; IS__CGSCC____-LABEL: define {{[^@]+}}@cos_test2 516; IS__CGSCC____-SAME: (float [[X:%.*]]) #[[ATTR16:[0-9]+]] { 517; IS__CGSCC____-NEXT: [[C:%.*]] = call float @llvm.cos.f32(float [[X]]) #[[ATTR20:[0-9]+]] 518; IS__CGSCC____-NEXT: ret float [[C]] 519; 520 %c = call float @llvm.cos(float %x) 521 ret float %c 522} 523;. 524; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind optsize readnone ssp uwtable willreturn } 525; IS__TUNIT____: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind uwtable willreturn } 526; IS__TUNIT____: attributes #[[ATTR2]] = { argmemonly nofree norecurse nounwind uwtable willreturn } 527; IS__TUNIT____: attributes #[[ATTR3]] = { noinline nosync nounwind uwtable } 528; IS__TUNIT____: attributes #[[ATTR4]] = { noinline nounwind uwtable } 529; IS__TUNIT____: attributes #[[ATTR5]] = { nofree noinline noreturn nosync nounwind readnone uwtable willreturn } 530; IS__TUNIT____: attributes #[[ATTR6]] = { nofree nounwind willreturn } 531; IS__TUNIT____: attributes #[[ATTR7]] = { nofree nounwind } 532; IS__TUNIT____: attributes #[[ATTR8]] = { nofree nosync nounwind willreturn } 533; IS__TUNIT____: attributes #[[ATTR9]] = { nofree nosync nounwind } 534; IS__TUNIT____: attributes #[[ATTR10]] = { argmemonly nofree nosync nounwind willreturn } 535; IS__TUNIT____: attributes #[[ATTR11]] = { argmemonly nofree nosync nounwind willreturn writeonly } 536; IS__TUNIT____: attributes #[[ATTR12:[0-9]+]] = { convergent readnone } 537; IS__TUNIT____: attributes #[[ATTR13]] = { readnone } 538; IS__TUNIT____: attributes #[[ATTR14]] = { nounwind } 539; IS__TUNIT____: attributes #[[ATTR15]] = { nofree nosync nounwind readnone willreturn } 540; IS__TUNIT____: attributes #[[ATTR16:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn } 541; IS__TUNIT____: attributes #[[ATTR17]] = { willreturn } 542; IS__TUNIT____: attributes #[[ATTR18]] = { willreturn writeonly } 543; IS__TUNIT____: attributes #[[ATTR19]] = { readnone willreturn } 544;. 545; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind optsize readnone ssp uwtable willreturn } 546; IS__CGSCC_OPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind uwtable willreturn } 547; IS__CGSCC_OPM: attributes #[[ATTR2]] = { argmemonly nofree norecurse nounwind uwtable willreturn } 548; IS__CGSCC_OPM: attributes #[[ATTR3]] = { noinline nosync nounwind uwtable } 549; IS__CGSCC_OPM: attributes #[[ATTR4]] = { noinline nounwind uwtable } 550; IS__CGSCC_OPM: attributes #[[ATTR5]] = { nofree noinline noreturn nosync nounwind readnone uwtable willreturn } 551; IS__CGSCC_OPM: attributes #[[ATTR6]] = { nofree norecurse nounwind willreturn } 552; IS__CGSCC_OPM: attributes #[[ATTR7]] = { nofree norecurse nounwind } 553; IS__CGSCC_OPM: attributes #[[ATTR8]] = { nofree norecurse nosync nounwind willreturn } 554; IS__CGSCC_OPM: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind } 555; IS__CGSCC_OPM: attributes #[[ATTR10]] = { argmemonly nofree nosync nounwind willreturn } 556; IS__CGSCC_OPM: attributes #[[ATTR11]] = { argmemonly nofree nosync nounwind willreturn writeonly } 557; IS__CGSCC_OPM: attributes #[[ATTR12:[0-9]+]] = { convergent readnone } 558; IS__CGSCC_OPM: attributes #[[ATTR13]] = { readnone } 559; IS__CGSCC_OPM: attributes #[[ATTR14]] = { nounwind } 560; IS__CGSCC_OPM: attributes #[[ATTR15]] = { nofree norecurse nosync nounwind readnone willreturn } 561; IS__CGSCC_OPM: attributes #[[ATTR16]] = { nofree nosync nounwind readnone willreturn } 562; IS__CGSCC_OPM: attributes #[[ATTR17:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn } 563; IS__CGSCC_OPM: attributes #[[ATTR18]] = { willreturn } 564; IS__CGSCC_OPM: attributes #[[ATTR19]] = { willreturn writeonly } 565; IS__CGSCC_OPM: attributes #[[ATTR20]] = { readnone willreturn } 566;. 567; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind optsize readnone ssp uwtable willreturn } 568; IS__CGSCC_NPM: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind uwtable willreturn } 569; IS__CGSCC_NPM: attributes #[[ATTR2]] = { argmemonly nofree norecurse nounwind uwtable willreturn } 570; IS__CGSCC_NPM: attributes #[[ATTR3]] = { noinline nosync nounwind uwtable } 571; IS__CGSCC_NPM: attributes #[[ATTR4]] = { noinline nounwind uwtable } 572; IS__CGSCC_NPM: attributes #[[ATTR5]] = { nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn } 573; IS__CGSCC_NPM: attributes #[[ATTR6]] = { nofree norecurse nounwind willreturn } 574; IS__CGSCC_NPM: attributes #[[ATTR7]] = { nofree norecurse nounwind } 575; IS__CGSCC_NPM: attributes #[[ATTR8]] = { nofree norecurse nosync nounwind willreturn } 576; IS__CGSCC_NPM: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind } 577; IS__CGSCC_NPM: attributes #[[ATTR10]] = { argmemonly nofree nosync nounwind willreturn } 578; IS__CGSCC_NPM: attributes #[[ATTR11]] = { argmemonly nofree nosync nounwind willreturn writeonly } 579; IS__CGSCC_NPM: attributes #[[ATTR12:[0-9]+]] = { convergent readnone } 580; IS__CGSCC_NPM: attributes #[[ATTR13]] = { readnone } 581; IS__CGSCC_NPM: attributes #[[ATTR14]] = { nounwind } 582; IS__CGSCC_NPM: attributes #[[ATTR15]] = { nofree norecurse nosync nounwind readnone willreturn } 583; IS__CGSCC_NPM: attributes #[[ATTR16]] = { nofree nosync nounwind readnone willreturn } 584; IS__CGSCC_NPM: attributes #[[ATTR17:[0-9]+]] = { nofree nosync nounwind readnone speculatable willreturn } 585; IS__CGSCC_NPM: attributes #[[ATTR18]] = { willreturn } 586; IS__CGSCC_NPM: attributes #[[ATTR19]] = { willreturn writeonly } 587; IS__CGSCC_NPM: attributes #[[ATTR20]] = { readnone willreturn } 588;. 589