1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=thumbv7m -mattr=+dsp %s -o - | FileCheck %s --check-prefix=DSP
3; RUN: llc -mtriple=armv7a %s -o - | FileCheck %s --check-prefix=ARM7
4; RUN: llc -mtriple=thumbv7m -mattr=-dsp %s -o - | FileCheck %s --check-prefix=NODSP
5
6define hidden i32 @SMMULR_SMMLAR(i32 %a, i32 %b0, i32 %b1, i32 %Xn, i32 %Xn1) local_unnamed_addr {
7; DSP-LABEL: SMMULR_SMMLAR:
8; DSP:       @ %bb.0: @ %entry
9; DSP-NEXT:    ldr r0, [sp]
10; DSP-NEXT:    smmulr r0, r0, r2
11; DSP-NEXT:    smmlar r0, r3, r1, r0
12; DSP-NEXT:    bx lr
13;
14; ARM7-LABEL: SMMULR_SMMLAR:
15; ARM7:       @ %bb.0: @ %entry
16; ARM7-NEXT:    ldr r0, [sp]
17; ARM7-NEXT:    smmulr r0, r0, r2
18; ARM7-NEXT:    smmlar r0, r3, r1, r0
19; ARM7-NEXT:    bx lr
20;
21; NODSP-LABEL: SMMULR_SMMLAR:
22; NODSP:       @ %bb.0: @ %entry
23; NODSP-NEXT:    push {r4, lr}
24; NODSP-NEXT:    ldr.w lr, [sp, #8]
25; NODSP-NEXT:    movs r0, #0
26; NODSP-NEXT:    mov.w r4, #-2147483648
27; NODSP-NEXT:    mov.w r12, #-2147483648
28; NODSP-NEXT:    smlal r4, r0, lr, r2
29; NODSP-NEXT:    smlal r12, r0, r3, r1
30; NODSP-NEXT:    pop {r4, pc}
31entry:
32  %conv = sext i32 %b1 to i64
33  %conv1 = sext i32 %Xn1 to i64
34  %mul = mul nsw i64 %conv1, %conv
35  %add = add nsw i64 %mul, 2147483648
36  %0 = and i64 %add, -4294967296
37  %conv4 = sext i32 %b0 to i64
38  %conv5 = sext i32 %Xn to i64
39  %mul6 = mul nsw i64 %conv5, %conv4
40  %add7 = add i64 %mul6, 2147483648
41  %add8 = add i64 %add7, %0
42  %1 = lshr i64 %add8, 32
43  %conv10 = trunc i64 %1 to i32
44  ret i32 %conv10
45}
46
47define hidden i32 @SMMULR(i32 %a, i32 %b) local_unnamed_addr {
48; DSP-LABEL: SMMULR:
49; DSP:       @ %bb.0: @ %entry
50; DSP-NEXT:    smmulr r0, r1, r0
51; DSP-NEXT:    bx lr
52;
53; ARM7-LABEL: SMMULR:
54; ARM7:       @ %bb.0: @ %entry
55; ARM7-NEXT:    smmulr r0, r1, r0
56; ARM7-NEXT:    bx lr
57;
58; NODSP-LABEL: SMMULR:
59; NODSP:       @ %bb.0: @ %entry
60; NODSP-NEXT:    movs r2, #0
61; NODSP-NEXT:    mov.w r3, #-2147483648
62; NODSP-NEXT:    smlal r3, r2, r1, r0
63; NODSP-NEXT:    mov r0, r2
64; NODSP-NEXT:    bx lr
65entry:
66  %conv = sext i32 %a to i64
67  %conv1 = sext i32 %b to i64
68  %mul = mul nsw i64 %conv1, %conv
69  %add = add nsw i64 %mul, 2147483648
70  %0 = lshr i64 %add, 32
71  %conv2 = trunc i64 %0 to i32
72  ret i32 %conv2
73}
74
75define hidden i32 @SMMUL(i32 %a, i32 %b) local_unnamed_addr {
76; DSP-LABEL: SMMUL:
77; DSP:       @ %bb.0: @ %entry
78; DSP-NEXT:    smmul r0, r1, r0
79; DSP-NEXT:    bx lr
80;
81; ARM7-LABEL: SMMUL:
82; ARM7:       @ %bb.0: @ %entry
83; ARM7-NEXT:    smmul r0, r1, r0
84; ARM7-NEXT:    bx lr
85;
86; NODSP-LABEL: SMMUL:
87; NODSP:       @ %bb.0: @ %entry
88; NODSP-NEXT:    smull r1, r0, r1, r0
89; NODSP-NEXT:    bx lr
90entry:
91  %conv = sext i32 %a to i64
92  %conv1 = sext i32 %b to i64
93  %mul = mul nsw i64 %conv1, %conv
94  %0 = lshr i64 %mul, 32
95  %conv2 = trunc i64 %0 to i32
96  ret i32 %conv2
97}
98
99define hidden i32 @SMMLSR(i32 %a, i32 %b, i32 %c) local_unnamed_addr {
100; DSP-LABEL: SMMLSR:
101; DSP:       @ %bb.0: @ %entry
102; DSP-NEXT:    smmlsr r0, r2, r1, r0
103; DSP-NEXT:    bx lr
104;
105; ARM7-LABEL: SMMLSR:
106; ARM7:       @ %bb.0: @ %entry
107; ARM7-NEXT:    smmlsr r0, r2, r1, r0
108; ARM7-NEXT:    bx lr
109;
110; NODSP-LABEL: SMMLSR:
111; NODSP:       @ %bb.0: @ %entry
112; NODSP-NEXT:    smull r1, r2, r2, r1
113; NODSP-NEXT:    rsbs.w r1, r1, #-2147483648
114; NODSP-NEXT:    sbcs r0, r2
115; NODSP-NEXT:    bx lr
116entry:
117  %conv6 = zext i32 %a to i64
118  %shl = shl nuw i64 %conv6, 32
119  %conv1 = sext i32 %b to i64
120  %conv2 = sext i32 %c to i64
121  %mul = mul nsw i64 %conv2, %conv1
122  %sub = or i64 %shl, 2147483648
123  %add = sub i64 %sub, %mul
124  %0 = lshr i64 %add, 32
125  %conv3 = trunc i64 %0 to i32
126  ret i32 %conv3
127}
128
129define hidden i32 @NOT_SMMLSR(i32 %a, i32 %b, i32 %c) local_unnamed_addr {
130; DSP-LABEL: NOT_SMMLSR:
131; DSP:       @ %bb.0: @ %entry
132; DSP-NEXT:    smmulr r1, r2, r1
133; DSP-NEXT:    subs r0, r0, r1
134; DSP-NEXT:    bx lr
135;
136; ARM7-LABEL: NOT_SMMLSR:
137; ARM7:       @ %bb.0: @ %entry
138; ARM7-NEXT:    smmulr r1, r2, r1
139; ARM7-NEXT:    sub r0, r0, r1
140; ARM7-NEXT:    bx lr
141;
142; NODSP-LABEL: NOT_SMMLSR:
143; NODSP:       @ %bb.0: @ %entry
144; NODSP-NEXT:    mov.w r12, #0
145; NODSP-NEXT:    mov.w r3, #-2147483648
146; NODSP-NEXT:    smlal r3, r12, r2, r1
147; NODSP-NEXT:    sub.w r0, r0, r12
148; NODSP-NEXT:    bx lr
149entry:
150  %conv = sext i32 %b to i64
151  %conv1 = sext i32 %c to i64
152  %mul = mul nsw i64 %conv1, %conv
153  %add = add nsw i64 %mul, 2147483648
154  %0 = lshr i64 %add, 32
155  %conv2 = trunc i64 %0 to i32
156  %sub = sub nsw i32 %a, %conv2
157  ret i32 %sub
158}
159
160define hidden i32 @SMMLS(i32 %a, i32 %b, i32 %c) local_unnamed_addr {
161; DSP-LABEL: SMMLS:
162; DSP:       @ %bb.0: @ %entry
163; DSP-NEXT:    smmls r0, r2, r1, r0
164; DSP-NEXT:    bx lr
165;
166; ARM7-LABEL: SMMLS:
167; ARM7:       @ %bb.0: @ %entry
168; ARM7-NEXT:    smmls r0, r2, r1, r0
169; ARM7-NEXT:    bx lr
170;
171; NODSP-LABEL: SMMLS:
172; NODSP:       @ %bb.0: @ %entry
173; NODSP-NEXT:    smull r1, r2, r2, r1
174; NODSP-NEXT:    rsbs r1, r1, #0
175; NODSP-NEXT:    sbcs r0, r2
176; NODSP-NEXT:    bx lr
177entry:
178  %conv5 = zext i32 %a to i64
179  %shl = shl nuw i64 %conv5, 32
180  %conv1 = sext i32 %b to i64
181  %conv2 = sext i32 %c to i64
182  %mul = mul nsw i64 %conv2, %conv1
183  %sub = sub nsw i64 %shl, %mul
184  %0 = lshr i64 %sub, 32
185  %conv3 = trunc i64 %0 to i32
186  ret i32 %conv3
187}
188
189define hidden i32 @NOT_SMMLS(i32 %a, i32 %b, i32 %c) local_unnamed_addr {
190; DSP-LABEL: NOT_SMMLS:
191; DSP:       @ %bb.0: @ %entry
192; DSP-NEXT:    smmul r1, r2, r1
193; DSP-NEXT:    subs r0, r0, r1
194; DSP-NEXT:    bx lr
195;
196; ARM7-LABEL: NOT_SMMLS:
197; ARM7:       @ %bb.0: @ %entry
198; ARM7-NEXT:    smmul r1, r2, r1
199; ARM7-NEXT:    sub r0, r0, r1
200; ARM7-NEXT:    bx lr
201;
202; NODSP-LABEL: NOT_SMMLS:
203; NODSP:       @ %bb.0: @ %entry
204; NODSP-NEXT:    smull r1, r2, r2, r1
205; NODSP-NEXT:    subs r0, r0, r2
206; NODSP-NEXT:    bx lr
207entry:
208  %conv = sext i32 %b to i64
209  %conv1 = sext i32 %c to i64
210  %mul = mul nsw i64 %conv1, %conv
211  %0 = lshr i64 %mul, 32
212  %conv2 = trunc i64 %0 to i32
213  %sub = sub nsw i32 %a, %conv2
214  ret i32 %sub
215}
216
217define hidden i32 @SMMLA(i32 %a, i32 %b, i32 %c) local_unnamed_addr {
218; DSP-LABEL: SMMLA:
219; DSP:       @ %bb.0: @ %entry
220; DSP-NEXT:    smmla r0, r1, r2, r0
221; DSP-NEXT:    bx lr
222;
223; ARM7-LABEL: SMMLA:
224; ARM7:       @ %bb.0: @ %entry
225; ARM7-NEXT:    smmla r0, r2, r1, r0
226; ARM7-NEXT:    bx lr
227;
228; NODSP-LABEL: SMMLA:
229; NODSP:       @ %bb.0: @ %entry
230; NODSP-NEXT:    smull r1, r2, r2, r1
231; NODSP-NEXT:    add r0, r2
232; NODSP-NEXT:    bx lr
233entry:
234  %conv = sext i32 %b to i64
235  %conv1 = sext i32 %c to i64
236  %mul = mul nsw i64 %conv1, %conv
237  %0 = lshr i64 %mul, 32
238  %conv2 = trunc i64 %0 to i32
239  %add = add nsw i32 %conv2, %a
240  ret i32 %add
241}
242
243define hidden i32 @SMMLAR(i32 %a, i32 %b, i32 %c) local_unnamed_addr {
244; DSP-LABEL: SMMLAR:
245; DSP:       @ %bb.0: @ %entry
246; DSP-NEXT:    smmlar r0, r2, r1, r0
247; DSP-NEXT:    bx lr
248;
249; ARM7-LABEL: SMMLAR:
250; ARM7:       @ %bb.0: @ %entry
251; ARM7-NEXT:    smmlar r0, r2, r1, r0
252; ARM7-NEXT:    bx lr
253;
254; NODSP-LABEL: SMMLAR:
255; NODSP:       @ %bb.0: @ %entry
256; NODSP-NEXT:    mov.w r3, #-2147483648
257; NODSP-NEXT:    smlal r3, r0, r2, r1
258; NODSP-NEXT:    bx lr
259entry:
260  %conv7 = zext i32 %a to i64
261  %shl = shl nuw i64 %conv7, 32
262  %conv1 = sext i32 %b to i64
263  %conv2 = sext i32 %c to i64
264  %mul = mul nsw i64 %conv2, %conv1
265  %add = or i64 %shl, 2147483648
266  %add3 = add i64 %add, %mul
267  %0 = lshr i64 %add3, 32
268  %conv4 = trunc i64 %0 to i32
269  ret i32 %conv4
270}
271
272define hidden i32 @NOT_SMMLA(i32 %a, i32 %b, i32 %c) local_unnamed_addr {
273; DSP-LABEL: NOT_SMMLA:
274; DSP:       @ %bb.0: @ %entry
275; DSP-NEXT:    smmul r1, r2, r1
276; DSP-NEXT:    eor r1, r1, #-2147483648
277; DSP-NEXT:    add r0, r1
278; DSP-NEXT:    bx lr
279;
280; ARM7-LABEL: NOT_SMMLA:
281; ARM7:       @ %bb.0: @ %entry
282; ARM7-NEXT:    smmul r1, r2, r1
283; ARM7-NEXT:    eor r1, r1, #-2147483648
284; ARM7-NEXT:    add r0, r1, r0
285; ARM7-NEXT:    bx lr
286;
287; NODSP-LABEL: NOT_SMMLA:
288; NODSP:       @ %bb.0: @ %entry
289; NODSP-NEXT:    smull r1, r2, r2, r1
290; NODSP-NEXT:    eor r1, r2, #-2147483648
291; NODSP-NEXT:    add r0, r1
292; NODSP-NEXT:    bx lr
293entry:
294  %conv = sext i32 %b to i64
295  %conv1 = sext i32 %c to i64
296  %mul = mul nsw i64 %conv1, %conv
297  %0 = lshr i64 %mul, 32
298  %conv2 = trunc i64 %0 to i32
299  %add = xor i32 %conv2, -2147483648
300  %add3 = add i32 %add, %a
301  ret i32 %add3
302}
303