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=riscv64 -verify-machineinstrs < %s \
7 ; RUN: | FileCheck %s --check-prefix=RV64I
8 ; RUN: llc -mtriple=riscv64 -mattr=+zbb -verify-machineinstrs < %s \
9 ; RUN: | FileCheck %s --check-prefix=RV64ZBB
11 declare i32 @llvm.abs.i32(i32, i1 immarg)
12 declare i64 @llvm.abs.i64(i64, i1 immarg)
14 define i32 @neg_abs32(i32 %x) {
15 ; RV32I-LABEL: neg_abs32:
17 ; RV32I-NEXT: srai a1, a0, 31
18 ; RV32I-NEXT: xor a0, a0, a1
19 ; RV32I-NEXT: sub a0, a1, a0
22 ; RV32ZBB-LABEL: neg_abs32:
24 ; RV32ZBB-NEXT: neg a1, a0
25 ; RV32ZBB-NEXT: min a0, a0, a1
28 ; RV64I-LABEL: neg_abs32:
30 ; RV64I-NEXT: sraiw a1, a0, 31
31 ; RV64I-NEXT: xor a0, a0, a1
32 ; RV64I-NEXT: subw a0, a1, a0
35 ; RV64ZBB-LABEL: neg_abs32:
37 ; RV64ZBB-NEXT: sraiw a1, a0, 31
38 ; RV64ZBB-NEXT: xor a0, a0, a1
39 ; RV64ZBB-NEXT: subw a0, a1, a0
41 %abs = tail call i32 @llvm.abs.i32(i32 %x, i1 true)
42 %neg = sub nsw i32 0, %abs
46 define i32 @select_neg_abs32(i32 %x) {
47 ; RV32I-LABEL: select_neg_abs32:
49 ; RV32I-NEXT: srai a1, a0, 31
50 ; RV32I-NEXT: xor a0, a0, a1
51 ; RV32I-NEXT: sub a0, a1, a0
54 ; RV32ZBB-LABEL: select_neg_abs32:
56 ; RV32ZBB-NEXT: neg a1, a0
57 ; RV32ZBB-NEXT: min a0, a0, a1
60 ; RV64I-LABEL: select_neg_abs32:
62 ; RV64I-NEXT: sraiw a1, a0, 31
63 ; RV64I-NEXT: xor a0, a0, a1
64 ; RV64I-NEXT: subw a0, a1, a0
67 ; RV64ZBB-LABEL: select_neg_abs32:
69 ; RV64ZBB-NEXT: sraiw a1, a0, 31
70 ; RV64ZBB-NEXT: xor a0, a0, a1
71 ; RV64ZBB-NEXT: subw a0, a1, a0
73 %1 = icmp slt i32 %x, 0
74 %2 = sub nsw i32 0, %x
75 %3 = select i1 %1, i32 %x, i32 %2
79 define i64 @neg_abs64(i64 %x) {
80 ; RV32I-LABEL: neg_abs64:
82 ; RV32I-NEXT: srai a2, a1, 31
83 ; RV32I-NEXT: xor a0, a0, a2
84 ; RV32I-NEXT: sltu a3, a2, a0
85 ; RV32I-NEXT: xor a1, a1, a2
86 ; RV32I-NEXT: sub a1, a2, a1
87 ; RV32I-NEXT: sub a1, a1, a3
88 ; RV32I-NEXT: sub a0, a2, a0
91 ; RV32ZBB-LABEL: neg_abs64:
93 ; RV32ZBB-NEXT: srai a2, a1, 31
94 ; RV32ZBB-NEXT: xor a0, a0, a2
95 ; RV32ZBB-NEXT: sltu a3, a2, a0
96 ; RV32ZBB-NEXT: xor a1, a1, a2
97 ; RV32ZBB-NEXT: sub a1, a2, a1
98 ; RV32ZBB-NEXT: sub a1, a1, a3
99 ; RV32ZBB-NEXT: sub a0, a2, a0
102 ; RV64I-LABEL: neg_abs64:
104 ; RV64I-NEXT: srai a1, a0, 63
105 ; RV64I-NEXT: xor a0, a0, a1
106 ; RV64I-NEXT: sub a0, a1, a0
109 ; RV64ZBB-LABEL: neg_abs64:
111 ; RV64ZBB-NEXT: neg a1, a0
112 ; RV64ZBB-NEXT: min a0, a0, a1
114 %abs = tail call i64 @llvm.abs.i64(i64 %x, i1 true)
115 %neg = sub nsw i64 0, %abs
119 define i64 @select_neg_abs64(i64 %x) {
120 ; RV32I-LABEL: select_neg_abs64:
122 ; RV32I-NEXT: srai a2, a1, 31
123 ; RV32I-NEXT: xor a0, a0, a2
124 ; RV32I-NEXT: sltu a3, a2, a0
125 ; RV32I-NEXT: xor a1, a1, a2
126 ; RV32I-NEXT: sub a1, a2, a1
127 ; RV32I-NEXT: sub a1, a1, a3
128 ; RV32I-NEXT: sub a0, a2, a0
131 ; RV32ZBB-LABEL: select_neg_abs64:
133 ; RV32ZBB-NEXT: srai a2, a1, 31
134 ; RV32ZBB-NEXT: xor a0, a0, a2
135 ; RV32ZBB-NEXT: sltu a3, a2, a0
136 ; RV32ZBB-NEXT: xor a1, a1, a2
137 ; RV32ZBB-NEXT: sub a1, a2, a1
138 ; RV32ZBB-NEXT: sub a1, a1, a3
139 ; RV32ZBB-NEXT: sub a0, a2, a0
142 ; RV64I-LABEL: select_neg_abs64:
144 ; RV64I-NEXT: srai a1, a0, 63
145 ; RV64I-NEXT: xor a0, a0, a1
146 ; RV64I-NEXT: sub a0, a1, a0
149 ; RV64ZBB-LABEL: select_neg_abs64:
151 ; RV64ZBB-NEXT: neg a1, a0
152 ; RV64ZBB-NEXT: min a0, a0, a1
154 %1 = icmp slt i64 %x, 0
155 %2 = sub nsw i64 0, %x
156 %3 = select i1 %1, i64 %x, i64 %2
160 define i32 @neg_abs32_multiuse(i32 %x, ptr %y) {
161 ; RV32I-LABEL: neg_abs32_multiuse:
163 ; RV32I-NEXT: srai a2, a0, 31
164 ; RV32I-NEXT: xor a0, a0, a2
165 ; RV32I-NEXT: sub a2, a0, a2
166 ; RV32I-NEXT: neg a0, a2
167 ; RV32I-NEXT: sw a2, 0(a1)
170 ; RV32ZBB-LABEL: neg_abs32_multiuse:
172 ; RV32ZBB-NEXT: neg a2, a0
173 ; RV32ZBB-NEXT: max a2, a0, a2
174 ; RV32ZBB-NEXT: neg a0, a2
175 ; RV32ZBB-NEXT: sw a2, 0(a1)
178 ; RV64I-LABEL: neg_abs32_multiuse:
180 ; RV64I-NEXT: sraiw a2, a0, 31
181 ; RV64I-NEXT: xor a0, a0, a2
182 ; RV64I-NEXT: subw a2, a0, a2
183 ; RV64I-NEXT: negw a0, a2
184 ; RV64I-NEXT: sw a2, 0(a1)
187 ; RV64ZBB-LABEL: neg_abs32_multiuse:
189 ; RV64ZBB-NEXT: sext.w a0, a0
190 ; RV64ZBB-NEXT: negw a2, a0
191 ; RV64ZBB-NEXT: max a2, a0, a2
192 ; RV64ZBB-NEXT: negw a0, a2
193 ; RV64ZBB-NEXT: sw a2, 0(a1)
195 %abs = tail call i32 @llvm.abs.i32(i32 %x, i1 true)
196 store i32 %abs, ptr %y
197 %neg = sub nsw i32 0, %abs
201 define i64 @neg_abs64_multiuse(i64 %x, ptr %y) {
202 ; RV32I-LABEL: neg_abs64_multiuse:
204 ; RV32I-NEXT: bgez a1, .LBB5_2
205 ; RV32I-NEXT: # %bb.1:
206 ; RV32I-NEXT: snez a3, a0
207 ; RV32I-NEXT: neg a1, a1
208 ; RV32I-NEXT: sub a1, a1, a3
209 ; RV32I-NEXT: neg a0, a0
210 ; RV32I-NEXT: .LBB5_2:
211 ; RV32I-NEXT: sw a0, 0(a2)
212 ; RV32I-NEXT: snez a3, a0
213 ; RV32I-NEXT: neg a4, a1
214 ; RV32I-NEXT: sub a3, a4, a3
215 ; RV32I-NEXT: neg a0, a0
216 ; RV32I-NEXT: sw a1, 4(a2)
217 ; RV32I-NEXT: mv a1, a3
220 ; RV32ZBB-LABEL: neg_abs64_multiuse:
222 ; RV32ZBB-NEXT: bgez a1, .LBB5_2
223 ; RV32ZBB-NEXT: # %bb.1:
224 ; RV32ZBB-NEXT: snez a3, a0
225 ; RV32ZBB-NEXT: neg a1, a1
226 ; RV32ZBB-NEXT: sub a1, a1, a3
227 ; RV32ZBB-NEXT: neg a0, a0
228 ; RV32ZBB-NEXT: .LBB5_2:
229 ; RV32ZBB-NEXT: sw a0, 0(a2)
230 ; RV32ZBB-NEXT: snez a3, a0
231 ; RV32ZBB-NEXT: neg a4, a1
232 ; RV32ZBB-NEXT: sub a3, a4, a3
233 ; RV32ZBB-NEXT: neg a0, a0
234 ; RV32ZBB-NEXT: sw a1, 4(a2)
235 ; RV32ZBB-NEXT: mv a1, a3
238 ; RV64I-LABEL: neg_abs64_multiuse:
240 ; RV64I-NEXT: srai a2, a0, 63
241 ; RV64I-NEXT: xor a0, a0, a2
242 ; RV64I-NEXT: sub a2, a0, a2
243 ; RV64I-NEXT: neg a0, a2
244 ; RV64I-NEXT: sd a2, 0(a1)
247 ; RV64ZBB-LABEL: neg_abs64_multiuse:
249 ; RV64ZBB-NEXT: neg a2, a0
250 ; RV64ZBB-NEXT: max a2, a0, a2
251 ; RV64ZBB-NEXT: neg a0, a2
252 ; RV64ZBB-NEXT: sd a2, 0(a1)
254 %abs = tail call i64 @llvm.abs.i64(i64 %x, i1 true)
255 store i64 %abs, ptr %y
256 %neg = sub nsw i64 0, %abs