1; RUN: llc -march=mipsel -mcpu=mips32 -mattr=+fp64,+msa,-nooddspreg < %s | FileCheck %s -check-prefix=ALL -check-prefix=ODDSPREG
2; RUN: llc -march=mipsel -mcpu=mips32 -mattr=+fp64,+msa,+nooddspreg < %s | FileCheck %s -check-prefix=ALL -check-prefix=NOODDSPREG
3
4@v4f32 = global <4 x float> zeroinitializer
5
6define void @msa_insert_0(float %a) {
7entry:
8  ; Force the float into an odd-numbered register using named registers and
9  ; load the vector.
10  %b = call float asm sideeffect "mov.s $0, $1", "={$f13},{$f12}" (float %a)
11  %0 = load volatile <4 x float>* @v4f32
12
13  ; Clobber all except $f12/$w12 and $f13
14  ;
15  ; The intention is that if odd single precision registers are permitted, the
16  ; allocator will choose $f12/$w12 for the vector and $f13 for the float to
17  ; avoid the spill/reload.
18  ;
19  ; On the other hand, if odd single precision registers are not permitted, it
20  ; must copy $f13 to an even-numbered register before inserting into the
21  ; vector.
22  call void asm sideeffect "# Clobber", "~{$f0},~{$f1},~{$f2},~{$f3},~{$f4},~{$f5},~{$f6},~{$f7},~{$f8},~{$f9},~{$f10},~{$f11},~{$f14},~{$f15},~{$f16},~{$f17},~{$f18},~{$f19},~{$f20},~{$f21},~{$f22},~{$f23},~{$f24},~{$f25},~{$f26},~{$f27},~{$f28},~{$f29},~{$f30},~{$f31}"()
23  %1 = insertelement <4 x float> %0, float %b, i32 0
24  store <4 x float> %1, <4 x float>* @v4f32
25  ret void
26}
27
28; ALL-LABEL:  msa_insert_0:
29; ALL:            mov.s $f13, $f12
30; ALL:            lw $[[R0:[0-9]+]], %got(v4f32)(
31; ALL:            ld.w $w[[W0:[0-9]+]], 0($[[R0]])
32; NOODDSPREG:     mov.s $f[[F0:[0-9]+]], $f13
33; NOODDSPREG:     insve.w $w[[W0]][0], $w[[F0]][0]
34; ODDSPREG:       insve.w $w[[W0]][0], $w13[0]
35; ALL:            # Clobber
36; ALL-NOT: sdc1
37; ALL-NOT: ldc1
38; ALL:            st.w $w[[W0]], 0($[[R0]])
39
40define void @msa_insert_1(float %a) {
41entry:
42  ; Force the float into an odd-numbered register using named registers and
43  ; load the vector.
44  %b = call float asm sideeffect "mov.s $0, $1", "={$f13},{$f12}" (float %a)
45  %0 = load volatile <4 x float>* @v4f32
46
47  ; Clobber all except $f12/$w12 and $f13
48  ;
49  ; The intention is that if odd single precision registers are permitted, the
50  ; allocator will choose $f12/$w12 for the vector and $f13 for the float to
51  ; avoid the spill/reload.
52  ;
53  ; On the other hand, if odd single precision registers are not permitted, it
54  ; must copy $f13 to an even-numbered register before inserting into the
55  ; vector.
56  call void asm sideeffect "# Clobber", "~{$f0},~{$f1},~{$f2},~{$f3},~{$f4},~{$f5},~{$f6},~{$f7},~{$f8},~{$f9},~{$f10},~{$f11},~{$f14},~{$f15},~{$f16},~{$f17},~{$f18},~{$f19},~{$f20},~{$f21},~{$f22},~{$f23},~{$f24},~{$f25},~{$f26},~{$f27},~{$f28},~{$f29},~{$f30},~{$f31}"()
57  %1 = insertelement <4 x float> %0, float %b, i32 1
58  store <4 x float> %1, <4 x float>* @v4f32
59  ret void
60}
61
62; ALL-LABEL:  msa_insert_1:
63; ALL:            mov.s $f13, $f12
64; ALL:            lw $[[R0:[0-9]+]], %got(v4f32)(
65; ALL:            ld.w $w[[W0:[0-9]+]], 0($[[R0]])
66; NOODDSPREG:     mov.s $f[[F0:[0-9]+]], $f13
67; NOODDSPREG:     insve.w $w[[W0]][1], $w[[F0]][0]
68; ODDSPREG:       insve.w $w[[W0]][1], $w13[0]
69; ALL:            # Clobber
70; ALL-NOT: sdc1
71; ALL-NOT: ldc1
72; ALL:            st.w $w[[W0]], 0($[[R0]])
73
74define float @msa_extract_0() {
75entry:
76  %0 = load volatile <4 x float>* @v4f32
77  %1 = call <4 x float> asm sideeffect "move.v $0, $1", "={$w13},{$w12}" (<4 x float> %0)
78
79  ; Clobber all except $f12, and $f13
80  ;
81  ; The intention is that if odd single precision registers are permitted, the
82  ; allocator will choose $f13/$w13 for the vector since that saves on moves.
83  ;
84  ; On the other hand, if odd single precision registers are not permitted, it
85  ; must move it to $f12/$w12.
86  call void asm sideeffect "# Clobber", "~{$f0},~{$f1},~{$f2},~{$f3},~{$f4},~{$f5},~{$f6},~{$f7},~{$f8},~{$f9},~{$f10},~{$f11},~{$f14},~{$f15},~{$f16},~{$f17},~{$f18},~{$f19},~{$f20},~{$f21},~{$f22},~{$f23},~{$f24},~{$f25},~{$f26},~{$f27},~{$f28},~{$f29},~{$f30},~{$f31}"()
87
88  %2 = extractelement <4 x float> %1, i32 0
89  ret float %2
90}
91
92; ALL-LABEL:  msa_extract_0:
93; ALL:            lw $[[R0:[0-9]+]], %got(v4f32)(
94; ALL:            ld.w $w12, 0($[[R0]])
95; ALL:            move.v $w[[W0:13]], $w12
96; NOODDSPREG:     move.v $w[[W0:12]], $w13
97; ALL:            # Clobber
98; ALL-NOT: st.w
99; ALL-NOT: ld.w
100; ALL:            mov.s $f0, $f[[W0]]
101
102define float @msa_extract_1() {
103entry:
104  %0 = load volatile <4 x float>* @v4f32
105  %1 = call <4 x float> asm sideeffect "move.v $0, $1", "={$w13},{$w12}" (<4 x float> %0)
106
107  ; Clobber all except $f13
108  ;
109  ; The intention is that if odd single precision registers are permitted, the
110  ; allocator will choose $f13/$w13 for the vector since that saves on moves.
111  ;
112  ; On the other hand, if odd single precision registers are not permitted, it
113  ; must be spilled.
114  call void asm sideeffect "# Clobber", "~{$f0},~{$f1},~{$f2},~{$f3},~{$f4},~{$f5},~{$f6},~{$f7},~{$f8},~{$f9},~{$f10},~{$f11},~{$f12},~{$f14},~{$f15},~{$f16},~{$f17},~{$f18},~{$f19},~{$f20},~{$f21},~{$f22},~{$f23},~{$f24},~{$f25},~{$f26},~{$f27},~{$f28},~{$f29},~{$f30},~{$f31}"()
115
116  %2 = extractelement <4 x float> %1, i32 1
117  ret float %2
118}
119
120; ALL-LABEL:  msa_extract_1:
121; ALL:            lw $[[R0:[0-9]+]], %got(v4f32)(
122; ALL:            ld.w $w12, 0($[[R0]])
123; ALL:            splati.w $w[[W0:[0-9]+]], $w13[1]
124; NOODDSPREG:     st.w $w[[W0]], 0($sp)
125; ODDSPREG-NOT: st.w
126; ODDSPREG-NOT: ld.w
127; ALL:            # Clobber
128; ODDSPREG-NOT: st.w
129; ODDSPREG-NOT: ld.w
130; NOODDSPREG:     ld.w $w0, 0($sp)
131; ODDSPREG:       mov.s $f0, $f[[W0]]
132