1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc < %s -mtriple=thumbv7m-none-eabi | FileCheck %s --check-prefix=CHECK-T2 --check-prefix=CHECK-T2NODSP
3; RUN: llc < %s -mtriple=thumbv7em-none-eabi | FileCheck %s --check-prefix=CHECK-T2 --check-prefix=CHECK-T2DSP
4; RUN: llc < %s -mtriple=armv5te-none-none-eabi | FileCheck %s --check-prefix=CHECK-ARM --check-prefix=CHECK-ARM6
5; RUN: llc < %s -mtriple=armv8a-none-eabi | FileCheck %s --check-prefix=CHECK-ARM --check-prefix=CHECK-ARM8
6
7define i32 @qdadd(i32 %x, i32 %y) nounwind {
8; CHECK-T2NODSP-LABEL: qdadd:
9; CHECK-T2NODSP:       @ %bb.0:
10; CHECK-T2NODSP-NEXT:    .save {r7, lr}
11; CHECK-T2NODSP-NEXT:    push {r7, lr}
12; CHECK-T2NODSP-NEXT:    movs r3, #0
13; CHECK-T2NODSP-NEXT:    adds.w r12, r0, r0
14; CHECK-T2NODSP-NEXT:    it mi
15; CHECK-T2NODSP-NEXT:    movmi r3, #1
16; CHECK-T2NODSP-NEXT:    cmp r3, #0
17; CHECK-T2NODSP-NEXT:    mov.w r3, #-2147483648
18; CHECK-T2NODSP-NEXT:    mov.w lr, #0
19; CHECK-T2NODSP-NEXT:    it ne
20; CHECK-T2NODSP-NEXT:    mvnne r3, #-2147483648
21; CHECK-T2NODSP-NEXT:    cmp r12, r0
22; CHECK-T2NODSP-NEXT:    it vc
23; CHECK-T2NODSP-NEXT:    movvc r3, r12
24; CHECK-T2NODSP-NEXT:    adds r0, r3, r1
25; CHECK-T2NODSP-NEXT:    mov.w r2, #-2147483648
26; CHECK-T2NODSP-NEXT:    it mi
27; CHECK-T2NODSP-NEXT:    movmi.w lr, #1
28; CHECK-T2NODSP-NEXT:    cmp.w lr, #0
29; CHECK-T2NODSP-NEXT:    it ne
30; CHECK-T2NODSP-NEXT:    mvnne r2, #-2147483648
31; CHECK-T2NODSP-NEXT:    cmp r0, r3
32; CHECK-T2NODSP-NEXT:    it vc
33; CHECK-T2NODSP-NEXT:    movvc r2, r0
34; CHECK-T2NODSP-NEXT:    mov r0, r2
35; CHECK-T2NODSP-NEXT:    pop {r7, pc}
36;
37; CHECK-T2DSP-LABEL: qdadd:
38; CHECK-T2DSP:       @ %bb.0:
39; CHECK-T2DSP-NEXT:    qdadd r0, r1, r0
40; CHECK-T2DSP-NEXT:    bx lr
41;
42; CHECK-ARM-LABEL: qdadd:
43; CHECK-ARM:       @ %bb.0:
44; CHECK-ARM-NEXT:    qdadd r0, r1, r0
45; CHECK-ARM-NEXT:    bx lr
46  %z = call i32 @llvm.sadd.sat.i32(i32 %x, i32 %x)
47  %tmp = call i32 @llvm.sadd.sat.i32(i32 %z, i32 %y)
48  ret i32 %tmp
49}
50
51define i32 @qdadd_c(i32 %x, i32 %y) nounwind {
52; CHECK-T2NODSP-LABEL: qdadd_c:
53; CHECK-T2NODSP:       @ %bb.0:
54; CHECK-T2NODSP-NEXT:    .save {r7, lr}
55; CHECK-T2NODSP-NEXT:    push {r7, lr}
56; CHECK-T2NODSP-NEXT:    movs r3, #0
57; CHECK-T2NODSP-NEXT:    adds.w r12, r0, r0
58; CHECK-T2NODSP-NEXT:    it mi
59; CHECK-T2NODSP-NEXT:    movmi r3, #1
60; CHECK-T2NODSP-NEXT:    cmp r3, #0
61; CHECK-T2NODSP-NEXT:    mov.w r3, #-2147483648
62; CHECK-T2NODSP-NEXT:    mov.w lr, #0
63; CHECK-T2NODSP-NEXT:    it ne
64; CHECK-T2NODSP-NEXT:    mvnne r3, #-2147483648
65; CHECK-T2NODSP-NEXT:    cmp r12, r0
66; CHECK-T2NODSP-NEXT:    it vc
67; CHECK-T2NODSP-NEXT:    movvc r3, r12
68; CHECK-T2NODSP-NEXT:    adds r0, r1, r3
69; CHECK-T2NODSP-NEXT:    mov.w r2, #-2147483648
70; CHECK-T2NODSP-NEXT:    it mi
71; CHECK-T2NODSP-NEXT:    movmi.w lr, #1
72; CHECK-T2NODSP-NEXT:    cmp.w lr, #0
73; CHECK-T2NODSP-NEXT:    it ne
74; CHECK-T2NODSP-NEXT:    mvnne r2, #-2147483648
75; CHECK-T2NODSP-NEXT:    cmp r0, r1
76; CHECK-T2NODSP-NEXT:    it vc
77; CHECK-T2NODSP-NEXT:    movvc r2, r0
78; CHECK-T2NODSP-NEXT:    mov r0, r2
79; CHECK-T2NODSP-NEXT:    pop {r7, pc}
80;
81; CHECK-T2DSP-LABEL: qdadd_c:
82; CHECK-T2DSP:       @ %bb.0:
83; CHECK-T2DSP-NEXT:    qdadd r0, r1, r0
84; CHECK-T2DSP-NEXT:    bx lr
85;
86; CHECK-ARM-LABEL: qdadd_c:
87; CHECK-ARM:       @ %bb.0:
88; CHECK-ARM-NEXT:    qdadd r0, r1, r0
89; CHECK-ARM-NEXT:    bx lr
90  %z = call i32 @llvm.sadd.sat.i32(i32 %x, i32 %x)
91  %tmp = call i32 @llvm.sadd.sat.i32(i32 %y, i32 %z)
92  ret i32 %tmp
93}
94
95define i32 @qdsub(i32 %x, i32 %y) nounwind {
96; CHECK-T2NODSP-LABEL: qdsub:
97; CHECK-T2NODSP:       @ %bb.0:
98; CHECK-T2NODSP-NEXT:    .save {r7, lr}
99; CHECK-T2NODSP-NEXT:    push {r7, lr}
100; CHECK-T2NODSP-NEXT:    movs r3, #0
101; CHECK-T2NODSP-NEXT:    adds.w r12, r0, r0
102; CHECK-T2NODSP-NEXT:    it mi
103; CHECK-T2NODSP-NEXT:    movmi r3, #1
104; CHECK-T2NODSP-NEXT:    cmp r3, #0
105; CHECK-T2NODSP-NEXT:    mov.w r3, #-2147483648
106; CHECK-T2NODSP-NEXT:    mov.w lr, #0
107; CHECK-T2NODSP-NEXT:    it ne
108; CHECK-T2NODSP-NEXT:    mvnne r3, #-2147483648
109; CHECK-T2NODSP-NEXT:    cmp r12, r0
110; CHECK-T2NODSP-NEXT:    it vc
111; CHECK-T2NODSP-NEXT:    movvc r3, r12
112; CHECK-T2NODSP-NEXT:    subs r0, r1, r3
113; CHECK-T2NODSP-NEXT:    mov.w r2, #-2147483648
114; CHECK-T2NODSP-NEXT:    it mi
115; CHECK-T2NODSP-NEXT:    movmi.w lr, #1
116; CHECK-T2NODSP-NEXT:    cmp.w lr, #0
117; CHECK-T2NODSP-NEXT:    it ne
118; CHECK-T2NODSP-NEXT:    mvnne r2, #-2147483648
119; CHECK-T2NODSP-NEXT:    cmp r1, r3
120; CHECK-T2NODSP-NEXT:    it vc
121; CHECK-T2NODSP-NEXT:    movvc r2, r0
122; CHECK-T2NODSP-NEXT:    mov r0, r2
123; CHECK-T2NODSP-NEXT:    pop {r7, pc}
124;
125; CHECK-T2DSP-LABEL: qdsub:
126; CHECK-T2DSP:       @ %bb.0:
127; CHECK-T2DSP-NEXT:    qdsub r0, r1, r0
128; CHECK-T2DSP-NEXT:    bx lr
129;
130; CHECK-ARM-LABEL: qdsub:
131; CHECK-ARM:       @ %bb.0:
132; CHECK-ARM-NEXT:    qdsub r0, r1, r0
133; CHECK-ARM-NEXT:    bx lr
134  %z = call i32 @llvm.sadd.sat.i32(i32 %x, i32 %x)
135  %tmp = call i32 @llvm.ssub.sat.i32(i32 %y, i32 %z)
136  ret i32 %tmp
137}
138
139define i32 @qdsub_c(i32 %x, i32 %y) nounwind {
140; CHECK-T2NODSP-LABEL: qdsub_c:
141; CHECK-T2NODSP:       @ %bb.0:
142; CHECK-T2NODSP-NEXT:    .save {r7, lr}
143; CHECK-T2NODSP-NEXT:    push {r7, lr}
144; CHECK-T2NODSP-NEXT:    movs r3, #0
145; CHECK-T2NODSP-NEXT:    adds.w r12, r0, r0
146; CHECK-T2NODSP-NEXT:    it mi
147; CHECK-T2NODSP-NEXT:    movmi r3, #1
148; CHECK-T2NODSP-NEXT:    cmp r3, #0
149; CHECK-T2NODSP-NEXT:    mov.w r3, #-2147483648
150; CHECK-T2NODSP-NEXT:    mov.w lr, #0
151; CHECK-T2NODSP-NEXT:    it ne
152; CHECK-T2NODSP-NEXT:    mvnne r3, #-2147483648
153; CHECK-T2NODSP-NEXT:    cmp r12, r0
154; CHECK-T2NODSP-NEXT:    it vc
155; CHECK-T2NODSP-NEXT:    movvc r3, r12
156; CHECK-T2NODSP-NEXT:    subs r0, r3, r1
157; CHECK-T2NODSP-NEXT:    mov.w r2, #-2147483648
158; CHECK-T2NODSP-NEXT:    it mi
159; CHECK-T2NODSP-NEXT:    movmi.w lr, #1
160; CHECK-T2NODSP-NEXT:    cmp.w lr, #0
161; CHECK-T2NODSP-NEXT:    it ne
162; CHECK-T2NODSP-NEXT:    mvnne r2, #-2147483648
163; CHECK-T2NODSP-NEXT:    cmp r3, r1
164; CHECK-T2NODSP-NEXT:    it vc
165; CHECK-T2NODSP-NEXT:    movvc r2, r0
166; CHECK-T2NODSP-NEXT:    mov r0, r2
167; CHECK-T2NODSP-NEXT:    pop {r7, pc}
168;
169; CHECK-T2DSP-LABEL: qdsub_c:
170; CHECK-T2DSP:       @ %bb.0:
171; CHECK-T2DSP-NEXT:    qadd r0, r0, r0
172; CHECK-T2DSP-NEXT:    qsub r0, r0, r1
173; CHECK-T2DSP-NEXT:    bx lr
174;
175; CHECK-ARM-LABEL: qdsub_c:
176; CHECK-ARM:       @ %bb.0:
177; CHECK-ARM-NEXT:    qadd r0, r0, r0
178; CHECK-ARM-NEXT:    qsub r0, r0, r1
179; CHECK-ARM-NEXT:    bx lr
180  %z = call i32 @llvm.sadd.sat.i32(i32 %x, i32 %x)
181  %tmp = call i32 @llvm.ssub.sat.i32(i32 %z, i32 %y)
182  ret i32 %tmp
183}
184
185declare i32 @llvm.sadd.sat.i32(i32, i32)
186declare i32 @llvm.ssub.sat.i32(i32, i32)
187