]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
lra: Updates of biggest mode for hard regs [PR112278]
authorRichard Sandiford <richard.sandiford@arm.com>
Tue, 5 Dec 2023 09:20:55 +0000 (09:20 +0000)
committerRichard Sandiford <richard.sandiford@arm.com>
Tue, 5 Dec 2023 09:20:55 +0000 (09:20 +0000)
LRA keeps track of the biggest mode for both hard registers and
pseudos.  The updates assume that the modes are ordered, i.e. that
we can tell whether one is no bigger than the other at compile time.

That is (or at least seemed to be) a reasonable restriction for pseudos.
But it isn't necessarily so for hard registers, since the uses of hard
registers can be logically distinct.  The testcase is an example of this.

The biggest mode of hard registers is also special for other reasons.
As the existing comment says:

  /* A reg can have a biggest_mode of VOIDmode if it was only ever seen as
     part of a multi-word register.  In that case, just use the reg_rtx
     mode.  Do the same also if the biggest mode was larger than a register
     or we can not compare the modes.  Otherwise, limit the size to that of
     the biggest access in the function or to the natural mode at least.  */

This patch applies the same approach to the updates.

gcc/
PR rtl-optimization/112278
* lra-int.h (lra_update_biggest_mode): New function.
* lra-coalesce.cc (merge_pseudos): Use it.
* lra-lives.cc (process_bb_lives): Likewise.
* lra.cc (new_insn_reg): Likewise.

gcc/testsuite/
PR rtl-optimization/112278
* gcc.target/aarch64/sve/pr112278.c: New test.

gcc/lra-coalesce.cc
gcc/lra-int.h
gcc/lra-lives.cc
gcc/lra.cc
gcc/testsuite/gcc.target/aarch64/sve/pr112278.c [new file with mode: 0644]

index 04a5bbd714b44ad2f0b010db9e1f2b257995f2c8..d8ca096c35fc9aff5caffded14c1109b8bd5bc7d 100644 (file)
@@ -112,9 +112,7 @@ merge_pseudos (int regno1, int regno2)
     = (lra_merge_live_ranges
        (lra_reg_info[first].live_ranges,
        lra_copy_live_range_list (lra_reg_info[first2].live_ranges)));
-  if (partial_subreg_p (lra_reg_info[first].biggest_mode,
-                       lra_reg_info[first2].biggest_mode))
-    lra_reg_info[first].biggest_mode = lra_reg_info[first2].biggest_mode;
+  lra_update_biggest_mode (first, lra_reg_info[first2].biggest_mode);
 }
 
 /* Change pseudos in *LOC on their coalescing group
index d7ec7c7dc7fc1a355a00356013b1e9b69bf95bd1..5cdf92be7fc36c4ea54ec3cf3fd3e522a88a5d80 100644 (file)
@@ -535,4 +535,19 @@ lra_assign_reg_val (int from, int to)
   lra_reg_info[to].offset = lra_reg_info[from].offset;
 }
 
+/* Update REGNO's biggest recorded mode so that it includes a reference
+   in mode MODE.  */
+inline void
+lra_update_biggest_mode (int regno, machine_mode mode)
+{
+  if (!ordered_p (GET_MODE_SIZE (lra_reg_info[regno].biggest_mode),
+                 GET_MODE_SIZE (mode)))
+    {
+      gcc_checking_assert (HARD_REGISTER_NUM_P (regno));
+      lra_reg_info[regno].biggest_mode = reg_raw_mode[regno];
+    }
+  else if (partial_subreg_p (lra_reg_info[regno].biggest_mode, mode))
+    lra_reg_info[regno].biggest_mode = mode;
+}
+
 #endif /* GCC_LRA_INT_H */
index f60e564da82fa864fe0f65e55cb3d8f1f85dfca4..0b204232849ac24ca79498ad11b21966e2ee68f3 100644 (file)
@@ -770,9 +770,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
        {
          int regno = reg->regno;
 
-         if (partial_subreg_p (lra_reg_info[regno].biggest_mode,
-                               reg->biggest_mode))
-           lra_reg_info[regno].biggest_mode = reg->biggest_mode;
+         lra_update_biggest_mode (regno, reg->biggest_mode);
          if (HARD_REGISTER_NUM_P (regno))
            lra_hard_reg_usage[regno] += freq;
        }
index c917a1adee245691cb4779c25a69b0c85ee202ea..29e2a3506e159dcf52c7b0a5fa8f87dec58d84f4 100644 (file)
@@ -581,9 +581,8 @@ new_insn_reg (rtx_insn *insn, int regno, enum op_type type,
   lra_insn_reg *ir = lra_insn_reg_pool.allocate ();
   ir->type = type;
   ir->biggest_mode = mode;
-  if (NONDEBUG_INSN_P (insn)
-      && partial_subreg_p (lra_reg_info[regno].biggest_mode, mode))
-    lra_reg_info[regno].biggest_mode = mode;
+  if (NONDEBUG_INSN_P (insn))
+    lra_update_biggest_mode (regno, mode);
   ir->subreg_p = subreg_p;
   ir->early_clobber_alts = early_clobber_alts;
   ir->regno = regno;
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr112278.c b/gcc/testsuite/gcc.target/aarch64/sve/pr112278.c
new file mode 100644 (file)
index 0000000..4f56add
--- /dev/null
@@ -0,0 +1,15 @@
+#include <arm_neon.h>
+#include <arm_sve.h>
+
+void
+f (void)
+{
+  {
+    register svint8_t v0 asm ("z0");
+    asm volatile ("" : "=w" (v0));
+  }
+  {
+    register int8x8x4_t v0 asm ("v0");
+    asm volatile ("" : "=w" (v0));
+  }
+}