• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc -march=mipsel --disable-machine-licm -mcpu=mips32   -relocation-model=pic < %s | \
2; RUN:   FileCheck %s -check-prefixes=ALL,MIPS32-ANY,NO-SEB-SEH,CHECK-EL,NOT-MICROMIPS
3; RUN: llc -march=mipsel --disable-machine-licm -mcpu=mips32r2 -relocation-model=pic -verify-machineinstrs < %s | \
4; RUN:   FileCheck %s -check-prefixes=ALL,MIPS32-ANY,HAS-SEB-SEH,CHECK-EL,NOT-MICROMIPS
5; RUN: llc -march=mipsel --disable-machine-licm -mcpu=mips32r6 -relocation-model=pic -verify-machineinstrs < %s | \
6; RUN:   FileCheck %s -check-prefixes=ALL,MIPS32-ANY,HAS-SEB-SEH,CHECK-EL,MIPSR6
7; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips4    -relocation-model=pic < %s | \
8; RUN:   FileCheck %s -check-prefixes=ALL,MIPS64-ANY,NO-SEB-SEH,CHECK-EL,NOT-MICROMIPS
9; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips64   -relocation-model=pic < %s | \
10; RUN:   FileCheck %s -check-prefixes=ALL,MIPS64-ANY,NO-SEB-SEH,CHECK-EL,NOT-MICROMIPS
11; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips64r2 -relocation-model=pic -verify-machineinstrs < %s | \
12; RUN:   FileCheck %s -check-prefixes=ALL,MIPS64-ANY,HAS-SEB-SEH,CHECK-EL,NOT-MICROMIPS
13; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips64r6 -relocation-model=pic < %s | \
14; RUN:   FileCheck %s -check-prefixes=ALL,MIPS64-ANY,HAS-SEB-SEH,CHECK-EL,MIPSR6
15; RUN: llc -march=mips64 -O0 -mcpu=mips64r6 -relocation-model=pic -verify-machineinstrs < %s | \
16; RUN:   FileCheck %s -check-prefixes=ALL-LABEL,MIPS64-ANY,O0
17; RUN: llc -march=mipsel --disable-machine-licm -mcpu=mips32r2 -mattr=micromips -relocation-model=pic < %s | \
18; RUN:   FileCheck %s -check-prefixes=ALL,MIPS32-ANY,HAS-SEB-SEH,CHECK-EL,MICROMIPS
19
20; Keep one big-endian check so that we don't reduce testing, but don't add more
21; since endianness doesn't affect the body of the atomic operations.
22; RUN: llc -march=mips   --disable-machine-licm -mcpu=mips32 -relocation-model=pic < %s | \
23; RUN:   FileCheck %s -check-prefixes=ALL,MIPS32-ANY,NO-SEB-SEH,CHECK-EB,NOT-MICROMIPS
24
25@x = common global i32 0, align 4
26
27define i32 @AtomicLoadAdd32(i32 signext %incr) nounwind {
28entry:
29  %0 = atomicrmw add i32* @x, i32 %incr monotonic
30  ret i32 %0
31
32; ALL-LABEL: AtomicLoadAdd32:
33
34; MIPS32-ANY:    lw      $[[R0:[0-9]+]], %got(x)
35; MIPS64-ANY:    ld      $[[R0:[0-9]+]], %got_disp(x)(
36
37; O0:        $[[BB0:[A-Z_0-9]+]]:
38; O0:            ld      $[[R1:[0-9]+]]
39; O0-NEXT:       ll      $[[R2:[0-9]+]], 0($[[R1]])
40
41; ALL:       $[[BB0:[A-Z_0-9]+]]:
42; ALL:           ll      $[[R3:[0-9]+]], 0($[[R0]])
43; ALL:           addu    $[[R4:[0-9]+]], $[[R3]], $4
44; ALL:           sc      $[[R4]], 0($[[R0]])
45; NOT-MICROMIPS: beqz    $[[R4]], $[[BB0]]
46; MICROMIPS:     beqzc   $[[R4]], $[[BB0]]
47; MIPSR6:        beqzc   $[[R4]], $[[BB0]]
48}
49
50define i32 @AtomicLoadNand32(i32 signext %incr) nounwind {
51entry:
52  %0 = atomicrmw nand i32* @x, i32 %incr monotonic
53  ret i32 %0
54
55; ALL-LABEL: AtomicLoadNand32:
56
57; MIPS32-ANY:    lw      $[[R0:[0-9]+]], %got(x)
58; MIPS64-ANY:    ld      $[[R0:[0-9]+]], %got_disp(x)(
59
60
61
62; ALL:       $[[BB0:[A-Z_0-9]+]]:
63; ALL:           ll      $[[R1:[0-9]+]], 0($[[R0]])
64; ALL:           and     $[[R3:[0-9]+]], $[[R1]], $4
65; ALL:           nor     $[[R2:[0-9]+]], $zero, $[[R3]]
66; ALL:           sc      $[[R2]], 0($[[R0]])
67; NOT-MICROMIPS: beqz    $[[R2]], $[[BB0]]
68; MICROMIPS:     beqzc   $[[R2]], $[[BB0]]
69; MIPSR6:        beqzc   $[[R2]], $[[BB0]]
70}
71
72define i32 @AtomicSwap32(i32 signext %newval) nounwind {
73entry:
74  %newval.addr = alloca i32, align 4
75  store i32 %newval, i32* %newval.addr, align 4
76  %tmp = load i32, i32* %newval.addr, align 4
77  %0 = atomicrmw xchg i32* @x, i32 %tmp monotonic
78  ret i32 %0
79
80; ALL-LABEL: AtomicSwap32:
81
82; MIPS32-ANY:    lw      $[[R0:[0-9]+]], %got(x)
83; MIPS64-ANY:    ld      $[[R0:[0-9]+]], %got_disp(x)
84
85; ALL:       $[[BB0:[A-Z_0-9]+]]:
86; ALL:           ll      ${{[0-9]+}}, 0($[[R0]])
87; ALL:           sc      $[[R2:[0-9]+]], 0($[[R0]])
88; NOT-MICROMIPS: beqz    $[[R2]], $[[BB0]]
89; MICROMIPS:     beqzc   $[[R2]], $[[BB0]]
90; MIPSR6:        beqzc   $[[R2]], $[[BB0]]
91}
92
93define i32 @AtomicCmpSwap32(i32 signext %oldval, i32 signext %newval) nounwind {
94entry:
95  %newval.addr = alloca i32, align 4
96  store i32 %newval, i32* %newval.addr, align 4
97  %tmp = load i32, i32* %newval.addr, align 4
98  %0 = cmpxchg i32* @x, i32 %oldval, i32 %tmp monotonic monotonic
99  %1 = extractvalue { i32, i1 } %0, 0
100  ret i32 %1
101
102; ALL-LABEL: AtomicCmpSwap32:
103
104; MIPS32-ANY:    lw      $[[R0:[0-9]+]], %got(x)
105; MIPS64-ANY:    ld      $[[R0:[0-9]+]], %got_disp(x)(
106
107; ALL:       $[[BB0:[A-Z_0-9]+]]:
108; ALL:           ll      $2, 0($[[R0]])
109; NOT-MICROMIPS: bne     $2, $4, $[[BB1:[A-Z_0-9]+]]
110; MICROMIPS:     bne     $2, $4, $[[BB1:[A-Z_0-9]+]]
111; MIPSR6:        bnec    $2, $4, $[[BB1:[A-Z_0-9]+]]
112; ALL:           sc      $[[R2:[0-9]+]], 0($[[R0]])
113; NOT-MICROMIPS: beqz    $[[R2]], $[[BB0]]
114; MICROMIPS:     beqzc   $[[R2]], $[[BB0]]
115; MIPSR6:        beqzc   $[[R2]], $[[BB0]]
116; ALL:       $[[BB1]]:
117}
118
119
120
121@y = common global i8 0, align 1
122
123define signext i8 @AtomicLoadAdd8(i8 signext %incr) nounwind {
124entry:
125  %0 = atomicrmw add i8* @y, i8 %incr monotonic
126  ret i8 %0
127
128; ALL-LABEL: AtomicLoadAdd8:
129
130; MIPS32-ANY:    lw      $[[R0:[0-9]+]], %got(y)
131; MIPS64-ANY:    ld      $[[R0:[0-9]+]], %got_disp(y)(
132
133; ALL:           addiu   $[[R1:[0-9]+]], $zero, -4
134; ALL:           and     $[[R2:[0-9]+]], $[[R0]], $[[R1]]
135; ALL:           andi    $[[R3:[0-9]+]], $[[R0]], 3
136; CHECK-EB:      xori    $[[R4:[0-9]+]], $[[R3]], 3
137; CHECK-EB:      sll     $[[R5:[0-9]+]], $[[R4]], 3
138; CHECK-EL:      sll     $[[R5:[0-9]+]], $[[R3]], 3
139; ALL:           ori     $[[R6:[0-9]+]], $zero, 255
140; ALL:           sllv    $[[R7:[0-9]+]], $[[R6]], $[[R5]]
141; ALL:           nor     $[[R8:[0-9]+]], $zero, $[[R7]]
142; ALL:           sllv    $[[R9:[0-9]+]], $4, $[[R5]]
143
144; O0:        $[[BB0:[A-Z_0-9]+]]:
145; O0:            ld      $[[R10:[0-9]+]]
146; O0-NEXT:       ll      $[[R11:[0-9]+]], 0($[[R10]])
147
148; ALL:       $[[BB0:[A-Z_0-9]+]]:
149; ALL:           ll      $[[R12:[0-9]+]], 0($[[R2]])
150; ALL:           addu    $[[R13:[0-9]+]], $[[R12]], $[[R9]]
151; ALL:           and     $[[R14:[0-9]+]], $[[R13]], $[[R7]]
152; ALL:           and     $[[R15:[0-9]+]], $[[R12]], $[[R8]]
153; ALL:           or      $[[R16:[0-9]+]], $[[R15]], $[[R14]]
154; ALL:           sc      $[[R16]], 0($[[R2]])
155; NOT-MICROMIPS: beqz    $[[R16]], $[[BB0]]
156; MICROMIPS:     beqzc   $[[R16]], $[[BB0]]
157; MIPSR6:        beqzc   $[[R16]], $[[BB0]]
158
159; ALL:           and     $[[R17:[0-9]+]], $[[R12]], $[[R7]]
160; ALL:           srlv    $[[R18:[0-9]+]], $[[R17]], $[[R5]]
161
162; NO-SEB-SEH:    sll     $[[R19:[0-9]+]], $[[R18]], 24
163; NO-SEB-SEH:    sra     $2, $[[R19]], 24
164
165; HAS-SEB-SEH:   seb     $2, $[[R18]]
166}
167
168define signext i8 @AtomicLoadSub8(i8 signext %incr) nounwind {
169entry:
170  %0 = atomicrmw sub i8* @y, i8 %incr monotonic
171  ret i8 %0
172
173; ALL-LABEL: AtomicLoadSub8:
174
175; MIPS32-ANY: lw      $[[R0:[0-9]+]], %got(y)
176; MIPS64-ANY: ld      $[[R0:[0-9]+]], %got_disp(y)(
177
178; ALL:        addiu   $[[R1:[0-9]+]], $zero, -4
179; ALL:        and     $[[R2:[0-9]+]], $[[R0]], $[[R1]]
180; ALL:        andi    $[[R3:[0-9]+]], $[[R0]], 3
181; CHECK-EL:   sll     $[[R5:[0-9]+]], $[[R3]], 3
182; CHECK-EB:   xori    $[[R4:[0-9]+]], $[[R3]], 3
183; CHECK-EB:   sll     $[[R5:[0-9]+]], $[[R4]], 3
184; ALL:        ori     $[[R6:[0-9]+]], $zero, 255
185; ALL:        sllv    $[[R7:[0-9]+]], $[[R6]], $[[R5]]
186; ALL:        nor     $[[R8:[0-9]+]], $zero, $[[R7]]
187; ALL:        sllv    $[[R9:[0-9]+]], $4, $[[R5]]
188
189; O0:        $[[BB0:[A-Z_0-9]+]]:
190; O0:            ld      $[[R10:[0-9]+]]
191; O0-NEXT:       ll      $[[R11:[0-9]+]], 0($[[R10]])
192
193; ALL:    $[[BB0:[A-Z_0-9]+]]:
194; ALL:        ll      $[[R12:[0-9]+]], 0($[[R2]])
195; ALL:        subu    $[[R13:[0-9]+]], $[[R12]], $[[R9]]
196; ALL:        and     $[[R14:[0-9]+]], $[[R13]], $[[R7]]
197; ALL:        and     $[[R15:[0-9]+]], $[[R12]], $[[R8]]
198; ALL:        or      $[[R16:[0-9]+]], $[[R15]], $[[R14]]
199; ALL:        sc      $[[R16]], 0($[[R2]])
200; NOT-MICROMIPS: beqz    $[[R16]], $[[BB0]]
201; MICROMIPS:  beqzc   $[[R16]], $[[BB0]]
202; MIPSR6:     beqzc   $[[R16]], $[[BB0]]
203
204; ALL:        and     $[[R17:[0-9]+]], $[[R12]], $[[R7]]
205; ALL:        srlv    $[[R18:[0-9]+]], $[[R17]], $[[R5]]
206
207; NO-SEB-SEH: sll     $[[R19:[0-9]+]], $[[R18]], 24
208; NO-SEB-SEH: sra     $2, $[[R19]], 24
209
210; HAS-SEB-SEH:seb     $2, $[[R18]]
211}
212
213define signext i8 @AtomicLoadNand8(i8 signext %incr) nounwind {
214entry:
215  %0 = atomicrmw nand i8* @y, i8 %incr monotonic
216  ret i8 %0
217
218; ALL-LABEL: AtomicLoadNand8:
219
220; MIPS32-ANY:    lw      $[[R0:[0-9]+]], %got(y)
221; MIPS64-ANY:    ld      $[[R0:[0-9]+]], %got_disp(y)(
222
223; ALL:           addiu   $[[R1:[0-9]+]], $zero, -4
224; ALL:           and     $[[R2:[0-9]+]], $[[R0]], $[[R1]]
225; ALL:           andi    $[[R3:[0-9]+]], $[[R0]], 3
226; CHECK-EL:      sll     $[[R5:[0-9]+]], $[[R3]], 3
227; CHECK-EB:      xori    $[[R4:[0-9]+]], $[[R3]], 3
228; CHECK-EB:      sll     $[[R5:[0-9]+]], $[[R4]], 3
229; ALL:           ori     $[[R6:[0-9]+]], $zero, 255
230; ALL:           sllv    $[[R7:[0-9]+]], $[[R6]], $[[R5]]
231; ALL:           nor     $[[R8:[0-9]+]], $zero, $[[R7]]
232; ALL:           sllv    $[[R9:[0-9]+]], $4, $[[R5]]
233
234; O0:        $[[BB0:[A-Z_0-9]+]]:
235; O0:            ld      $[[R10:[0-9]+]]
236; O0-NEXT:       ll      $[[R11:[0-9]+]], 0($[[R10]])
237
238; ALL:       $[[BB0:[A-Z_0-9]+]]:
239; ALL:           ll      $[[R12:[0-9]+]], 0($[[R2]])
240; ALL:           and     $[[R13:[0-9]+]], $[[R12]], $[[R9]]
241; ALL:           nor     $[[R14:[0-9]+]], $zero, $[[R13]]
242; ALL:           and     $[[R15:[0-9]+]], $[[R14]], $[[R7]]
243; ALL:           and     $[[R16:[0-9]+]], $[[R12]], $[[R8]]
244; ALL:           or      $[[R17:[0-9]+]], $[[R16]], $[[R15]]
245; ALL:           sc      $[[R17]], 0($[[R2]])
246; NOT-MICROMIPS: beqz    $[[R17]], $[[BB0]]
247; MICROMIPS:     beqzc   $[[R17]], $[[BB0]]
248; MIPSR6:        beqzc   $[[R17]], $[[BB0]]
249
250; ALL:           and     $[[R18:[0-9]+]], $[[R12]], $[[R7]]
251; ALL:           srlv    $[[R19:[0-9]+]], $[[R18]], $[[R5]]
252
253; NO-SEB-SEH:    sll     $[[R20:[0-9]+]], $[[R19]], 24
254; NO-SEB-SEH:    sra     $2, $[[R20]], 24
255
256; HAS-SEB-SEH:   seb     $2, $[[R19]]
257}
258
259define signext i8 @AtomicSwap8(i8 signext %newval) nounwind {
260entry:
261  %0 = atomicrmw xchg i8* @y, i8 %newval monotonic
262  ret i8 %0
263
264; ALL-LABEL: AtomicSwap8:
265
266; MIPS32-ANY:    lw      $[[R0:[0-9]+]], %got(y)
267; MIPS64-ANY:    ld      $[[R0:[0-9]+]], %got_disp(y)(
268
269; ALL:           addiu   $[[R1:[0-9]+]], $zero, -4
270; ALL:           and     $[[R2:[0-9]+]], $[[R0]], $[[R1]]
271; ALL:           andi    $[[R3:[0-9]+]], $[[R0]], 3
272; CHECK-EL:      sll     $[[R5:[0-9]+]], $[[R3]], 3
273; CHECK-EB:      xori    $[[R4:[0-9]+]], $[[R3]], 3
274; CHECK-EB:      sll     $[[R5:[0-9]+]], $[[R4]], 3
275; ALL:           ori     $[[R6:[0-9]+]], $zero, 255
276; ALL:           sllv    $[[R7:[0-9]+]], $[[R6]], $[[R5]]
277; ALL:           nor     $[[R8:[0-9]+]], $zero, $[[R7]]
278; ALL:           sllv    $[[R9:[0-9]+]], $4, $[[R5]]
279
280; ALL:       $[[BB0:[A-Z_0-9]+]]:
281; ALL:           ll      $[[R10:[0-9]+]], 0($[[R2]])
282; ALL:           and     $[[R18:[0-9]+]], $[[R9]], $[[R7]]
283; ALL:           and     $[[R13:[0-9]+]], $[[R10]], $[[R8]]
284; ALL:           or      $[[R14:[0-9]+]], $[[R13]], $[[R18]]
285; ALL:           sc      $[[R14]], 0($[[R2]])
286; NOT-MICROMIPS: beqz    $[[R14]], $[[BB0]]
287; MICROMIPS:     beqzc   $[[R14]], $[[BB0]]
288; MIPSR6:        beqzc   $[[R14]], $[[BB0]]
289
290; ALL:           and     $[[R15:[0-9]+]], $[[R10]], $[[R7]]
291; ALL:           srlv    $[[R16:[0-9]+]], $[[R15]], $[[R5]]
292
293; NO-SEB-SEH:    sll     $[[R17:[0-9]+]], $[[R16]], 24
294; NO-SEB-SEH:    sra     $2, $[[R17]], 24
295
296; HAS-SEB-SEH:   seb     $2, $[[R16]]
297
298}
299
300define signext i8 @AtomicCmpSwap8(i8 signext %oldval, i8 signext %newval) nounwind {
301entry:
302  %pair0 = cmpxchg i8* @y, i8 %oldval, i8 %newval monotonic monotonic
303  %0 = extractvalue { i8, i1 } %pair0, 0
304  ret i8 %0
305
306; ALL-LABEL: AtomicCmpSwap8:
307
308; MIPS32-ANY:    lw      $[[R0:[0-9]+]], %got(y)
309; MIPS64-ANY:    ld      $[[R0:[0-9]+]], %got_disp(y)(
310
311; ALL:           addiu   $[[R1:[0-9]+]], $zero, -4
312; ALL:           and     $[[R2:[0-9]+]], $[[R0]], $[[R1]]
313; ALL:           andi    $[[R3:[0-9]+]], $[[R0]], 3
314; CHECK-EL:      sll     $[[R5:[0-9]+]], $[[R3]], 3
315; CHECK-EB:      xori    $[[R4:[0-9]+]], $[[R3]], 3
316; CHECK-EB:      sll     $[[R5:[0-9]+]], $[[R4]], 3
317; ALL:           ori     $[[R6:[0-9]+]], $zero, 255
318; ALL:           sllv    $[[R7:[0-9]+]], $[[R6]], $[[R5]]
319; ALL:           nor     $[[R8:[0-9]+]], $zero, $[[R7]]
320; ALL:           andi    $[[R9:[0-9]+]], $4, 255
321; ALL:           sllv    $[[R10:[0-9]+]], $[[R9]], $[[R5]]
322; ALL:           andi    $[[R11:[0-9]+]], $5, 255
323; ALL:           sllv    $[[R12:[0-9]+]], $[[R11]], $[[R5]]
324
325; ALL:       $[[BB0:[A-Z_0-9]+]]:
326; ALL:           ll      $[[R13:[0-9]+]], 0($[[R2]])
327; ALL:           and     $[[R14:[0-9]+]], $[[R13]], $[[R7]]
328; NOT-MICROMIPS: bne     $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]]
329; MICROMIPS:     bne     $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]]
330; MIPSR6:        bnec    $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]]
331
332; ALL:           and     $[[R15:[0-9]+]], $[[R13]], $[[R8]]
333; ALL:           or      $[[R16:[0-9]+]], $[[R15]], $[[R12]]
334; ALL:           sc      $[[R16]], 0($[[R2]])
335; NOT-MICROMIPS: beqz    $[[R16]], $[[BB0]]
336; MICROMIPS:     beqzc   $[[R16]], $[[BB0]]
337; MIPSR6:        beqzc   $[[R16]], $[[BB0]]
338
339; ALL:       $[[BB1]]:
340; ALL:           srlv    $[[R17:[0-9]+]], $[[R14]], $[[R5]]
341
342; NO-SEB-SEH:    sll     $[[R18:[0-9]+]], $[[R17]], 24
343; NO-SEB-SEH:    sra     $2, $[[R18]], 24
344
345; HAS-SEB-SEH:   seb     $2, $[[R17]]
346}
347
348define i1 @AtomicCmpSwapRes8(i8* %ptr, i8 signext %oldval, i8 signext %newval) nounwind {
349entry:
350  %0 = cmpxchg i8* %ptr, i8 %oldval, i8 %newval monotonic monotonic
351  %1 = extractvalue { i8, i1 } %0, 1
352  ret i1 %1
353; ALL-LABEL: AtomicCmpSwapRes8
354
355; ALL:           addiu   $[[R1:[0-9]+]], $zero, -4
356; ALL:           and     $[[R2:[0-9]+]], $4, $[[R1]]
357; ALL:           andi    $[[R3:[0-9]+]], $4, 3
358; CHECK-EL:      sll     $[[R5:[0-9]+]], $[[R3]], 3
359; CHECK-EB:      xori    $[[R4:[0-9]+]], $[[R3]], 3
360; CHECK-EB:      sll     $[[R5:[0-9]+]], $[[R4]], 3
361; ALL:           ori     $[[R6:[0-9]+]], $zero, 255
362; ALL:           sllv    $[[R7:[0-9]+]], $[[R6]], $[[R5]]
363; ALL:           nor     $[[R8:[0-9]+]], $zero, $[[R7]]
364; ALL:           andi    $[[R9:[0-9]+]], $5, 255
365; ALL:           sllv    $[[R10:[0-9]+]], $[[R9]], $[[R5]]
366; ALL:           andi    $[[R11:[0-9]+]], $6, 255
367; ALL:           sllv    $[[R12:[0-9]+]], $[[R11]], $[[R5]]
368
369; ALL:       $[[BB0:[A-Z_0-9]+]]:
370; ALL:           ll      $[[R13:[0-9]+]], 0($[[R2]])
371; ALL:           and     $[[R14:[0-9]+]], $[[R13]], $[[R7]]
372; NOT-MICROMIPS: bne     $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]]
373; MICROMIPS:     bne     $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]]
374; MIPSR6:        bnec    $[[R14]], $[[R10]], $[[BB1:[A-Z_0-9]+]]
375
376; ALL:           and     $[[R15:[0-9]+]], $[[R13]], $[[R8]]
377; ALL:           or      $[[R16:[0-9]+]], $[[R15]], $[[R12]]
378; ALL:           sc      $[[R16]], 0($[[R2]])
379; NOT-MICROMIPS: beqz    $[[R16]], $[[BB0]]
380; MICROMIPS:     beqzc   $[[R16]], $[[BB0]]
381; MIPSR6:        beqzc   $[[R16]], $[[BB0]]
382
383; ALL:       $[[BB1]]:
384; ALL:           srlv    $[[R17:[0-9]+]], $[[R14]], $[[R5]]
385
386; NO-SEB-SEH:    sll     $[[R18:[0-9]+]], $[[R17]], 24
387; NO-SEB-SEH:    sra     $[[R19:[0-9]+]], $[[R18]], 24
388
389; FIXME: -march=mips produces a redundant sign extension here...
390; NO-SEB-SEH:    sll     $[[R20:[0-9]+]], $5, 24
391; NO-SEB-SEH:    sra     $[[R20]], $[[R20]], 24
392
393; HAS-SEB-SEH:   seb     $[[R19:[0-9]+]], $[[R17]]
394
395; FIXME: ...Leading to this split check.
396; NO-SEB-SEH:    xor     $[[R21:[0-9]+]], $[[R19]], $[[R20]]
397; HAS-SEB-SEH:   xor     $[[R21:[0-9]+]], $[[R19]], $5
398
399; ALL: sltiu   $2, $[[R21]], 1
400}
401
402; Check one i16 so that we cover the seh sign extend
403@z = common global i16 0, align 1
404
405define signext i16 @AtomicLoadAdd16(i16 signext %incr) nounwind {
406entry:
407  %0 = atomicrmw add i16* @z, i16 %incr monotonic
408  ret i16 %0
409
410; ALL-LABEL: AtomicLoadAdd16:
411
412; MIPS32-ANY:    lw      $[[R0:[0-9]+]], %got(z)
413; MIPS64-ANY:    ld      $[[R0:[0-9]+]], %got_disp(z)(
414
415; ALL:           addiu   $[[R1:[0-9]+]], $zero, -4
416; ALL:           and     $[[R2:[0-9]+]], $[[R0]], $[[R1]]
417; ALL:           andi    $[[R3:[0-9]+]], $[[R0]], 3
418; CHECK-EB:      xori    $[[R4:[0-9]+]], $[[R3]], 2
419; CHECK-EB:      sll     $[[R5:[0-9]+]], $[[R4]], 3
420; CHECK-EL:      sll     $[[R5:[0-9]+]], $[[R3]], 3
421; ALL:           ori     $[[R6:[0-9]+]], $zero, 65535
422; ALL:           sllv    $[[R7:[0-9]+]], $[[R6]], $[[R5]]
423; ALL:           nor     $[[R8:[0-9]+]], $zero, $[[R7]]
424; ALL:           sllv    $[[R9:[0-9]+]], $4, $[[R5]]
425
426; O0:        $[[BB0:[A-Z_0-9]+]]:
427; O0:            ld      $[[R10:[0-9]+]]
428; O0-NEXT:       ll      $[[R11:[0-9]+]], 0($[[R10]])
429
430; ALL:       $[[BB0:[A-Z_0-9]+]]:
431; ALL:           ll      $[[R12:[0-9]+]], 0($[[R2]])
432; ALL:           addu    $[[R13:[0-9]+]], $[[R12]], $[[R9]]
433; ALL:           and     $[[R14:[0-9]+]], $[[R13]], $[[R7]]
434; ALL:           and     $[[R15:[0-9]+]], $[[R12]], $[[R8]]
435; ALL:           or      $[[R16:[0-9]+]], $[[R15]], $[[R14]]
436; ALL:           sc      $[[R16]], 0($[[R2]])
437; NOT-MICROMIPS: beqz    $[[R16]], $[[BB0]]
438; MICROMIPS:     beqzc   $[[R16]], $[[BB0]]
439; MIPSR6:        beqzc   $[[R16]], $[[BB0]]
440
441; ALL:           and     $[[R17:[0-9]+]], $[[R12]], $[[R7]]
442; ALL:           srlv    $[[R18:[0-9]+]], $[[R17]], $[[R5]]
443
444; NO-SEB-SEH:    sll     $[[R19:[0-9]+]], $[[R18]], 16
445; NO-SEB-SEH:    sra     $2, $[[R19]], 16
446
447; MIPS32R2:      seh     $2, $[[R18]]
448}
449
450; Test that the i16 return value from cmpxchg is recognised as signed,
451; so that setCC doesn't end up comparing an unsigned value to a signed
452; value.
453; The rest of the functions here are testing the atomic expansion, so
454; we just match the end of the function.
455define {i16, i1} @foo(i16* %addr, i16 %l, i16 %r, i16 %new) {
456  %desired = add i16 %l, %r
457  %res = cmpxchg i16* %addr, i16 %desired, i16 %new seq_cst seq_cst
458  ret {i16, i1} %res
459
460; ALL-LABEL: foo
461; MIPSR6:        addu    $[[R2:[0-9]+]], $[[R1:[0-9]+]], $[[R0:[0-9]+]]
462; NOT-MICROMIPS: addu    $[[R2:[0-9]+]], $[[R1:[0-9]+]], $[[R0:[0-9]+]]
463; MICROMIPS:     addu16  $[[R2:[0-9]+]], $[[R1:[0-9]+]], $[[R0:[0-9]+]]
464
465; ALL:           sync
466
467; ALL:           andi    $[[R3:[0-9]+]], $[[R2]], 65535
468; ALL:       $[[BB0:[A-Z_0-9]+]]:
469; ALL:           ll      $[[R4:[0-9]+]], 0($[[R5:[0-9]+]])
470; ALL:           and     $[[R6:[0-9]+]], $[[R4]], $
471; ALL:           and     $[[R7:[0-9]+]], $[[R4]], $
472; ALL:           or      $[[R8:[0-9]+]], $[[R7]], $
473; ALL:           sc      $[[R8]], 0($[[R5]])
474; NOT-MICROMIPS: beqz    $[[R8]], $[[BB0]]
475; MICROMIPS:     beqzc   $[[R8]], $[[BB0]]
476; MIPSR6:        beqzc   $[[R8]], $[[BB0]]
477
478; ALL:           srlv    $[[R9:[0-9]+]], $[[R6]], $
479
480; NO-SEB-SEH:    sll     $[[R10:[0-9]+]], $[[R9]], 16
481; NO-SEB-SEH:    sra     $[[R11:[0-9]+]], $[[R10]], 16
482
483; NO-SEB-SEH:    sll     $[[R12:[0-9]+]], $[[R2]], 16
484; NO-SEB-SEH:    sra     $[[R13:[0-9]+]], $[[R12]], 16
485
486; HAS-SEB-SEH:   seh     $[[R11:[0-9]+]], $[[R9]]
487; HAS-SEB-SEH:   seh     $[[R13:[0-9]+]], $[[R2]]
488
489; ALL:           xor     $[[R12:[0-9]+]], $[[R11]], $[[R13]]
490; ALL:           sltiu   $3, $[[R12]], 1
491; ALL:           sync
492}
493
494@countsint = common global i32 0, align 4
495
496define i32 @CheckSync(i32 signext %v) nounwind noinline {
497entry:
498  %0 = atomicrmw add i32* @countsint, i32 %v seq_cst
499  ret i32 %0
500
501; ALL-LABEL: CheckSync:
502
503; ALL:           sync
504; ALL:           ll
505; ALL:           sc
506; ALL:           beq
507; ALL:           sync
508}
509
510; make sure that this assertion in
511; TwoAddressInstructionPass::TryInstructionTransform does not fail:
512;
513; line 1203: assert(TargetRegisterInfo::isVirtualRegister(regB) &&
514;
515; it failed when MipsDAGToDAGISel::ReplaceUsesWithZeroReg replaced an
516; operand of an atomic instruction with register $zero.
517@a = external global i32
518
519define i32 @zeroreg() nounwind {
520entry:
521  %pair0 = cmpxchg i32* @a, i32 1, i32 0 seq_cst seq_cst
522  %0 = extractvalue { i32, i1 } %pair0, 0
523  %1 = icmp eq i32 %0, 1
524  %conv = zext i1 %1 to i32
525  ret i32 %conv
526}
527
528; Check that MIPS32R6 has the correct offset range.
529; FIXME: At the moment, we don't seem to do addr+offset for any atomic load/store.
530define i32 @AtomicLoadAdd32_OffGt9Bit(i32 signext %incr) nounwind {
531entry:
532  %0 = atomicrmw add i32* getelementptr(i32, i32* @x, i32 256), i32 %incr monotonic
533  ret i32 %0
534
535; ALL-LABEL: AtomicLoadAdd32_OffGt9Bit:
536
537; MIPS32-ANY:    lw      $[[R0:[0-9]+]], %got(x)
538; MIPS64-ANY:    ld      $[[R0:[0-9]+]], %got_disp(x)(
539
540; ALL:           addiu   $[[PTR:[0-9]+]], $[[R0]], 1024
541; ALL:       $[[BB0:[A-Z_0-9]+]]:
542; ALL:           ll      $[[R1:[0-9]+]], 0($[[PTR]])
543; ALL:           addu    $[[R2:[0-9]+]], $[[R1]], $4
544; ALL:           sc      $[[R2]], 0($[[PTR]])
545; NOT-MICROMIPS: beqz    $[[R2]], $[[BB0]]
546; MICROMIPS:     beqzc   $[[R2]], $[[BB0]]
547; MIPSR6:        beqzc   $[[R2]], $[[BB0]]
548}
549