1; RUN: opt -basicaa -dse -S < %s | FileCheck %s 2 3target 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" 4target triple = "x86_64-apple-macosx10.7.0" 5 6; Sanity tests for atomic stores. 7; Note that it turns out essentially every transformation DSE does is legal on 8; atomic ops, just some transformations are not allowed across release-acquire pairs. 9 10@x = common global i32 0, align 4 11@y = common global i32 0, align 4 12 13declare void @randomop(i32*) 14 15; DSE across unordered store (allowed) 16define void @test1() { 17; CHECK-LABEL: test1 18; CHECK-NOT: store i32 0 19; CHECK: store i32 1 20 store i32 0, i32* @x 21 store atomic i32 0, i32* @y unordered, align 4 22 store i32 1, i32* @x 23 ret void 24} 25 26; DSE across seq_cst load (allowed) 27define i32 @test2() { 28; CHECK-LABEL: test2 29; CHECK-NOT: store i32 0 30; CHECK: store i32 1 31 store i32 0, i32* @x 32 %x = load atomic i32* @y seq_cst, align 4 33 store i32 1, i32* @x 34 ret i32 %x 35} 36 37; DSE across seq_cst store (allowed) 38define void @test3() { 39; CHECK-LABEL: test3 40; CHECK-NOT: store i32 0 41; CHECK: store atomic i32 2 42 store i32 0, i32* @x 43 store atomic i32 2, i32* @y seq_cst, align 4 44 store i32 1, i32* @x 45 ret void 46} 47 48; DSE remove unordered store (allowed) 49define void @test4() { 50; CHECK-LABEL: test4 51; CHECK-NOT: store atomic 52; CHECK: store i32 1 53 store atomic i32 0, i32* @x unordered, align 4 54 store i32 1, i32* @x 55 ret void 56} 57 58; DSE unordered store overwriting non-atomic store (allowed) 59define void @test5() { 60; CHECK-LABEL: test5 61; CHECK: store atomic i32 1 62 store i32 0, i32* @x 63 store atomic i32 1, i32* @x unordered, align 4 64 ret void 65} 66 67; DSE no-op unordered atomic store (allowed) 68define void @test6() { 69; CHECK-LABEL: test6 70; CHECK-NOT: store 71; CHECK: ret void 72 %x = load atomic i32* @x unordered, align 4 73 store atomic i32 %x, i32* @x unordered, align 4 74 ret void 75} 76 77; DSE seq_cst store (be conservative; DSE doesn't have infrastructure 78; to reason about atomic operations). 79define void @test7() { 80; CHECK-LABEL: test7 81; CHECK: store atomic 82 %a = alloca i32 83 store atomic i32 0, i32* %a seq_cst, align 4 84 ret void 85} 86 87; DSE and seq_cst load (be conservative; DSE doesn't have infrastructure 88; to reason about atomic operations). 89define i32 @test8() { 90; CHECK-LABEL: test8 91; CHECK: store 92; CHECK: load atomic 93 %a = alloca i32 94 call void @randomop(i32* %a) 95 store i32 0, i32* %a, align 4 96 %x = load atomic i32* @x seq_cst, align 4 97 ret i32 %x 98} 99 100; DSE across monotonic load (allowed as long as the eliminated store isUnordered) 101define i32 @test9() { 102; CHECK-LABEL: test9 103; CHECK-NOT: store i32 0 104; CHECK: store i32 1 105 store i32 0, i32* @x 106 %x = load atomic i32* @y monotonic, align 4 107 store i32 1, i32* @x 108 ret i32 %x 109} 110 111; DSE across monotonic store (allowed as long as the eliminated store isUnordered) 112define void @test10() { 113; CHECK-LABEL: test10 114; CHECK-NOT: store i32 0 115; CHECK: store i32 1 116 store i32 0, i32* @x 117 store atomic i32 42, i32* @y monotonic, align 4 118 store i32 1, i32* @x 119 ret void 120} 121 122; DSE across monotonic load (forbidden since the eliminated store is atomic) 123define i32 @test11() { 124; CHECK-LABEL: test11 125; CHECK: store atomic i32 0 126; CHECK: store atomic i32 1 127 store atomic i32 0, i32* @x monotonic, align 4 128 %x = load atomic i32* @y monotonic, align 4 129 store atomic i32 1, i32* @x monotonic, align 4 130 ret i32 %x 131} 132 133; DSE across monotonic store (forbidden since the eliminated store is atomic) 134define void @test12() { 135; CHECK-LABEL: test12 136; CHECK: store atomic i32 0 137; CHECK: store atomic i32 1 138 store atomic i32 0, i32* @x monotonic, align 4 139 store atomic i32 42, i32* @y monotonic, align 4 140 store atomic i32 1, i32* @x monotonic, align 4 141 ret void 142} 143 144; DSE is allowed across a pair of an atomic read and then write. 145define i32 @test13() { 146; CHECK-LABEL: test13 147; CHECK-NOT: store i32 0 148; CHECK: store i32 1 149 store i32 0, i32* @x 150 %x = load atomic i32* @y seq_cst, align 4 151 store atomic i32 %x, i32* @y seq_cst, align 4 152 store i32 1, i32* @x 153 ret i32 %x 154} 155 156; Same if it is acquire-release instead of seq_cst/seq_cst 157define i32 @test14() { 158; CHECK-LABEL: test14 159; CHECK-NOT: store i32 0 160; CHECK: store i32 1 161 store i32 0, i32* @x 162 %x = load atomic i32* @y acquire, align 4 163 store atomic i32 %x, i32* @y release, align 4 164 store i32 1, i32* @x 165 ret i32 %x 166} 167 168; But DSE is not allowed across a release-acquire pair. 169define i32 @test15() { 170; CHECK-LABEL: test15 171; CHECK: store i32 0 172; CHECK: store i32 1 173 store i32 0, i32* @x 174 store atomic i32 0, i32* @y release, align 4 175 %x = load atomic i32* @y acquire, align 4 176 store i32 1, i32* @x 177 ret i32 %x 178} 179