330 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=dse -S < %s | FileCheck %s3 4target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"5target triple = "x86_64-apple-macosx10.7.0"6 7; Basic correctness tests for atomic stores.8; Note that it turns out essentially every transformation DSE does is legal on9; atomic ops, just some transformations are not allowed across release-acquire pairs.10 11@x = common global i32 0, align 412@y = common global i32 0, align 413 14declare void @randomop(ptr)15 16; DSE across unordered store (allowed)17define void @test1() {18; CHECK-LABEL: @test1(19; CHECK-NEXT: store atomic i32 0, ptr @y unordered, align 420; CHECK-NEXT: store i32 1, ptr @x, align 421; CHECK-NEXT: ret void22;23 store i32 0, ptr @x24 store atomic i32 0, ptr @y unordered, align 425 store i32 1, ptr @x26 ret void27}28 29; DSE remove unordered store (allowed)30define void @test4() {31; CHECK-LABEL: @test4(32; CHECK-NEXT: store i32 1, ptr @x, align 433; CHECK-NEXT: ret void34;35 store atomic i32 0, ptr @x unordered, align 436 store i32 1, ptr @x37 ret void38}39 40; DSE unordered store overwriting non-atomic store (allowed)41define void @test5() {42; CHECK-LABEL: @test5(43; CHECK-NEXT: store atomic i32 1, ptr @x unordered, align 444; CHECK-NEXT: ret void45;46 store i32 0, ptr @x47 store atomic i32 1, ptr @x unordered, align 448 ret void49}50 51; DSE no-op unordered atomic store (allowed)52define void @test6() {53; CHECK-LABEL: @test6(54; CHECK-NEXT: ret void55;56 %x = load atomic i32, ptr @x unordered, align 457 store atomic i32 %x, ptr @x unordered, align 458 ret void59}60 61; DSE seq_cst store (be conservative; DSE doesn't have infrastructure62; to reason about atomic operations).63define void @test7() {64; CHECK-LABEL: @test7(65; CHECK-NEXT: [[A:%.*]] = alloca i32, align 466; CHECK-NEXT: store atomic i32 0, ptr [[A]] seq_cst, align 467; CHECK-NEXT: ret void68;69 %a = alloca i3270 store atomic i32 0, ptr %a seq_cst, align 471 ret void72}73 74; DSE and seq_cst load (be conservative; DSE doesn't have infrastructure75; to reason about atomic operations).76define i32 @test8() {77; CHECK-LABEL: @test8(78; CHECK-NEXT: [[A:%.*]] = alloca i32, align 479; CHECK-NEXT: call void @randomop(ptr [[A]])80; CHECK-NEXT: store i32 0, ptr [[A]], align 481; CHECK-NEXT: [[X:%.*]] = load atomic i32, ptr @x seq_cst, align 482; CHECK-NEXT: ret i32 [[X]]83;84 %a = alloca i3285 call void @randomop(ptr %a)86 store i32 0, ptr %a, align 487 %x = load atomic i32, ptr @x seq_cst, align 488 ret i32 %x89}90 91; DSE across monotonic store (allowed as long as the eliminated store isUnordered)92define void @test10() {93; CHECK-LABEL: test1094; CHECK-NOT: store i32 095; CHECK: store i32 196 store i32 0, ptr @x97 store atomic i32 42, ptr @y monotonic, align 498 store i32 1, ptr @x99 ret void100}101 102; DSE across monotonic load (forbidden since the eliminated store is atomic)103define i32 @test11() {104; CHECK-LABEL: @test11(105; CHECK-NEXT: store atomic i32 0, ptr @x monotonic, align 4106; CHECK-NEXT: [[X:%.*]] = load atomic i32, ptr @y monotonic, align 4107; CHECK-NEXT: store atomic i32 1, ptr @x monotonic, align 4108; CHECK-NEXT: ret i32 [[X]]109;110 store atomic i32 0, ptr @x monotonic, align 4111 %x = load atomic i32, ptr @y monotonic, align 4112 store atomic i32 1, ptr @x monotonic, align 4113 ret i32 %x114}115 116; DSE across monotonic store (forbidden since the eliminated store is atomic)117define void @test12() {118; CHECK-LABEL: @test12(119; CHECK-NEXT: store atomic i32 0, ptr @x monotonic, align 4120; CHECK-NEXT: store atomic i32 42, ptr @y monotonic, align 4121; CHECK-NEXT: store atomic i32 1, ptr @x monotonic, align 4122; CHECK-NEXT: ret void123;124 store atomic i32 0, ptr @x monotonic, align 4125 store atomic i32 42, ptr @y monotonic, align 4126 store atomic i32 1, ptr @x monotonic, align 4127 ret void128}129 130; But DSE is not allowed across a release-acquire pair.131define i32 @test15() {132; CHECK-LABEL: @test15(133; CHECK-NEXT: store i32 0, ptr @x, align 4134; CHECK-NEXT: store atomic i32 0, ptr @y release, align 4135; CHECK-NEXT: [[X:%.*]] = load atomic i32, ptr @y acquire, align 4136; CHECK-NEXT: store i32 1, ptr @x, align 4137; CHECK-NEXT: ret i32 [[X]]138;139 store i32 0, ptr @x140 store atomic i32 0, ptr @y release, align 4141 %x = load atomic i32, ptr @y acquire, align 4142 store i32 1, ptr @x143 ret i32 %x144}145 146@z = common global i64 0, align 4147@a = common global i64 0, align 4148 149; Be conservative, do not kill regular store.150define i64 @test_atomicrmw_0() {151; CHECK-LABEL: @test_atomicrmw_0(152; CHECK-NEXT: store i64 1, ptr @z, align 8153; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr @z, i64 -1 monotonic154; CHECK-NEXT: ret i64 [[RES]]155;156 store i64 1, ptr @z157 %res = atomicrmw add ptr @z, i64 -1 monotonic158 ret i64 %res159}160 161; Be conservative, do not kill regular store.162define i64 @test_atomicrmw_1() {163; CHECK-LABEL: @test_atomicrmw_1(164; CHECK-NEXT: store i64 1, ptr @z, align 8165; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr @z, i64 -1 acq_rel166; CHECK-NEXT: ret i64 [[RES]]167;168 store i64 1, ptr @z169 %res = atomicrmw add ptr @z, i64 -1 acq_rel170 ret i64 %res171}172 173; Monotonic atomicrmw should not block eliminating no-aliasing stores.174define i64 @test_atomicrmw_2() {175; CHECK-LABEL: @test_atomicrmw_2(176; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr @a, i64 -1 monotonic177; CHECK-NEXT: store i64 2, ptr @z, align 8178; CHECK-NEXT: ret i64 [[RES]]179;180 store i64 1, ptr @z181 %res = atomicrmw add ptr @a, i64 -1 monotonic182 store i64 2, ptr @z183 ret i64 %res184}185 186; Be conservative, do not eliminate stores across atomic operations > monotonic.187define i64 @test_atomicrmw_3() {188; CHECK-LABEL: @test_atomicrmw_3(189; CHECK-NEXT: store i64 1, ptr @z, align 8190; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr @a, i64 -1 release191; CHECK-NEXT: store i64 2, ptr @z, align 8192; CHECK-NEXT: ret i64 [[RES]]193;194 store i64 1, ptr @z195 %res = atomicrmw add ptr @a, i64 -1 release196 store i64 2, ptr @z197 ret i64 %res198}199 200; Be conservative, do not eliminate may-alias stores.201define i64 @test_atomicrmw_4(ptr %ptr) {202; CHECK-LABEL: @test_atomicrmw_4(203; CHECK-NEXT: store i64 1, ptr @z, align 8204; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr [[PTR:%.*]], i64 -1 monotonic205; CHECK-NEXT: store i64 2, ptr @z, align 8206; CHECK-NEXT: ret i64 [[RES]]207;208 store i64 1, ptr @z209 %res = atomicrmw add ptr %ptr, i64 -1 monotonic210 store i64 2, ptr @z211 ret i64 %res212}213 214; Be conservative, do not eliminate aliasing stores.215define i64 @test_atomicrmw_5() {216; CHECK-LABEL: @test_atomicrmw_5(217; CHECK-NEXT: store i64 1, ptr @z, align 8218; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr @z, i64 -1 monotonic219; CHECK-NEXT: store i64 2, ptr @z, align 8220; CHECK-NEXT: ret i64 [[RES]]221;222 store i64 1, ptr @z223 %res = atomicrmw add ptr @z, i64 -1 monotonic224 store i64 2, ptr @z225 ret i64 %res226}227 228; Be conservative, do not eliminate non-monotonic cmpxchg.229define { i32, i1} @test_cmpxchg_1() {230; CHECK-LABEL: @test_cmpxchg_1(231; CHECK-NEXT: store i32 1, ptr @x, align 4232; CHECK-NEXT: [[RET:%.*]] = cmpxchg volatile ptr @x, i32 10, i32 20 seq_cst monotonic233; CHECK-NEXT: store i32 2, ptr @x, align 4234; CHECK-NEXT: ret { i32, i1 } [[RET]]235;236 store i32 1, ptr @x237 %ret = cmpxchg volatile ptr @x, i32 10, i32 20 seq_cst monotonic238 store i32 2, ptr @x239 ret { i32, i1 } %ret240}241 242; Monotonic cmpxchg should not block DSE for non-aliasing stores.243define { i32, i1} @test_cmpxchg_2() {244; CHECK-LABEL: @test_cmpxchg_2(245; CHECK-NEXT: [[RET:%.*]] = cmpxchg volatile ptr @y, i32 10, i32 20 monotonic monotonic246; CHECK-NEXT: store i32 2, ptr @x, align 4247; CHECK-NEXT: ret { i32, i1 } [[RET]]248;249 store i32 1, ptr @x250 %ret = cmpxchg volatile ptr @y, i32 10, i32 20 monotonic monotonic251 store i32 2, ptr @x252 ret { i32, i1 } %ret253}254 255; Be conservative, do not eliminate non-monotonic cmpxchg.256define { i32, i1} @test_cmpxchg_3() {257; CHECK-LABEL: @test_cmpxchg_3(258; CHECK-NEXT: store i32 1, ptr @x, align 4259; CHECK-NEXT: [[RET:%.*]] = cmpxchg volatile ptr @y, i32 10, i32 20 seq_cst seq_cst260; CHECK-NEXT: store i32 2, ptr @x, align 4261; CHECK-NEXT: ret { i32, i1 } [[RET]]262;263 store i32 1, ptr @x264 %ret = cmpxchg volatile ptr @y, i32 10, i32 20 seq_cst seq_cst265 store i32 2, ptr @x266 ret { i32, i1 } %ret267}268 269; Be conservative, do not eliminate may-alias stores.270define { i32, i1} @test_cmpxchg_4(ptr %ptr) {271; CHECK-LABEL: @test_cmpxchg_4(272; CHECK-NEXT: store i32 1, ptr @x, align 4273; CHECK-NEXT: [[RET:%.*]] = cmpxchg volatile ptr [[PTR:%.*]], i32 10, i32 20 monotonic monotonic274; CHECK-NEXT: store i32 2, ptr @x, align 4275; CHECK-NEXT: ret { i32, i1 } [[RET]]276;277 store i32 1, ptr @x278 %ret = cmpxchg volatile ptr %ptr, i32 10, i32 20 monotonic monotonic279 store i32 2, ptr @x280 ret { i32, i1 } %ret281}282 283; Be conservative, do not eliminate alias stores.284define { i32, i1} @test_cmpxchg_5(ptr %ptr) {285; CHECK-LABEL: @test_cmpxchg_5(286; CHECK-NEXT: store i32 1, ptr @x, align 4287; CHECK-NEXT: [[RET:%.*]] = cmpxchg volatile ptr @x, i32 10, i32 20 monotonic monotonic288; CHECK-NEXT: store i32 2, ptr @x, align 4289; CHECK-NEXT: ret { i32, i1 } [[RET]]290;291 store i32 1, ptr @x292 %ret = cmpxchg volatile ptr @x, i32 10, i32 20 monotonic monotonic293 store i32 2, ptr @x294 ret { i32, i1 } %ret295}296 297; **** Noop load->store tests **************************************************298 299; We can optimize unordered atomic loads or stores.300define void @test_load_atomic(ptr %Q) {301; CHECK-LABEL: @test_load_atomic(302; CHECK-NEXT: ret void303;304 %a = load atomic i32, ptr %Q unordered, align 4305 store atomic i32 %a, ptr %Q unordered, align 4306 ret void307}308 309; We can optimize unordered atomic loads or stores.310define void @test_store_atomic(ptr %Q) {311; CHECK-LABEL: @test_store_atomic(312; CHECK-NEXT: ret void313;314 %a = load i32, ptr %Q315 store atomic i32 %a, ptr %Q unordered, align 4316 ret void317}318 319; We can NOT optimize release atomic loads or stores.320define void @test_store_atomic_release(ptr %Q) {321; CHECK-LABEL: @test_store_atomic_release(322; CHECK-NEXT: [[A:%.*]] = load i32, ptr [[Q:%.*]], align 4323; CHECK-NEXT: store atomic i32 [[A]], ptr [[Q]] release, align 4324; CHECK-NEXT: ret void325;326 %a = load i32, ptr %Q327 store atomic i32 %a, ptr %Q release, align 4328 ret void329}330