]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[IRA]: Check autoinc and memory address after temporary equivalence substitution
authorVladimir N. Makarov <vmakarov@redhat.com>
Fri, 10 Nov 2023 16:14:46 +0000 (11:14 -0500)
committerVladimir N. Makarov <vmakarov@redhat.com>
Fri, 10 Nov 2023 16:15:50 +0000 (11:15 -0500)
My previous RA patches to take register equivalence into account do
temporary register equivalence substitution to find out that the
equivalence can be consumed by insns.  The insn with the substitution is
checked on validity using target-depended code.  This code expects that
autoinc operations work on register but this register can be substituted
by equivalent memory.  The patch fixes this problem.  The patch also adds
checking that the substitution can be consumed in memory address too.

gcc/ChangeLog:

PR target/112337
* ira-costs.cc: (validate_autoinc_and_mem_addr_p): New function.
(equiv_can_be_consumed_p): Use it.

gcc/testsuite/ChangeLog:

PR target/112337
* gcc.target/arm/pr112337.c: New.

gcc/ira-costs.cc
gcc/testsuite/gcc.target/arm/pr112337.c [new file with mode: 0644]

index 50f80779025766432a8187788382e43ffd48c51a..e0528e76a645d62c1f85db3f411544b78cec7b3e 100644 (file)
@@ -1758,13 +1758,46 @@ process_bb_node_for_costs (ira_loop_tree_node_t loop_tree_node)
     process_bb_for_costs (bb);
 }
 
+/* Return true if all autoinc rtx in X change only a register and memory is
+   valid.  */
+static bool
+validate_autoinc_and_mem_addr_p (rtx x)
+{
+  enum rtx_code code = GET_CODE (x);
+  if (GET_RTX_CLASS (code) == RTX_AUTOINC)
+    return REG_P (XEXP (x, 0));
+  const char *fmt = GET_RTX_FORMAT (code);
+  for (int i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    if (fmt[i] == 'e')
+      {
+       if (!validate_autoinc_and_mem_addr_p (XEXP (x, i)))
+         return false;
+      }
+    else if (fmt[i] == 'E')
+      {
+       for (int j = 0; j < XVECLEN (x, i); j++)
+         if (!validate_autoinc_and_mem_addr_p (XVECEXP (x, i, j)))
+           return false;
+      }
+  /* Check memory after checking autoinc to guarantee that autoinc is already
+     valid for machine-dependent code checking memory address.  */
+  return (!MEM_P (x)
+         || memory_address_addr_space_p (GET_MODE (x), XEXP (x, 0),
+                                         MEM_ADDR_SPACE (x)));
+}
+
 /* Check that reg REGNO can be changed by TO in INSN.  Return true in case the
    result insn would be valid one.  */
 static bool
 equiv_can_be_consumed_p (int regno, rtx to, rtx_insn *insn)
 {
   validate_replace_src_group (regno_reg_rtx[regno], to, insn);
-  bool res = verify_changes (0);
+  /* We can change register to equivalent memory in autoinc rtl.  Some code
+     including verify_changes assumes that autoinc contains only a register.
+     So check this first.  */
+  bool res = validate_autoinc_and_mem_addr_p (PATTERN (insn));
+  if (res)
+    res = verify_changes (0);
   cancel_changes (0);
   return res;
 }
diff --git a/gcc/testsuite/gcc.target/arm/pr112337.c b/gcc/testsuite/gcc.target/arm/pr112337.c
new file mode 100644 (file)
index 0000000..5dacf0a
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=armv8.1-m.main+fp.dp+mve.fp -mfloat-abi=hard" } */
+
+#pragma GCC arm "arm_mve_types.h"
+int32x4_t h(void *p) { return __builtin_mve_vldrwq_sv4si(p); }
+void g(int32x4_t);
+void f(int, int, int, short, int *p) {
+  int *bias = p;
+  for (;;) {
+    int32x4_t d = h(bias);
+    bias += 4;
+    g(d);
+  }
+}