1; RUN: llc < %s -march=sparcv9 -verify-machineinstrs | FileCheck %s 2 3; CHECK-LABEL: test_atomic_i8 4; CHECK: ldub [%o0] 5; CHECK: membar 6; CHECK: ldub [%o1] 7; CHECK: membar 8; CHECK: membar 9; CHECK: stb {{.+}}, [%o2] 10define i8 @test_atomic_i8(i8* %ptr1, i8* %ptr2, i8* %ptr3) { 11entry: 12 %0 = load atomic i8, i8* %ptr1 acquire, align 1 13 %1 = load atomic i8, i8* %ptr2 acquire, align 1 14 %2 = add i8 %0, %1 15 store atomic i8 %2, i8* %ptr3 release, align 1 16 ret i8 %2 17} 18 19; CHECK-LABEL: test_atomic_i16 20; CHECK: lduh [%o0] 21; CHECK: membar 22; CHECK: lduh [%o1] 23; CHECK: membar 24; CHECK: membar 25; CHECK: sth {{.+}}, [%o2] 26define i16 @test_atomic_i16(i16* %ptr1, i16* %ptr2, i16* %ptr3) { 27entry: 28 %0 = load atomic i16, i16* %ptr1 acquire, align 2 29 %1 = load atomic i16, i16* %ptr2 acquire, align 2 30 %2 = add i16 %0, %1 31 store atomic i16 %2, i16* %ptr3 release, align 2 32 ret i16 %2 33} 34 35; CHECK-LABEL: test_atomic_i32 36; CHECK: ld [%o0] 37; CHECK: membar 38; CHECK: ld [%o1] 39; CHECK: membar 40; CHECK: membar 41; CHECK: st {{.+}}, [%o2] 42define i32 @test_atomic_i32(i32* %ptr1, i32* %ptr2, i32* %ptr3) { 43entry: 44 %0 = load atomic i32, i32* %ptr1 acquire, align 4 45 %1 = load atomic i32, i32* %ptr2 acquire, align 4 46 %2 = add i32 %0, %1 47 store atomic i32 %2, i32* %ptr3 release, align 4 48 ret i32 %2 49} 50 51; CHECK-LABEL: test_atomic_i64 52; CHECK: ldx [%o0] 53; CHECK: membar 54; CHECK: ldx [%o1] 55; CHECK: membar 56; CHECK: membar 57; CHECK: stx {{.+}}, [%o2] 58define i64 @test_atomic_i64(i64* %ptr1, i64* %ptr2, i64* %ptr3) { 59entry: 60 %0 = load atomic i64, i64* %ptr1 acquire, align 8 61 %1 = load atomic i64, i64* %ptr2 acquire, align 8 62 %2 = add i64 %0, %1 63 store atomic i64 %2, i64* %ptr3 release, align 8 64 ret i64 %2 65} 66 67;; TODO: the "move %icc" and related instructions are totally 68;; redundant here. There's something weird happening in optimization 69;; of the success value of cmpxchg. 70 71; CHECK-LABEL: test_cmpxchg_i8 72; CHECK: and %o1, -4, %o2 73; CHECK: mov 3, %o3 74; CHECK: andn %o3, %o1, %o1 75; CHECK: sll %o1, 3, %o1 76; CHECK: mov 255, %o3 77; CHECK: sll %o3, %o1, %o5 78; CHECK: xor %o5, -1, %o3 79; CHECK: mov 123, %o4 80; CHECK: ld [%o2], %g2 81; CHECK: sll %o4, %o1, %o4 82; CHECK: and %o0, 255, %o0 83; CHECK: sll %o0, %o1, %o0 84; CHECK: andn %g2, %o5, %g2 85; CHECK: mov %g0, %o5 86; CHECK: [[LABEL1:\.L.*]]: 87; CHECK: or %g2, %o4, %g3 88; CHECK: or %g2, %o0, %g4 89; CHECK: cas [%o2], %g4, %g3 90; CHECK: cmp %g3, %g4 91; CHECK: mov %o5, %g4 92; CHECK: move %icc, 1, %g4 93; CHECK: cmp %g4, 0 94; CHECK: bne [[LABEL2:\.L.*]] 95; CHECK: nop 96; CHECK: and %g3, %o3, %g4 97; CHECK: cmp %g2, %g4 98; CHECK: bne [[LABEL1]] 99; CHECK: mov %g4, %g2 100; CHECK: [[LABEL2]]: 101; CHECK: retl 102; CHECK: srl %g3, %o1, %o0 103define i8 @test_cmpxchg_i8(i8 %a, i8* %ptr) { 104entry: 105 %pair = cmpxchg i8* %ptr, i8 %a, i8 123 monotonic monotonic 106 %b = extractvalue { i8, i1 } %pair, 0 107 ret i8 %b 108} 109 110; CHECK-LABEL: test_cmpxchg_i16 111 112; CHECK: and %o1, -4, %o2 113; CHECK: and %o1, 3, %o1 114; CHECK: xor %o1, 2, %o1 115; CHECK: sll %o1, 3, %o1 116; CHECK: sethi 63, %o3 117; CHECK: or %o3, 1023, %o4 118; CHECK: sll %o4, %o1, %o5 119; CHECK: xor %o5, -1, %o3 120; CHECK: and %o0, %o4, %o4 121; CHECK: ld [%o2], %g2 122; CHECK: mov 123, %o0 123; CHECK: sll %o0, %o1, %o0 124; CHECK: sll %o4, %o1, %o4 125; CHECK: andn %g2, %o5, %g2 126; CHECK: mov %g0, %o5 127; CHECK: [[LABEL1:\.L.*]]: 128; CHECK: or %g2, %o0, %g3 129; CHECK: or %g2, %o4, %g4 130; CHECK: cas [%o2], %g4, %g3 131; CHECK: cmp %g3, %g4 132; CHECK: mov %o5, %g4 133; CHECK: move %icc, 1, %g4 134; CHECK: cmp %g4, 0 135; CHECK: bne [[LABEL2:\.L.*]] 136; CHECK: nop 137; CHECK: and %g3, %o3, %g4 138; CHECK: cmp %g2, %g4 139; CHECK: bne [[LABEL1]] 140; CHECK: mov %g4, %g2 141; CHECK: [[LABEL2]]: 142; CHECK: retl 143; CHECK: srl %g3, %o1, %o0 144define i16 @test_cmpxchg_i16(i16 %a, i16* %ptr) { 145entry: 146 %pair = cmpxchg i16* %ptr, i16 %a, i16 123 monotonic monotonic 147 %b = extractvalue { i16, i1 } %pair, 0 148 ret i16 %b 149} 150 151; CHECK-LABEL: test_cmpxchg_i32 152; CHECK: mov 123, [[R:%[gilo][0-7]]] 153; CHECK: cas [%o1], %o0, [[R]] 154 155define i32 @test_cmpxchg_i32(i32 %a, i32* %ptr) { 156entry: 157 %pair = cmpxchg i32* %ptr, i32 %a, i32 123 monotonic monotonic 158 %b = extractvalue { i32, i1 } %pair, 0 159 ret i32 %b 160} 161 162; CHECK-LABEL: test_cmpxchg_i64 163; CHECK: mov 123, [[R:%[gilo][0-7]]] 164; CHECK: casx [%o1], %o0, [[R]] 165 166define i64 @test_cmpxchg_i64(i64 %a, i64* %ptr) { 167entry: 168 %pair = cmpxchg i64* %ptr, i64 %a, i64 123 monotonic monotonic 169 %b = extractvalue { i64, i1 } %pair, 0 170 ret i64 %b 171} 172 173; CHECK-LABEL: test_swap_i8 174; CHECK: mov 42, [[R:%[gilo][0-7]]] 175; CHECK: cas 176 177define i8 @test_swap_i8(i8 %a, i8* %ptr) { 178entry: 179 %b = atomicrmw xchg i8* %ptr, i8 42 monotonic 180 ret i8 %b 181} 182 183; CHECK-LABEL: test_swap_i16 184; CHECK: mov 42, [[R:%[gilo][0-7]]] 185; CHECK: cas 186 187define i16 @test_swap_i16(i16 %a, i16* %ptr) { 188entry: 189 %b = atomicrmw xchg i16* %ptr, i16 42 monotonic 190 ret i16 %b 191} 192 193; CHECK-LABEL: test_swap_i32 194; CHECK: mov 42, [[R:%[gilo][0-7]]] 195; CHECK: swap [%o1], [[R]] 196 197define i32 @test_swap_i32(i32 %a, i32* %ptr) { 198entry: 199 %b = atomicrmw xchg i32* %ptr, i32 42 monotonic 200 ret i32 %b 201} 202 203; CHECK-LABEL: test_swap_i64 204; CHECK: casx [%o1], 205 206define i64 @test_swap_i64(i64 %a, i64* %ptr) { 207entry: 208 %b = atomicrmw xchg i64* %ptr, i64 42 monotonic 209 ret i64 %b 210} 211 212; CHECK-LABEL: test_load_sub_i8 213; CHECK: membar 214; CHECK: .L{{.*}}: 215; CHECK: sub 216; CHECK: cas [{{%[gilo][0-7]}}] 217; CHECK: membar 218define zeroext i8 @test_load_sub_i8(i8* %p, i8 zeroext %v) { 219entry: 220 %0 = atomicrmw sub i8* %p, i8 %v seq_cst 221 ret i8 %0 222} 223 224; CHECK-LABEL: test_load_sub_i16 225; CHECK: membar 226; CHECK: .L{{.*}}: 227; CHECK: sub 228; CHECK: cas [{{%[gilo][0-7]}}] 229; CHECK: membar 230define zeroext i16 @test_load_sub_i16(i16* %p, i16 zeroext %v) { 231entry: 232 %0 = atomicrmw sub i16* %p, i16 %v seq_cst 233 ret i16 %0 234} 235 236; CHECK-LABEL: test_load_add_i32 237; CHECK: membar 238; CHECK: mov %g0 239; CHECK: mov [[U:%[gilo][0-7]]], [[V:%[gilo][0-7]]] 240; CHECK: add [[U:%[gilo][0-7]]], %o1, [[V2:%[gilo][0-7]]] 241; CHECK: cas [%o0], [[V]], [[V2]] 242; CHECK: membar 243define zeroext i32 @test_load_add_i32(i32* %p, i32 zeroext %v) { 244entry: 245 %0 = atomicrmw add i32* %p, i32 %v seq_cst 246 ret i32 %0 247} 248 249; CHECK-LABEL: test_load_sub_64 250; CHECK: membar 251; CHECK: sub 252; CHECK: casx [%o0] 253; CHECK: membar 254define zeroext i64 @test_load_sub_64(i64* %p, i64 zeroext %v) { 255entry: 256 %0 = atomicrmw sub i64* %p, i64 %v seq_cst 257 ret i64 %0 258} 259 260; CHECK-LABEL: test_load_xor_32 261; CHECK: membar 262; CHECK: xor 263; CHECK: cas [%o0] 264; CHECK: membar 265define zeroext i32 @test_load_xor_32(i32* %p, i32 zeroext %v) { 266entry: 267 %0 = atomicrmw xor i32* %p, i32 %v seq_cst 268 ret i32 %0 269} 270 271; CHECK-LABEL: test_load_and_32 272; CHECK: membar 273; CHECK: and 274; CHECK-NOT: xor 275; CHECK: cas [%o0] 276; CHECK: membar 277define zeroext i32 @test_load_and_32(i32* %p, i32 zeroext %v) { 278entry: 279 %0 = atomicrmw and i32* %p, i32 %v seq_cst 280 ret i32 %0 281} 282 283; CHECK-LABEL: test_load_nand_32 284; CHECK: membar 285; CHECK: and 286; CHECK: xor 287; CHECK: cas [%o0] 288; CHECK: membar 289define zeroext i32 @test_load_nand_32(i32* %p, i32 zeroext %v) { 290entry: 291 %0 = atomicrmw nand i32* %p, i32 %v seq_cst 292 ret i32 %0 293} 294 295; CHECK-LABEL: test_load_max_64 296; CHECK: membar 297; CHECK: cmp 298; CHECK: movg %xcc 299; CHECK: casx [%o0] 300; CHECK: membar 301define zeroext i64 @test_load_max_64(i64* %p, i64 zeroext %v) { 302entry: 303 %0 = atomicrmw max i64* %p, i64 %v seq_cst 304 ret i64 %0 305} 306 307; CHECK-LABEL: test_load_umin_32 308; CHECK: membar 309; CHECK: cmp 310; CHECK: movleu %icc 311; CHECK: cas [%o0] 312; CHECK: membar 313define zeroext i32 @test_load_umin_32(i32* %p, i32 zeroext %v) { 314entry: 315 %0 = atomicrmw umin i32* %p, i32 %v seq_cst 316 ret i32 %0 317} 318