]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[PR118067][LRA]: Check secondary memory mode for the reg class
authorVladimir N. Makarov <vmakarov@redhat.com>
Fri, 17 Jan 2025 20:56:29 +0000 (15:56 -0500)
committerVladimir N. Makarov <vmakarov@redhat.com>
Fri, 17 Jan 2025 20:57:12 +0000 (15:57 -0500)
  This is the second patch for the PR for the new test.  The patch
solves problem in the case when secondary memory mode (SImode in the
PR test) returned by hook secondary_memory_needed_mode can not be used
for reg class (ALL_MASK_REGS) involved in secondary memory moves.  The
patch uses reg mode instead of one returned by
secondary_memory_needed_mode in this case.

gcc/ChangeLog:

PR rtl-optimization/118067
* lra-constraints.cc (invalid_mode_reg_p): New function.
(curr_insn_transform): Use it to check mode returned by target
secondary_memory_needed_mode.

gcc/testsuite/ChangeLog:

* gcc.target/i386/pr118067-2.c: New.

gcc/lra-constraints.cc
gcc/testsuite/gcc.target/i386/pr118067-2.c [new file with mode: 0644]

index 3d5abcfaeb0bf9ae1810d557ce4654b6df0a70d4..cd19da294db3bdce66f0758e8915e8820a6914cc 100644 (file)
@@ -4129,6 +4129,19 @@ swap_operands (int nop)
   lra_update_dup (curr_id, nop + 1);
 }
 
+/* Return TRUE if X is a (subreg of) reg and there are no hard regs of X class
+   which can contain value of MODE.  */
+static bool invalid_mode_reg_p (enum machine_mode mode, rtx x)
+{
+  if (SUBREG_P (x))
+    x = SUBREG_REG (x);
+  if (! REG_P (x))
+    return false;
+  enum reg_class rclass = get_reg_class (REGNO (x));
+  return hard_reg_set_subset_p (ira_prohibited_class_mode_regs[rclass][mode],
+                               reg_class_contents[rclass]);
+}
+
 /* Main entry point of the constraint code: search the body of the
    current insn to choose the best alternative.  It is mimicking insn
    alternative cost calculation model of former reload pass.  That is
@@ -4389,6 +4402,10 @@ curr_insn_transform (bool check_only_p)
       rld = partial_subreg_p (GET_MODE (src), GET_MODE (dest)) ? src : dest;
       rld_mode = GET_MODE (rld);
       sec_mode = targetm.secondary_memory_needed_mode (rld_mode);
+      if (rld_mode != sec_mode
+         && (invalid_mode_reg_p (sec_mode, dest)
+             || invalid_mode_reg_p (sec_mode, src)))
+       sec_mode = rld_mode;
       new_reg = lra_create_new_reg (sec_mode, NULL_RTX, NO_REGS, NULL,
                                    "secondary");
       /* If the mode is changed, it should be wider.  */
diff --git a/gcc/testsuite/gcc.target/i386/pr118067-2.c b/gcc/testsuite/gcc.target/i386/pr118067-2.c
new file mode 100644 (file)
index 0000000..831871d
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O -fno-split-wide-types -mavx512f -mcpu=k8" } */
+
+typedef unsigned short U __attribute__((__vector_size__(64)));
+typedef int V __attribute__((__vector_size__(64)));
+typedef __int128 W __attribute__((__vector_size__(64)));
+
+W
+foo(U u, V v)
+{
+  W w;
+  /* __asm__ volatile ("" : "=v"(w)); prevents the -Wuninitialized warning */
+  u[0] >>= 1;
+  v %= (V)w;
+  return (W)u + (W)v;
+}