1 ;; Machine description for T-Head vendor extensions
2 ;; Copyright (C) 2021-2024 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 "*th_addsl<mode>4"
23 [(set (match_operand:X 0 "register_operand" "=r")
24 (plus:X (ashift:X (match_operand:X 1 "register_operand" "r")
25 (match_operand:QI 2 "imm123_operand" "Ds3"))
26 (match_operand:X 3 "register_operand" "r")))]
28 "th.addsl\t%0,%3,%1,%2"
29 [(set_attr "type" "bitmanip")
30 (set_attr "mode" "<X:MODE>")])
34 (define_insn "*th_srri<mode>3"
35 [(set (match_operand:GPR 0 "register_operand" "=r")
36 (rotatert:GPR (match_operand:GPR 1 "register_operand" "r")
37 (match_operand 2 "const_int_operand" "n")))]
38 "TARGET_XTHEADBB && (TARGET_64BIT || <MODE>mode == SImode)"
40 bool wform = TARGET_64BIT && (<MODE>mode == SImode);
41 operands[2] = GEN_INT (INTVAL (operands[2])
42 & (GET_MODE_BITSIZE (<MODE>mode) - 1));
43 return wform ? "th.srriw\t%0,%1,%2" : "th.srri\t%0,%1,%2";
45 [(set_attr "type" "bitmanip")
46 (set_attr "mode" "<GPR:MODE>")])
48 (define_insn "*th_ext<mode>4"
49 [(set (match_operand:GPR 0 "register_operand" "=r")
50 (sign_extract:GPR (match_operand:GPR 1 "register_operand" "r")
51 (match_operand 2 "const_int_operand")
52 (match_operand 3 "const_int_operand")))]
55 operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
56 return "th.ext\t%0,%1,%2,%3";
58 [(set_attr "type" "bitmanip")
59 (set_attr "mode" "<GPR:MODE>")])
61 (define_insn "*extendhi<SUPERQI:mode>2_th_ext"
62 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
64 (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
65 "TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
69 [(set_attr "type" "bitmanip,load")
70 (set_attr "mode" "<SUPERQI:MODE>")])
72 (define_insn "*extendqi<SUPERQI:mode>2_th_ext"
73 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r")
75 (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
76 "TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
80 [(set_attr "type" "bitmanip,load")
81 (set_attr "mode" "<SUPERQI:MODE>")])
83 (define_insn "*th_extu<mode>4"
84 [(set (match_operand:GPR 0 "register_operand" "=r")
85 (zero_extract:GPR (match_operand:GPR 1 "register_operand" "r")
86 (match_operand 2 "const_int_operand")
87 (match_operand 3 "const_int_operand")))]
90 operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
91 return "th.extu\t%0,%1,%2,%3";
93 [(set_attr "type" "bitmanip")
94 (set_attr "mode" "<GPR:MODE>")])
96 (define_insn "*zero_extendsidi2_th_extu"
97 [(set (match_operand:DI 0 "register_operand" "=r,r")
98 (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
99 "TARGET_64BIT && TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
103 [(set_attr "type" "bitmanip,load")
104 (set_attr "mode" "DI")])
106 (define_insn "*zero_extendhi<GPR:mode>2_th_extu"
107 [(set (match_operand:GPR 0 "register_operand" "=r,r")
108 (zero_extend:GPR (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
109 "TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
113 [(set_attr "type" "bitmanip,load")
114 (set_attr "mode" "<GPR:MODE>")])
116 (define_insn "*th_clz<mode>2"
117 [(set (match_operand:X 0 "register_operand" "=r")
118 (clz:X (match_operand:X 1 "register_operand" "r")))]
121 [(set_attr "type" "bitmanip")
122 (set_attr "mode" "<X:MODE>")])
124 (define_insn "th_rev<mode>2"
125 [(set (match_operand:GPR 0 "register_operand" "=r")
126 (bswap:GPR (match_operand:GPR 1 "register_operand" "r")))]
127 "TARGET_XTHEADBB && (TARGET_64BIT || <MODE>mode == SImode)"
129 bool wform = TARGET_64BIT && (<MODE>mode == SImode);
130 return wform ? "th.revw\t%0,%1" : "th.rev\t%0,%1";
132 [(set_attr "type" "bitmanip")
133 (set_attr "mode" "<GPR:MODE>")])
135 (define_insn "th_tstnbz<mode>2"
136 [(set (match_operand:X 0 "register_operand" "=r")
137 (unspec:X [(match_operand:X 1 "register_operand" "r")] UNSPEC_ORC_B))]
140 [(set_attr "type" "bitmanip")])
144 (define_insn "*th_tst<mode>3"
145 [(set (match_operand:X 0 "register_operand" "=r")
146 (zero_extract:X (match_operand:X 1 "register_operand" "r")
148 (match_operand 2 "const_int_operand" "n")))]
149 "TARGET_XTHEADBS && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
151 [(set_attr "type" "bitmanip")])
155 (define_insn "*th_cond_mov<GPR:mode><GPR2:mode>"
156 [(set (match_operand:GPR 0 "register_operand" "=r,r")
158 (match_operator 4 "equality_operator"
159 [(match_operand:GPR2 1 "register_operand" "r,r")
161 (match_operand:GPR 2 "reg_or_0_operand" "rJ,0")
162 (match_operand:GPR 3 "reg_or_0_operand" "0,rJ")))]
163 "TARGET_XTHEADCONDMOV"
165 if (which_alternative == 0)
166 return "th.mv%C4z\t%0,%z2,%1";
168 /* Invert the condition and take else-block. */
169 rtx_code code = GET_CODE (operands[4]);
170 code = (code == EQ) ? NE : EQ;
171 operands[4] = gen_rtx_fmt_ee (code, VOIDmode, operands[1], const0_rtx);
172 return "th.mv%C4z\t%0,%z3,%1";
174 [(set_attr "type" "condmove")
175 (set_attr "mode" "<GPR:MODE>")])
179 ;; In RV32, we lack fmv.x.d and fmv.d.x, but XTheadFmv has instructions
180 ;; that cover this case.
182 (define_insn "th_fmv_hw_w_x"
183 [(set (match_operand:DF 0 "register_operand" "=f")
184 (unspec:DF [(match_operand:SI 1 "register_operand" "r")
185 (match_operand:SI 2 "register_operand" "r")]
187 "!TARGET_64BIT && TARGET_XTHEADFMV"
188 "fmv.w.x\t%0,%2\n\tth.fmv.hw.x\t%0,%1"
189 [(set_attr "move_type" "move")
190 (set_attr "type" "fmove")
191 (set_attr "mode" "DF")])
193 (define_insn "th_fmv_x_w"
194 [(set (match_operand:SI 0 "register_operand" "=r")
195 (unspec:SI [(match_operand:DF 1 "register_operand" "f")]
197 "!TARGET_64BIT && TARGET_XTHEADFMV"
199 [(set_attr "move_type" "move")
200 (set_attr "type" "fmove")
201 (set_attr "mode" "DF")])
203 (define_insn "th_fmv_x_hw"
204 [(set (match_operand:SI 0 "register_operand" "=r")
205 (unspec:SI [(match_operand:DF 1 "register_operand" "f")]
206 UNSPEC_XTHEADFMV_HW))]
207 "!TARGET_64BIT && TARGET_XTHEADFMV"
209 [(set_attr "move_type" "move")
210 (set_attr "type" "fmove")
211 (set_attr "mode" "DF")])
233 (define_insn "th_int_push"
234 [(unspec_volatile [(const_int 0)] UNSPECV_XTHEADINT_PUSH)
235 (use (reg:SI RETURN_ADDR_REGNUM))
236 (use (reg:SI T0_REGNUM))
237 (use (reg:SI T1_REGNUM))
238 (use (reg:SI T2_REGNUM))
239 (use (reg:SI A0_REGNUM))
240 (use (reg:SI A1_REGNUM))
241 (use (reg:SI A2_REGNUM))
242 (use (reg:SI A3_REGNUM))
243 (use (reg:SI A4_REGNUM))
244 (use (reg:SI A5_REGNUM))
245 (use (reg:SI A6_REGNUM))
246 (use (reg:SI A7_REGNUM))
247 (use (reg:SI T3_REGNUM))
248 (use (reg:SI T4_REGNUM))
249 (use (reg:SI T5_REGNUM))
250 (use (reg:SI T6_REGNUM))]
251 "TARGET_XTHEADINT && !TARGET_64BIT"
253 [(set_attr "type" "store")
254 (set_attr "mode" "SI")])
256 (define_insn "th_int_pop"
257 [(unspec_volatile [(const_int 0)] UNSPECV_XTHEADINT_POP)
258 (clobber (reg:SI RETURN_ADDR_REGNUM))
259 (clobber (reg:SI T0_REGNUM))
260 (clobber (reg:SI T1_REGNUM))
261 (clobber (reg:SI T2_REGNUM))
262 (clobber (reg:SI A0_REGNUM))
263 (clobber (reg:SI A1_REGNUM))
264 (clobber (reg:SI A2_REGNUM))
265 (clobber (reg:SI A3_REGNUM))
266 (clobber (reg:SI A4_REGNUM))
267 (clobber (reg:SI A5_REGNUM))
268 (clobber (reg:SI A6_REGNUM))
269 (clobber (reg:SI A7_REGNUM))
270 (clobber (reg:SI T3_REGNUM))
271 (clobber (reg:SI T4_REGNUM))
272 (clobber (reg:SI T5_REGNUM))
273 (clobber (reg:SI T6_REGNUM))
275 "TARGET_XTHEADINT && !TARGET_64BIT"
277 [(set_attr "type" "ret")
278 (set_attr "mode" "SI")])
282 (define_insn "*th_mula<mode>"
283 [(set (match_operand:X 0 "register_operand" "=r")
284 (plus:X (mult:X (match_operand:X 1 "register_operand" "r")
285 (match_operand:X 2 "register_operand" "r"))
286 (match_operand:X 3 "register_operand" "0")))]
289 [(set_attr "type" "imul")
290 (set_attr "mode" "<MODE>")]
293 (define_insn "*th_mulawsi"
294 [(set (match_operand:DI 0 "register_operand" "=r")
296 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
297 (match_operand:SI 2 "register_operand" "r"))
298 (match_operand:SI 3 "register_operand" "0"))))]
299 "TARGET_XTHEADMAC && TARGET_64BIT"
300 "th.mulaw\\t%0,%1,%2"
301 [(set_attr "type" "imul")
302 (set_attr "mode" "SI")]
305 (define_insn "*th_mulawsi2"
306 [(set (match_operand:SI 0 "register_operand" "=r")
307 (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
308 (match_operand:SI 2 "register_operand" "r"))
309 (match_operand:SI 3 "register_operand" "0")))]
310 "TARGET_XTHEADMAC && TARGET_64BIT"
311 "th.mulaw\\t%0,%1,%2"
312 [(set_attr "type" "imul")
313 (set_attr "mode" "SI")]
316 (define_insn "*th_maddhisi4"
317 [(set (match_operand:SI 0 "register_operand" "=r")
320 (sign_extend:SI (match_operand:HI 1 "register_operand" " r"))
321 (sign_extend:SI (match_operand:HI 2 "register_operand" " r")))
322 (match_operand:SI 3 "register_operand" " 0")))]
324 "th.mulah\\t%0,%1,%2"
325 [(set_attr "type" "imul")
326 (set_attr "mode" "SI")]
329 (define_insn "*th_sextw_maddhisi4"
330 [(set (match_operand:DI 0 "register_operand" "=r")
334 (sign_extend:SI (match_operand:HI 1 "register_operand" " r"))
335 (sign_extend:SI (match_operand:HI 2 "register_operand" " r")))
336 (match_operand:SI 3 "register_operand" " 0"))))]
337 "TARGET_XTHEADMAC && TARGET_64BIT"
338 "th.mulah\\t%0,%1,%2"
339 [(set_attr "type" "imul")
340 (set_attr "mode" "SI")]
343 (define_insn "*th_muls<mode>"
344 [(set (match_operand:X 0 "register_operand" "=r")
345 (minus:X (match_operand:X 3 "register_operand" "0")
346 (mult:X (match_operand:X 1 "register_operand" "r")
347 (match_operand:X 2 "register_operand" "r"))))]
350 [(set_attr "type" "imul")
351 (set_attr "mode" "<MODE>")]
354 (define_insn "*th_mulswsi"
355 [(set (match_operand:DI 0 "register_operand" "=r")
357 (minus:SI (match_operand:SI 3 "register_operand" "0")
358 (mult:SI (match_operand:SI 1 "register_operand" "r")
359 (match_operand:SI 2 "register_operand" "r")))))]
360 "TARGET_XTHEADMAC && TARGET_64BIT"
361 "th.mulsw\\t%0,%1,%2"
362 [(set_attr "type" "imul")
363 (set_attr "mode" "SI")]
366 (define_insn "*th_mulswsi2"
367 [(set (match_operand:SI 0 "register_operand" "=r")
368 (minus:SI (match_operand:SI 3 "register_operand" "0")
369 (mult:SI (match_operand:SI 1 "register_operand" "r")
370 (match_operand:SI 2 "register_operand" "r"))))]
371 "TARGET_XTHEADMAC && TARGET_64BIT"
372 "th.mulsw\\t%0,%1,%2"
373 [(set_attr "type" "imul")
374 (set_attr "mode" "SI")]
377 (define_insn "*th_msubhisi4"
378 [(set (match_operand:SI 0 "register_operand" "=r")
379 (minus:SI (match_operand:SI 3 "register_operand" " 0")
380 (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" " r"))
381 (sign_extend:SI (match_operand:HI 2 "register_operand" " r")))))]
383 "th.mulsh\\t%0,%1,%2"
384 [(set_attr "type" "imul")
385 (set_attr "mode" "SI")]
388 (define_insn "*th_sextw_msubhisi4"
389 [(set (match_operand:DI 0 "register_operand" "=r")
391 (minus:SI (match_operand:SI 3 "register_operand" " 0")
393 (sign_extend:SI (match_operand:HI 1 "register_operand" " r"))
394 (sign_extend:SI (match_operand:HI 2 "register_operand" " r"))))))]
395 "TARGET_XTHEADMAC && TARGET_64BIT"
396 "th.mulsh\\t%0,%1,%2"
397 [(set_attr "type" "imul")
398 (set_attr "mode" "SI")]
403 ;; MEMPAIR load 64/32 bit
404 (define_insn "*th_mempair_load_<GPR:mode>2"
405 [(set (match_operand:GPR 0 "register_operand" "=r")
406 (match_operand:GPR 1 "memory_operand" "m"))
407 (set (match_operand:GPR 2 "register_operand" "=r")
408 (match_operand:GPR 3 "memory_operand" "m"))]
409 "TARGET_XTHEADMEMPAIR && reload_completed
410 && th_mempair_operands_p (operands, true, <GPR:MODE>mode)"
411 { return th_mempair_output_move (operands, true, <GPR:MODE>mode, UNKNOWN); }
412 [(set_attr "move_type" "load")
413 (set_attr "type" "load")
414 (set_attr "mode" "<GPR:MODE>")])
416 ;; MEMPAIR store 64/32 bit
417 (define_insn "*th_mempair_store_<GPR:mode>2"
418 [(set (match_operand:GPR 0 "memory_operand" "=m")
419 (match_operand:GPR 1 "register_operand" "r"))
420 (set (match_operand:GPR 2 "memory_operand" "=m")
421 (match_operand:GPR 3 "register_operand" "r"))]
422 "TARGET_XTHEADMEMPAIR && reload_completed
423 && th_mempair_operands_p (operands, false, <GPR:MODE>mode)"
424 { return th_mempair_output_move (operands, false, <GPR:MODE>mode, UNKNOWN); }
425 [(set_attr "move_type" "store")
426 (set_attr "type" "store")
427 (set_attr "mode" "<GPR:MODE>")])
429 ;; MEMPAIR load DI extended signed SI
430 (define_insn "*th_mempair_load_extendsidi2"
431 [(set (match_operand:DI 0 "register_operand" "=r")
432 (sign_extend:DI (match_operand:SI 1 "memory_operand" "m")))
433 (set (match_operand:DI 2 "register_operand" "=r")
434 (sign_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
435 "TARGET_XTHEADMEMPAIR && TARGET_64BIT && reload_completed
436 && th_mempair_operands_p (operands, true, SImode)"
437 { return th_mempair_output_move (operands, true, SImode, SIGN_EXTEND); }
438 [(set_attr "move_type" "load")
439 (set_attr "type" "load")
440 (set_attr "mode" "DI")
441 (set_attr "length" "8")])
443 ;; MEMPAIR load DI extended unsigned SI
444 (define_insn "*th_mempair_load_zero_extendsidi2"
445 [(set (match_operand:DI 0 "register_operand" "=r")
446 (zero_extend:DI (match_operand:SI 1 "memory_operand" "m")))
447 (set (match_operand:DI 2 "register_operand" "=r")
448 (zero_extend:DI (match_operand:SI 3 "memory_operand" "m")))]
449 "TARGET_XTHEADMEMPAIR && TARGET_64BIT && reload_completed
450 && th_mempair_operands_p (operands, true, SImode)"
451 { return th_mempair_output_move (operands, true, SImode, ZERO_EXTEND); }
452 [(set_attr "move_type" "load")
453 (set_attr "type" "load")
454 (set_attr "mode" "DI")
455 (set_attr "length" "8")])
459 ;; Help reload to add a displacement for the base register.
460 ;; In the case `zext(*(uN*)(base+(zext(rN)<<1)))` LRA splits
461 ;; off two new instructions: a) `new_base = base + disp`, and
462 ;; b) `index = zext(rN)<<1`. The index calculation has no
463 ;; corresponding instruction pattern and needs this insn_and_split
466 (define_insn_and_split "*th_memidx_operand"
467 [(set (match_operand:DI 0 "register_operand" "=r")
469 (zero_extend:DI (subreg:SI (match_operand:DI 1 "register_operand" "r") 0))
470 (match_operand 2 "const_int_operand" "n")))]
471 "TARGET_64BIT && TARGET_XTHEADMEMIDX && lra_in_progress"
474 [(set (match_dup 0) (zero_extend:DI (subreg:SI (match_dup 1) 0)))
475 (set (match_dup 0) (ashift:DI (match_dup 0) (match_dup 2)))]
477 [(set_attr "type" "bitmanip")])
479 (define_insn "*th_memidx_zero_extendqi<SUPERQI:mode>2"
480 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r,r,r,r,r")
482 (match_operand:QI 1 "nonimmediate_operand"
483 " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
484 "TARGET_XTHEADMEMIDX"
492 [(set_attr "move_type" "andi,load,load,load,load,load")
493 (set_attr "mode" "<SUPERQI:MODE>")])
495 (define_insn "*th_memidx_extendsidi2"
496 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r")
498 (match_operand:SI 1 "nonimmediate_operand"
499 " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
500 "TARGET_64BIT && TARGET_XTHEADMEMIDX"
508 [(set_attr "move_type" "move,load,load,load,load,load")
509 (set_attr "mode" "DI")])
511 ;; XTheadMemIdx (without XTheadBb)
513 (define_insn_and_split "*th_memidx_zero_extendsidi2"
514 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r")
516 (match_operand:SI 1 "nonimmediate_operand"
517 " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
518 "TARGET_64BIT && TARGET_XTHEADMEMIDX && !TARGET_XTHEADBB"
527 && REG_P (operands[1])
528 && !paradoxical_subreg_p (operands[0])"
530 (ashift:DI (match_dup 1) (const_int 32)))
532 (lshiftrt:DI (match_dup 0) (const_int 32)))]
533 { operands[1] = gen_lowpart (DImode, operands[1]); }
534 [(set_attr "move_type" "shift_shift,load,load,load,load,load")
535 (set_attr "mode" "DI")])
537 (define_insn_and_split "*th_memidx_zero_extendhi<GPR:mode>2"
538 [(set (match_operand:GPR 0 "register_operand" "=r,r,r,r,r,r")
540 (match_operand:HI 1 "nonimmediate_operand"
541 " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
542 "TARGET_XTHEADMEMIDX && !TARGET_XTHEADBB"
551 && REG_P (operands[1])
552 && !paradoxical_subreg_p (operands[0])"
554 (ashift:GPR (match_dup 1) (match_dup 2)))
556 (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
558 operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
559 operands[2] = GEN_INT(GET_MODE_BITSIZE(<GPR:MODE>mode) - 16);
561 [(set_attr "move_type" "shift_shift,load,load,load,load,load")
562 (set_attr "mode" "<GPR:MODE>")])
564 (define_insn_and_split "*th_memidx_extend<SHORT:mode><SUPERQI:mode>2"
565 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r,r,r,r,r")
567 (match_operand:SHORT 1 "nonimmediate_operand"
568 " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
569 "TARGET_XTHEADMEMIDX && !TARGET_XTHEADBB"
572 th.l<SHORT:size>ia\t%0,%1
573 th.l<SHORT:size>ib\t%0,%1
574 th.lr<SHORT:size>\t%0,%1
575 th.lur<SHORT:size>\t%0,%1
576 l<SHORT:size>\t%0,%1"
578 && REG_P (operands[1])
579 && !paradoxical_subreg_p (operands[0])"
580 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
581 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 2)))]
583 operands[0] = gen_lowpart (SImode, operands[0]);
584 operands[1] = gen_lowpart (SImode, operands[1]);
585 operands[2] = GEN_INT (GET_MODE_BITSIZE (SImode)
586 - GET_MODE_BITSIZE (<SHORT:MODE>mode));
588 [(set_attr "move_type" "shift_shift,load,load,load,load,load")
589 (set_attr "mode" "SI")])
591 ;; XTheadMemIdx (with XTheadBb)
593 (define_insn "*th_memidx_bb_zero_extendsidi2"
594 [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r,r")
596 (match_operand:SI 1 "nonimmediate_operand"
597 " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
598 "TARGET_64BIT && TARGET_XTHEADMEMIDX && TARGET_XTHEADBB"
606 [(set_attr "move_type" "shift_shift,load,load,load,load,load")
607 (set_attr "mode" "DI")])
609 (define_insn "*th_memidx_bb_zero_extendhi<GPR:mode>2"
610 [(set (match_operand:GPR 0 "register_operand" "=r,r,r,r,r,r")
612 (match_operand:HI 1 "nonimmediate_operand"
613 " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
614 "TARGET_XTHEADMEMIDX && TARGET_XTHEADBB"
622 [(set_attr "move_type" "shift_shift,load,load,load,load,load")
623 (set_attr "mode" "<GPR:MODE>")])
625 (define_insn "*th_memidx_bb_extendhi<GPR:mode>2"
626 [(set (match_operand:GPR 0 "register_operand" "=r,r,r,r,r,r")
628 (match_operand:HI 1 "nonimmediate_operand"
629 " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
630 "TARGET_XTHEADMEMIDX && TARGET_XTHEADBB"
638 [(set_attr "move_type" "shift_shift,load,load,load,load,load")
639 (set_attr "mode" "<GPR:MODE>")])
641 (define_insn "*th_memidx_bb_extendqi<SUPERQI:mode>2"
642 [(set (match_operand:SUPERQI 0 "register_operand" "=r,r,r,r,r,r")
644 (match_operand:QI 1 "nonimmediate_operand"
645 " r,th_m_mia,th_m_mib,th_m_mir,th_m_miu,m")))]
646 "TARGET_XTHEADMEMIDX && TARGET_XTHEADBB"
654 [(set_attr "move_type" "shift_shift,load,load,load,load,load")
655 (set_attr "mode" "<SUPERQI:MODE>")])
657 ;; All modes that are supported by XTheadMemIdx
658 (define_mode_iterator TH_M_ANYI [(QI "TARGET_XTHEADMEMIDX")
659 (HI "TARGET_XTHEADMEMIDX")
660 (SI "TARGET_XTHEADMEMIDX")
661 (DI "TARGET_64BIT && TARGET_XTHEADMEMIDX")])
663 ;; All modes that are supported by XTheadFMemIdx
664 (define_mode_iterator TH_M_ANYF [(SF "TARGET_HARD_FLOAT && TARGET_XTHEADFMEMIDX")
665 (DF "TARGET_DOUBLE_FLOAT && TARGET_XTHEADFMEMIDX")])
667 ;; All non-extension modes that are supported by XTheadMemIdx
668 (define_mode_iterator TH_M_NOEXTI [(SI "!TARGET_64BIT && TARGET_XTHEADMEMIDX")
669 (DI "TARGET_64BIT && TARGET_XTHEADMEMIDX")])
671 ;; All non-extension modes that are supported by XTheadFMemIdx
672 (define_mode_iterator TH_M_NOEXTF [(SF "TARGET_HARD_FLOAT && TARGET_XTHEADFMEMIDX")
673 (DF "TARGET_DOUBLE_FLOAT && TARGET_XTHEADFMEMIDX")])
675 ;; XTheadMemIdx optimizations
676 ;; All optimizations attempt to improve the operand utilization of
677 ;; XTheadMemIdx instructions, where one sign or zero extended
678 ;; register-index-operand can be shifted left by a 2-bit immediate.
680 ;; The basic idea is the following optimization:
681 ;; (set (reg 0) (op (reg 1) (imm 2)))
682 ;; (set (reg 3) (mem (plus (reg 0) (reg 4)))
684 ;; (set (reg 3) (mem (plus (reg 4) (op2 (reg 1) (imm 2))))
685 ;; This optimization only valid if (reg 0) has no further uses.
687 ;; The three-instruction case is as follows:
688 ;; (set (reg 0) (op1 (reg 1) (imm 2)))
689 ;; (set (reg 3) (op2 (reg 0) (imm 4)))
690 ;; (set (reg 5) (mem (plus (reg 3) (reg 6)))
692 ;; (set (reg 5) (mem (plus (reg 6) (op2 (reg 1) (imm 2/4)))))
693 ;; This optimization is only valid if (reg 0) and (reg 3) have no further uses.
695 ;; The optimization cases are:
696 ;; I) fold 2-bit ashift of register offset into mem-plus RTX
697 ;; US) fold 32-bit zero-extended (shift) offset into mem-plus
698 ;; UZ) fold 32-bit zero-extended (zext) offset into mem-plus
700 ;; The first optimization case is targeting the th.lr<MODE> instructions.
701 ;; The other optimization cases are targeting the th.lur<MODE> instructions
702 ;; and have to consider two forms of zero-extensions:
703 ;; - ashift-32 + lshiftrt-{29..32} if there are no zero-extension instructions.
704 ;; Left-shift amounts of 29..31 indicate a left-shifted zero-extended value.
705 ;; - zero-extend32 if there are zero-extension instructions (XTheadBb or Zbb).
707 ;; We always have three peephole passes per optimization case:
708 ;; a) no-extended (X) word-load
709 ;; b) any-extend (SUBX) word-load
712 ;; Note, that SHIFTs will be converted to MULTs during combine.
714 (define_insn_and_split "*th_memidx_I_a"
715 [(set (match_operand:TH_M_NOEXTI 0 "register_operand" "=r")
716 (mem:TH_M_NOEXTI (plus:X
717 (mult:X (match_operand:X 1 "register_operand" "r")
718 (match_operand:QI 2 "immediate_operand" "i"))
719 (match_operand:X 3 "register_operand" "r"))))]
721 && CONST_INT_P (operands[2])
722 && pow2p_hwi (INTVAL (operands[2]))
723 && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)"
727 (mem:TH_M_NOEXTI (plus:X
729 (ashift:X (match_dup 1) (match_dup 2)))))]
730 { operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
734 (define_insn_and_split "*th_memidx_I_b"
735 [(set (match_operand:X 0 "register_operand" "=r")
736 (any_extend:X (mem:SUBX (plus:X
737 (mult:X (match_operand:X 1 "register_operand" "r")
738 (match_operand:QI 2 "immediate_operand" "i"))
739 (match_operand:X 3 "register_operand" "r")))))]
741 && CONST_INT_P (operands[2])
742 && pow2p_hwi (INTVAL (operands[2]))
743 && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)"
747 (any_extend:X (mem:SUBX (plus:X
749 (ashift:X (match_dup 1) (match_dup 2))))))]
750 { operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
754 (define_insn_and_split "*th_memidx_I_c"
755 [(set (mem:TH_M_ANYI (plus:X
756 (mult:X (match_operand:X 1 "register_operand" "r")
757 (match_operand:QI 2 "immediate_operand" "i"))
758 (match_operand:X 3 "register_operand" "r")))
759 (match_operand:TH_M_ANYI 0 "register_operand" "r"))]
761 && CONST_INT_P (operands[2])
762 && pow2p_hwi (INTVAL (operands[2]))
763 && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)"
766 [(set (mem:TH_M_ANYI (plus:X
768 (ashift:X (match_dup 1) (match_dup 2))))
770 { operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
774 (define_insn_and_split "*th_memidx_US_a"
775 [(set (match_operand:TH_M_NOEXTI 0 "register_operand" "=r")
776 (mem:TH_M_NOEXTI (plus:DI
778 (mult:DI (match_operand:DI 1 "register_operand" "r")
779 (match_operand:QI 2 "immediate_operand" "i"))
780 (match_operand:DI 3 "immediate_operand" "i"))
781 (match_operand:DI 4 "register_operand" "r"))))]
782 "TARGET_64BIT && TARGET_XTHEADMEMIDX
783 && CONST_INT_P (operands[2])
784 && pow2p_hwi (INTVAL (operands[2]))
785 && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)
786 && CONST_INT_P (operands[3])
787 && (INTVAL (operands[3]) >> exact_log2 (INTVAL (operands[2]))) == 0xffffffff"
791 (mem:TH_M_NOEXTI (plus:DI
793 (ashift:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))))]
794 { operands[1] = gen_lowpart (SImode, operands[1]);
795 operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
799 (define_insn_and_split "*th_memidx_US_b"
800 [(set (match_operand:X 0 "register_operand" "=r")
801 (any_extend:X (mem:SUBX (plus:DI
803 (mult:DI (match_operand:DI 1 "register_operand" "r")
804 (match_operand:QI 2 "immediate_operand" "i"))
805 (match_operand:DI 3 "immediate_operand" "i"))
806 (match_operand:DI 4 "register_operand" "r")))))]
807 "TARGET_64BIT && TARGET_XTHEADMEMIDX
808 && CONST_INT_P (operands[2])
809 && pow2p_hwi (INTVAL (operands[2]))
810 && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)
811 && CONST_INT_P (operands[3])
812 && (INTVAL (operands[3]) >> exact_log2 (INTVAL (operands[2]))) == 0xffffffff"
816 (any_extend:X (mem:SUBX (plus:DI
818 (ashift:DI (zero_extend:DI (match_dup 1)) (match_dup 2))))))]
819 { operands[1] = gen_lowpart (SImode, operands[1]);
820 operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
824 (define_insn_and_split "*th_memidx_US_c"
825 [(set (mem:TH_M_ANYI (plus:DI
827 (mult:DI (match_operand:DI 1 "register_operand" "r")
828 (match_operand:QI 2 "immediate_operand" "i"))
829 (match_operand:DI 3 "immediate_operand" "i"))
830 (match_operand:DI 4 "register_operand" "r")))
831 (match_operand:TH_M_ANYI 0 "register_operand" "r"))]
832 "TARGET_64BIT && TARGET_XTHEADMEMIDX
833 && CONST_INT_P (operands[2])
834 && pow2p_hwi (INTVAL (operands[2]))
835 && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)
836 && CONST_INT_P (operands[3])
837 && (INTVAL (operands[3]) >> exact_log2 (INTVAL (operands[2]))) == 0xffffffff"
840 [(set (mem:TH_M_ANYI (plus:DI
842 (ashift:DI (zero_extend:DI (match_dup 1)) (match_dup 2))))
844 { operands[1] = gen_lowpart (SImode, operands[1]);
845 operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
849 (define_insn_and_split "*th_memidx_UZ_a"
850 [(set (match_operand:TH_M_NOEXTI 0 "register_operand" "=r")
851 (mem:TH_M_NOEXTI (plus:DI
852 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
853 (match_operand:DI 2 "register_operand" "r"))))]
854 "TARGET_64BIT && TARGET_XTHEADMEMIDX"
858 (mem:TH_M_NOEXTI (plus:DI
860 (zero_extend:DI (match_dup 1)))))]
863 (define_insn_and_split "*th_memidx_UZ_b"
864 [(set (match_operand:X 0 "register_operand" "=r")
865 (any_extend:X (mem:SUBX (plus:DI
866 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
867 (match_operand:DI 2 "register_operand" "r")))))]
868 "TARGET_64BIT && TARGET_XTHEADMEMIDX"
872 (any_extend:X (mem:SUBX (plus:DI
874 (zero_extend:DI (match_dup 1))))))]
877 (define_insn_and_split "*th_memidx_UZ_c"
878 [(set (mem:TH_M_ANYI (plus:DI
879 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
880 (match_operand:DI 2 "register_operand" "r")))
881 (match_operand:TH_M_ANYI 0 "register_operand" "r"))]
882 "TARGET_64BIT && TARGET_XTHEADMEMIDX"
885 [(set (mem:TH_M_ANYI (plus:DI
887 (zero_extend:DI (match_dup 1))))
892 ;; Note, that we might get GP registers in FP-mode (reg:DF a2)
893 ;; which cannot be handled by the XTheadFMemIdx instructions.
894 ;; This might even happend after register allocation.
895 ;; We could implement splitters that undo the combiner results
896 ;; if "after_reload && !HARDFP_REG_P (operands[0])", but this
897 ;; raises even more questions (e.g. split into what?).
898 ;; So let's solve this by simply requiring XTheadMemIdx
899 ;; which provides the necessary instructions to cover this case.
901 (define_insn "*th_fmemidx_movsf_hardfloat"
902 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,th_m_mir,f,th_m_miu")
903 (match_operand:SF 1 "move_operand" " th_m_mir,f,th_m_miu,f"))]
904 "TARGET_HARD_FLOAT && TARGET_XTHEADFMEMIDX && TARGET_XTHEADMEMIDX
905 && (register_operand (operands[0], SFmode)
906 || reg_or_0_operand (operands[1], SFmode))"
907 { return riscv_output_move (operands[0], operands[1]); }
908 [(set_attr "move_type" "fpload,fpstore,fpload,fpstore")
909 (set_attr "mode" "SF")])
911 (define_insn "*th_fmemidx_movdf_hardfloat_rv64"
912 [(set (match_operand:DF 0 "nonimmediate_operand" "=f,th_m_mir,f,th_m_miu")
913 (match_operand:DF 1 "move_operand" " th_m_mir,f,th_m_miu,f"))]
914 "TARGET_64BIT && TARGET_DOUBLE_FLOAT && TARGET_XTHEADFMEMIDX
915 && TARGET_XTHEADMEMIDX
916 && (register_operand (operands[0], DFmode)
917 || reg_or_0_operand (operands[1], DFmode))"
918 { return riscv_output_move (operands[0], operands[1]); }
919 [(set_attr "move_type" "fpload,fpstore,fpload,fpstore")
920 (set_attr "mode" "DF")])
922 ;; XTheadFMemIdx optimizations
923 ;; Similar like XTheadMemIdx optimizations, but less cases.
925 (define_insn_and_split "*th_fmemidx_I_a"
926 [(set (match_operand:TH_M_NOEXTF 0 "register_operand" "=f")
927 (mem:TH_M_NOEXTF (plus:X
928 (mult:X (match_operand:X 1 "register_operand" "r")
929 (match_operand:QI 2 "immediate_operand" "i"))
930 (match_operand:X 3 "register_operand" "r"))))]
931 "TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX
932 && CONST_INT_P (operands[2])
933 && pow2p_hwi (INTVAL (operands[2]))
934 && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)"
936 "&& reload_completed"
938 (mem:TH_M_NOEXTF (plus:X
940 (ashift:X (match_dup 1) (match_dup 2)))))]
941 { operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
943 [(set_attr "move_type" "fpload")
944 (set_attr "mode" "<UNITMODE>")
945 (set_attr "type" "fmove")
946 (set (attr "length") (const_int 16))])
948 (define_insn_and_split "*th_fmemidx_I_c"
949 [(set (mem:TH_M_ANYF (plus:X
950 (mult:X (match_operand:X 1 "register_operand" "r")
951 (match_operand:QI 2 "immediate_operand" "i"))
952 (match_operand:X 3 "register_operand" "r")))
953 (match_operand:TH_M_ANYF 0 "register_operand" "f"))]
954 "TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX
955 && CONST_INT_P (operands[2])
956 && pow2p_hwi (INTVAL (operands[2]))
957 && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)"
960 [(set (mem:TH_M_ANYF (plus:X
962 (ashift:X (match_dup 1) (match_dup 2))))
964 { operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
968 (define_insn_and_split "*th_fmemidx_US_a"
969 [(set (match_operand:TH_M_NOEXTF 0 "register_operand" "=f")
970 (mem:TH_M_NOEXTF (plus:DI
972 (mult:DI (match_operand:DI 1 "register_operand" "r")
973 (match_operand:QI 2 "immediate_operand" "i"))
974 (match_operand:DI 3 "immediate_operand" "i"))
975 (match_operand:DI 4 "register_operand" "r"))))]
976 "TARGET_64BIT && TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX
977 && CONST_INT_P (operands[2])
978 && pow2p_hwi (INTVAL (operands[2]))
979 && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)
980 && CONST_INT_P (operands[3])
981 && (INTVAL (operands[3]) >> exact_log2 (INTVAL (operands[2]))) == 0xffffffff"
983 "&& reload_completed"
985 (mem:TH_M_NOEXTF (plus:DI
987 (ashift:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))))]
988 { operands[1] = gen_lowpart (SImode, operands[1]);
989 operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
991 [(set_attr "move_type" "fpload")
992 (set_attr "mode" "<UNITMODE>")
993 (set_attr "type" "fmove")
994 (set (attr "length") (const_int 16))])
996 (define_insn_and_split "*th_fmemidx_US_c"
997 [(set (mem:TH_M_ANYF (plus:DI
999 (mult:DI (match_operand:DI 1 "register_operand" "r")
1000 (match_operand:QI 2 "immediate_operand" "i"))
1001 (match_operand:DI 3 "immediate_operand" "i"))
1002 (match_operand:DI 4 "register_operand" "r")))
1003 (match_operand:TH_M_ANYF 0 "register_operand" "f"))]
1004 "TARGET_64BIT && TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX
1005 && CONST_INT_P (operands[2])
1006 && pow2p_hwi (INTVAL (operands[2]))
1007 && IN_RANGE (exact_log2 (INTVAL (operands[2])), 1, 3)
1008 && CONST_INT_P (operands[3])
1009 && (INTVAL (operands[3]) >> exact_log2 (INTVAL (operands[2]))) == 0xffffffff"
1012 [(set (mem:TH_M_ANYF (plus:DI
1014 (ashift:DI (zero_extend:DI (match_dup 1)) (match_dup 2))))
1016 { operands[1] = gen_lowpart (SImode, operands[1]);
1017 operands[2] = GEN_INT (exact_log2 (INTVAL (operands [2])));
1021 (define_insn_and_split "*th_fmemidx_UZ_a"
1022 [(set (match_operand:TH_M_NOEXTF 0 "register_operand" "=f")
1023 (mem:TH_M_NOEXTF (plus:DI
1024 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
1025 (match_operand:DI 2 "register_operand" "r"))))]
1026 "TARGET_64BIT && TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX
1027 && (!HARD_REGISTER_NUM_P (REGNO (operands[0])) || HARDFP_REG_P (REGNO (operands[0])))"
1029 "&& reload_completed"
1031 (mem:TH_M_NOEXTF (plus:DI
1033 (zero_extend:DI (match_dup 1)))))]
1035 [(set_attr "move_type" "fpload")
1036 (set_attr "mode" "<UNITMODE>")
1037 (set_attr "type" "fmove")
1038 (set (attr "length") (const_int 16))])
1040 (define_insn_and_split "*th_fmemidx_UZ_c"
1041 [(set (mem:TH_M_ANYF (plus:DI
1042 (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
1043 (match_operand:DI 2 "register_operand" "r")))
1044 (match_operand:TH_M_ANYF 0 "register_operand" "f"))]
1045 "TARGET_64BIT && TARGET_XTHEADMEMIDX && TARGET_XTHEADFMEMIDX"
1048 [(set (mem:TH_M_ANYF (plus:DI
1050 (zero_extend:DI (match_dup 1))))
1054 (include "thead-peephole.md")