[gcc(refs/vendors/riscv/heads/gcc-13-with-riscv-opts)] RISC-V: Fix RVV can change mode class bug

Jeff Law law@gcc.gnu.org
Tue Sep 26 15:09:57 GMT 2023


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

commit c46e2bb1efc9145d74404f9324446d13899da325
Author: Juzhe-Zhong <juzhe.zhong@rivai.ai>
Date:   Tue Sep 19 10:59:22 2023 +0800

    RISC-V: Fix RVV can change mode class bug
    
    After support the VLS mode conversion, current case triggers a latent bug that we are
    lucky we didn't encounter.
    
    This is a real bug in 'cprop_hardreg':
    
    orig:RVVMF8BI,16,16
    new:V32BI,32,0
    during RTL pass: cprop_hardreg
    auto.c: In function 'main':
    auto.c:79:1: internal compiler error: in partial_subreg_p, at rtl.h:3186
       79 | }
          | ^
    0x10979a7 partial_subreg_p(machine_mode, machine_mode)
            ../../../../gcc/gcc/rtl.h:3186
    0x1723eda mode_change_ok
            ../../../../gcc/gcc/regcprop.cc:402
    0x1724007 maybe_mode_change
            ../../../../gcc/gcc/regcprop.cc:436
    0x172445d find_oldest_value_reg
            ../../../../gcc/gcc/regcprop.cc:489
    0x172534d copyprop_hardreg_forward_1
            ../../../../gcc/gcc/regcprop.cc:808
    0x1727017 cprop_hardreg_bb
            ../../../../gcc/gcc/regcprop.cc:1358
    0x17272f7 execute
            ../../../../gcc/gcc/regcprop.cc:1425
    
    When trying to do reg copy propagation between RVVMF8BI (precision = 16,16)
    and V32BI (precision = 32,0).
    
    The assertion failed in partial_subreg_p:
    gcc_checking_assert (ordered_p (outer_prec, inner_prec));
    
    In regcprop.cc:
    
      if (partial_subreg_p (orig_mode, new_mode))
        return false;
    
    If orig_mode (RVVMF8BI) smaller than new_mode (V32BI), we don't do the hard reg propogation.
    However, the 'partial_subreg_p' cause ICE since gcc_checking_assert (ordered_p (outer_prec, inner_prec)).
    
    After analysis in aarch64.cc, they do careful block in 'TARGET_CAN_CHANGE_MODE_CLASS'.
    So it's reasonable block regcprop when old mode size maybe_lt than new mode size since we won't do the
    copy propgation.
    
    gcc/ChangeLog:
    
            * config/riscv/riscv.cc (riscv_can_change_mode_class): Block unordered VLA and VLS modes.
    
    (cherry picked from commit e1817426e85f2181a97ac4f71a87baaa9645b1b5)

Diff:
---
 gcc/config/riscv/riscv.cc | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 8c766e2e2be..f1b721d54d1 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -8536,12 +8536,26 @@ riscv_slow_unaligned_access (machine_mode, unsigned int)
 /* Implement TARGET_CAN_CHANGE_MODE_CLASS.  */
 
 static bool
-riscv_can_change_mode_class (machine_mode, machine_mode, reg_class_t rclass)
-{
+riscv_can_change_mode_class (machine_mode from, machine_mode to,
+			     reg_class_t rclass)
+{
+  /* We have RVV VLS modes and VLA modes sharing same REG_CLASS.
+     In 'cprop_hardreg' stage, we will try to do hard reg copy propagation
+     between wider mode (FROM) and narrow mode (TO).
+
+     E.g. We should not allow copy propagation
+	- RVVMF8BI (precision = [16, 16]) -> V32BI (precision = [32, 0])
+     since we can't order their size which will cause ICE in regcprop.
+
+     TODO: Even though they are have different size, they always change
+     the whole register.  We may enhance such case in regcprop to optimize
+     it in the future.  */
+  if (reg_classes_intersect_p (V_REGS, rclass)
+      && !ordered_p (GET_MODE_PRECISION (from), GET_MODE_PRECISION (to)))
+    return false;
   return !reg_classes_intersect_p (FP_REGS, rclass);
 }
 
-
 /* Implement TARGET_CONSTANT_ALIGNMENT.  */
 
 static HOST_WIDE_INT


More information about the Gcc-cvs mailing list