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