Like r16-727-g2ec5082dd24cef but the call to partial_subreg_p happens
in a later place, maybe_mode_change.
For this example we have VNx4QImode and DImode which are not ordered.
Bootstrapped and tested on aarch64-linux-gnu.
PR rtl-optimization/124649
gcc/ChangeLog:
* regcprop.cc (maybe_mode_change): Return early
for unordered modes.
gcc/testsuite/ChangeLog:
* gcc.dg/torture/pr124649-1.c: New test.
Signed-off-by: Andrew Pinski <[email protected]>
---
gcc/regcprop.cc | 8 ++++++++
gcc/testsuite/gcc.dg/torture/pr124649-1.c | 15 +++++++++++++++
2 files changed, 23 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/torture/pr124649-1.c
diff --git a/gcc/regcprop.cc b/gcc/regcprop.cc
index b1f00ca0435..2a9956353cc 100644
--- a/gcc/regcprop.cc
+++ b/gcc/regcprop.cc
@@ -431,6 +431,14 @@ maybe_mode_change (machine_mode orig_mode, machine_mode
copy_mode,
machine_mode new_mode, unsigned int regno,
unsigned int copy_regno ATTRIBUTE_UNUSED)
{
+ /* All three modes precision have to be ordered to each other,
+ otherwise partial_subreg_p won't work. */
+ if (!ordered_p (GET_MODE_PRECISION (orig_mode),
+ GET_MODE_PRECISION (copy_mode))
+ || !ordered_p (GET_MODE_PRECISION (copy_mode),
+ GET_MODE_PRECISION (new_mode)))
+ return NULL_RTX;
+
if (partial_subreg_p (copy_mode, orig_mode)
&& partial_subreg_p (copy_mode, new_mode))
return NULL_RTX;
diff --git a/gcc/testsuite/gcc.dg/torture/pr124649-1.c
b/gcc/testsuite/gcc.dg/torture/pr124649-1.c
new file mode 100644
index 00000000000..4cd84d7c4cf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr124649-1.c
@@ -0,0 +1,15 @@
+/* PR rtl-optimization/124649 */
+/* { dg-do compile } */
+/* { dg-additional-options "-mcpu=neoverse-v1" { target aarch64*-*-* } } */
+
+void f(char *g, int b) {
+ int k = b & 4 + 1;
+ int c[b];
+ if (k == 1)
+ b >>= 3;
+ b &= 1;
+ c[0] = b;
+ for (int i = 0; i < k; i++)
+ g[i] = c[i];
+}
+
--
2.43.0