1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -global-isel -march=amdgcn -mcpu=gfx700 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX7 %s
3; RUN: llc -global-isel -march=amdgcn -mcpu=gfx801 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX8 %s
4; RUN: llc -global-isel -march=amdgcn -mcpu=gfx900 -verify-machineinstrs < %s | FileCheck -check-prefixes=GFX9 %s
5
6define i32 @v_usubo_i32(i32 %a, i32 %b) {
7; GFX7-LABEL: v_usubo_i32:
8; GFX7:       ; %bb.0:
9; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
10; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
11; GFX7-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
12; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
13; GFX7-NEXT:    s_setpc_b64 s[30:31]
14;
15; GFX8-LABEL: v_usubo_i32:
16; GFX8:       ; %bb.0:
17; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
18; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, v0, v1
19; GFX8-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
20; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, v0, v1
21; GFX8-NEXT:    s_setpc_b64 s[30:31]
22;
23; GFX9-LABEL: v_usubo_i32:
24; GFX9:       ; %bb.0:
25; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
26; GFX9-NEXT:    v_sub_co_u32_e32 v0, vcc, v0, v1
27; GFX9-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
28; GFX9-NEXT:    v_sub_u32_e32 v0, v0, v1
29; GFX9-NEXT:    s_setpc_b64 s[30:31]
30  %usubo = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %a, i32 %b)
31  %sub = extractvalue {i32, i1} %usubo, 0
32  %of = extractvalue {i32, i1} %usubo, 1
33  %of.zext = zext i1 %of to i32
34  %ret = sub i32 %sub, %of.zext
35  ret i32 %ret
36}
37
38define i64 @v_usubo_i64(i64 %a, i64 %b) {
39; GFX7-LABEL: v_usubo_i64:
40; GFX7:       ; %bb.0:
41; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
42; GFX7-NEXT:    v_sub_i32_e32 v4, vcc, v0, v2
43; GFX7-NEXT:    v_subb_u32_e32 v5, vcc, v1, v3, vcc
44; GFX7-NEXT:    v_cmp_lt_u64_e32 vcc, v[0:1], v[2:3]
45; GFX7-NEXT:    v_cndmask_b32_e64 v0, 0, 1, vcc
46; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v4, v0
47; GFX7-NEXT:    v_subbrev_u32_e32 v1, vcc, 0, v5, vcc
48; GFX7-NEXT:    s_setpc_b64 s[30:31]
49;
50; GFX8-LABEL: v_usubo_i64:
51; GFX8:       ; %bb.0:
52; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
53; GFX8-NEXT:    v_sub_u32_e32 v4, vcc, v0, v2
54; GFX8-NEXT:    v_subb_u32_e32 v5, vcc, v1, v3, vcc
55; GFX8-NEXT:    v_cmp_lt_u64_e32 vcc, v[0:1], v[2:3]
56; GFX8-NEXT:    v_cndmask_b32_e64 v0, 0, 1, vcc
57; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, v4, v0
58; GFX8-NEXT:    v_subbrev_u32_e32 v1, vcc, 0, v5, vcc
59; GFX8-NEXT:    s_setpc_b64 s[30:31]
60;
61; GFX9-LABEL: v_usubo_i64:
62; GFX9:       ; %bb.0:
63; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
64; GFX9-NEXT:    v_sub_co_u32_e32 v4, vcc, v0, v2
65; GFX9-NEXT:    v_subb_co_u32_e32 v5, vcc, v1, v3, vcc
66; GFX9-NEXT:    v_cmp_lt_u64_e32 vcc, v[0:1], v[2:3]
67; GFX9-NEXT:    v_cndmask_b32_e64 v0, 0, 1, vcc
68; GFX9-NEXT:    v_sub_co_u32_e32 v0, vcc, v4, v0
69; GFX9-NEXT:    v_subbrev_co_u32_e32 v1, vcc, 0, v5, vcc
70; GFX9-NEXT:    s_setpc_b64 s[30:31]
71  %usubo = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 %b)
72  %sub = extractvalue {i64, i1} %usubo, 0
73  %of = extractvalue {i64, i1} %usubo, 1
74  %of.zext = zext i1 %of to i64
75  %ret = sub i64 %sub, %of.zext
76  ret i64 %ret
77}
78
79define i8 @v_usubo_i8(i8 %a, i8 %b) {
80; GFX7-LABEL: v_usubo_i8:
81; GFX7:       ; %bb.0:
82; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
83; GFX7-NEXT:    v_and_b32_e32 v0, 0xff, v0
84; GFX7-NEXT:    v_and_b32_e32 v1, 0xff, v1
85; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
86; GFX7-NEXT:    v_and_b32_e32 v1, 0xff, v0
87; GFX7-NEXT:    v_cmp_ne_u32_e32 vcc, v0, v1
88; GFX7-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
89; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
90; GFX7-NEXT:    s_setpc_b64 s[30:31]
91;
92; GFX8-LABEL: v_usubo_i8:
93; GFX8:       ; %bb.0:
94; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
95; GFX8-NEXT:    v_and_b32_e32 v0, 0xff, v0
96; GFX8-NEXT:    v_and_b32_e32 v1, 0xff, v1
97; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, v0, v1
98; GFX8-NEXT:    v_and_b32_e32 v1, 0xff, v0
99; GFX8-NEXT:    v_cmp_ne_u32_e32 vcc, v0, v1
100; GFX8-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
101; GFX8-NEXT:    v_sub_u16_e32 v0, v0, v1
102; GFX8-NEXT:    s_setpc_b64 s[30:31]
103;
104; GFX9-LABEL: v_usubo_i8:
105; GFX9:       ; %bb.0:
106; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
107; GFX9-NEXT:    v_sub_u32_sdwa v0, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:BYTE_0
108; GFX9-NEXT:    v_cmp_ne_u32_sdwa s[4:5], v0, v0 src0_sel:DWORD src1_sel:BYTE_0
109; GFX9-NEXT:    v_cndmask_b32_e64 v1, 0, 1, s[4:5]
110; GFX9-NEXT:    v_sub_u16_e32 v0, v0, v1
111; GFX9-NEXT:    s_setpc_b64 s[30:31]
112  %usubo = call {i8, i1} @llvm.usub.with.overflow.i8(i8 %a, i8 %b)
113  %sub = extractvalue {i8, i1} %usubo, 0
114  %of = extractvalue {i8, i1} %usubo, 1
115  %of.zext = zext i1 %of to i8
116  %ret = sub i8 %sub, %of.zext
117  ret i8 %ret
118}
119
120define i7 @v_usubo_i7(i7 %a, i7 %b) {
121; GFX7-LABEL: v_usubo_i7:
122; GFX7:       ; %bb.0:
123; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
124; GFX7-NEXT:    v_and_b32_e32 v0, 0x7f, v0
125; GFX7-NEXT:    v_and_b32_e32 v1, 0x7f, v1
126; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
127; GFX7-NEXT:    v_and_b32_e32 v1, 0x7f, v0
128; GFX7-NEXT:    v_cmp_ne_u32_e32 vcc, v0, v1
129; GFX7-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
130; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
131; GFX7-NEXT:    s_setpc_b64 s[30:31]
132;
133; GFX8-LABEL: v_usubo_i7:
134; GFX8:       ; %bb.0:
135; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
136; GFX8-NEXT:    v_and_b32_e32 v0, 0x7f, v0
137; GFX8-NEXT:    v_and_b32_e32 v1, 0x7f, v1
138; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, v0, v1
139; GFX8-NEXT:    v_and_b32_e32 v1, 0x7f, v0
140; GFX8-NEXT:    v_cmp_ne_u32_e32 vcc, v0, v1
141; GFX8-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
142; GFX8-NEXT:    v_sub_u16_e32 v0, v0, v1
143; GFX8-NEXT:    s_setpc_b64 s[30:31]
144;
145; GFX9-LABEL: v_usubo_i7:
146; GFX9:       ; %bb.0:
147; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
148; GFX9-NEXT:    v_and_b32_e32 v0, 0x7f, v0
149; GFX9-NEXT:    v_and_b32_e32 v1, 0x7f, v1
150; GFX9-NEXT:    v_sub_u32_e32 v0, v0, v1
151; GFX9-NEXT:    v_and_b32_e32 v1, 0x7f, v0
152; GFX9-NEXT:    v_cmp_ne_u32_e32 vcc, v0, v1
153; GFX9-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
154; GFX9-NEXT:    v_sub_u16_e32 v0, v0, v1
155; GFX9-NEXT:    s_setpc_b64 s[30:31]
156  %usubo = call {i7, i1} @llvm.usub.with.overflow.i7(i7 %a, i7 %b)
157  %sub = extractvalue {i7, i1} %usubo, 0
158  %of = extractvalue {i7, i1} %usubo, 1
159  %of.zext = zext i1 %of to i7
160  %ret = sub i7 %sub, %of.zext
161  ret i7 %ret
162}
163
164define <2 x i32> @v_usubo_v2i32(<2 x i32> %a, <2 x i32> %b) {
165; GFX7-LABEL: v_usubo_v2i32:
166; GFX7:       ; %bb.0:
167; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
168; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v0, v2
169; GFX7-NEXT:    v_cndmask_b32_e64 v2, 0, 1, vcc
170; GFX7-NEXT:    v_sub_i32_e32 v1, vcc, v1, v3
171; GFX7-NEXT:    v_cndmask_b32_e64 v3, 0, 1, vcc
172; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v0, v2
173; GFX7-NEXT:    v_sub_i32_e32 v1, vcc, v1, v3
174; GFX7-NEXT:    s_setpc_b64 s[30:31]
175;
176; GFX8-LABEL: v_usubo_v2i32:
177; GFX8:       ; %bb.0:
178; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
179; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, v0, v2
180; GFX8-NEXT:    v_cndmask_b32_e64 v2, 0, 1, vcc
181; GFX8-NEXT:    v_sub_u32_e32 v1, vcc, v1, v3
182; GFX8-NEXT:    v_cndmask_b32_e64 v3, 0, 1, vcc
183; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, v0, v2
184; GFX8-NEXT:    v_sub_u32_e32 v1, vcc, v1, v3
185; GFX8-NEXT:    s_setpc_b64 s[30:31]
186;
187; GFX9-LABEL: v_usubo_v2i32:
188; GFX9:       ; %bb.0:
189; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
190; GFX9-NEXT:    v_sub_co_u32_e32 v0, vcc, v0, v2
191; GFX9-NEXT:    v_cndmask_b32_e64 v2, 0, 1, vcc
192; GFX9-NEXT:    v_sub_co_u32_e32 v1, vcc, v1, v3
193; GFX9-NEXT:    v_cndmask_b32_e64 v3, 0, 1, vcc
194; GFX9-NEXT:    v_sub_u32_e32 v0, v0, v2
195; GFX9-NEXT:    v_sub_u32_e32 v1, v1, v3
196; GFX9-NEXT:    s_setpc_b64 s[30:31]
197  %usubo = call {<2 x i32>, <2 x i1>} @llvm.usub.with.overflow.v2i32(<2 x i32> %a, <2 x i32> %b)
198  %sub = extractvalue {<2 x i32>, <2 x i1>} %usubo, 0
199  %of = extractvalue {<2 x i32>, <2 x i1>} %usubo, 1
200  %of.zext = zext <2 x i1> %of to <2 x i32>
201  %ret = sub <2 x i32> %sub, %of.zext
202  ret <2 x i32> %ret
203}
204
205define i32 @v_ssubo_i32(i32 %a, i32 %b) {
206; GFX7-LABEL: v_ssubo_i32:
207; GFX7:       ; %bb.0:
208; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
209; GFX7-NEXT:    v_sub_i32_e32 v2, vcc, v0, v1
210; GFX7-NEXT:    v_cmp_lt_i32_e32 vcc, v2, v0
211; GFX7-NEXT:    v_cmp_lt_i32_e64 s[4:5], 0, v1
212; GFX7-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
213; GFX7-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
214; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v2, v0
215; GFX7-NEXT:    s_setpc_b64 s[30:31]
216;
217; GFX8-LABEL: v_ssubo_i32:
218; GFX8:       ; %bb.0:
219; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
220; GFX8-NEXT:    v_sub_u32_e32 v2, vcc, v0, v1
221; GFX8-NEXT:    v_cmp_lt_i32_e32 vcc, v2, v0
222; GFX8-NEXT:    v_cmp_lt_i32_e64 s[4:5], 0, v1
223; GFX8-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
224; GFX8-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
225; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, v2, v0
226; GFX8-NEXT:    s_setpc_b64 s[30:31]
227;
228; GFX9-LABEL: v_ssubo_i32:
229; GFX9:       ; %bb.0:
230; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
231; GFX9-NEXT:    v_sub_u32_e32 v2, v0, v1
232; GFX9-NEXT:    v_cmp_lt_i32_e32 vcc, v2, v0
233; GFX9-NEXT:    v_cmp_lt_i32_e64 s[4:5], 0, v1
234; GFX9-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
235; GFX9-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
236; GFX9-NEXT:    v_sub_u32_e32 v0, v2, v0
237; GFX9-NEXT:    s_setpc_b64 s[30:31]
238  %ssubo = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)
239  %sub = extractvalue {i32, i1} %ssubo, 0
240  %of = extractvalue {i32, i1} %ssubo, 1
241  %of.zext = zext i1 %of to i32
242  %ret = sub i32 %sub, %of.zext
243  ret i32 %ret
244}
245
246define i64 @v_ssubo_i64(i64 %a, i64 %b) {
247; GFX7-LABEL: v_ssubo_i64:
248; GFX7:       ; %bb.0:
249; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
250; GFX7-NEXT:    v_sub_i32_e32 v4, vcc, v0, v2
251; GFX7-NEXT:    v_subb_u32_e32 v5, vcc, v1, v3, vcc
252; GFX7-NEXT:    v_cmp_lt_i64_e32 vcc, v[4:5], v[0:1]
253; GFX7-NEXT:    v_cmp_lt_i64_e64 s[4:5], 0, v[2:3]
254; GFX7-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
255; GFX7-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
256; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v4, v0
257; GFX7-NEXT:    v_subbrev_u32_e32 v1, vcc, 0, v5, vcc
258; GFX7-NEXT:    s_setpc_b64 s[30:31]
259;
260; GFX8-LABEL: v_ssubo_i64:
261; GFX8:       ; %bb.0:
262; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
263; GFX8-NEXT:    v_sub_u32_e32 v4, vcc, v0, v2
264; GFX8-NEXT:    v_subb_u32_e32 v5, vcc, v1, v3, vcc
265; GFX8-NEXT:    v_cmp_lt_i64_e32 vcc, v[4:5], v[0:1]
266; GFX8-NEXT:    v_cmp_lt_i64_e64 s[4:5], 0, v[2:3]
267; GFX8-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
268; GFX8-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
269; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, v4, v0
270; GFX8-NEXT:    v_subbrev_u32_e32 v1, vcc, 0, v5, vcc
271; GFX8-NEXT:    s_setpc_b64 s[30:31]
272;
273; GFX9-LABEL: v_ssubo_i64:
274; GFX9:       ; %bb.0:
275; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
276; GFX9-NEXT:    v_sub_co_u32_e32 v4, vcc, v0, v2
277; GFX9-NEXT:    v_subb_co_u32_e32 v5, vcc, v1, v3, vcc
278; GFX9-NEXT:    v_cmp_lt_i64_e32 vcc, v[4:5], v[0:1]
279; GFX9-NEXT:    v_cmp_lt_i64_e64 s[4:5], 0, v[2:3]
280; GFX9-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
281; GFX9-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
282; GFX9-NEXT:    v_sub_co_u32_e32 v0, vcc, v4, v0
283; GFX9-NEXT:    v_subbrev_co_u32_e32 v1, vcc, 0, v5, vcc
284; GFX9-NEXT:    s_setpc_b64 s[30:31]
285  %ssubo = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)
286  %sub = extractvalue {i64, i1} %ssubo, 0
287  %of = extractvalue {i64, i1} %ssubo, 1
288  %of.zext = zext i1 %of to i64
289  %ret = sub i64 %sub, %of.zext
290  ret i64 %ret
291}
292
293define <2 x i32> @v_ssubo_v2i32(<2 x i32> %a, <2 x i32> %b) {
294; GFX7-LABEL: v_ssubo_v2i32:
295; GFX7:       ; %bb.0:
296; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
297; GFX7-NEXT:    v_sub_i32_e32 v4, vcc, v0, v2
298; GFX7-NEXT:    v_sub_i32_e32 v5, vcc, v1, v3
299; GFX7-NEXT:    v_cmp_lt_i32_e32 vcc, v4, v0
300; GFX7-NEXT:    v_cmp_lt_i32_e64 s[4:5], v5, v1
301; GFX7-NEXT:    v_cmp_lt_i32_e64 s[6:7], 0, v2
302; GFX7-NEXT:    v_cmp_lt_i32_e64 s[8:9], 0, v3
303; GFX7-NEXT:    s_xor_b64 s[6:7], s[6:7], vcc
304; GFX7-NEXT:    s_xor_b64 s[4:5], s[8:9], s[4:5]
305; GFX7-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[6:7]
306; GFX7-NEXT:    v_cndmask_b32_e64 v1, 0, 1, s[4:5]
307; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v4, v0
308; GFX7-NEXT:    v_sub_i32_e32 v1, vcc, v5, v1
309; GFX7-NEXT:    s_setpc_b64 s[30:31]
310;
311; GFX8-LABEL: v_ssubo_v2i32:
312; GFX8:       ; %bb.0:
313; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
314; GFX8-NEXT:    v_sub_u32_e32 v4, vcc, v0, v2
315; GFX8-NEXT:    v_sub_u32_e32 v5, vcc, v1, v3
316; GFX8-NEXT:    v_cmp_lt_i32_e32 vcc, v4, v0
317; GFX8-NEXT:    v_cmp_lt_i32_e64 s[4:5], v5, v1
318; GFX8-NEXT:    v_cmp_lt_i32_e64 s[6:7], 0, v2
319; GFX8-NEXT:    v_cmp_lt_i32_e64 s[8:9], 0, v3
320; GFX8-NEXT:    s_xor_b64 s[6:7], s[6:7], vcc
321; GFX8-NEXT:    s_xor_b64 s[4:5], s[8:9], s[4:5]
322; GFX8-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[6:7]
323; GFX8-NEXT:    v_cndmask_b32_e64 v1, 0, 1, s[4:5]
324; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, v4, v0
325; GFX8-NEXT:    v_sub_u32_e32 v1, vcc, v5, v1
326; GFX8-NEXT:    s_setpc_b64 s[30:31]
327;
328; GFX9-LABEL: v_ssubo_v2i32:
329; GFX9:       ; %bb.0:
330; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
331; GFX9-NEXT:    v_sub_u32_e32 v4, v0, v2
332; GFX9-NEXT:    v_sub_u32_e32 v5, v1, v3
333; GFX9-NEXT:    v_cmp_lt_i32_e32 vcc, v4, v0
334; GFX9-NEXT:    v_cmp_lt_i32_e64 s[4:5], v5, v1
335; GFX9-NEXT:    v_cmp_lt_i32_e64 s[6:7], 0, v2
336; GFX9-NEXT:    v_cmp_lt_i32_e64 s[8:9], 0, v3
337; GFX9-NEXT:    s_xor_b64 s[6:7], s[6:7], vcc
338; GFX9-NEXT:    s_xor_b64 s[4:5], s[8:9], s[4:5]
339; GFX9-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[6:7]
340; GFX9-NEXT:    v_cndmask_b32_e64 v1, 0, 1, s[4:5]
341; GFX9-NEXT:    v_sub_u32_e32 v0, v4, v0
342; GFX9-NEXT:    v_sub_u32_e32 v1, v5, v1
343; GFX9-NEXT:    s_setpc_b64 s[30:31]
344  %ssubo = call {<2 x i32>, <2 x i1>} @llvm.ssub.with.overflow.v2i32(<2 x i32> %a, <2 x i32> %b)
345  %sub = extractvalue {<2 x i32>, <2 x i1>} %ssubo, 0
346  %of = extractvalue {<2 x i32>, <2 x i1>} %ssubo, 1
347  %of.zext = zext <2 x i1> %of to <2 x i32>
348  %ret = sub <2 x i32> %sub, %of.zext
349  ret <2 x i32> %ret
350}
351
352define i8 @v_ssubo_i8(i8 %a, i8 %b) {
353; GFX7-LABEL: v_ssubo_i8:
354; GFX7:       ; %bb.0:
355; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
356; GFX7-NEXT:    v_sub_i32_e32 v2, vcc, v0, v1
357; GFX7-NEXT:    v_bfe_i32 v3, v2, 0, 8
358; GFX7-NEXT:    v_bfe_i32 v0, v0, 0, 8
359; GFX7-NEXT:    v_cmp_lt_i32_e32 vcc, v3, v0
360; GFX7-NEXT:    v_bfe_i32 v0, v1, 0, 8
361; GFX7-NEXT:    v_cmp_lt_i32_e64 s[4:5], 0, v0
362; GFX7-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
363; GFX7-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
364; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v2, v0
365; GFX7-NEXT:    s_setpc_b64 s[30:31]
366;
367; GFX8-LABEL: v_ssubo_i8:
368; GFX8:       ; %bb.0:
369; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
370; GFX8-NEXT:    v_sub_u16_e32 v2, v0, v1
371; GFX8-NEXT:    v_bfe_i32 v3, v2, 0, 8
372; GFX8-NEXT:    v_bfe_i32 v0, v0, 0, 8
373; GFX8-NEXT:    v_cmp_lt_i32_e32 vcc, v3, v0
374; GFX8-NEXT:    v_bfe_i32 v0, v1, 0, 8
375; GFX8-NEXT:    v_cmp_lt_i32_e64 s[4:5], 0, v0
376; GFX8-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
377; GFX8-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
378; GFX8-NEXT:    v_sub_u16_e32 v0, v2, v0
379; GFX8-NEXT:    s_setpc_b64 s[30:31]
380;
381; GFX9-LABEL: v_ssubo_i8:
382; GFX9:       ; %bb.0:
383; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
384; GFX9-NEXT:    v_sub_u16_e32 v2, v0, v1
385; GFX9-NEXT:    v_cmp_lt_i32_sdwa s[4:5], sext(v2), sext(v0) src0_sel:BYTE_0 src1_sel:BYTE_0
386; GFX9-NEXT:    v_mov_b32_e32 v0, 0
387; GFX9-NEXT:    v_cmp_gt_i32_sdwa s[6:7], sext(v1), v0 src0_sel:BYTE_0 src1_sel:DWORD
388; GFX9-NEXT:    s_xor_b64 s[4:5], s[6:7], s[4:5]
389; GFX9-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
390; GFX9-NEXT:    v_sub_u16_e32 v0, v2, v0
391; GFX9-NEXT:    s_setpc_b64 s[30:31]
392  %ssubo = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 %a, i8 %b)
393  %sub = extractvalue {i8, i1} %ssubo, 0
394  %of = extractvalue {i8, i1} %ssubo, 1
395  %of.zext = zext i1 %of to i8
396  %ret = sub i8 %sub, %of.zext
397  ret i8 %ret
398}
399
400define i7 @v_ssubo_i7(i7 %a, i7 %b) {
401; GFX7-LABEL: v_ssubo_i7:
402; GFX7:       ; %bb.0:
403; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
404; GFX7-NEXT:    v_sub_i32_e32 v2, vcc, v0, v1
405; GFX7-NEXT:    v_bfe_i32 v3, v2, 0, 7
406; GFX7-NEXT:    v_bfe_i32 v0, v0, 0, 7
407; GFX7-NEXT:    v_cmp_lt_i32_e32 vcc, v3, v0
408; GFX7-NEXT:    v_bfe_i32 v0, v1, 0, 7
409; GFX7-NEXT:    v_cmp_lt_i32_e64 s[4:5], 0, v0
410; GFX7-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
411; GFX7-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
412; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v2, v0
413; GFX7-NEXT:    s_setpc_b64 s[30:31]
414;
415; GFX8-LABEL: v_ssubo_i7:
416; GFX8:       ; %bb.0:
417; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
418; GFX8-NEXT:    v_sub_u16_e32 v2, v0, v1
419; GFX8-NEXT:    v_bfe_i32 v3, v2, 0, 7
420; GFX8-NEXT:    v_bfe_i32 v0, v0, 0, 7
421; GFX8-NEXT:    v_cmp_lt_i32_e32 vcc, v3, v0
422; GFX8-NEXT:    v_bfe_i32 v0, v1, 0, 7
423; GFX8-NEXT:    v_cmp_lt_i32_e64 s[4:5], 0, v0
424; GFX8-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
425; GFX8-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
426; GFX8-NEXT:    v_sub_u16_e32 v0, v2, v0
427; GFX8-NEXT:    s_setpc_b64 s[30:31]
428;
429; GFX9-LABEL: v_ssubo_i7:
430; GFX9:       ; %bb.0:
431; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
432; GFX9-NEXT:    v_sub_u16_e32 v2, v0, v1
433; GFX9-NEXT:    v_bfe_i32 v3, v2, 0, 7
434; GFX9-NEXT:    v_bfe_i32 v0, v0, 0, 7
435; GFX9-NEXT:    v_cmp_lt_i32_e32 vcc, v3, v0
436; GFX9-NEXT:    v_bfe_i32 v0, v1, 0, 7
437; GFX9-NEXT:    v_cmp_lt_i32_e64 s[4:5], 0, v0
438; GFX9-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
439; GFX9-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
440; GFX9-NEXT:    v_sub_u16_e32 v0, v2, v0
441; GFX9-NEXT:    s_setpc_b64 s[30:31]
442  %ssubo = call {i7, i1} @llvm.ssub.with.overflow.i7(i7 %a, i7 %b)
443  %sub = extractvalue {i7, i1} %ssubo, 0
444  %of = extractvalue {i7, i1} %ssubo, 1
445  %of.zext = zext i1 %of to i7
446  %ret = sub i7 %sub, %of.zext
447  ret i7 %ret
448}
449
450define amdgpu_ps i32 @s_usubo_i32(i32 inreg %a, i32 inreg %b) {
451; GFX7-LABEL: s_usubo_i32:
452; GFX7:       ; %bb.0:
453; GFX7-NEXT:    s_sub_u32 s0, s0, s1
454; GFX7-NEXT:    s_cselect_b32 s1, 1, 0
455; GFX7-NEXT:    s_sub_i32 s0, s0, s1
456; GFX7-NEXT:    ; return to shader part epilog
457;
458; GFX8-LABEL: s_usubo_i32:
459; GFX8:       ; %bb.0:
460; GFX8-NEXT:    s_sub_u32 s0, s0, s1
461; GFX8-NEXT:    s_cselect_b32 s1, 1, 0
462; GFX8-NEXT:    s_sub_i32 s0, s0, s1
463; GFX8-NEXT:    ; return to shader part epilog
464;
465; GFX9-LABEL: s_usubo_i32:
466; GFX9:       ; %bb.0:
467; GFX9-NEXT:    s_sub_u32 s0, s0, s1
468; GFX9-NEXT:    s_cselect_b32 s1, 1, 0
469; GFX9-NEXT:    s_sub_i32 s0, s0, s1
470; GFX9-NEXT:    ; return to shader part epilog
471  %usubo = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %a, i32 %b)
472  %sub = extractvalue {i32, i1} %usubo, 0
473  %of = extractvalue {i32, i1} %usubo, 1
474  %of.zext = zext i1 %of to i32
475  %ret = sub i32 %sub, %of.zext
476  ret i32 %ret
477}
478
479define amdgpu_ps i64 @s_usubo_i64(i64 inreg %a, i64 inreg %b) {
480; GFX7-LABEL: s_usubo_i64:
481; GFX7:       ; %bb.0:
482; GFX7-NEXT:    v_mov_b32_e32 v0, s2
483; GFX7-NEXT:    v_mov_b32_e32 v1, s3
484; GFX7-NEXT:    v_cmp_lt_u64_e32 vcc, s[0:1], v[0:1]
485; GFX7-NEXT:    s_sub_u32 s4, s0, s2
486; GFX7-NEXT:    s_subb_u32 s5, s1, s3
487; GFX7-NEXT:    v_cndmask_b32_e64 v0, 0, 1, vcc
488; GFX7-NEXT:    v_mov_b32_e32 v1, s5
489; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, s4, v0
490; GFX7-NEXT:    v_subbrev_u32_e32 v1, vcc, 0, v1, vcc
491; GFX7-NEXT:    v_readfirstlane_b32 s0, v0
492; GFX7-NEXT:    v_readfirstlane_b32 s1, v1
493; GFX7-NEXT:    ; return to shader part epilog
494;
495; GFX8-LABEL: s_usubo_i64:
496; GFX8:       ; %bb.0:
497; GFX8-NEXT:    v_mov_b32_e32 v0, s2
498; GFX8-NEXT:    v_mov_b32_e32 v1, s3
499; GFX8-NEXT:    v_cmp_lt_u64_e32 vcc, s[0:1], v[0:1]
500; GFX8-NEXT:    s_sub_u32 s4, s0, s2
501; GFX8-NEXT:    s_subb_u32 s5, s1, s3
502; GFX8-NEXT:    v_cndmask_b32_e64 v0, 0, 1, vcc
503; GFX8-NEXT:    v_mov_b32_e32 v1, s5
504; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, s4, v0
505; GFX8-NEXT:    v_subbrev_u32_e32 v1, vcc, 0, v1, vcc
506; GFX8-NEXT:    v_readfirstlane_b32 s0, v0
507; GFX8-NEXT:    v_readfirstlane_b32 s1, v1
508; GFX8-NEXT:    ; return to shader part epilog
509;
510; GFX9-LABEL: s_usubo_i64:
511; GFX9:       ; %bb.0:
512; GFX9-NEXT:    v_mov_b32_e32 v0, s2
513; GFX9-NEXT:    v_mov_b32_e32 v1, s3
514; GFX9-NEXT:    v_cmp_lt_u64_e32 vcc, s[0:1], v[0:1]
515; GFX9-NEXT:    s_sub_u32 s4, s0, s2
516; GFX9-NEXT:    s_subb_u32 s5, s1, s3
517; GFX9-NEXT:    v_cndmask_b32_e64 v0, 0, 1, vcc
518; GFX9-NEXT:    v_mov_b32_e32 v1, s5
519; GFX9-NEXT:    v_sub_co_u32_e32 v0, vcc, s4, v0
520; GFX9-NEXT:    v_subbrev_co_u32_e32 v1, vcc, 0, v1, vcc
521; GFX9-NEXT:    v_readfirstlane_b32 s0, v0
522; GFX9-NEXT:    v_readfirstlane_b32 s1, v1
523; GFX9-NEXT:    ; return to shader part epilog
524  %usubo = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 %b)
525  %sub = extractvalue {i64, i1} %usubo, 0
526  %of = extractvalue {i64, i1} %usubo, 1
527  %of.zext = zext i1 %of to i64
528  %ret = sub i64 %sub, %of.zext
529  ret i64 %ret
530}
531
532define amdgpu_ps <2 x i32> @s_usubo_v2i32(<2 x i32> inreg %a, <2 x i32> inreg %b) {
533; GFX7-LABEL: s_usubo_v2i32:
534; GFX7:       ; %bb.0:
535; GFX7-NEXT:    s_sub_u32 s0, s0, s2
536; GFX7-NEXT:    s_cselect_b32 s2, 1, 0
537; GFX7-NEXT:    s_sub_u32 s1, s1, s3
538; GFX7-NEXT:    s_cselect_b32 s3, 1, 0
539; GFX7-NEXT:    s_sub_i32 s0, s0, s2
540; GFX7-NEXT:    s_sub_i32 s1, s1, s3
541; GFX7-NEXT:    ; return to shader part epilog
542;
543; GFX8-LABEL: s_usubo_v2i32:
544; GFX8:       ; %bb.0:
545; GFX8-NEXT:    s_sub_u32 s0, s0, s2
546; GFX8-NEXT:    s_cselect_b32 s2, 1, 0
547; GFX8-NEXT:    s_sub_u32 s1, s1, s3
548; GFX8-NEXT:    s_cselect_b32 s3, 1, 0
549; GFX8-NEXT:    s_sub_i32 s0, s0, s2
550; GFX8-NEXT:    s_sub_i32 s1, s1, s3
551; GFX8-NEXT:    ; return to shader part epilog
552;
553; GFX9-LABEL: s_usubo_v2i32:
554; GFX9:       ; %bb.0:
555; GFX9-NEXT:    s_sub_u32 s0, s0, s2
556; GFX9-NEXT:    s_cselect_b32 s2, 1, 0
557; GFX9-NEXT:    s_sub_u32 s1, s1, s3
558; GFX9-NEXT:    s_cselect_b32 s3, 1, 0
559; GFX9-NEXT:    s_sub_i32 s0, s0, s2
560; GFX9-NEXT:    s_sub_i32 s1, s1, s3
561; GFX9-NEXT:    ; return to shader part epilog
562  %usubo = call {<2 x i32>, <2 x i1>} @llvm.usub.with.overflow.v2i32(<2 x i32> %a, <2 x i32> %b)
563  %sub = extractvalue {<2 x i32>, <2 x i1>} %usubo, 0
564  %of = extractvalue {<2 x i32>, <2 x i1>} %usubo, 1
565  %of.zext = zext <2 x i1> %of to <2 x i32>
566  %ret = sub <2 x i32> %sub, %of.zext
567  ret <2 x i32> %ret
568}
569
570define i8 @s_usubo_i8(i8 %a, i8 %b) {
571; GFX7-LABEL: s_usubo_i8:
572; GFX7:       ; %bb.0:
573; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
574; GFX7-NEXT:    v_and_b32_e32 v0, 0xff, v0
575; GFX7-NEXT:    v_and_b32_e32 v1, 0xff, v1
576; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
577; GFX7-NEXT:    v_and_b32_e32 v1, 0xff, v0
578; GFX7-NEXT:    v_cmp_ne_u32_e32 vcc, v0, v1
579; GFX7-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
580; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
581; GFX7-NEXT:    s_setpc_b64 s[30:31]
582;
583; GFX8-LABEL: s_usubo_i8:
584; GFX8:       ; %bb.0:
585; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
586; GFX8-NEXT:    v_and_b32_e32 v0, 0xff, v0
587; GFX8-NEXT:    v_and_b32_e32 v1, 0xff, v1
588; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, v0, v1
589; GFX8-NEXT:    v_and_b32_e32 v1, 0xff, v0
590; GFX8-NEXT:    v_cmp_ne_u32_e32 vcc, v0, v1
591; GFX8-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
592; GFX8-NEXT:    v_sub_u16_e32 v0, v0, v1
593; GFX8-NEXT:    s_setpc_b64 s[30:31]
594;
595; GFX9-LABEL: s_usubo_i8:
596; GFX9:       ; %bb.0:
597; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
598; GFX9-NEXT:    v_sub_u32_sdwa v0, v0, v1 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:BYTE_0 src1_sel:BYTE_0
599; GFX9-NEXT:    v_cmp_ne_u32_sdwa s[4:5], v0, v0 src0_sel:DWORD src1_sel:BYTE_0
600; GFX9-NEXT:    v_cndmask_b32_e64 v1, 0, 1, s[4:5]
601; GFX9-NEXT:    v_sub_u16_e32 v0, v0, v1
602; GFX9-NEXT:    s_setpc_b64 s[30:31]
603  %usubo = call {i8, i1} @llvm.usub.with.overflow.i8(i8 %a, i8 %b)
604  %sub = extractvalue {i8, i1} %usubo, 0
605  %of = extractvalue {i8, i1} %usubo, 1
606  %of.zext = zext i1 %of to i8
607  %ret = sub i8 %sub, %of.zext
608  ret i8 %ret
609}
610
611define i7 @s_usubo_i7(i7 %a, i7 %b) {
612; GFX7-LABEL: s_usubo_i7:
613; GFX7:       ; %bb.0:
614; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
615; GFX7-NEXT:    v_and_b32_e32 v0, 0x7f, v0
616; GFX7-NEXT:    v_and_b32_e32 v1, 0x7f, v1
617; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
618; GFX7-NEXT:    v_and_b32_e32 v1, 0x7f, v0
619; GFX7-NEXT:    v_cmp_ne_u32_e32 vcc, v0, v1
620; GFX7-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
621; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
622; GFX7-NEXT:    s_setpc_b64 s[30:31]
623;
624; GFX8-LABEL: s_usubo_i7:
625; GFX8:       ; %bb.0:
626; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
627; GFX8-NEXT:    v_and_b32_e32 v0, 0x7f, v0
628; GFX8-NEXT:    v_and_b32_e32 v1, 0x7f, v1
629; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, v0, v1
630; GFX8-NEXT:    v_and_b32_e32 v1, 0x7f, v0
631; GFX8-NEXT:    v_cmp_ne_u32_e32 vcc, v0, v1
632; GFX8-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
633; GFX8-NEXT:    v_sub_u16_e32 v0, v0, v1
634; GFX8-NEXT:    s_setpc_b64 s[30:31]
635;
636; GFX9-LABEL: s_usubo_i7:
637; GFX9:       ; %bb.0:
638; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
639; GFX9-NEXT:    v_and_b32_e32 v0, 0x7f, v0
640; GFX9-NEXT:    v_and_b32_e32 v1, 0x7f, v1
641; GFX9-NEXT:    v_sub_u32_e32 v0, v0, v1
642; GFX9-NEXT:    v_and_b32_e32 v1, 0x7f, v0
643; GFX9-NEXT:    v_cmp_ne_u32_e32 vcc, v0, v1
644; GFX9-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
645; GFX9-NEXT:    v_sub_u16_e32 v0, v0, v1
646; GFX9-NEXT:    s_setpc_b64 s[30:31]
647  %usubo = call {i7, i1} @llvm.usub.with.overflow.i7(i7 %a, i7 %b)
648  %sub = extractvalue {i7, i1} %usubo, 0
649  %of = extractvalue {i7, i1} %usubo, 1
650  %of.zext = zext i1 %of to i7
651  %ret = sub i7 %sub, %of.zext
652  ret i7 %ret
653}
654
655define amdgpu_ps i32 @s_ssubo_i32(i32 inreg %a, i32 inreg %b) {
656; GFX7-LABEL: s_ssubo_i32:
657; GFX7:       ; %bb.0:
658; GFX7-NEXT:    s_sub_i32 s2, s0, s1
659; GFX7-NEXT:    s_cmp_lt_i32 s2, s0
660; GFX7-NEXT:    s_cselect_b32 s0, 1, 0
661; GFX7-NEXT:    s_cmp_gt_i32 s1, 0
662; GFX7-NEXT:    s_cselect_b32 s1, 1, 0
663; GFX7-NEXT:    s_xor_b32 s0, s1, s0
664; GFX7-NEXT:    s_and_b32 s0, s0, 1
665; GFX7-NEXT:    s_sub_i32 s0, s2, s0
666; GFX7-NEXT:    ; return to shader part epilog
667;
668; GFX8-LABEL: s_ssubo_i32:
669; GFX8:       ; %bb.0:
670; GFX8-NEXT:    s_sub_i32 s2, s0, s1
671; GFX8-NEXT:    s_cmp_lt_i32 s2, s0
672; GFX8-NEXT:    s_cselect_b32 s0, 1, 0
673; GFX8-NEXT:    s_cmp_gt_i32 s1, 0
674; GFX8-NEXT:    s_cselect_b32 s1, 1, 0
675; GFX8-NEXT:    s_xor_b32 s0, s1, s0
676; GFX8-NEXT:    s_and_b32 s0, s0, 1
677; GFX8-NEXT:    s_sub_i32 s0, s2, s0
678; GFX8-NEXT:    ; return to shader part epilog
679;
680; GFX9-LABEL: s_ssubo_i32:
681; GFX9:       ; %bb.0:
682; GFX9-NEXT:    s_sub_i32 s2, s0, s1
683; GFX9-NEXT:    s_cmp_lt_i32 s2, s0
684; GFX9-NEXT:    s_cselect_b32 s0, 1, 0
685; GFX9-NEXT:    s_cmp_gt_i32 s1, 0
686; GFX9-NEXT:    s_cselect_b32 s1, 1, 0
687; GFX9-NEXT:    s_xor_b32 s0, s1, s0
688; GFX9-NEXT:    s_and_b32 s0, s0, 1
689; GFX9-NEXT:    s_sub_i32 s0, s2, s0
690; GFX9-NEXT:    ; return to shader part epilog
691  %ssubo = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)
692  %sub = extractvalue {i32, i1} %ssubo, 0
693  %of = extractvalue {i32, i1} %ssubo, 1
694  %of.zext = zext i1 %of to i32
695  %ret = sub i32 %sub, %of.zext
696  ret i32 %ret
697}
698
699define amdgpu_ps i64 @s_ssubo_i64(i64 inreg %a, i64 inreg %b) {
700; GFX7-LABEL: s_ssubo_i64:
701; GFX7:       ; %bb.0:
702; GFX7-NEXT:    s_sub_u32 s4, s0, s2
703; GFX7-NEXT:    v_mov_b32_e32 v0, s0
704; GFX7-NEXT:    s_subb_u32 s5, s1, s3
705; GFX7-NEXT:    v_mov_b32_e32 v1, s1
706; GFX7-NEXT:    v_cmp_lt_i64_e32 vcc, s[4:5], v[0:1]
707; GFX7-NEXT:    v_cmp_gt_i64_e64 s[0:1], s[2:3], 0
708; GFX7-NEXT:    v_mov_b32_e32 v1, s5
709; GFX7-NEXT:    s_xor_b64 s[0:1], s[0:1], vcc
710; GFX7-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[0:1]
711; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, s4, v0
712; GFX7-NEXT:    v_subbrev_u32_e32 v1, vcc, 0, v1, vcc
713; GFX7-NEXT:    v_readfirstlane_b32 s0, v0
714; GFX7-NEXT:    v_readfirstlane_b32 s1, v1
715; GFX7-NEXT:    ; return to shader part epilog
716;
717; GFX8-LABEL: s_ssubo_i64:
718; GFX8:       ; %bb.0:
719; GFX8-NEXT:    s_sub_u32 s4, s0, s2
720; GFX8-NEXT:    v_mov_b32_e32 v0, s0
721; GFX8-NEXT:    s_subb_u32 s5, s1, s3
722; GFX8-NEXT:    v_mov_b32_e32 v1, s1
723; GFX8-NEXT:    v_cmp_lt_i64_e32 vcc, s[4:5], v[0:1]
724; GFX8-NEXT:    v_cmp_gt_i64_e64 s[0:1], s[2:3], 0
725; GFX8-NEXT:    v_mov_b32_e32 v1, s5
726; GFX8-NEXT:    s_xor_b64 s[0:1], s[0:1], vcc
727; GFX8-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[0:1]
728; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, s4, v0
729; GFX8-NEXT:    v_subbrev_u32_e32 v1, vcc, 0, v1, vcc
730; GFX8-NEXT:    v_readfirstlane_b32 s0, v0
731; GFX8-NEXT:    v_readfirstlane_b32 s1, v1
732; GFX8-NEXT:    ; return to shader part epilog
733;
734; GFX9-LABEL: s_ssubo_i64:
735; GFX9:       ; %bb.0:
736; GFX9-NEXT:    s_sub_u32 s4, s0, s2
737; GFX9-NEXT:    v_mov_b32_e32 v0, s0
738; GFX9-NEXT:    s_subb_u32 s5, s1, s3
739; GFX9-NEXT:    v_mov_b32_e32 v1, s1
740; GFX9-NEXT:    v_cmp_lt_i64_e32 vcc, s[4:5], v[0:1]
741; GFX9-NEXT:    v_cmp_gt_i64_e64 s[0:1], s[2:3], 0
742; GFX9-NEXT:    v_mov_b32_e32 v1, s5
743; GFX9-NEXT:    s_xor_b64 s[0:1], s[0:1], vcc
744; GFX9-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[0:1]
745; GFX9-NEXT:    v_sub_co_u32_e32 v0, vcc, s4, v0
746; GFX9-NEXT:    v_subbrev_co_u32_e32 v1, vcc, 0, v1, vcc
747; GFX9-NEXT:    v_readfirstlane_b32 s0, v0
748; GFX9-NEXT:    v_readfirstlane_b32 s1, v1
749; GFX9-NEXT:    ; return to shader part epilog
750  %ssubo = call {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)
751  %sub = extractvalue {i64, i1} %ssubo, 0
752  %of = extractvalue {i64, i1} %ssubo, 1
753  %of.zext = zext i1 %of to i64
754  %ret = sub i64 %sub, %of.zext
755  ret i64 %ret
756}
757
758define amdgpu_ps <2 x i32> @s_ssubo_v2i32(<2 x i32> inreg %a, <2 x i32> inreg %b) {
759; GFX7-LABEL: s_ssubo_v2i32:
760; GFX7:       ; %bb.0:
761; GFX7-NEXT:    s_sub_i32 s4, s0, s2
762; GFX7-NEXT:    s_sub_i32 s5, s1, s3
763; GFX7-NEXT:    s_cmp_lt_i32 s4, s0
764; GFX7-NEXT:    s_cselect_b32 s0, 1, 0
765; GFX7-NEXT:    s_cmp_lt_i32 s5, s1
766; GFX7-NEXT:    s_cselect_b32 s1, 1, 0
767; GFX7-NEXT:    s_cmp_gt_i32 s2, 0
768; GFX7-NEXT:    s_cselect_b32 s2, 1, 0
769; GFX7-NEXT:    s_cmp_gt_i32 s3, 0
770; GFX7-NEXT:    s_cselect_b32 s3, 1, 0
771; GFX7-NEXT:    s_xor_b32 s0, s2, s0
772; GFX7-NEXT:    s_xor_b32 s1, s3, s1
773; GFX7-NEXT:    s_and_b32 s0, s0, 1
774; GFX7-NEXT:    s_and_b32 s1, s1, 1
775; GFX7-NEXT:    s_sub_i32 s0, s4, s0
776; GFX7-NEXT:    s_sub_i32 s1, s5, s1
777; GFX7-NEXT:    ; return to shader part epilog
778;
779; GFX8-LABEL: s_ssubo_v2i32:
780; GFX8:       ; %bb.0:
781; GFX8-NEXT:    s_sub_i32 s4, s0, s2
782; GFX8-NEXT:    s_sub_i32 s5, s1, s3
783; GFX8-NEXT:    s_cmp_lt_i32 s4, s0
784; GFX8-NEXT:    s_cselect_b32 s0, 1, 0
785; GFX8-NEXT:    s_cmp_lt_i32 s5, s1
786; GFX8-NEXT:    s_cselect_b32 s1, 1, 0
787; GFX8-NEXT:    s_cmp_gt_i32 s2, 0
788; GFX8-NEXT:    s_cselect_b32 s2, 1, 0
789; GFX8-NEXT:    s_cmp_gt_i32 s3, 0
790; GFX8-NEXT:    s_cselect_b32 s3, 1, 0
791; GFX8-NEXT:    s_xor_b32 s0, s2, s0
792; GFX8-NEXT:    s_xor_b32 s1, s3, s1
793; GFX8-NEXT:    s_and_b32 s0, s0, 1
794; GFX8-NEXT:    s_and_b32 s1, s1, 1
795; GFX8-NEXT:    s_sub_i32 s0, s4, s0
796; GFX8-NEXT:    s_sub_i32 s1, s5, s1
797; GFX8-NEXT:    ; return to shader part epilog
798;
799; GFX9-LABEL: s_ssubo_v2i32:
800; GFX9:       ; %bb.0:
801; GFX9-NEXT:    s_sub_i32 s4, s0, s2
802; GFX9-NEXT:    s_sub_i32 s5, s1, s3
803; GFX9-NEXT:    s_cmp_lt_i32 s4, s0
804; GFX9-NEXT:    s_cselect_b32 s0, 1, 0
805; GFX9-NEXT:    s_cmp_lt_i32 s5, s1
806; GFX9-NEXT:    s_cselect_b32 s1, 1, 0
807; GFX9-NEXT:    s_cmp_gt_i32 s2, 0
808; GFX9-NEXT:    s_cselect_b32 s2, 1, 0
809; GFX9-NEXT:    s_cmp_gt_i32 s3, 0
810; GFX9-NEXT:    s_cselect_b32 s3, 1, 0
811; GFX9-NEXT:    s_xor_b32 s0, s2, s0
812; GFX9-NEXT:    s_xor_b32 s1, s3, s1
813; GFX9-NEXT:    s_and_b32 s0, s0, 1
814; GFX9-NEXT:    s_and_b32 s1, s1, 1
815; GFX9-NEXT:    s_sub_i32 s0, s4, s0
816; GFX9-NEXT:    s_sub_i32 s1, s5, s1
817; GFX9-NEXT:    ; return to shader part epilog
818  %ssubo = call {<2 x i32>, <2 x i1>} @llvm.ssub.with.overflow.v2i32(<2 x i32> %a, <2 x i32> %b)
819  %sub = extractvalue {<2 x i32>, <2 x i1>} %ssubo, 0
820  %of = extractvalue {<2 x i32>, <2 x i1>} %ssubo, 1
821  %of.zext = zext <2 x i1> %of to <2 x i32>
822  %ret = sub <2 x i32> %sub, %of.zext
823  ret <2 x i32> %ret
824}
825
826define i8 @s_ssubo_i8(i8 %a, i8 %b) {
827; GFX7-LABEL: s_ssubo_i8:
828; GFX7:       ; %bb.0:
829; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
830; GFX7-NEXT:    v_sub_i32_e32 v2, vcc, v0, v1
831; GFX7-NEXT:    v_bfe_i32 v3, v2, 0, 8
832; GFX7-NEXT:    v_bfe_i32 v0, v0, 0, 8
833; GFX7-NEXT:    v_cmp_lt_i32_e32 vcc, v3, v0
834; GFX7-NEXT:    v_bfe_i32 v0, v1, 0, 8
835; GFX7-NEXT:    v_cmp_lt_i32_e64 s[4:5], 0, v0
836; GFX7-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
837; GFX7-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
838; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v2, v0
839; GFX7-NEXT:    s_setpc_b64 s[30:31]
840;
841; GFX8-LABEL: s_ssubo_i8:
842; GFX8:       ; %bb.0:
843; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
844; GFX8-NEXT:    v_sub_u16_e32 v2, v0, v1
845; GFX8-NEXT:    v_bfe_i32 v3, v2, 0, 8
846; GFX8-NEXT:    v_bfe_i32 v0, v0, 0, 8
847; GFX8-NEXT:    v_cmp_lt_i32_e32 vcc, v3, v0
848; GFX8-NEXT:    v_bfe_i32 v0, v1, 0, 8
849; GFX8-NEXT:    v_cmp_lt_i32_e64 s[4:5], 0, v0
850; GFX8-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
851; GFX8-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
852; GFX8-NEXT:    v_sub_u16_e32 v0, v2, v0
853; GFX8-NEXT:    s_setpc_b64 s[30:31]
854;
855; GFX9-LABEL: s_ssubo_i8:
856; GFX9:       ; %bb.0:
857; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
858; GFX9-NEXT:    v_sub_u16_e32 v2, v0, v1
859; GFX9-NEXT:    v_cmp_lt_i32_sdwa s[4:5], sext(v2), sext(v0) src0_sel:BYTE_0 src1_sel:BYTE_0
860; GFX9-NEXT:    v_mov_b32_e32 v0, 0
861; GFX9-NEXT:    v_cmp_gt_i32_sdwa s[6:7], sext(v1), v0 src0_sel:BYTE_0 src1_sel:DWORD
862; GFX9-NEXT:    s_xor_b64 s[4:5], s[6:7], s[4:5]
863; GFX9-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
864; GFX9-NEXT:    v_sub_u16_e32 v0, v2, v0
865; GFX9-NEXT:    s_setpc_b64 s[30:31]
866  %ssubo = call {i8, i1} @llvm.ssub.with.overflow.i8(i8 %a, i8 %b)
867  %sub = extractvalue {i8, i1} %ssubo, 0
868  %of = extractvalue {i8, i1} %ssubo, 1
869  %of.zext = zext i1 %of to i8
870  %ret = sub i8 %sub, %of.zext
871  ret i8 %ret
872}
873
874define i7 @s_ssubo_i7(i7 %a, i7 %b) {
875; GFX7-LABEL: s_ssubo_i7:
876; GFX7:       ; %bb.0:
877; GFX7-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
878; GFX7-NEXT:    v_sub_i32_e32 v2, vcc, v0, v1
879; GFX7-NEXT:    v_bfe_i32 v3, v2, 0, 7
880; GFX7-NEXT:    v_bfe_i32 v0, v0, 0, 7
881; GFX7-NEXT:    v_cmp_lt_i32_e32 vcc, v3, v0
882; GFX7-NEXT:    v_bfe_i32 v0, v1, 0, 7
883; GFX7-NEXT:    v_cmp_lt_i32_e64 s[4:5], 0, v0
884; GFX7-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
885; GFX7-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
886; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v2, v0
887; GFX7-NEXT:    s_setpc_b64 s[30:31]
888;
889; GFX8-LABEL: s_ssubo_i7:
890; GFX8:       ; %bb.0:
891; GFX8-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
892; GFX8-NEXT:    v_sub_u16_e32 v2, v0, v1
893; GFX8-NEXT:    v_bfe_i32 v3, v2, 0, 7
894; GFX8-NEXT:    v_bfe_i32 v0, v0, 0, 7
895; GFX8-NEXT:    v_cmp_lt_i32_e32 vcc, v3, v0
896; GFX8-NEXT:    v_bfe_i32 v0, v1, 0, 7
897; GFX8-NEXT:    v_cmp_lt_i32_e64 s[4:5], 0, v0
898; GFX8-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
899; GFX8-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
900; GFX8-NEXT:    v_sub_u16_e32 v0, v2, v0
901; GFX8-NEXT:    s_setpc_b64 s[30:31]
902;
903; GFX9-LABEL: s_ssubo_i7:
904; GFX9:       ; %bb.0:
905; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
906; GFX9-NEXT:    v_sub_u16_e32 v2, v0, v1
907; GFX9-NEXT:    v_bfe_i32 v3, v2, 0, 7
908; GFX9-NEXT:    v_bfe_i32 v0, v0, 0, 7
909; GFX9-NEXT:    v_cmp_lt_i32_e32 vcc, v3, v0
910; GFX9-NEXT:    v_bfe_i32 v0, v1, 0, 7
911; GFX9-NEXT:    v_cmp_lt_i32_e64 s[4:5], 0, v0
912; GFX9-NEXT:    s_xor_b64 s[4:5], s[4:5], vcc
913; GFX9-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[4:5]
914; GFX9-NEXT:    v_sub_u16_e32 v0, v2, v0
915; GFX9-NEXT:    s_setpc_b64 s[30:31]
916  %ssubo = call {i7, i1} @llvm.ssub.with.overflow.i7(i7 %a, i7 %b)
917  %sub = extractvalue {i7, i1} %ssubo, 0
918  %of = extractvalue {i7, i1} %ssubo, 1
919  %of.zext = zext i1 %of to i7
920  %ret = sub i7 %sub, %of.zext
921  ret i7 %ret
922}
923
924define amdgpu_ps i32 @usubo_i32_sv(i32 inreg %a, i32 %b) {
925; GFX7-LABEL: usubo_i32_sv:
926; GFX7:       ; %bb.0:
927; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, s0, v0
928; GFX7-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
929; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
930; GFX7-NEXT:    v_readfirstlane_b32 s0, v0
931; GFX7-NEXT:    ; return to shader part epilog
932;
933; GFX8-LABEL: usubo_i32_sv:
934; GFX8:       ; %bb.0:
935; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, s0, v0
936; GFX8-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
937; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, v0, v1
938; GFX8-NEXT:    v_readfirstlane_b32 s0, v0
939; GFX8-NEXT:    ; return to shader part epilog
940;
941; GFX9-LABEL: usubo_i32_sv:
942; GFX9:       ; %bb.0:
943; GFX9-NEXT:    v_sub_co_u32_e32 v0, vcc, s0, v0
944; GFX9-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
945; GFX9-NEXT:    v_sub_u32_e32 v0, v0, v1
946; GFX9-NEXT:    v_readfirstlane_b32 s0, v0
947; GFX9-NEXT:    ; return to shader part epilog
948  %usubo = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %a, i32 %b)
949  %sub = extractvalue {i32, i1} %usubo, 0
950  %of = extractvalue {i32, i1} %usubo, 1
951  %of.zext = zext i1 %of to i32
952  %ret = sub i32 %sub, %of.zext
953  ret i32 %ret
954}
955
956define amdgpu_ps i16 @usubo_i16_sv(i16 inreg %a, i16 %b) {
957; GFX7-LABEL: usubo_i16_sv:
958; GFX7:       ; %bb.0:
959; GFX7-NEXT:    s_and_b32 s0, s0, 0xffff
960; GFX7-NEXT:    v_and_b32_e32 v0, 0xffff, v0
961; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, s0, v0
962; GFX7-NEXT:    v_and_b32_e32 v1, 0xffff, v0
963; GFX7-NEXT:    v_cmp_ne_u32_e32 vcc, v0, v1
964; GFX7-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
965; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v0, v1
966; GFX7-NEXT:    v_readfirstlane_b32 s0, v0
967; GFX7-NEXT:    ; return to shader part epilog
968;
969; GFX8-LABEL: usubo_i16_sv:
970; GFX8:       ; %bb.0:
971; GFX8-NEXT:    s_and_b32 s0, s0, 0xffff
972; GFX8-NEXT:    v_and_b32_e32 v0, 0xffff, v0
973; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, s0, v0
974; GFX8-NEXT:    v_and_b32_e32 v1, 0xffff, v0
975; GFX8-NEXT:    v_cmp_ne_u32_e32 vcc, v0, v1
976; GFX8-NEXT:    v_cndmask_b32_e64 v1, 0, 1, vcc
977; GFX8-NEXT:    v_sub_u16_e32 v0, v0, v1
978; GFX8-NEXT:    v_readfirstlane_b32 s0, v0
979; GFX8-NEXT:    ; return to shader part epilog
980;
981; GFX9-LABEL: usubo_i16_sv:
982; GFX9:       ; %bb.0:
983; GFX9-NEXT:    s_and_b32 s0, s0, 0xffff
984; GFX9-NEXT:    v_sub_u32_sdwa v0, s0, v0 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:WORD_0
985; GFX9-NEXT:    v_cmp_ne_u32_sdwa s[0:1], v0, v0 src0_sel:DWORD src1_sel:WORD_0
986; GFX9-NEXT:    v_cndmask_b32_e64 v1, 0, 1, s[0:1]
987; GFX9-NEXT:    v_sub_u16_e32 v0, v0, v1
988; GFX9-NEXT:    v_readfirstlane_b32 s0, v0
989; GFX9-NEXT:    ; return to shader part epilog
990  %usubo = call {i16, i1} @llvm.usub.with.overflow.i16(i16 %a, i16 %b)
991  %sub = extractvalue {i16, i1} %usubo, 0
992  %of = extractvalue {i16, i1} %usubo, 1
993  %of.zext = zext i1 %of to i16
994  %ret = sub i16 %sub, %of.zext
995  ret i16 %ret
996}
997
998define amdgpu_ps i32 @ssubo_i32_sv(i32 inreg %a, i32 %b) {
999; GFX7-LABEL: ssubo_i32_sv:
1000; GFX7:       ; %bb.0:
1001; GFX7-NEXT:    v_sub_i32_e32 v1, vcc, s0, v0
1002; GFX7-NEXT:    v_cmp_gt_i32_e32 vcc, s0, v1
1003; GFX7-NEXT:    v_cmp_lt_i32_e64 s[0:1], 0, v0
1004; GFX7-NEXT:    s_xor_b64 s[0:1], s[0:1], vcc
1005; GFX7-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[0:1]
1006; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v1, v0
1007; GFX7-NEXT:    v_readfirstlane_b32 s0, v0
1008; GFX7-NEXT:    ; return to shader part epilog
1009;
1010; GFX8-LABEL: ssubo_i32_sv:
1011; GFX8:       ; %bb.0:
1012; GFX8-NEXT:    v_sub_u32_e32 v1, vcc, s0, v0
1013; GFX8-NEXT:    v_cmp_gt_i32_e32 vcc, s0, v1
1014; GFX8-NEXT:    v_cmp_lt_i32_e64 s[0:1], 0, v0
1015; GFX8-NEXT:    s_xor_b64 s[0:1], s[0:1], vcc
1016; GFX8-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[0:1]
1017; GFX8-NEXT:    v_sub_u32_e32 v0, vcc, v1, v0
1018; GFX8-NEXT:    v_readfirstlane_b32 s0, v0
1019; GFX8-NEXT:    ; return to shader part epilog
1020;
1021; GFX9-LABEL: ssubo_i32_sv:
1022; GFX9:       ; %bb.0:
1023; GFX9-NEXT:    v_sub_u32_e32 v1, s0, v0
1024; GFX9-NEXT:    v_cmp_gt_i32_e32 vcc, s0, v1
1025; GFX9-NEXT:    v_cmp_lt_i32_e64 s[0:1], 0, v0
1026; GFX9-NEXT:    s_xor_b64 s[0:1], s[0:1], vcc
1027; GFX9-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[0:1]
1028; GFX9-NEXT:    v_sub_u32_e32 v0, v1, v0
1029; GFX9-NEXT:    v_readfirstlane_b32 s0, v0
1030; GFX9-NEXT:    ; return to shader part epilog
1031  %ssubo = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)
1032  %sub = extractvalue {i32, i1} %ssubo, 0
1033  %of = extractvalue {i32, i1} %ssubo, 1
1034  %of.zext = zext i1 %of to i32
1035  %ret = sub i32 %sub, %of.zext
1036  ret i32 %ret
1037}
1038
1039define amdgpu_ps i16 @ssubo_i16_sv(i16 inreg %a, i16 %b) {
1040; GFX7-LABEL: ssubo_i16_sv:
1041; GFX7:       ; %bb.0:
1042; GFX7-NEXT:    v_sub_i32_e32 v1, vcc, s0, v0
1043; GFX7-NEXT:    v_bfe_i32 v2, v1, 0, 16
1044; GFX7-NEXT:    s_sext_i32_i16 s0, s0
1045; GFX7-NEXT:    v_bfe_i32 v0, v0, 0, 16
1046; GFX7-NEXT:    v_cmp_gt_i32_e32 vcc, s0, v2
1047; GFX7-NEXT:    v_cmp_lt_i32_e64 s[0:1], 0, v0
1048; GFX7-NEXT:    s_xor_b64 s[0:1], s[0:1], vcc
1049; GFX7-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[0:1]
1050; GFX7-NEXT:    v_sub_i32_e32 v0, vcc, v1, v0
1051; GFX7-NEXT:    v_readfirstlane_b32 s0, v0
1052; GFX7-NEXT:    ; return to shader part epilog
1053;
1054; GFX8-LABEL: ssubo_i16_sv:
1055; GFX8:       ; %bb.0:
1056; GFX8-NEXT:    v_sub_u16_e32 v1, s0, v0
1057; GFX8-NEXT:    v_cmp_gt_i16_e32 vcc, s0, v1
1058; GFX8-NEXT:    v_cmp_lt_i16_e64 s[0:1], 0, v0
1059; GFX8-NEXT:    s_xor_b64 s[0:1], s[0:1], vcc
1060; GFX8-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[0:1]
1061; GFX8-NEXT:    v_sub_u16_e32 v0, v1, v0
1062; GFX8-NEXT:    v_readfirstlane_b32 s0, v0
1063; GFX8-NEXT:    ; return to shader part epilog
1064;
1065; GFX9-LABEL: ssubo_i16_sv:
1066; GFX9:       ; %bb.0:
1067; GFX9-NEXT:    v_sub_u16_e32 v1, s0, v0
1068; GFX9-NEXT:    v_cmp_gt_i16_e32 vcc, s0, v1
1069; GFX9-NEXT:    v_cmp_lt_i16_e64 s[0:1], 0, v0
1070; GFX9-NEXT:    s_xor_b64 s[0:1], s[0:1], vcc
1071; GFX9-NEXT:    v_cndmask_b32_e64 v0, 0, 1, s[0:1]
1072; GFX9-NEXT:    v_sub_u16_e32 v0, v1, v0
1073; GFX9-NEXT:    v_readfirstlane_b32 s0, v0
1074; GFX9-NEXT:    ; return to shader part epilog
1075  %ssubo = call {i16, i1} @llvm.ssub.with.overflow.i16(i16 %a, i16 %b)
1076  %sub = extractvalue {i16, i1} %ssubo, 0
1077  %of = extractvalue {i16, i1} %ssubo, 1
1078  %of.zext = zext i1 %of to i16
1079  %ret = sub i16 %sub, %of.zext
1080  ret i16 %ret
1081}
1082
1083declare {i7, i1} @llvm.usub.with.overflow.i7(i7 %a, i7 %b)
1084declare {i8, i1} @llvm.usub.with.overflow.i8(i8 %a, i8 %b)
1085declare {i16, i1} @llvm.usub.with.overflow.i16(i16 %a, i16 %b)
1086declare {i32, i1} @llvm.usub.with.overflow.i32(i32 %a, i32 %b)
1087declare {i64, i1} @llvm.usub.with.overflow.i64(i64 %a, i64 %b)
1088declare {<2 x i32>, <2 x i1>} @llvm.usub.with.overflow.v2i32(<2 x i32> %a, <2 x i32> %b)
1089
1090declare {i7, i1} @llvm.ssub.with.overflow.i7(i7 %a, i7 %b)
1091declare {i8, i1} @llvm.ssub.with.overflow.i8(i8 %a, i8 %b)
1092declare {i16, i1} @llvm.ssub.with.overflow.i16(i16 %a, i16 %b)
1093declare {i32, i1} @llvm.ssub.with.overflow.i32(i32 %a, i32 %b)
1094declare {i64, i1} @llvm.ssub.with.overflow.i64(i64 %a, i64 %b)
1095declare {<2 x i32>, <2 x i1>} @llvm.ssub.with.overflow.v2i32(<2 x i32> %a, <2 x i32> %b)
1096