]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[PATCH] RISC-V: Fix some widen-complicate tests.
authorRobin Dapp <rdapp.gcc@gmail.com>
Sat, 15 Feb 2025 16:21:34 +0000 (09:21 -0700)
committerJeff Law <jlaw@ventanamicro.com>
Sat, 15 Feb 2025 16:21:34 +0000 (09:21 -0700)
this patch adds two bridge patterns for combine in order to fix the
widen-complicate tests that regressed since GCC 14.

They key is to allow combination with a ephemeral binary-operation insn
that widens its first operand.  This can subsequently be combined two
a double-widening insn.  If the combination doesn't happen we fall back
to the original non-combined two insns.  We have been doing the same
thing for multiply-add patterns for a while.

There are still remaining tests of a similar kind that fail.  The issue
there is indeed that combine (now) lacks the capability to continue in
cases where there is no apparent local progress but two or three
seemingly no-progress combinations would help us get a better "global" result.

late_combine cannot rescue us here either because it only performs a
propagation if the source can be propagated into all its uses which is
not the case here.  What we might need to do is create internal functions
for those widening operations and combine/simplify at gimple-level already.

I have done testing on rv64gcv_zvl512b but on an older local commit.
Curious what the CI has to say about it now.

Regards
 Robin

gcc/ChangeLog:

* config/riscv/autovec-opt.md
(*single_widen_first_<any_widen_binop:optab><any_extend:su><mode>):
New combine "bridge" pattern.

gcc/config/riscv/autovec-opt.md

index 53431863441c71e7ce5a66b58c1fce2b6ded8e36..0c3b0cc7e05f8d57d2cbb5b8359648c0c89e2900 100644 (file)
 }
 [(set_attr "type" "viwalu")])
 
+; This is a bridge pattern for combine.  Although we do not have a
+; pattern that extends just the first operand it helps combine bridge
+; the gap to the pred_dual_widen insns.
+; If combination fails it will just expand two a separate extend and
+; a binop again.
+(define_insn_and_split "*single_widen_first_sub<any_extend:su><mode>"
+  [(set (match_operand:VWEXTI 0 "register_operand")
+       (minus:VWEXTI
+         (any_extend:VWEXTI
+           (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))
+         (match_operand:VWEXTI 2 "register_operand")))]
+  "TARGET_VECTOR && can_create_pseudo_p ()"
+  "#"
+  "&& 1"
+  [(const_int 0)]
+{
+  insn_code extend_icode = code_for_pred_vf2 (<any_extend:CODE>, <MODE>mode);
+  rtx tmp = gen_reg_rtx (<MODE>mode);
+  rtx extend_ops[] = {tmp, operands[1]};
+  riscv_vector::emit_vlmax_insn (extend_icode, riscv_vector::UNARY_OP, extend_ops);
+
+  rtx ops[] = {operands[0], tmp, operands[2]};
+  insn_code icode = code_for_pred (MINUS, <MODE>mode);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops);
+  DONE;
+}
+[(set_attr "type" "vector")])
+
 (define_insn_and_split "*single_widen_add<any_extend:su><mode>"
   [(set (match_operand:VWEXTI 0 "register_operand")
        (plus:VWEXTI
   insn_code extend_icode = code_for_pred_vf2 (<any_extend:CODE>, <MODE>mode);
   rtx tmp = gen_reg_rtx (<MODE>mode);
   rtx extend_ops[] = {tmp, operands[2]};
-  riscv_vector::emit_vlmax_insn (extend_icode, riscv_vector::UNARY_OP, extend_ops);
+  riscv_vector::emit_vlmax_insn (extend_icode, riscv_vector::UNARY_OP,
+                                extend_ops);
 
   rtx ops[] = {operands[0], operands[1], tmp};
   insn_code icode = code_for_pred (MULT, <MODE>mode);
 }
 [(set_attr "type" "vfwalu")])
 
+; This is a bridge pattern for combine (see above).
+(define_insn_and_split "*single_widen_first_sub<mode>"
+  [(set (match_operand:VWEXTF 0 "register_operand")
+       (minus:VWEXTF
+         (float_extend:VWEXTF
+           (match_operand:<V_DOUBLE_TRUNC> 1 "register_operand"))
+         (match_operand:VWEXTF 2 "register_operand")))]
+  "TARGET_VECTOR && can_create_pseudo_p ()"
+  "#"
+  "&& 1"
+  [(const_int 0)]
+{
+  insn_code extend_icode = code_for_pred_extend (<MODE>mode);
+  rtx tmp = gen_reg_rtx (<MODE>mode);
+  rtx extend_ops[] = {tmp, operands[1]};
+  riscv_vector::emit_vlmax_insn (extend_icode, riscv_vector::UNARY_OP,
+                                extend_ops);
+
+  rtx ops[] = {operands[0], tmp, operands[2]};
+  insn_code icode = code_for_pred (MINUS, <MODE>mode);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP_FRM_DYN, ops);
+  DONE;
+}
+[(set_attr "type" "vector")])
+
 ;; This combine pattern does not correspond to an single instruction,
 ;; i.e. there is no vfwmul.wv instruction. This is a temporary pattern
 ;; produced by a combine pass and if there is no further combine into