xref: /llvm-project/llvm/test/CodeGen/ARM/ssub_sat_plus.ll (revision e0ed0333f0fed2e73f805afd58b61176a87aa3ad)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=thumbv6m-none-eabi | FileCheck %s --check-prefix=CHECK-T1
3; RUN: llc < %s -mtriple=thumbv7m-none-eabi | FileCheck %s --check-prefix=CHECK-T2 --check-prefix=CHECK-T2NODSP
4; RUN: llc < %s -mtriple=thumbv7em-none-eabi | FileCheck %s --check-prefix=CHECK-T2 --check-prefix=CHECK-T2DSP
5; RUN: llc < %s -mtriple=armv8a-none-eabi | FileCheck %s --check-prefix=CHECK-ARM
6
7declare i4 @llvm.ssub.sat.i4(i4, i4)
8declare i8 @llvm.ssub.sat.i8(i8, i8)
9declare i16 @llvm.ssub.sat.i16(i16, i16)
10declare i32 @llvm.ssub.sat.i32(i32, i32)
11declare i64 @llvm.ssub.sat.i64(i64, i64)
12
13define i32 @func32(i32 %x, i32 %y, i32 %z) nounwind {
14; CHECK-T1-LABEL: func32:
15; CHECK-T1:       @ %bb.0:
16; CHECK-T1-NEXT:    muls r1, r2, r1
17; CHECK-T1-NEXT:    subs r0, r0, r1
18; CHECK-T1-NEXT:    bvc .LBB0_2
19; CHECK-T1-NEXT:  @ %bb.1:
20; CHECK-T1-NEXT:    asrs r1, r0, #31
21; CHECK-T1-NEXT:    movs r0, #1
22; CHECK-T1-NEXT:    lsls r0, r0, #31
23; CHECK-T1-NEXT:    eors r0, r1
24; CHECK-T1-NEXT:  .LBB0_2:
25; CHECK-T1-NEXT:    bx lr
26;
27; CHECK-T2NODSP-LABEL: func32:
28; CHECK-T2NODSP:       @ %bb.0:
29; CHECK-T2NODSP-NEXT:    mls r3, r1, r2, r0
30; CHECK-T2NODSP-NEXT:    mov.w r12, #-2147483648
31; CHECK-T2NODSP-NEXT:    muls r1, r2, r1
32; CHECK-T2NODSP-NEXT:    cmp r0, r1
33; CHECK-T2NODSP-NEXT:    it vs
34; CHECK-T2NODSP-NEXT:    eorvs.w r3, r12, r3, asr #31
35; CHECK-T2NODSP-NEXT:    mov r0, r3
36; CHECK-T2NODSP-NEXT:    bx lr
37;
38; CHECK-T2DSP-LABEL: func32:
39; CHECK-T2DSP:       @ %bb.0:
40; CHECK-T2DSP-NEXT:    muls r1, r2, r1
41; CHECK-T2DSP-NEXT:    qsub r0, r0, r1
42; CHECK-T2DSP-NEXT:    bx lr
43;
44; CHECK-ARM-LABEL: func32:
45; CHECK-ARM:       @ %bb.0:
46; CHECK-ARM-NEXT:    mul r1, r1, r2
47; CHECK-ARM-NEXT:    qsub r0, r0, r1
48; CHECK-ARM-NEXT:    bx lr
49  %a = mul i32 %y, %z
50  %tmp = call i32 @llvm.ssub.sat.i32(i32 %x, i32 %a)
51  ret i32 %tmp
52}
53
54define i64 @func64(i64 %x, i64 %y, i64 %z) nounwind {
55; CHECK-T1-LABEL: func64:
56; CHECK-T1:       @ %bb.0:
57; CHECK-T1-NEXT:    .save {r4, r5, r7, lr}
58; CHECK-T1-NEXT:    push {r4, r5, r7, lr}
59; CHECK-T1-NEXT:    ldr r2, [sp, #20]
60; CHECK-T1-NEXT:    mov r5, r1
61; CHECK-T1-NEXT:    eors r5, r2
62; CHECK-T1-NEXT:    ldr r3, [sp, #16]
63; CHECK-T1-NEXT:    subs r4, r0, r3
64; CHECK-T1-NEXT:    mov r3, r1
65; CHECK-T1-NEXT:    sbcs r3, r2
66; CHECK-T1-NEXT:    eors r1, r3
67; CHECK-T1-NEXT:    ands r1, r5
68; CHECK-T1-NEXT:    asrs r0, r3, #31
69; CHECK-T1-NEXT:    movs r2, #1
70; CHECK-T1-NEXT:    lsls r2, r2, #31
71; CHECK-T1-NEXT:    eors r2, r0
72; CHECK-T1-NEXT:    cmp r1, #0
73; CHECK-T1-NEXT:    bpl .LBB1_3
74; CHECK-T1-NEXT:  @ %bb.1:
75; CHECK-T1-NEXT:    bpl .LBB1_4
76; CHECK-T1-NEXT:  .LBB1_2:
77; CHECK-T1-NEXT:    mov r1, r2
78; CHECK-T1-NEXT:    pop {r4, r5, r7, pc}
79; CHECK-T1-NEXT:  .LBB1_3:
80; CHECK-T1-NEXT:    mov r0, r4
81; CHECK-T1-NEXT:    bmi .LBB1_2
82; CHECK-T1-NEXT:  .LBB1_4:
83; CHECK-T1-NEXT:    mov r2, r3
84; CHECK-T1-NEXT:    mov r1, r2
85; CHECK-T1-NEXT:    pop {r4, r5, r7, pc}
86;
87; CHECK-T2-LABEL: func64:
88; CHECK-T2:       @ %bb.0:
89; CHECK-T2-NEXT:    ldr r2, [sp]
90; CHECK-T2-NEXT:    ldr.w r12, [sp, #4]
91; CHECK-T2-NEXT:    subs r0, r0, r2
92; CHECK-T2-NEXT:    sbc.w r2, r1, r12
93; CHECK-T2-NEXT:    eor.w r3, r1, r12
94; CHECK-T2-NEXT:    eors r1, r2
95; CHECK-T2-NEXT:    ands r1, r3
96; CHECK-T2-NEXT:    it mi
97; CHECK-T2-NEXT:    asrmi r0, r2, #31
98; CHECK-T2-NEXT:    mov.w r1, #-2147483648
99; CHECK-T2-NEXT:    it mi
100; CHECK-T2-NEXT:    eormi.w r2, r1, r2, asr #31
101; CHECK-T2-NEXT:    mov r1, r2
102; CHECK-T2-NEXT:    bx lr
103;
104; CHECK-ARM-LABEL: func64:
105; CHECK-ARM:       @ %bb.0:
106; CHECK-ARM-NEXT:    ldr r12, [sp]
107; CHECK-ARM-NEXT:    ldr r2, [sp, #4]
108; CHECK-ARM-NEXT:    subs r0, r0, r12
109; CHECK-ARM-NEXT:    eor r3, r1, r2
110; CHECK-ARM-NEXT:    sbc r2, r1, r2
111; CHECK-ARM-NEXT:    eor r1, r1, r2
112; CHECK-ARM-NEXT:    ands r1, r3, r1
113; CHECK-ARM-NEXT:    asrmi r0, r2, #31
114; CHECK-ARM-NEXT:    mov r1, #-2147483648
115; CHECK-ARM-NEXT:    eormi r2, r1, r2, asr #31
116; CHECK-ARM-NEXT:    mov r1, r2
117; CHECK-ARM-NEXT:    bx lr
118  %a = mul i64 %y, %z
119  %tmp = call i64 @llvm.ssub.sat.i64(i64 %x, i64 %z)
120  ret i64 %tmp
121}
122
123define signext i16 @func16(i16 signext %x, i16 signext %y, i16 signext %z) nounwind {
124; CHECK-T1-LABEL: func16:
125; CHECK-T1:       @ %bb.0:
126; CHECK-T1-NEXT:    muls r1, r2, r1
127; CHECK-T1-NEXT:    sxth r1, r1
128; CHECK-T1-NEXT:    subs r0, r0, r1
129; CHECK-T1-NEXT:    ldr r1, .LCPI2_0
130; CHECK-T1-NEXT:    cmp r0, r1
131; CHECK-T1-NEXT:    blt .LBB2_2
132; CHECK-T1-NEXT:  @ %bb.1:
133; CHECK-T1-NEXT:    mov r0, r1
134; CHECK-T1-NEXT:  .LBB2_2:
135; CHECK-T1-NEXT:    ldr r1, .LCPI2_1
136; CHECK-T1-NEXT:    cmp r0, r1
137; CHECK-T1-NEXT:    bgt .LBB2_4
138; CHECK-T1-NEXT:  @ %bb.3:
139; CHECK-T1-NEXT:    mov r0, r1
140; CHECK-T1-NEXT:  .LBB2_4:
141; CHECK-T1-NEXT:    bx lr
142; CHECK-T1-NEXT:    .p2align 2
143; CHECK-T1-NEXT:  @ %bb.5:
144; CHECK-T1-NEXT:  .LCPI2_0:
145; CHECK-T1-NEXT:    .long 32767 @ 0x7fff
146; CHECK-T1-NEXT:  .LCPI2_1:
147; CHECK-T1-NEXT:    .long 4294934528 @ 0xffff8000
148;
149; CHECK-T2NODSP-LABEL: func16:
150; CHECK-T2NODSP:       @ %bb.0:
151; CHECK-T2NODSP-NEXT:    muls r1, r2, r1
152; CHECK-T2NODSP-NEXT:    sxth r1, r1
153; CHECK-T2NODSP-NEXT:    subs r0, r0, r1
154; CHECK-T2NODSP-NEXT:    ssat r0, #16, r0
155; CHECK-T2NODSP-NEXT:    bx lr
156;
157; CHECK-T2DSP-LABEL: func16:
158; CHECK-T2DSP:       @ %bb.0:
159; CHECK-T2DSP-NEXT:    muls r1, r2, r1
160; CHECK-T2DSP-NEXT:    qsub16 r0, r0, r1
161; CHECK-T2DSP-NEXT:    sxth r0, r0
162; CHECK-T2DSP-NEXT:    bx lr
163;
164; CHECK-ARM-LABEL: func16:
165; CHECK-ARM:       @ %bb.0:
166; CHECK-ARM-NEXT:    smulbb r1, r1, r2
167; CHECK-ARM-NEXT:    qsub16 r0, r0, r1
168; CHECK-ARM-NEXT:    sxth r0, r0
169; CHECK-ARM-NEXT:    bx lr
170  %a = mul i16 %y, %z
171  %tmp = call i16 @llvm.ssub.sat.i16(i16 %x, i16 %a)
172  ret i16 %tmp
173}
174
175define signext i8 @func8(i8 signext %x, i8 signext %y, i8 signext %z) nounwind {
176; CHECK-T1-LABEL: func8:
177; CHECK-T1:       @ %bb.0:
178; CHECK-T1-NEXT:    muls r1, r2, r1
179; CHECK-T1-NEXT:    sxtb r1, r1
180; CHECK-T1-NEXT:    subs r0, r0, r1
181; CHECK-T1-NEXT:    movs r1, #127
182; CHECK-T1-NEXT:    cmp r0, #127
183; CHECK-T1-NEXT:    blt .LBB3_2
184; CHECK-T1-NEXT:  @ %bb.1:
185; CHECK-T1-NEXT:    mov r0, r1
186; CHECK-T1-NEXT:  .LBB3_2:
187; CHECK-T1-NEXT:    mvns r1, r1
188; CHECK-T1-NEXT:    cmp r0, r1
189; CHECK-T1-NEXT:    bgt .LBB3_4
190; CHECK-T1-NEXT:  @ %bb.3:
191; CHECK-T1-NEXT:    mov r0, r1
192; CHECK-T1-NEXT:  .LBB3_4:
193; CHECK-T1-NEXT:    bx lr
194;
195; CHECK-T2NODSP-LABEL: func8:
196; CHECK-T2NODSP:       @ %bb.0:
197; CHECK-T2NODSP-NEXT:    muls r1, r2, r1
198; CHECK-T2NODSP-NEXT:    sxtb r1, r1
199; CHECK-T2NODSP-NEXT:    subs r0, r0, r1
200; CHECK-T2NODSP-NEXT:    ssat r0, #8, r0
201; CHECK-T2NODSP-NEXT:    bx lr
202;
203; CHECK-T2DSP-LABEL: func8:
204; CHECK-T2DSP:       @ %bb.0:
205; CHECK-T2DSP-NEXT:    muls r1, r2, r1
206; CHECK-T2DSP-NEXT:    qsub8 r0, r0, r1
207; CHECK-T2DSP-NEXT:    sxtb r0, r0
208; CHECK-T2DSP-NEXT:    bx lr
209;
210; CHECK-ARM-LABEL: func8:
211; CHECK-ARM:       @ %bb.0:
212; CHECK-ARM-NEXT:    smulbb r1, r1, r2
213; CHECK-ARM-NEXT:    qsub8 r0, r0, r1
214; CHECK-ARM-NEXT:    sxtb r0, r0
215; CHECK-ARM-NEXT:    bx lr
216  %a = mul i8 %y, %z
217  %tmp = call i8 @llvm.ssub.sat.i8(i8 %x, i8 %a)
218  ret i8 %tmp
219}
220
221define signext i4 @func4(i4 signext %x, i4 signext %y, i4 signext %z) nounwind {
222; CHECK-T1-LABEL: func4:
223; CHECK-T1:       @ %bb.0:
224; CHECK-T1-NEXT:    muls r1, r2, r1
225; CHECK-T1-NEXT:    lsls r1, r1, #28
226; CHECK-T1-NEXT:    asrs r1, r1, #28
227; CHECK-T1-NEXT:    subs r0, r0, r1
228; CHECK-T1-NEXT:    movs r1, #7
229; CHECK-T1-NEXT:    cmp r0, #7
230; CHECK-T1-NEXT:    blt .LBB4_2
231; CHECK-T1-NEXT:  @ %bb.1:
232; CHECK-T1-NEXT:    mov r0, r1
233; CHECK-T1-NEXT:  .LBB4_2:
234; CHECK-T1-NEXT:    mvns r1, r1
235; CHECK-T1-NEXT:    cmp r0, r1
236; CHECK-T1-NEXT:    bgt .LBB4_4
237; CHECK-T1-NEXT:  @ %bb.3:
238; CHECK-T1-NEXT:    mov r0, r1
239; CHECK-T1-NEXT:  .LBB4_4:
240; CHECK-T1-NEXT:    bx lr
241;
242; CHECK-T2NODSP-LABEL: func4:
243; CHECK-T2NODSP:       @ %bb.0:
244; CHECK-T2NODSP-NEXT:    muls r1, r2, r1
245; CHECK-T2NODSP-NEXT:    lsls r1, r1, #28
246; CHECK-T2NODSP-NEXT:    sub.w r0, r0, r1, asr #28
247; CHECK-T2NODSP-NEXT:    ssat r0, #4, r0
248; CHECK-T2NODSP-NEXT:    bx lr
249;
250; CHECK-T2DSP-LABEL: func4:
251; CHECK-T2DSP:       @ %bb.0:
252; CHECK-T2DSP-NEXT:    muls r1, r2, r1
253; CHECK-T2DSP-NEXT:    lsls r0, r0, #28
254; CHECK-T2DSP-NEXT:    lsls r1, r1, #28
255; CHECK-T2DSP-NEXT:    qsub r0, r0, r1
256; CHECK-T2DSP-NEXT:    asrs r0, r0, #28
257; CHECK-T2DSP-NEXT:    bx lr
258;
259; CHECK-ARM-LABEL: func4:
260; CHECK-ARM:       @ %bb.0:
261; CHECK-ARM-NEXT:    smulbb r1, r1, r2
262; CHECK-ARM-NEXT:    lsl r0, r0, #28
263; CHECK-ARM-NEXT:    lsl r1, r1, #28
264; CHECK-ARM-NEXT:    qsub r0, r0, r1
265; CHECK-ARM-NEXT:    asr r0, r0, #28
266; CHECK-ARM-NEXT:    bx lr
267  %a = mul i4 %y, %z
268  %tmp = call i4 @llvm.ssub.sat.i4(i4 %x, i4 %a)
269  ret i4 %tmp
270}
271