RISC-V: Fix RVV can change mode class bug
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Testing passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-arm |
success
|
Testing passed
|
Commit Message
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): Fix RVV mode change bug.
---
gcc/config/riscv/riscv.cc | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
Comments
Sorry for I made a mistake here.
Change 'mayb_lt' into '!ordered_p' in V2:
https://gcc.gnu.org/pipermail/gcc-patches/2023-September/630835.html
juzhe.zhong@rivai.ai
From: Juzhe-Zhong
Date: 2023-09-19 10:25
To: gcc-patches
CC: kito.cheng; kito.cheng; jeffreyalaw; rdapp.gcc; Juzhe-Zhong
Subject: [PATCH] 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): Fix RVV mode change bug.
---
gcc/config/riscv/riscv.cc | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 8c766e2e2be..28b45a87351 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -8536,8 +8536,22 @@ 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 such propagation cause ICE and execution FAIL.
+
+ However, we could allow copy propagation
+ - RVVMF4 (precision = [32, 32]) -> V32BI (precision = [32, 0])
+ since RVVMF4 always >= RV32BI. */
+ if (reg_classes_intersect_p (V_REGS, rclass)
+ && maybe_lt (GET_MODE_PRECISION (from), GET_MODE_PRECISION (to)))
+ return false;
return !reg_classes_intersect_p (FP_REGS, rclass);
}
--
2.36.3
@@ -8536,8 +8536,22 @@ 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 such propagation cause ICE and execution FAIL.
+
+ However, we could allow copy propagation
+ - RVVMF4 (precision = [32, 32]) -> V32BI (precision = [32, 0])
+ since RVVMF4 always >= RV32BI. */
+ if (reg_classes_intersect_p (V_REGS, rclass)
+ && maybe_lt (GET_MODE_PRECISION (from), GET_MODE_PRECISION (to)))
+ return false;
return !reg_classes_intersect_p (FP_REGS, rclass);
}