1; RUN: llc -mtriple=x86_64-pc-linux -mcpu=corei7 < %s | FileCheck %s
2
3; MMX packed sub opcodes were wrongly marked as commutative.
4; This test checks that the operands of packed sub instructions are
5; never interchanged by the "Two-Address instruction pass".
6
7declare { i64, double } @getFirstParam()
8declare { i64, double } @getSecondParam()
9
10define i64 @test_psubb() {
11entry:
12  %call = tail call { i64, double } @getFirstParam()
13  %0 = extractvalue { i64, double } %call, 0
14  %call2 = tail call { i64, double } @getSecondParam()
15  %1 = extractvalue { i64, double } %call2, 0
16  %__m1.0.insert.i = insertelement <1 x i64> undef, i64 %0, i32 0
17  %__m2.0.insert.i = insertelement <1 x i64> undef, i64 %1, i32 0
18  %2 = bitcast <1 x i64> %__m1.0.insert.i to <8 x i8>
19  %3 = bitcast <8 x i8> %2 to x86_mmx
20  %4 = bitcast <1 x i64> %__m2.0.insert.i to <8 x i8>
21  %5 = bitcast <8 x i8> %4 to x86_mmx
22  %6 = tail call x86_mmx @llvm.x86.mmx.psub.b(x86_mmx %3, x86_mmx %5) nounwind
23  %7 = bitcast x86_mmx %6 to <8 x i8>
24  %8 = bitcast <8 x i8> %7 to <1 x i64>
25  %retval.0.extract.i15 = extractelement <1 x i64> %8, i32 0
26  ret i64 %retval.0.extract.i15
27}
28
29; CHECK-LABEL: test_psubb:
30; CHECK:   callq getFirstParam
31; CHECK:   movq %rax, [[TEMP:%[a-z0-9]+]]
32; CHECK:   callq getSecondParam
33; CHECK:   movd [[TEMP]], [[PARAM1:%[a-z0-9]+]]
34; CHECK:   movd %rax, [[PARAM2:%[a-z0-9]+]]
35; CHECK:   psubb [[PARAM2]], [[PARAM1]]
36; CHECK: ret
37
38define i64 @test_psubw() {
39entry:
40  %call = tail call { i64, double } @getFirstParam()
41  %0 = extractvalue { i64, double } %call, 0
42  %call2 = tail call { i64, double } @getSecondParam()
43  %1 = extractvalue { i64, double } %call2, 0
44  %__m1.0.insert.i = insertelement <1 x i64> undef, i64 %0, i32 0
45  %__m2.0.insert.i = insertelement <1 x i64> undef, i64 %1, i32 0
46  %2 = bitcast <1 x i64> %__m1.0.insert.i to <4 x i16>
47  %3 = bitcast <4 x i16> %2 to x86_mmx
48  %4 = bitcast <1 x i64> %__m2.0.insert.i to <4 x i16>
49  %5 = bitcast <4 x i16> %4 to x86_mmx
50  %6 = tail call x86_mmx @llvm.x86.mmx.psub.w(x86_mmx %3, x86_mmx %5) nounwind
51  %7 = bitcast x86_mmx %6 to <4 x i16>
52  %8 = bitcast <4 x i16> %7 to <1 x i64>
53  %retval.0.extract.i15 = extractelement <1 x i64> %8, i32 0
54  ret i64 %retval.0.extract.i15
55}
56
57; CHECK-LABEL: test_psubw:
58; CHECK:   callq getFirstParam
59; CHECK:   movq %rax, [[TEMP:%[a-z0-9]+]]
60; CHECK:   callq getSecondParam
61; CHECK:   movd [[TEMP]], [[PARAM1:%[a-z0-9]+]]
62; CHECK:   movd %rax, [[PARAM2:%[a-z0-9]+]]
63; CHECK:   psubw [[PARAM2]], [[PARAM1]]
64; CHECK: ret
65
66
67define i64 @test_psubd() {
68entry:
69  %call = tail call { i64, double } @getFirstParam()
70  %0 = extractvalue { i64, double } %call, 0
71  %call2 = tail call { i64, double } @getSecondParam()
72  %1 = extractvalue { i64, double } %call2, 0
73  %__m1.0.insert.i = insertelement <1 x i64> undef, i64 %0, i32 0
74  %__m2.0.insert.i = insertelement <1 x i64> undef, i64 %1, i32 0
75  %2 = bitcast <1 x i64> %__m1.0.insert.i to <2 x i32>
76  %3 = bitcast <2 x i32> %2 to x86_mmx
77  %4 = bitcast <1 x i64> %__m2.0.insert.i to <2 x i32>
78  %5 = bitcast <2 x i32> %4 to x86_mmx
79  %6 = tail call x86_mmx @llvm.x86.mmx.psub.d(x86_mmx %3, x86_mmx %5) nounwind
80  %7 = bitcast x86_mmx %6 to <2 x i32>
81  %8 = bitcast <2 x i32> %7 to <1 x i64>
82  %retval.0.extract.i15 = extractelement <1 x i64> %8, i32 0
83  ret i64 %retval.0.extract.i15
84}
85
86; CHECK-LABEL: test_psubd:
87; CHECK:   callq getFirstParam
88; CHECK:   movq %rax, [[TEMP:%[a-z0-9]+]]
89; CHECK:   callq getSecondParam
90; CHECK:   movd [[TEMP]], [[PARAM1:%[a-z0-9]+]]
91; CHECK:   movd %rax, [[PARAM2:%[a-z0-9]+]]
92; CHECK:   psubd [[PARAM2]], [[PARAM1]]
93; CHECK: ret
94
95define i64 @test_psubsb() {
96entry:
97  %call = tail call { i64, double } @getFirstParam()
98  %0 = extractvalue { i64, double } %call, 0
99  %call2 = tail call { i64, double } @getSecondParam()
100  %1 = extractvalue { i64, double } %call2, 0
101  %__m1.0.insert.i = insertelement <1 x i64> undef, i64 %0, i32 0
102  %__m2.0.insert.i = insertelement <1 x i64> undef, i64 %1, i32 0
103  %2 = bitcast <1 x i64> %__m1.0.insert.i to <8 x i8>
104  %3 = bitcast <8 x i8> %2 to x86_mmx
105  %4 = bitcast <1 x i64> %__m2.0.insert.i to <8 x i8>
106  %5 = bitcast <8 x i8> %4 to x86_mmx
107  %6 = tail call x86_mmx @llvm.x86.mmx.psubs.b(x86_mmx %3, x86_mmx %5) nounwind
108  %7 = bitcast x86_mmx %6 to <8 x i8>
109  %8 = bitcast <8 x i8> %7 to <1 x i64>
110  %retval.0.extract.i15 = extractelement <1 x i64> %8, i32 0
111  ret i64 %retval.0.extract.i15
112}
113
114; CHECK-LABEL: test_psubsb:
115; CHECK:   callq getFirstParam
116; CHECK:   movq %rax, [[TEMP:%[a-z0-9]+]]
117; CHECK:   callq getSecondParam
118; CHECK:   movd [[TEMP]], [[PARAM1:%[a-z0-9]+]]
119; CHECK:   movd %rax, [[PARAM2:%[a-z0-9]+]]
120; CHECK:   psubsb [[PARAM2]], [[PARAM1]]
121; CHECK: ret
122
123define i64 @test_psubswv() {
124entry:
125  %call = tail call { i64, double } @getFirstParam()
126  %0 = extractvalue { i64, double } %call, 0
127  %call2 = tail call { i64, double } @getSecondParam()
128  %1 = extractvalue { i64, double } %call2, 0
129  %__m1.0.insert.i = insertelement <1 x i64> undef, i64 %0, i32 0
130  %__m2.0.insert.i = insertelement <1 x i64> undef, i64 %1, i32 0
131  %2 = bitcast <1 x i64> %__m1.0.insert.i to <4 x i16>
132  %3 = bitcast <4 x i16> %2 to x86_mmx
133  %4 = bitcast <1 x i64> %__m2.0.insert.i to <4 x i16>
134  %5 = bitcast <4 x i16> %4 to x86_mmx
135  %6 = tail call x86_mmx @llvm.x86.mmx.psubs.w(x86_mmx %3, x86_mmx %5) nounwind
136  %7 = bitcast x86_mmx %6 to <4 x i16>
137  %8 = bitcast <4 x i16> %7 to <1 x i64>
138  %retval.0.extract.i15 = extractelement <1 x i64> %8, i32 0
139  ret i64 %retval.0.extract.i15
140}
141
142; CHECK-LABEL: test_psubswv:
143; CHECK:   callq getFirstParam
144; CHECK:   movq %rax, [[TEMP:%[a-z0-9]+]]
145; CHECK:   callq getSecondParam
146; CHECK:   movd [[TEMP]], [[PARAM1:%[a-z0-9]+]]
147; CHECK:   movd %rax, [[PARAM2:%[a-z0-9]+]]
148; CHECK:   psubsw [[PARAM2]], [[PARAM1]]
149; CHECK: ret
150
151define i64 @test_psubusbv() {
152entry:
153  %call = tail call { i64, double } @getFirstParam()
154  %0 = extractvalue { i64, double } %call, 0
155  %call2 = tail call { i64, double } @getSecondParam()
156  %1 = extractvalue { i64, double } %call2, 0
157  %__m1.0.insert.i = insertelement <1 x i64> undef, i64 %0, i32 0
158  %__m2.0.insert.i = insertelement <1 x i64> undef, i64 %1, i32 0
159  %2 = bitcast <1 x i64> %__m1.0.insert.i to <8 x i8>
160  %3 = bitcast <8 x i8> %2 to x86_mmx
161  %4 = bitcast <1 x i64> %__m2.0.insert.i to <8 x i8>
162  %5 = bitcast <8 x i8> %4 to x86_mmx
163  %6 = tail call x86_mmx @llvm.x86.mmx.psubus.b(x86_mmx %3, x86_mmx %5) nounwind
164  %7 = bitcast x86_mmx %6 to <8 x i8>
165  %8 = bitcast <8 x i8> %7 to <1 x i64>
166  %retval.0.extract.i15 = extractelement <1 x i64> %8, i32 0
167  ret i64 %retval.0.extract.i15
168}
169
170; CHECK-LABEL: test_psubusbv:
171; CHECK:   callq getFirstParam
172; CHECK:   movq %rax, [[TEMP:%[a-z0-9]+]]
173; CHECK:   callq getSecondParam
174; CHECK:   movd [[TEMP]], [[PARAM1:%[a-z0-9]+]]
175; CHECK:   movd %rax, [[PARAM2:%[a-z0-9]+]]
176; CHECK:   psubusb [[PARAM2]], [[PARAM1]]
177; CHECK: ret
178
179define i64 @test_psubuswv() {
180entry:
181  %call = tail call { i64, double } @getFirstParam()
182  %0 = extractvalue { i64, double } %call, 0
183  %call2 = tail call { i64, double } @getSecondParam()
184  %1 = extractvalue { i64, double } %call2, 0
185  %__m1.0.insert.i = insertelement <1 x i64> undef, i64 %0, i32 0
186  %__m2.0.insert.i = insertelement <1 x i64> undef, i64 %1, i32 0
187  %2 = bitcast <1 x i64> %__m1.0.insert.i to <4 x i16>
188  %3 = bitcast <4 x i16> %2 to x86_mmx
189  %4 = bitcast <1 x i64> %__m2.0.insert.i to <4 x i16>
190  %5 = bitcast <4 x i16> %4 to x86_mmx
191  %6 = tail call x86_mmx @llvm.x86.mmx.psubus.w(x86_mmx %3, x86_mmx %5) nounwind
192  %7 = bitcast x86_mmx %6 to <4 x i16>
193  %8 = bitcast <4 x i16> %7 to <1 x i64>
194  %retval.0.extract.i15 = extractelement <1 x i64> %8, i32 0
195  ret i64 %retval.0.extract.i15
196}
197
198; CHECK-LABEL: test_psubuswv:
199; CHECK:   callq getFirstParam
200; CHECK:   movq %rax, [[TEMP:%[a-z0-9]+]]
201; CHECK:   callq getSecondParam
202; CHECK:   movd [[TEMP]], [[PARAM1:%[a-z0-9]+]]
203; CHECK:   movd %rax, [[PARAM2:%[a-z0-9]+]]
204; CHECK:   psubusw [[PARAM2]], [[PARAM1]]
205; CHECK: ret
206
207
208declare x86_mmx @llvm.x86.mmx.psubus.w(x86_mmx, x86_mmx) nounwind readnone
209
210declare x86_mmx @llvm.x86.mmx.psubus.b(x86_mmx, x86_mmx) nounwind readnone
211
212declare x86_mmx @llvm.x86.mmx.psubs.w(x86_mmx, x86_mmx) nounwind readnone
213
214declare x86_mmx @llvm.x86.mmx.psubs.b(x86_mmx, x86_mmx) nounwind readnone
215
216declare x86_mmx @llvm.x86.mmx.psub.d(x86_mmx, x86_mmx) nounwind readnone
217
218declare x86_mmx @llvm.x86.mmx.psub.w(x86_mmx, x86_mmx) nounwind readnone
219
220declare x86_mmx @llvm.x86.mmx.psub.b(x86_mmx, x86_mmx) nounwind readnone
221