1 ;; Machine description for RISC-V Bit Manipulation operations.
2 ;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
4 ;; This file is part of GCC.
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)
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.
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/>.
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"
29 [(set_attr "type" "bitmanip,load")
30 (set_attr "mode" "DI")])
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")))]
39 [(set_attr "type" "bitmanip")
40 (set_attr "mode" "<X:MODE>")])
42 (define_insn "*shNadduw"
43 [(set (match_operand:DI 0 "register_operand" "=r")
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")])
55 ;; During combine, we may encounter an attempt to combine
56 ;; slli rtmp, rs, #imm
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
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)
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;
82 /* If the bias + scale don't add up to operand[2], reject. */
83 if ((scale + bias) != UINTVAL (operands[2]))
86 /* If the shift-amount is out-of-range for sh[123]add.uw, reject. */
87 if ((scale < 1) || (scale > 3))
90 /* If there's no bias, the '*shNadduw' pattern should have matched. */
94 operands[6] = GEN_INT (bias);
95 operands[7] = GEN_INT (scale);
96 operands[8] = GEN_INT (0xffffffffULL << scale);
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"
106 [(set_attr "type" "bitmanip")
107 (set_attr "mode" "DI")])
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"
117 [(set_attr "type" "bitmanip")
118 (set_attr "mode" "DI")])
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")))]
128 [(set_attr "type" "bitmanip")
129 (set_attr "mode" "<X:MODE>")])
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.
135 [(set (match_operand:DI 0 "register_operand")
136 (and:DI (neg:DI (ge:DI (match_operand:DI 1 "register_operand")
138 (match_operand:DI 2 "register_operand")))
139 (clobber (match_operand:DI 3 "register_operand"))]
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)))])
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"))))]
150 [(set_attr "type" "bitmanip")
151 (set_attr "mode" "<X:MODE>")])
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")))]
157 "<bitmanip_insn>%~\t%0,%1"
158 [(set_attr "type" "bitmanip")
159 (set_attr "mode" "SI")])
161 (define_insn "*<bitmanip_optab>disi2"
162 [(set (match_operand:DI 0 "register_operand" "=r")
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")])
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")])
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")))]
185 [(set_attr "type" "bitmanip,load")
186 (set_attr "mode" "<GPR:MODE>")])
188 (define_insn "*extend<SHORT:mode><SUPERQI:mode>2_zbb"
189 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
191 (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
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>")])
199 (define_insn "*zero_extendhi<GPR:mode>2_zbb"
200 [(set (match_operand:GPR 0 "register_operand" "=r,r")
202 (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
207 [(set_attr "type" "bitmanip,load")
208 (set_attr "mode" "HI")])
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")))]
216 [(set_attr "type" "bitmanip")])
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"
224 [(set_attr "type" "bitmanip")])
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"
232 [(set_attr "type" "bitmanip")])
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")))]
240 [(set_attr "type" "bitmanip")])
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"
248 [(set_attr "type" "bitmanip")])
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"
256 [(set_attr "type" "bitmanip")])
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))]
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")))]
271 [(set_attr "type" "bitmanip")])
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
277 (define_expand "bswaphi2"
278 [(set (match_operand:HI 0 "register_operand" "=r")
279 (bswap:HI (match_operand:HI 1 "register_operand" "r")))]
282 rtx tmp = gen_reg_rtx (word_mode);
283 rtx newop1 = gen_lowpart (word_mode, operands[1]);
285 emit_insn (gen_bswapdi2 (tmp, newop1));
287 emit_insn (gen_bswapsi2 (tmp, newop1));
288 rtx tmp1 = gen_reg_rtx (word_mode);
290 emit_insn (gen_lshrdi3 (tmp1, tmp, GEN_INT (64 - 16)));
292 emit_insn (gen_lshrsi3 (tmp1, tmp, GEN_INT (32 - 16)));
293 emit_move_insn (operands[0], gen_lowpart (HImode, tmp1));
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")))]
302 "<bitmanip_insn>\t%0,%1,%2"
303 [(set_attr "type" "bitmanip")])
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")))]
314 [(set_attr "type" "bitmanip")])
316 (define_insn "*bset<mode>_mask"
317 [(set (match_operand:X 0 "register_operand" "=r")
318 (ior:X (ashift:X (const_int 1)
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")))]
325 [(set_attr "type" "bitmanip")])
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")))]
333 [(set_attr "type" "bitmanip")])
335 (define_insn "*bset<mode>_1_mask"
336 [(set (match_operand:X 0 "register_operand" "=r")
337 (ashift:X (const_int 1)
339 (and:X (match_operand:X 1 "register_operand" "r")
340 (match_operand 2 "<X:shiftm1>" "<X:shiftm1p>")) 0)))]
343 [(set_attr "type" "bitmanip")])
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")))]
351 [(set_attr "type" "bitmanip")])
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")))]
360 [(set_attr "type" "bitmanip")])
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")))]
368 [(set_attr "type" "bitmanip")])
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")))]
377 [(set_attr "type" "bitmanip")])
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")))]
385 [(set_attr "type" "bitmanip")])
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")
392 (match_operand:QI 2 "register_operand" "r"))))]
395 [(set_attr "type" "bitmanip")])
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")
404 (match_operand:X 2 "register_operand" "r")))]
407 [(set_attr "type" "bitmanip")])
409 (define_insn "*bexti"
410 [(set (match_operand:X 0 "register_operand" "=r")
411 (zero_extract:X (match_operand:X 1 "register_operand" "r")
413 (match_operand 2 "immediate_operand" "n")))]
414 "TARGET_ZBS && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
416 [(set_attr "type" "bitmanip")])