https://gcc.gnu.org/g:d7a835a5309db81a129b0151c7e5deb25b0ec55c

commit r15-7568-gd7a835a5309db81a129b0151c7e5deb25b0ec55c
Author: Robin Dapp <rdapp....@gmail.com>
Date:   Sat Feb 15 09:21:34 2025 -0700

    [PATCH] RISC-V: Fix some widen-complicate tests.
    
    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.

Diff:
---
 gcc/config/riscv/autovec-opt.md | 56 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/gcc/config/riscv/autovec-opt.md b/gcc/config/riscv/autovec-opt.md
index 53431863441c..0c3b0cc7e05f 100644
--- a/gcc/config/riscv/autovec-opt.md
+++ b/gcc/config/riscv/autovec-opt.md
@@ -638,6 +638,34 @@
 }
 [(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
@@ -674,7 +702,8 @@
   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);
@@ -771,6 +800,31 @@
 }
 [(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

Reply via email to