]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/riscv/bitmanip.md
RISC-V: Split "(a & (1UL << bitno)) ? 0 : -1" to bext + addi
[thirdparty/gcc.git] / gcc / config / riscv / bitmanip.md
1 ;; Machine description for RISC-V Bit Manipulation operations.
2 ;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
3
4 ;; This file is part of GCC.
5
6 ;; GCC is free software; you can redistribute it and/or modify
7 ;; it under the terms of the GNU General Public License as published by
8 ;; the Free Software Foundation; either version 3, or (at your option)
9 ;; any later version.
10
11 ;; GCC is distributed in the hope that it will be useful,
12 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ;; GNU General Public License for more details.
15
16 ;; You should have received a copy of the GNU General Public License
17 ;; along with GCC; see the file COPYING3. If not see
18 ;; <http://www.gnu.org/licenses/>.
19
20 ;; ZBA extension.
21
22 (define_insn "*zero_extendsidi2_bitmanip"
23 [(set (match_operand:DI 0 "register_operand" "=r,r")
24 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
25 "TARGET_64BIT && TARGET_ZBA"
26 "@
27 zext.w\t%0,%1
28 lwu\t%0,%1"
29 [(set_attr "type" "bitmanip,load")
30 (set_attr "mode" "DI")])
31
32 (define_insn "*shNadd"
33 [(set (match_operand:X 0 "register_operand" "=r")
34 (plus:X (ashift:X (match_operand:X 1 "register_operand" "r")
35 (match_operand:QI 2 "imm123_operand" "Ds3"))
36 (match_operand:X 3 "register_operand" "r")))]
37 "TARGET_ZBA"
38 "sh%2add\t%0,%1,%3"
39 [(set_attr "type" "bitmanip")
40 (set_attr "mode" "<X:MODE>")])
41
42 (define_insn "*shNadduw"
43 [(set (match_operand:DI 0 "register_operand" "=r")
44 (plus:DI
45 (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
46 (match_operand:QI 2 "imm123_operand" "Ds3"))
47 (match_operand 3 "immediate_operand" "n"))
48 (match_operand:DI 4 "register_operand" "r")))]
49 "TARGET_64BIT && TARGET_ZBA
50 && (INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff"
51 "sh%2add.uw\t%0,%1,%4"
52 [(set_attr "type" "bitmanip")
53 (set_attr "mode" "DI")])
54
55 ;; During combine, we may encounter an attempt to combine
56 ;; slli rtmp, rs, #imm
57 ;; zext.w rtmp, rtmp
58 ;; sh[123]add rd, rtmp, rs2
59 ;; which will lead to the immediate not satisfying the above constraints.
60 ;; By splitting the compound expression, we can simplify to a slli and a
61 ;; sh[123]add.uw.
62 (define_split
63 [(set (match_operand:DI 0 "register_operand")
64 (plus:DI (and:DI (ashift:DI (match_operand:DI 1 "register_operand")
65 (match_operand:QI 2 "immediate_operand"))
66 (match_operand:DI 3 "consecutive_bits_operand"))
67 (match_operand:DI 4 "register_operand")))
68 (clobber (match_operand:DI 5 "register_operand"))]
69 "TARGET_64BIT && TARGET_ZBA"
70 [(set (match_dup 5) (ashift:DI (match_dup 1) (match_dup 6)))
71 (set (match_dup 0) (plus:DI (and:DI (ashift:DI (match_dup 5)
72 (match_dup 7))
73 (match_dup 8))
74 (match_dup 4)))]
75 {
76 unsigned HOST_WIDE_INT mask = UINTVAL (operands[3]);
77 /* scale: shift within the sh[123]add.uw */
78 unsigned HOST_WIDE_INT scale = 32 - clz_hwi (mask);
79 /* bias: pre-scale amount (i.e. the prior shift amount) */
80 int bias = ctz_hwi (mask) - scale;
81
82 /* If the bias + scale don't add up to operand[2], reject. */
83 if ((scale + bias) != UINTVAL (operands[2]))
84 FAIL;
85
86 /* If the shift-amount is out-of-range for sh[123]add.uw, reject. */
87 if ((scale < 1) || (scale > 3))
88 FAIL;
89
90 /* If there's no bias, the '*shNadduw' pattern should have matched. */
91 if (bias == 0)
92 FAIL;
93
94 operands[6] = GEN_INT (bias);
95 operands[7] = GEN_INT (scale);
96 operands[8] = GEN_INT (0xffffffffULL << scale);
97 })
98
99 (define_insn "*add.uw"
100 [(set (match_operand:DI 0 "register_operand" "=r")
101 (plus:DI (zero_extend:DI
102 (match_operand:SI 1 "register_operand" "r"))
103 (match_operand:DI 2 "register_operand" "r")))]
104 "TARGET_64BIT && TARGET_ZBA"
105 "add.uw\t%0,%1,%2"
106 [(set_attr "type" "bitmanip")
107 (set_attr "mode" "DI")])
108
109 (define_insn "*slliuw"
110 [(set (match_operand:DI 0 "register_operand" "=r")
111 (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
112 (match_operand:QI 2 "immediate_operand" "I"))
113 (match_operand 3 "immediate_operand" "n")))]
114 "TARGET_64BIT && TARGET_ZBA
115 && (INTVAL (operands[3]) >> INTVAL (operands[2])) == 0xffffffff"
116 "slli.uw\t%0,%1,%2"
117 [(set_attr "type" "bitmanip")
118 (set_attr "mode" "DI")])
119
120 ;; ZBB extension.
121
122 (define_insn "*<optab>_not<mode>"
123 [(set (match_operand:X 0 "register_operand" "=r")
124 (bitmanip_bitwise:X (not:X (match_operand:X 1 "register_operand" "r"))
125 (match_operand:X 2 "register_operand" "r")))]
126 "TARGET_ZBB"
127 "<insn>n\t%0,%2,%1"
128 [(set_attr "type" "bitmanip")
129 (set_attr "mode" "<X:MODE>")])
130
131 ;; '(a >= 0) ? b : 0' is emitted branchless (from if-conversion). Without a
132 ;; bit of extra help for combine (i.e., the below split), we end up emitting
133 ;; not/srai/and instead of combining the not into an andn.
134 (define_split
135 [(set (match_operand:DI 0 "register_operand")
136 (and:DI (neg:DI (ge:DI (match_operand:DI 1 "register_operand")
137 (const_int 0)))
138 (match_operand:DI 2 "register_operand")))
139 (clobber (match_operand:DI 3 "register_operand"))]
140 "TARGET_ZBB"
141 [(set (match_dup 3) (ashiftrt:DI (match_dup 1) (const_int 63)))
142 (set (match_dup 0) (and:DI (not:DI (match_dup 3)) (match_dup 2)))])
143
144 (define_insn "*xor_not<mode>"
145 [(set (match_operand:X 0 "register_operand" "=r")
146 (not:X (xor:X (match_operand:X 1 "register_operand" "r")
147 (match_operand:X 2 "register_operand" "r"))))]
148 "TARGET_ZBB"
149 "xnor\t%0,%1,%2"
150 [(set_attr "type" "bitmanip")
151 (set_attr "mode" "<X:MODE>")])
152
153 (define_insn "<bitmanip_optab>si2"
154 [(set (match_operand:SI 0 "register_operand" "=r")
155 (clz_ctz_pcnt:SI (match_operand:SI 1 "register_operand" "r")))]
156 "TARGET_ZBB"
157 "<bitmanip_insn>%~\t%0,%1"
158 [(set_attr "type" "bitmanip")
159 (set_attr "mode" "SI")])
160
161 (define_insn "*<bitmanip_optab>disi2"
162 [(set (match_operand:DI 0 "register_operand" "=r")
163 (sign_extend:DI
164 (clz_ctz_pcnt:SI (match_operand:SI 1 "register_operand" "r"))))]
165 "TARGET_64BIT && TARGET_ZBB"
166 "<bitmanip_insn>w\t%0,%1"
167 [(set_attr "type" "bitmanip")
168 (set_attr "mode" "SI")])
169
170 (define_insn "<bitmanip_optab>di2"
171 [(set (match_operand:DI 0 "register_operand" "=r")
172 (clz_ctz_pcnt:DI (match_operand:DI 1 "register_operand" "r")))]
173 "TARGET_64BIT && TARGET_ZBB"
174 "<bitmanip_insn>\t%0,%1"
175 [(set_attr "type" "bitmanip")
176 (set_attr "mode" "DI")])
177
178 (define_insn "*zero_extendhi<GPR:mode>2_bitmanip"
179 [(set (match_operand:GPR 0 "register_operand" "=r,r")
180 (zero_extend:GPR (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
181 "TARGET_ZBB"
182 "@
183 zext.h\t%0,%1
184 lhu\t%0,%1"
185 [(set_attr "type" "bitmanip,load")
186 (set_attr "mode" "<GPR:MODE>")])
187
188 (define_insn "*extend<SHORT:mode><SUPERQI:mode>2_zbb"
189 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
190 (sign_extend:SUPERQI
191 (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
192 "TARGET_ZBB"
193 "@
194 sext.<SHORT:size>\t%0,%1
195 l<SHORT:size>\t%0,%1"
196 [(set_attr "type" "bitmanip,load")
197 (set_attr "mode" "<SUPERQI:MODE>")])
198
199 (define_insn "*zero_extendhi<GPR:mode>2_zbb"
200 [(set (match_operand:GPR 0 "register_operand" "=r,r")
201 (zero_extend:GPR
202 (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
203 "TARGET_ZBB"
204 "@
205 zext.h\t%0,%1
206 lhu\t%0,%1"
207 [(set_attr "type" "bitmanip,load")
208 (set_attr "mode" "HI")])
209
210 (define_insn "rotrsi3"
211 [(set (match_operand:SI 0 "register_operand" "=r")
212 (rotatert:SI (match_operand:SI 1 "register_operand" "r")
213 (match_operand:QI 2 "arith_operand" "rI")))]
214 "TARGET_ZBB"
215 "ror%i2%~\t%0,%1,%2"
216 [(set_attr "type" "bitmanip")])
217
218 (define_insn "rotrdi3"
219 [(set (match_operand:DI 0 "register_operand" "=r")
220 (rotatert:DI (match_operand:DI 1 "register_operand" "r")
221 (match_operand:QI 2 "arith_operand" "rI")))]
222 "TARGET_64BIT && TARGET_ZBB"
223 "ror%i2\t%0,%1,%2"
224 [(set_attr "type" "bitmanip")])
225
226 (define_insn "rotrsi3_sext"
227 [(set (match_operand:DI 0 "register_operand" "=r")
228 (sign_extend:DI (rotatert:SI (match_operand:SI 1 "register_operand" "r")
229 (match_operand:QI 2 "register_operand" "r"))))]
230 "TARGET_64BIT && TARGET_ZBB"
231 "rorw\t%0,%1,%2"
232 [(set_attr "type" "bitmanip")])
233
234 (define_insn "rotlsi3"
235 [(set (match_operand:SI 0 "register_operand" "=r")
236 (rotate:SI (match_operand:SI 1 "register_operand" "r")
237 (match_operand:QI 2 "register_operand" "r")))]
238 "TARGET_ZBB"
239 "rol%~\t%0,%1,%2"
240 [(set_attr "type" "bitmanip")])
241
242 (define_insn "rotldi3"
243 [(set (match_operand:DI 0 "register_operand" "=r")
244 (rotate:DI (match_operand:DI 1 "register_operand" "r")
245 (match_operand:QI 2 "register_operand" "r")))]
246 "TARGET_64BIT && TARGET_ZBB"
247 "rol\t%0,%1,%2"
248 [(set_attr "type" "bitmanip")])
249
250 (define_insn "rotlsi3_sext"
251 [(set (match_operand:DI 0 "register_operand" "=r")
252 (sign_extend:DI (rotate:SI (match_operand:SI 1 "register_operand" "r")
253 (match_operand:QI 2 "register_operand" "r"))))]
254 "TARGET_64BIT && TARGET_ZBB"
255 "rolw\t%0,%1,%2"
256 [(set_attr "type" "bitmanip")])
257
258 ;; orc.b (or-combine) is added as an unspec for the benefit of the support
259 ;; for optimized string functions (such as strcmp).
260 (define_insn "orcb<mode>2"
261 [(set (match_operand:X 0 "register_operand" "=r")
262 (unspec:X [(match_operand:X 1 "register_operand" "r")] UNSPEC_ORC_B))]
263 "TARGET_ZBB"
264 "orc.b\t%0,%1")
265
266 (define_insn "bswap<mode>2"
267 [(set (match_operand:X 0 "register_operand" "=r")
268 (bswap:X (match_operand:X 1 "register_operand" "r")))]
269 "TARGET_ZBB"
270 "rev8\t%0,%1"
271 [(set_attr "type" "bitmanip")])
272
273 ;; HI bswap can be emulated using SI/DI bswap followed
274 ;; by a logical shift right
275 ;; SI bswap for TARGET_64BIT is already similarly in
276 ;; the common code.
277 (define_expand "bswaphi2"
278 [(set (match_operand:HI 0 "register_operand" "=r")
279 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
280 "TARGET_ZBB"
281 {
282 rtx tmp = gen_reg_rtx (word_mode);
283 rtx newop1 = gen_lowpart (word_mode, operands[1]);
284 if (TARGET_64BIT)
285 emit_insn (gen_bswapdi2 (tmp, newop1));
286 else
287 emit_insn (gen_bswapsi2 (tmp, newop1));
288 rtx tmp1 = gen_reg_rtx (word_mode);
289 if (TARGET_64BIT)
290 emit_insn (gen_lshrdi3 (tmp1, tmp, GEN_INT (64 - 16)));
291 else
292 emit_insn (gen_lshrsi3 (tmp1, tmp, GEN_INT (32 - 16)));
293 emit_move_insn (operands[0], gen_lowpart (HImode, tmp1));
294 DONE;
295 })
296
297 (define_insn "<bitmanip_optab><mode>3"
298 [(set (match_operand:X 0 "register_operand" "=r")
299 (bitmanip_minmax:X (match_operand:X 1 "register_operand" "r")
300 (match_operand:X 2 "register_operand" "r")))]
301 "TARGET_ZBB"
302 "<bitmanip_insn>\t%0,%1,%2"
303 [(set_attr "type" "bitmanip")])
304
305 ;; ZBS extension.
306
307 (define_insn "*bset<mode>"
308 [(set (match_operand:X 0 "register_operand" "=r")
309 (ior:X (ashift:X (const_int 1)
310 (match_operand:QI 2 "register_operand" "r"))
311 (match_operand:X 1 "register_operand" "r")))]
312 "TARGET_ZBS"
313 "bset\t%0,%1,%2"
314 [(set_attr "type" "bitmanip")])
315
316 (define_insn "*bset<mode>_mask"
317 [(set (match_operand:X 0 "register_operand" "=r")
318 (ior:X (ashift:X (const_int 1)
319 (subreg:QI
320 (and:X (match_operand:X 2 "register_operand" "r")
321 (match_operand 3 "<X:shiftm1>" "<X:shiftm1p>")) 0))
322 (match_operand:X 1 "register_operand" "r")))]
323 "TARGET_ZBS"
324 "bset\t%0,%1,%2"
325 [(set_attr "type" "bitmanip")])
326
327 (define_insn "*bset<mode>_1"
328 [(set (match_operand:X 0 "register_operand" "=r")
329 (ashift:X (const_int 1)
330 (match_operand:QI 1 "register_operand" "r")))]
331 "TARGET_ZBS"
332 "bset\t%0,x0,%1"
333 [(set_attr "type" "bitmanip")])
334
335 (define_insn "*bset<mode>_1_mask"
336 [(set (match_operand:X 0 "register_operand" "=r")
337 (ashift:X (const_int 1)
338 (subreg:QI
339 (and:X (match_operand:X 1 "register_operand" "r")
340 (match_operand 2 "<X:shiftm1>" "<X:shiftm1p>")) 0)))]
341 "TARGET_ZBS"
342 "bset\t%0,x0,%1"
343 [(set_attr "type" "bitmanip")])
344
345 (define_insn "*bseti<mode>"
346 [(set (match_operand:X 0 "register_operand" "=r")
347 (ior:X (match_operand:X 1 "register_operand" "r")
348 (match_operand:X 2 "single_bit_mask_operand" "DbS")))]
349 "TARGET_ZBS"
350 "bseti\t%0,%1,%S2"
351 [(set_attr "type" "bitmanip")])
352
353 (define_insn "*bclr<mode>"
354 [(set (match_operand:X 0 "register_operand" "=r")
355 (and:X (rotate:X (const_int -2)
356 (match_operand:QI 2 "register_operand" "r"))
357 (match_operand:X 1 "register_operand" "r")))]
358 "TARGET_ZBS"
359 "bclr\t%0,%1,%2"
360 [(set_attr "type" "bitmanip")])
361
362 (define_insn "*bclri<mode>"
363 [(set (match_operand:X 0 "register_operand" "=r")
364 (and:X (match_operand:X 1 "register_operand" "r")
365 (match_operand:X 2 "not_single_bit_mask_operand" "DnS")))]
366 "TARGET_ZBS"
367 "bclri\t%0,%1,%T2"
368 [(set_attr "type" "bitmanip")])
369
370 (define_insn "*binv<mode>"
371 [(set (match_operand:X 0 "register_operand" "=r")
372 (xor:X (ashift:X (const_int 1)
373 (match_operand:QI 2 "register_operand" "r"))
374 (match_operand:X 1 "register_operand" "r")))]
375 "TARGET_ZBS"
376 "binv\t%0,%1,%2"
377 [(set_attr "type" "bitmanip")])
378
379 (define_insn "*binvi<mode>"
380 [(set (match_operand:X 0 "register_operand" "=r")
381 (xor:X (match_operand:X 1 "register_operand" "r")
382 (match_operand:X 2 "single_bit_mask_operand" "DbS")))]
383 "TARGET_ZBS"
384 "binvi\t%0,%1,%S2"
385 [(set_attr "type" "bitmanip")])
386
387 (define_insn "*bext<mode>"
388 [(set (match_operand:X 0 "register_operand" "=r")
389 (zero_extract:X (match_operand:X 1 "register_operand" "r")
390 (const_int 1)
391 (zero_extend:X
392 (match_operand:QI 2 "register_operand" "r"))))]
393 "TARGET_ZBS"
394 "bext\t%0,%1,%2"
395 [(set_attr "type" "bitmanip")])
396
397 ;; When performing `(a & (1UL << bitno)) ? 0 : -1` the combiner
398 ;; usually has the `bitno` typed as X-mode (i.e. no further
399 ;; zero-extension is performed around the bitno).
400 (define_insn "*bext<mode>"
401 [(set (match_operand:X 0 "register_operand" "=r")
402 (zero_extract:X (match_operand:X 1 "register_operand" "r")
403 (const_int 1)
404 (match_operand:X 2 "register_operand" "r")))]
405 "TARGET_ZBS"
406 "bext\t%0,%1,%2"
407 [(set_attr "type" "bitmanip")])
408
409 (define_insn "*bexti"
410 [(set (match_operand:X 0 "register_operand" "=r")
411 (zero_extract:X (match_operand:X 1 "register_operand" "r")
412 (const_int 1)
413 (match_operand 2 "immediate_operand" "n")))]
414 "TARGET_ZBS && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
415 "bexti\t%0,%1,%2"
416 [(set_attr "type" "bitmanip")])