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