aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuzhe-Zhong <juzhe.zhong@rivai.ai>2023-09-19 10:59:22 +0800
committerLehua Ding <lehua.ding@rivai.ai>2023-09-19 20:06:23 +0800
commite1817426e85f2181a97ac4f71a87baaa9645b1b5 (patch)
tree658dd172b79d208de57932041a96ea9ff9998ab1
parent005888670a1a0e26d818449a0fbbc5eb3541e303 (diff)
downloadgcc-e1817426e85f2181a97ac4f71a87baaa9645b1b5.zip
gcc-e1817426e85f2181a97ac4f71a87baaa9645b1b5.tar.gz
gcc-e1817426e85f2181a97ac4f71a87baaa9645b1b5.tar.bz2
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.
-rw-r--r--gcc/config/riscv/riscv.cc20
1 files changed, 17 insertions, 3 deletions
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 8c766e2..f1b721d 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