1 ; RUN: opt -S < %s -instcombine | FileCheck %s 2 3 target 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" 4 target triple = "x86_64-apple-macosx10.7.0" 5 6 ; Check transforms involving atomic operations 7 8 define i32 @test1(i32* %p) { 9 ; CHECK-LABEL: define i32 @test1( 10 ; CHECK: %x = load atomic i32, i32* %p seq_cst, align 4 11 ; CHECK: shl i32 %x, 1 12 %x = load atomic i32, i32* %p seq_cst, align 4 13 %y = load i32, i32* %p, align 4 14 %z = add i32 %x, %y 15 ret i32 %z 16 } 17 18 define i32 @test2(i32* %p) { 19 ; CHECK-LABEL: define i32 @test2( 20 ; CHECK: %x = load volatile i32, i32* %p, align 4 21 ; CHECK: %y = load volatile i32, i32* %p, align 4 22 %x = load volatile i32, i32* %p, align 4 23 %y = load volatile i32, i32* %p, align 4 24 %z = add i32 %x, %y 25 ret i32 %z 26 } 27 28 ; The exact semantics of mixing volatile and non-volatile on the same 29 ; memory location are a bit unclear, but conservatively, we know we don't 30 ; want to remove the volatile. 31 define i32 @test3(i32* %p) { 32 ; CHECK-LABEL: define i32 @test3( 33 ; CHECK: %x = load volatile i32, i32* %p, align 4 34 %x = load volatile i32, i32* %p, align 4 35 %y = load i32, i32* %p, align 4 36 %z = add i32 %x, %y 37 ret i32 %z 38 } 39 40 ; Forwarding from a stronger ordered atomic is fine 41 define i32 @test4(i32* %p) { 42 ; CHECK-LABEL: define i32 @test4( 43 ; CHECK: %x = load atomic i32, i32* %p seq_cst, align 4 44 ; CHECK: shl i32 %x, 1 45 %x = load atomic i32, i32* %p seq_cst, align 4 46 %y = load atomic i32, i32* %p unordered, align 4 47 %z = add i32 %x, %y 48 ret i32 %z 49 } 50 51 ; Forwarding from a non-atomic is not. (The earlier load 52 ; could in priciple be promoted to atomic and then forwarded, 53 ; but we can't just drop the atomic from the load.) 54 define i32 @test5(i32* %p) { 55 ; CHECK-LABEL: define i32 @test5( 56 ; CHECK: %x = load atomic i32, i32* %p unordered, align 4 57 %x = load atomic i32, i32* %p unordered, align 4 58 %y = load i32, i32* %p, align 4 59 %z = add i32 %x, %y 60 ret i32 %z 61 } 62 63 ; Forwarding atomic to atomic is fine 64 define i32 @test6(i32* %p) { 65 ; CHECK-LABEL: define i32 @test6( 66 ; CHECK: %x = load atomic i32, i32* %p unordered, align 4 67 ; CHECK: shl i32 %x, 1 68 %x = load atomic i32, i32* %p unordered, align 4 69 %y = load atomic i32, i32* %p unordered, align 4 70 %z = add i32 %x, %y 71 ret i32 %z 72 } 73 74 ; FIXME: we currently don't do anything for monotonic 75 define i32 @test7(i32* %p) { 76 ; CHECK-LABEL: define i32 @test7( 77 ; CHECK: %x = load atomic i32, i32* %p seq_cst, align 4 78 ; CHECK: %y = load atomic i32, i32* %p monotonic, align 4 79 %x = load atomic i32, i32* %p seq_cst, align 4 80 %y = load atomic i32, i32* %p monotonic, align 4 81 %z = add i32 %x, %y 82 ret i32 %z 83 } 84 85 ; FIXME: We could forward in racy code 86 define i32 @test8(i32* %p) { 87 ; CHECK-LABEL: define i32 @test8( 88 ; CHECK: %x = load atomic i32, i32* %p seq_cst, align 4 89 ; CHECK: %y = load atomic i32, i32* %p acquire, align 4 90 %x = load atomic i32, i32* %p seq_cst, align 4 91 %y = load atomic i32, i32* %p acquire, align 4 92 %z = add i32 %x, %y 93 ret i32 %z 94 } 95 96 ; An unordered access to null is still unreachable. There's no 97 ; ordering imposed. 98 define i32 @test9() { 99 ; CHECK-LABEL: define i32 @test9( 100 ; CHECK: store i32 undef, i32* null 101 %x = load atomic i32, i32* null unordered, align 4 102 ret i32 %x 103 } 104 105 ; FIXME: Could also fold 106 define i32 @test10() { 107 ; CHECK-LABEL: define i32 @test10( 108 ; CHECK: load atomic i32, i32* null monotonic 109 %x = load atomic i32, i32* null monotonic, align 4 110 ret i32 %x 111 } 112 113 ; Would this be legal to fold? Probably? 114 define i32 @test11() { 115 ; CHECK-LABEL: define i32 @test11( 116 ; CHECK: load atomic i32, i32* null seq_cst 117 %x = load atomic i32, i32* null seq_cst, align 4 118 ret i32 %x 119 } 120 121 ; An unordered access to null is still unreachable. There's no 122 ; ordering imposed. 123 define i32 @test12() { 124 ; CHECK-LABEL: define i32 @test12( 125 ; CHECK: store atomic i32 undef, i32* null 126 store atomic i32 0, i32* null unordered, align 4 127 ret i32 0 128 } 129 130 ; FIXME: Could also fold 131 define i32 @test13() { 132 ; CHECK-LABEL: define i32 @test13( 133 ; CHECK: store atomic i32 0, i32* null monotonic 134 store atomic i32 0, i32* null monotonic, align 4 135 ret i32 0 136 } 137 138 ; Would this be legal to fold? Probably? 139 define i32 @test14() { 140 ; CHECK-LABEL: define i32 @test14( 141 ; CHECK: store atomic i32 0, i32* null seq_cst 142 store atomic i32 0, i32* null seq_cst, align 4 143 ret i32 0 144 } 145 146 @a = external global i32 147 @b = external global i32 148 149 define i32 @test15(i1 %cnd) { 150 ; CHECK-LABEL: define i32 @test15( 151 ; CHECK: load atomic i32, i32* @a unordered, align 4 152 ; CHECK: load atomic i32, i32* @b unordered, align 4 153 %addr = select i1 %cnd, i32* @a, i32* @b 154 %x = load atomic i32, i32* %addr unordered, align 4 155 ret i32 %x 156 } 157 158 ; FIXME: This would be legal to transform 159 define i32 @test16(i1 %cnd) { 160 ; CHECK-LABEL: define i32 @test16( 161 ; CHECK: load atomic i32, i32* %addr monotonic, align 4 162 %addr = select i1 %cnd, i32* @a, i32* @b 163 %x = load atomic i32, i32* %addr monotonic, align 4 164 ret i32 %x 165 } 166 167 ; FIXME: This would be legal to transform 168 define i32 @test17(i1 %cnd) { 169 ; CHECK-LABEL: define i32 @test17( 170 ; CHECK: load atomic i32, i32* %addr seq_cst, align 4 171 %addr = select i1 %cnd, i32* @a, i32* @b 172 %x = load atomic i32, i32* %addr seq_cst, align 4 173 ret i32 %x 174 } 175 176 define i32 @test22(i1 %cnd) { 177 ; CHECK-LABEL: define i32 @test22( 178 ; CHECK: [[PHI:%.*]] = phi i32 179 ; CHECK: store atomic i32 [[PHI]], i32* @a unordered, align 4 180 br i1 %cnd, label %block1, label %block2 181 182 block1: 183 store atomic i32 1, i32* @a unordered, align 4 184 br label %merge 185 block2: 186 store atomic i32 2, i32* @a unordered, align 4 187 br label %merge 188 189 merge: 190 ret i32 0 191 } 192 193 ; TODO: probably also legal here 194 define i32 @test23(i1 %cnd) { 195 ; CHECK-LABEL: define i32 @test23( 196 ; CHECK: br i1 %cnd, label %block1, label %block2 197 br i1 %cnd, label %block1, label %block2 198 199 block1: 200 store atomic i32 1, i32* @a monotonic, align 4 201 br label %merge 202 block2: 203 store atomic i32 2, i32* @a monotonic, align 4 204 br label %merge 205 206 merge: 207 ret i32 0 208 } 209 210 declare void @clobber() 211 212 define i32 @test18(float* %p) { 213 ; CHECK-LABEL: define i32 @test18( 214 ; CHECK: load atomic i32, i32* [[A:%.*]] unordered, align 4 215 ; CHECK: store atomic i32 [[B:%.*]], i32* [[C:%.*]] unordered, align 4 216 %x = load atomic float, float* %p unordered, align 4 217 call void @clobber() ;; keep the load around 218 store atomic float %x, float* %p unordered, align 4 219 ret i32 0 220 } 221 222 ; TODO: probably also legal in this case 223 define i32 @test19(float* %p) { 224 ; CHECK-LABEL: define i32 @test19( 225 ; CHECK: load atomic float, float* %p seq_cst, align 4 226 ; CHECK: store atomic float %x, float* %p seq_cst, align 4 227 %x = load atomic float, float* %p seq_cst, align 4 228 call void @clobber() ;; keep the load around 229 store atomic float %x, float* %p seq_cst, align 4 230 ret i32 0 231 } 232 233 define i32 @test20(i32** %p, i8* %v) { 234 ; CHECK-LABEL: define i32 @test20( 235 ; CHECK: store atomic i8* %v, i8** [[D:%.*]] unordered, align 4 236 %cast = bitcast i8* %v to i32* 237 store atomic i32* %cast, i32** %p unordered, align 4 238 ret i32 0 239 } 240 241 define i32 @test21(i32** %p, i8* %v) { 242 ; CHECK-LABEL: define i32 @test21( 243 ; CHECK: store atomic i32* %cast, i32** %p monotonic, align 4 244 %cast = bitcast i8* %v to i32* 245 store atomic i32* %cast, i32** %p monotonic, align 4 246 ret i32 0 247 } 248 249 define void @pr27490a(i8** %p1, i8** %p2) { 250 ; CHECK-LABEL: define void @pr27490 251 ; CHECK: %1 = bitcast i8** %p1 to i64* 252 ; CHECK: %l1 = load i64, i64* %1, align 8 253 ; CHECK: %2 = bitcast i8** %p2 to i64* 254 ; CHECK: store volatile i64 %l1, i64* %2, align 8 255 %l = load i8*, i8** %p1 256 store volatile i8* %l, i8** %p2 257 ret void 258 } 259 260 define void @pr27490b(i8** %p1, i8** %p2) { 261 ; CHECK-LABEL: define void @pr27490 262 ; CHECK: %1 = bitcast i8** %p1 to i64* 263 ; CHECK: %l1 = load i64, i64* %1, align 8 264 ; CHECK: %2 = bitcast i8** %p2 to i64* 265 ; CHECK: store atomic i64 %l1, i64* %2 seq_cst, align 8 266 %l = load i8*, i8** %p1 267 store atomic i8* %l, i8** %p2 seq_cst, align 8 268 ret void 269 } 270