xref: /llvm-project/llvm/test/CodeGen/RISCV/iabs.ll (revision 324c0a72061e8337a62f9af1ffc5bf6f59b8340c)
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
3; RUN:   | FileCheck %s --check-prefix=RV32I
4; RUN: llc -mtriple=riscv32 -mattr=+zbb -verify-machineinstrs < %s \
5; RUN:   | FileCheck %s --check-prefix=RV32ZBB
6; RUN: llc -mtriple=riscv32 -mattr=+experimental-zbt -verify-machineinstrs < %s \
7; RUN:   | FileCheck %s --check-prefix=RV32ZBT
8; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
9; RUN:   | FileCheck %s --check-prefix=RV64I
10; RUN: llc -mtriple=riscv64 -mattr=+zbb -verify-machineinstrs < %s \
11; RUN:   | FileCheck %s --check-prefix=RV64ZBB
12; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbt -verify-machineinstrs < %s \
13; RUN:   | FileCheck %s --check-prefix=RV64ZBT
14
15declare i8 @llvm.abs.i8(i8, i1 immarg)
16declare i16 @llvm.abs.i16(i16, i1 immarg)
17declare i32 @llvm.abs.i32(i32, i1 immarg)
18declare i64 @llvm.abs.i64(i64, i1 immarg)
19declare i128 @llvm.abs.i128(i128, i1 immarg)
20
21; FIXME: Sign extending the input to the input to the xor isn't needed and
22; causes an extra srai.
23define i8 @abs8(i8 %x) {
24; RV32I-LABEL: abs8:
25; RV32I:       # %bb.0:
26; RV32I-NEXT:    slli a0, a0, 24
27; RV32I-NEXT:    srai a1, a0, 24
28; RV32I-NEXT:    srai a0, a0, 31
29; RV32I-NEXT:    xor a1, a1, a0
30; RV32I-NEXT:    sub a0, a1, a0
31; RV32I-NEXT:    ret
32;
33; RV32ZBB-LABEL: abs8:
34; RV32ZBB:       # %bb.0:
35; RV32ZBB-NEXT:    sext.b a0, a0
36; RV32ZBB-NEXT:    neg a1, a0
37; RV32ZBB-NEXT:    max a0, a0, a1
38; RV32ZBB-NEXT:    ret
39;
40; RV32ZBT-LABEL: abs8:
41; RV32ZBT:       # %bb.0:
42; RV32ZBT-NEXT:    slli a0, a0, 24
43; RV32ZBT-NEXT:    srai a1, a0, 24
44; RV32ZBT-NEXT:    srai a0, a0, 31
45; RV32ZBT-NEXT:    xor a1, a1, a0
46; RV32ZBT-NEXT:    sub a0, a1, a0
47; RV32ZBT-NEXT:    ret
48;
49; RV64I-LABEL: abs8:
50; RV64I:       # %bb.0:
51; RV64I-NEXT:    slli a0, a0, 56
52; RV64I-NEXT:    srai a1, a0, 56
53; RV64I-NEXT:    srai a0, a0, 63
54; RV64I-NEXT:    xor a1, a1, a0
55; RV64I-NEXT:    sub a0, a1, a0
56; RV64I-NEXT:    ret
57;
58; RV64ZBB-LABEL: abs8:
59; RV64ZBB:       # %bb.0:
60; RV64ZBB-NEXT:    sext.b a0, a0
61; RV64ZBB-NEXT:    neg a1, a0
62; RV64ZBB-NEXT:    max a0, a0, a1
63; RV64ZBB-NEXT:    ret
64;
65; RV64ZBT-LABEL: abs8:
66; RV64ZBT:       # %bb.0:
67; RV64ZBT-NEXT:    slli a0, a0, 56
68; RV64ZBT-NEXT:    srai a1, a0, 56
69; RV64ZBT-NEXT:    srai a0, a0, 63
70; RV64ZBT-NEXT:    xor a1, a1, a0
71; RV64ZBT-NEXT:    sub a0, a1, a0
72; RV64ZBT-NEXT:    ret
73  %abs = tail call i8 @llvm.abs.i8(i8 %x, i1 true)
74  ret i8 %abs
75}
76
77; FIXME: Sign extending the input to the input to the xor isn't needed and
78; causes an extra srai.
79define i8 @select_abs8(i8 %x) {
80; RV32I-LABEL: select_abs8:
81; RV32I:       # %bb.0:
82; RV32I-NEXT:    slli a0, a0, 24
83; RV32I-NEXT:    srai a1, a0, 24
84; RV32I-NEXT:    srai a0, a0, 31
85; RV32I-NEXT:    xor a1, a1, a0
86; RV32I-NEXT:    sub a0, a1, a0
87; RV32I-NEXT:    ret
88;
89; RV32ZBB-LABEL: select_abs8:
90; RV32ZBB:       # %bb.0:
91; RV32ZBB-NEXT:    sext.b a0, a0
92; RV32ZBB-NEXT:    neg a1, a0
93; RV32ZBB-NEXT:    max a0, a0, a1
94; RV32ZBB-NEXT:    ret
95;
96; RV32ZBT-LABEL: select_abs8:
97; RV32ZBT:       # %bb.0:
98; RV32ZBT-NEXT:    slli a0, a0, 24
99; RV32ZBT-NEXT:    srai a1, a0, 24
100; RV32ZBT-NEXT:    srai a0, a0, 31
101; RV32ZBT-NEXT:    xor a1, a1, a0
102; RV32ZBT-NEXT:    sub a0, a1, a0
103; RV32ZBT-NEXT:    ret
104;
105; RV64I-LABEL: select_abs8:
106; RV64I:       # %bb.0:
107; RV64I-NEXT:    slli a0, a0, 56
108; RV64I-NEXT:    srai a1, a0, 56
109; RV64I-NEXT:    srai a0, a0, 63
110; RV64I-NEXT:    xor a1, a1, a0
111; RV64I-NEXT:    sub a0, a1, a0
112; RV64I-NEXT:    ret
113;
114; RV64ZBB-LABEL: select_abs8:
115; RV64ZBB:       # %bb.0:
116; RV64ZBB-NEXT:    sext.b a0, a0
117; RV64ZBB-NEXT:    neg a1, a0
118; RV64ZBB-NEXT:    max a0, a0, a1
119; RV64ZBB-NEXT:    ret
120;
121; RV64ZBT-LABEL: select_abs8:
122; RV64ZBT:       # %bb.0:
123; RV64ZBT-NEXT:    slli a0, a0, 56
124; RV64ZBT-NEXT:    srai a1, a0, 56
125; RV64ZBT-NEXT:    srai a0, a0, 63
126; RV64ZBT-NEXT:    xor a1, a1, a0
127; RV64ZBT-NEXT:    sub a0, a1, a0
128; RV64ZBT-NEXT:    ret
129  %1 = icmp slt i8 %x, 0
130  %2 = sub nsw i8 0, %x
131  %3 = select i1 %1, i8 %2, i8 %x
132  ret i8 %3
133}
134
135; FIXME: Sign extending the input to the input to the xor isn't needed and
136; causes an extra srai.
137define i16 @abs16(i16 %x) {
138; RV32I-LABEL: abs16:
139; RV32I:       # %bb.0:
140; RV32I-NEXT:    slli a0, a0, 16
141; RV32I-NEXT:    srai a1, a0, 16
142; RV32I-NEXT:    srai a0, a0, 31
143; RV32I-NEXT:    xor a1, a1, a0
144; RV32I-NEXT:    sub a0, a1, a0
145; RV32I-NEXT:    ret
146;
147; RV32ZBB-LABEL: abs16:
148; RV32ZBB:       # %bb.0:
149; RV32ZBB-NEXT:    sext.h a0, a0
150; RV32ZBB-NEXT:    neg a1, a0
151; RV32ZBB-NEXT:    max a0, a0, a1
152; RV32ZBB-NEXT:    ret
153;
154; RV32ZBT-LABEL: abs16:
155; RV32ZBT:       # %bb.0:
156; RV32ZBT-NEXT:    slli a0, a0, 16
157; RV32ZBT-NEXT:    srai a1, a0, 16
158; RV32ZBT-NEXT:    srai a0, a0, 31
159; RV32ZBT-NEXT:    xor a1, a1, a0
160; RV32ZBT-NEXT:    sub a0, a1, a0
161; RV32ZBT-NEXT:    ret
162;
163; RV64I-LABEL: abs16:
164; RV64I:       # %bb.0:
165; RV64I-NEXT:    slli a0, a0, 48
166; RV64I-NEXT:    srai a1, a0, 48
167; RV64I-NEXT:    srai a0, a0, 63
168; RV64I-NEXT:    xor a1, a1, a0
169; RV64I-NEXT:    sub a0, a1, a0
170; RV64I-NEXT:    ret
171;
172; RV64ZBB-LABEL: abs16:
173; RV64ZBB:       # %bb.0:
174; RV64ZBB-NEXT:    sext.h a0, a0
175; RV64ZBB-NEXT:    neg a1, a0
176; RV64ZBB-NEXT:    max a0, a0, a1
177; RV64ZBB-NEXT:    ret
178;
179; RV64ZBT-LABEL: abs16:
180; RV64ZBT:       # %bb.0:
181; RV64ZBT-NEXT:    slli a0, a0, 48
182; RV64ZBT-NEXT:    srai a1, a0, 48
183; RV64ZBT-NEXT:    srai a0, a0, 63
184; RV64ZBT-NEXT:    xor a1, a1, a0
185; RV64ZBT-NEXT:    sub a0, a1, a0
186; RV64ZBT-NEXT:    ret
187  %abs = tail call i16 @llvm.abs.i16(i16 %x, i1 true)
188  ret i16 %abs
189}
190
191; FIXME: Sign extending the input to the input to the xor isn't needed and
192; causes an extra srai.
193define i16 @select_abs16(i16 %x) {
194; RV32I-LABEL: select_abs16:
195; RV32I:       # %bb.0:
196; RV32I-NEXT:    slli a0, a0, 16
197; RV32I-NEXT:    srai a1, a0, 16
198; RV32I-NEXT:    srai a0, a0, 31
199; RV32I-NEXT:    xor a1, a1, a0
200; RV32I-NEXT:    sub a0, a1, a0
201; RV32I-NEXT:    ret
202;
203; RV32ZBB-LABEL: select_abs16:
204; RV32ZBB:       # %bb.0:
205; RV32ZBB-NEXT:    sext.h a0, a0
206; RV32ZBB-NEXT:    neg a1, a0
207; RV32ZBB-NEXT:    max a0, a0, a1
208; RV32ZBB-NEXT:    ret
209;
210; RV32ZBT-LABEL: select_abs16:
211; RV32ZBT:       # %bb.0:
212; RV32ZBT-NEXT:    slli a0, a0, 16
213; RV32ZBT-NEXT:    srai a1, a0, 16
214; RV32ZBT-NEXT:    srai a0, a0, 31
215; RV32ZBT-NEXT:    xor a1, a1, a0
216; RV32ZBT-NEXT:    sub a0, a1, a0
217; RV32ZBT-NEXT:    ret
218;
219; RV64I-LABEL: select_abs16:
220; RV64I:       # %bb.0:
221; RV64I-NEXT:    slli a0, a0, 48
222; RV64I-NEXT:    srai a1, a0, 48
223; RV64I-NEXT:    srai a0, a0, 63
224; RV64I-NEXT:    xor a1, a1, a0
225; RV64I-NEXT:    sub a0, a1, a0
226; RV64I-NEXT:    ret
227;
228; RV64ZBB-LABEL: select_abs16:
229; RV64ZBB:       # %bb.0:
230; RV64ZBB-NEXT:    sext.h a0, a0
231; RV64ZBB-NEXT:    neg a1, a0
232; RV64ZBB-NEXT:    max a0, a0, a1
233; RV64ZBB-NEXT:    ret
234;
235; RV64ZBT-LABEL: select_abs16:
236; RV64ZBT:       # %bb.0:
237; RV64ZBT-NEXT:    slli a0, a0, 48
238; RV64ZBT-NEXT:    srai a1, a0, 48
239; RV64ZBT-NEXT:    srai a0, a0, 63
240; RV64ZBT-NEXT:    xor a1, a1, a0
241; RV64ZBT-NEXT:    sub a0, a1, a0
242; RV64ZBT-NEXT:    ret
243  %1 = icmp slt i16 %x, 0
244  %2 = sub nsw i16 0, %x
245  %3 = select i1 %1, i16 %2, i16 %x
246  ret i16 %3
247}
248
249define i32 @abs32(i32 %x) {
250; RV32I-LABEL: abs32:
251; RV32I:       # %bb.0:
252; RV32I-NEXT:    srai a1, a0, 31
253; RV32I-NEXT:    xor a0, a0, a1
254; RV32I-NEXT:    sub a0, a0, a1
255; RV32I-NEXT:    ret
256;
257; RV32ZBB-LABEL: abs32:
258; RV32ZBB:       # %bb.0:
259; RV32ZBB-NEXT:    neg a1, a0
260; RV32ZBB-NEXT:    max a0, a0, a1
261; RV32ZBB-NEXT:    ret
262;
263; RV32ZBT-LABEL: abs32:
264; RV32ZBT:       # %bb.0:
265; RV32ZBT-NEXT:    srai a1, a0, 31
266; RV32ZBT-NEXT:    xor a0, a0, a1
267; RV32ZBT-NEXT:    sub a0, a0, a1
268; RV32ZBT-NEXT:    ret
269;
270; RV64I-LABEL: abs32:
271; RV64I:       # %bb.0:
272; RV64I-NEXT:    sraiw a1, a0, 31
273; RV64I-NEXT:    xor a0, a0, a1
274; RV64I-NEXT:    subw a0, a0, a1
275; RV64I-NEXT:    ret
276;
277; RV64ZBB-LABEL: abs32:
278; RV64ZBB:       # %bb.0:
279; RV64ZBB-NEXT:    sext.w a0, a0
280; RV64ZBB-NEXT:    neg a1, a0
281; RV64ZBB-NEXT:    max a0, a0, a1
282; RV64ZBB-NEXT:    ret
283;
284; RV64ZBT-LABEL: abs32:
285; RV64ZBT:       # %bb.0:
286; RV64ZBT-NEXT:    sraiw a1, a0, 31
287; RV64ZBT-NEXT:    xor a0, a0, a1
288; RV64ZBT-NEXT:    subw a0, a0, a1
289; RV64ZBT-NEXT:    ret
290  %abs = tail call i32 @llvm.abs.i32(i32 %x, i1 true)
291  ret i32 %abs
292}
293
294define i32 @select_abs32(i32 %x) {
295; RV32I-LABEL: select_abs32:
296; RV32I:       # %bb.0:
297; RV32I-NEXT:    srai a1, a0, 31
298; RV32I-NEXT:    xor a0, a0, a1
299; RV32I-NEXT:    sub a0, a0, a1
300; RV32I-NEXT:    ret
301;
302; RV32ZBB-LABEL: select_abs32:
303; RV32ZBB:       # %bb.0:
304; RV32ZBB-NEXT:    neg a1, a0
305; RV32ZBB-NEXT:    max a0, a0, a1
306; RV32ZBB-NEXT:    ret
307;
308; RV32ZBT-LABEL: select_abs32:
309; RV32ZBT:       # %bb.0:
310; RV32ZBT-NEXT:    srai a1, a0, 31
311; RV32ZBT-NEXT:    xor a0, a0, a1
312; RV32ZBT-NEXT:    sub a0, a0, a1
313; RV32ZBT-NEXT:    ret
314;
315; RV64I-LABEL: select_abs32:
316; RV64I:       # %bb.0:
317; RV64I-NEXT:    sraiw a1, a0, 31
318; RV64I-NEXT:    xor a0, a0, a1
319; RV64I-NEXT:    subw a0, a0, a1
320; RV64I-NEXT:    ret
321;
322; RV64ZBB-LABEL: select_abs32:
323; RV64ZBB:       # %bb.0:
324; RV64ZBB-NEXT:    sext.w a0, a0
325; RV64ZBB-NEXT:    neg a1, a0
326; RV64ZBB-NEXT:    max a0, a0, a1
327; RV64ZBB-NEXT:    ret
328;
329; RV64ZBT-LABEL: select_abs32:
330; RV64ZBT:       # %bb.0:
331; RV64ZBT-NEXT:    sraiw a1, a0, 31
332; RV64ZBT-NEXT:    xor a0, a0, a1
333; RV64ZBT-NEXT:    subw a0, a0, a1
334; RV64ZBT-NEXT:    ret
335  %1 = icmp slt i32 %x, 0
336  %2 = sub nsw i32 0, %x
337  %3 = select i1 %1, i32 %2, i32 %x
338  ret i32 %3
339}
340
341define i64 @abs64(i64 %x) {
342; RV32I-LABEL: abs64:
343; RV32I:       # %bb.0:
344; RV32I-NEXT:    bgez a1, .LBB6_2
345; RV32I-NEXT:  # %bb.1:
346; RV32I-NEXT:    snez a2, a0
347; RV32I-NEXT:    neg a0, a0
348; RV32I-NEXT:    add a1, a1, a2
349; RV32I-NEXT:    neg a1, a1
350; RV32I-NEXT:  .LBB6_2:
351; RV32I-NEXT:    ret
352;
353; RV32ZBB-LABEL: abs64:
354; RV32ZBB:       # %bb.0:
355; RV32ZBB-NEXT:    bgez a1, .LBB6_2
356; RV32ZBB-NEXT:  # %bb.1:
357; RV32ZBB-NEXT:    snez a2, a0
358; RV32ZBB-NEXT:    neg a0, a0
359; RV32ZBB-NEXT:    add a1, a1, a2
360; RV32ZBB-NEXT:    neg a1, a1
361; RV32ZBB-NEXT:  .LBB6_2:
362; RV32ZBB-NEXT:    ret
363;
364; RV32ZBT-LABEL: abs64:
365; RV32ZBT:       # %bb.0:
366; RV32ZBT-NEXT:    neg a2, a0
367; RV32ZBT-NEXT:    slti a3, a1, 0
368; RV32ZBT-NEXT:    cmov a2, a3, a2, a0
369; RV32ZBT-NEXT:    snez a0, a0
370; RV32ZBT-NEXT:    add a0, a1, a0
371; RV32ZBT-NEXT:    neg a0, a0
372; RV32ZBT-NEXT:    cmov a1, a3, a0, a1
373; RV32ZBT-NEXT:    mv a0, a2
374; RV32ZBT-NEXT:    ret
375;
376; RV64I-LABEL: abs64:
377; RV64I:       # %bb.0:
378; RV64I-NEXT:    srai a1, a0, 63
379; RV64I-NEXT:    xor a0, a0, a1
380; RV64I-NEXT:    sub a0, a0, a1
381; RV64I-NEXT:    ret
382;
383; RV64ZBB-LABEL: abs64:
384; RV64ZBB:       # %bb.0:
385; RV64ZBB-NEXT:    neg a1, a0
386; RV64ZBB-NEXT:    max a0, a0, a1
387; RV64ZBB-NEXT:    ret
388;
389; RV64ZBT-LABEL: abs64:
390; RV64ZBT:       # %bb.0:
391; RV64ZBT-NEXT:    srai a1, a0, 63
392; RV64ZBT-NEXT:    xor a0, a0, a1
393; RV64ZBT-NEXT:    sub a0, a0, a1
394; RV64ZBT-NEXT:    ret
395  %abs = tail call i64 @llvm.abs.i64(i64 %x, i1 true)
396  ret i64 %abs
397}
398
399define i64 @select_abs64(i64 %x) {
400; RV32I-LABEL: select_abs64:
401; RV32I:       # %bb.0:
402; RV32I-NEXT:    bgez a1, .LBB7_2
403; RV32I-NEXT:  # %bb.1:
404; RV32I-NEXT:    snez a2, a0
405; RV32I-NEXT:    neg a0, a0
406; RV32I-NEXT:    add a1, a1, a2
407; RV32I-NEXT:    neg a1, a1
408; RV32I-NEXT:  .LBB7_2:
409; RV32I-NEXT:    ret
410;
411; RV32ZBB-LABEL: select_abs64:
412; RV32ZBB:       # %bb.0:
413; RV32ZBB-NEXT:    bgez a1, .LBB7_2
414; RV32ZBB-NEXT:  # %bb.1:
415; RV32ZBB-NEXT:    snez a2, a0
416; RV32ZBB-NEXT:    neg a0, a0
417; RV32ZBB-NEXT:    add a1, a1, a2
418; RV32ZBB-NEXT:    neg a1, a1
419; RV32ZBB-NEXT:  .LBB7_2:
420; RV32ZBB-NEXT:    ret
421;
422; RV32ZBT-LABEL: select_abs64:
423; RV32ZBT:       # %bb.0:
424; RV32ZBT-NEXT:    neg a2, a0
425; RV32ZBT-NEXT:    slti a3, a1, 0
426; RV32ZBT-NEXT:    cmov a2, a3, a2, a0
427; RV32ZBT-NEXT:    snez a0, a0
428; RV32ZBT-NEXT:    add a0, a1, a0
429; RV32ZBT-NEXT:    neg a0, a0
430; RV32ZBT-NEXT:    cmov a1, a3, a0, a1
431; RV32ZBT-NEXT:    mv a0, a2
432; RV32ZBT-NEXT:    ret
433;
434; RV64I-LABEL: select_abs64:
435; RV64I:       # %bb.0:
436; RV64I-NEXT:    srai a1, a0, 63
437; RV64I-NEXT:    xor a0, a0, a1
438; RV64I-NEXT:    sub a0, a0, a1
439; RV64I-NEXT:    ret
440;
441; RV64ZBB-LABEL: select_abs64:
442; RV64ZBB:       # %bb.0:
443; RV64ZBB-NEXT:    neg a1, a0
444; RV64ZBB-NEXT:    max a0, a0, a1
445; RV64ZBB-NEXT:    ret
446;
447; RV64ZBT-LABEL: select_abs64:
448; RV64ZBT:       # %bb.0:
449; RV64ZBT-NEXT:    srai a1, a0, 63
450; RV64ZBT-NEXT:    xor a0, a0, a1
451; RV64ZBT-NEXT:    sub a0, a0, a1
452; RV64ZBT-NEXT:    ret
453  %1 = icmp slt i64 %x, 0
454  %2 = sub nsw i64 0, %x
455  %3 = select i1 %1, i64 %2, i64 %x
456  ret i64 %3
457}
458
459define i128 @abs128(i128 %x) {
460; RV32I-LABEL: abs128:
461; RV32I:       # %bb.0:
462; RV32I-NEXT:    lw a3, 0(a1)
463; RV32I-NEXT:    lw a2, 4(a1)
464; RV32I-NEXT:    lw a4, 12(a1)
465; RV32I-NEXT:    snez a5, a3
466; RV32I-NEXT:    mv a6, a5
467; RV32I-NEXT:    beqz a2, .LBB8_2
468; RV32I-NEXT:  # %bb.1:
469; RV32I-NEXT:    snez a6, a2
470; RV32I-NEXT:  .LBB8_2:
471; RV32I-NEXT:    lw a1, 8(a1)
472; RV32I-NEXT:    bgez a4, .LBB8_4
473; RV32I-NEXT:  # %bb.3:
474; RV32I-NEXT:    neg a7, a1
475; RV32I-NEXT:    sltu t0, a7, a6
476; RV32I-NEXT:    snez a1, a1
477; RV32I-NEXT:    add a1, a4, a1
478; RV32I-NEXT:    add a1, a1, t0
479; RV32I-NEXT:    neg a4, a1
480; RV32I-NEXT:    sub a1, a7, a6
481; RV32I-NEXT:    add a2, a2, a5
482; RV32I-NEXT:    neg a2, a2
483; RV32I-NEXT:    neg a3, a3
484; RV32I-NEXT:  .LBB8_4:
485; RV32I-NEXT:    sw a3, 0(a0)
486; RV32I-NEXT:    sw a1, 8(a0)
487; RV32I-NEXT:    sw a2, 4(a0)
488; RV32I-NEXT:    sw a4, 12(a0)
489; RV32I-NEXT:    ret
490;
491; RV32ZBB-LABEL: abs128:
492; RV32ZBB:       # %bb.0:
493; RV32ZBB-NEXT:    lw a3, 0(a1)
494; RV32ZBB-NEXT:    lw a2, 4(a1)
495; RV32ZBB-NEXT:    lw a4, 12(a1)
496; RV32ZBB-NEXT:    snez a5, a3
497; RV32ZBB-NEXT:    mv a6, a5
498; RV32ZBB-NEXT:    beqz a2, .LBB8_2
499; RV32ZBB-NEXT:  # %bb.1:
500; RV32ZBB-NEXT:    snez a6, a2
501; RV32ZBB-NEXT:  .LBB8_2:
502; RV32ZBB-NEXT:    lw a1, 8(a1)
503; RV32ZBB-NEXT:    bgez a4, .LBB8_4
504; RV32ZBB-NEXT:  # %bb.3:
505; RV32ZBB-NEXT:    neg a7, a1
506; RV32ZBB-NEXT:    sltu t0, a7, a6
507; RV32ZBB-NEXT:    snez a1, a1
508; RV32ZBB-NEXT:    add a1, a4, a1
509; RV32ZBB-NEXT:    add a1, a1, t0
510; RV32ZBB-NEXT:    neg a4, a1
511; RV32ZBB-NEXT:    sub a1, a7, a6
512; RV32ZBB-NEXT:    add a2, a2, a5
513; RV32ZBB-NEXT:    neg a2, a2
514; RV32ZBB-NEXT:    neg a3, a3
515; RV32ZBB-NEXT:  .LBB8_4:
516; RV32ZBB-NEXT:    sw a3, 0(a0)
517; RV32ZBB-NEXT:    sw a1, 8(a0)
518; RV32ZBB-NEXT:    sw a2, 4(a0)
519; RV32ZBB-NEXT:    sw a4, 12(a0)
520; RV32ZBB-NEXT:    ret
521;
522; RV32ZBT-LABEL: abs128:
523; RV32ZBT:       # %bb.0:
524; RV32ZBT-NEXT:    lw a2, 0(a1)
525; RV32ZBT-NEXT:    lw a3, 4(a1)
526; RV32ZBT-NEXT:    lw a4, 12(a1)
527; RV32ZBT-NEXT:    lw a1, 8(a1)
528; RV32ZBT-NEXT:    snez a5, a2
529; RV32ZBT-NEXT:    snez a6, a3
530; RV32ZBT-NEXT:    cmov a6, a3, a6, a5
531; RV32ZBT-NEXT:    neg a7, a1
532; RV32ZBT-NEXT:    sltu t0, a7, a6
533; RV32ZBT-NEXT:    snez t1, a1
534; RV32ZBT-NEXT:    add t1, a4, t1
535; RV32ZBT-NEXT:    add t0, t1, t0
536; RV32ZBT-NEXT:    neg t0, t0
537; RV32ZBT-NEXT:    slti t1, a4, 0
538; RV32ZBT-NEXT:    cmov a4, t1, t0, a4
539; RV32ZBT-NEXT:    sub a6, a7, a6
540; RV32ZBT-NEXT:    cmov a1, t1, a6, a1
541; RV32ZBT-NEXT:    add a5, a3, a5
542; RV32ZBT-NEXT:    neg a5, a5
543; RV32ZBT-NEXT:    cmov a3, t1, a5, a3
544; RV32ZBT-NEXT:    neg a5, a2
545; RV32ZBT-NEXT:    cmov a2, t1, a5, a2
546; RV32ZBT-NEXT:    sw a2, 0(a0)
547; RV32ZBT-NEXT:    sw a1, 8(a0)
548; RV32ZBT-NEXT:    sw a3, 4(a0)
549; RV32ZBT-NEXT:    sw a4, 12(a0)
550; RV32ZBT-NEXT:    ret
551;
552; RV64I-LABEL: abs128:
553; RV64I:       # %bb.0:
554; RV64I-NEXT:    bgez a1, .LBB8_2
555; RV64I-NEXT:  # %bb.1:
556; RV64I-NEXT:    snez a2, a0
557; RV64I-NEXT:    neg a0, a0
558; RV64I-NEXT:    add a1, a1, a2
559; RV64I-NEXT:    neg a1, a1
560; RV64I-NEXT:  .LBB8_2:
561; RV64I-NEXT:    ret
562;
563; RV64ZBB-LABEL: abs128:
564; RV64ZBB:       # %bb.0:
565; RV64ZBB-NEXT:    bgez a1, .LBB8_2
566; RV64ZBB-NEXT:  # %bb.1:
567; RV64ZBB-NEXT:    snez a2, a0
568; RV64ZBB-NEXT:    neg a0, a0
569; RV64ZBB-NEXT:    add a1, a1, a2
570; RV64ZBB-NEXT:    neg a1, a1
571; RV64ZBB-NEXT:  .LBB8_2:
572; RV64ZBB-NEXT:    ret
573;
574; RV64ZBT-LABEL: abs128:
575; RV64ZBT:       # %bb.0:
576; RV64ZBT-NEXT:    neg a2, a0
577; RV64ZBT-NEXT:    slti a3, a1, 0
578; RV64ZBT-NEXT:    cmov a2, a3, a2, a0
579; RV64ZBT-NEXT:    snez a0, a0
580; RV64ZBT-NEXT:    add a0, a1, a0
581; RV64ZBT-NEXT:    neg a0, a0
582; RV64ZBT-NEXT:    cmov a1, a3, a0, a1
583; RV64ZBT-NEXT:    mv a0, a2
584; RV64ZBT-NEXT:    ret
585  %abs = tail call i128 @llvm.abs.i128(i128 %x, i1 true)
586  ret i128 %abs
587}
588
589define i128 @select_abs128(i128 %x) {
590; RV32I-LABEL: select_abs128:
591; RV32I:       # %bb.0:
592; RV32I-NEXT:    lw a3, 0(a1)
593; RV32I-NEXT:    lw a2, 4(a1)
594; RV32I-NEXT:    lw a4, 12(a1)
595; RV32I-NEXT:    snez a5, a3
596; RV32I-NEXT:    mv a6, a5
597; RV32I-NEXT:    beqz a2, .LBB9_2
598; RV32I-NEXT:  # %bb.1:
599; RV32I-NEXT:    snez a6, a2
600; RV32I-NEXT:  .LBB9_2:
601; RV32I-NEXT:    lw a1, 8(a1)
602; RV32I-NEXT:    bgez a4, .LBB9_4
603; RV32I-NEXT:  # %bb.3:
604; RV32I-NEXT:    neg a7, a1
605; RV32I-NEXT:    sltu t0, a7, a6
606; RV32I-NEXT:    snez a1, a1
607; RV32I-NEXT:    add a1, a4, a1
608; RV32I-NEXT:    add a1, a1, t0
609; RV32I-NEXT:    neg a4, a1
610; RV32I-NEXT:    sub a1, a7, a6
611; RV32I-NEXT:    add a2, a2, a5
612; RV32I-NEXT:    neg a2, a2
613; RV32I-NEXT:    neg a3, a3
614; RV32I-NEXT:  .LBB9_4:
615; RV32I-NEXT:    sw a3, 0(a0)
616; RV32I-NEXT:    sw a1, 8(a0)
617; RV32I-NEXT:    sw a2, 4(a0)
618; RV32I-NEXT:    sw a4, 12(a0)
619; RV32I-NEXT:    ret
620;
621; RV32ZBB-LABEL: select_abs128:
622; RV32ZBB:       # %bb.0:
623; RV32ZBB-NEXT:    lw a3, 0(a1)
624; RV32ZBB-NEXT:    lw a2, 4(a1)
625; RV32ZBB-NEXT:    lw a4, 12(a1)
626; RV32ZBB-NEXT:    snez a5, a3
627; RV32ZBB-NEXT:    mv a6, a5
628; RV32ZBB-NEXT:    beqz a2, .LBB9_2
629; RV32ZBB-NEXT:  # %bb.1:
630; RV32ZBB-NEXT:    snez a6, a2
631; RV32ZBB-NEXT:  .LBB9_2:
632; RV32ZBB-NEXT:    lw a1, 8(a1)
633; RV32ZBB-NEXT:    bgez a4, .LBB9_4
634; RV32ZBB-NEXT:  # %bb.3:
635; RV32ZBB-NEXT:    neg a7, a1
636; RV32ZBB-NEXT:    sltu t0, a7, a6
637; RV32ZBB-NEXT:    snez a1, a1
638; RV32ZBB-NEXT:    add a1, a4, a1
639; RV32ZBB-NEXT:    add a1, a1, t0
640; RV32ZBB-NEXT:    neg a4, a1
641; RV32ZBB-NEXT:    sub a1, a7, a6
642; RV32ZBB-NEXT:    add a2, a2, a5
643; RV32ZBB-NEXT:    neg a2, a2
644; RV32ZBB-NEXT:    neg a3, a3
645; RV32ZBB-NEXT:  .LBB9_4:
646; RV32ZBB-NEXT:    sw a3, 0(a0)
647; RV32ZBB-NEXT:    sw a1, 8(a0)
648; RV32ZBB-NEXT:    sw a2, 4(a0)
649; RV32ZBB-NEXT:    sw a4, 12(a0)
650; RV32ZBB-NEXT:    ret
651;
652; RV32ZBT-LABEL: select_abs128:
653; RV32ZBT:       # %bb.0:
654; RV32ZBT-NEXT:    lw a2, 0(a1)
655; RV32ZBT-NEXT:    lw a3, 4(a1)
656; RV32ZBT-NEXT:    lw a4, 12(a1)
657; RV32ZBT-NEXT:    lw a1, 8(a1)
658; RV32ZBT-NEXT:    snez a5, a2
659; RV32ZBT-NEXT:    snez a6, a3
660; RV32ZBT-NEXT:    cmov a6, a3, a6, a5
661; RV32ZBT-NEXT:    neg a7, a1
662; RV32ZBT-NEXT:    sltu t0, a7, a6
663; RV32ZBT-NEXT:    snez t1, a1
664; RV32ZBT-NEXT:    add t1, a4, t1
665; RV32ZBT-NEXT:    add t0, t1, t0
666; RV32ZBT-NEXT:    neg t0, t0
667; RV32ZBT-NEXT:    slti t1, a4, 0
668; RV32ZBT-NEXT:    cmov a4, t1, t0, a4
669; RV32ZBT-NEXT:    sub a6, a7, a6
670; RV32ZBT-NEXT:    cmov a1, t1, a6, a1
671; RV32ZBT-NEXT:    add a5, a3, a5
672; RV32ZBT-NEXT:    neg a5, a5
673; RV32ZBT-NEXT:    cmov a3, t1, a5, a3
674; RV32ZBT-NEXT:    neg a5, a2
675; RV32ZBT-NEXT:    cmov a2, t1, a5, a2
676; RV32ZBT-NEXT:    sw a2, 0(a0)
677; RV32ZBT-NEXT:    sw a1, 8(a0)
678; RV32ZBT-NEXT:    sw a3, 4(a0)
679; RV32ZBT-NEXT:    sw a4, 12(a0)
680; RV32ZBT-NEXT:    ret
681;
682; RV64I-LABEL: select_abs128:
683; RV64I:       # %bb.0:
684; RV64I-NEXT:    bgez a1, .LBB9_2
685; RV64I-NEXT:  # %bb.1:
686; RV64I-NEXT:    snez a2, a0
687; RV64I-NEXT:    neg a0, a0
688; RV64I-NEXT:    add a1, a1, a2
689; RV64I-NEXT:    neg a1, a1
690; RV64I-NEXT:  .LBB9_2:
691; RV64I-NEXT:    ret
692;
693; RV64ZBB-LABEL: select_abs128:
694; RV64ZBB:       # %bb.0:
695; RV64ZBB-NEXT:    bgez a1, .LBB9_2
696; RV64ZBB-NEXT:  # %bb.1:
697; RV64ZBB-NEXT:    snez a2, a0
698; RV64ZBB-NEXT:    neg a0, a0
699; RV64ZBB-NEXT:    add a1, a1, a2
700; RV64ZBB-NEXT:    neg a1, a1
701; RV64ZBB-NEXT:  .LBB9_2:
702; RV64ZBB-NEXT:    ret
703;
704; RV64ZBT-LABEL: select_abs128:
705; RV64ZBT:       # %bb.0:
706; RV64ZBT-NEXT:    neg a2, a0
707; RV64ZBT-NEXT:    slti a3, a1, 0
708; RV64ZBT-NEXT:    cmov a2, a3, a2, a0
709; RV64ZBT-NEXT:    snez a0, a0
710; RV64ZBT-NEXT:    add a0, a1, a0
711; RV64ZBT-NEXT:    neg a0, a0
712; RV64ZBT-NEXT:    cmov a1, a3, a0, a1
713; RV64ZBT-NEXT:    mv a0, a2
714; RV64ZBT-NEXT:    ret
715  %1 = icmp slt i128 %x, 0
716  %2 = sub nsw i128 0, %x
717  %3 = select i1 %1, i128 %2, i128 %x
718  ret i128 %3
719}
720
721