Adding Richard since he's reviewed the generic opaque mode code in
the past and this patch contains some more eneric support.

GCC handles pseudos that are used uninitialized, by emitting a
(set (reg: <reg>) CONST0_RTX(regmode)) before their uninitialized
pseudo usage.  Currently, CONST0_RTX(mode) is NULL for opaque modes,
which leads to an ICE.  The solution is to enhance init_emit_once() to
add initialization of CONST0_RTX for opaque modes using a target hook,
since CONST0_RTX probably are different for each opaque mode and each
target.  The default hook throws an error to force the target to think
hard about what their CONST0_RTX values should be for each mode.

This passed bootstrap and regtesting on x86_64-linux and powerpc64le-linux
with no regressions.  Ok for mainline?

Peter


gcc/
        PR target/98872
        * config/rs6000/mma.md (*movoo): Accept zero constraint.
        (mma_xxsetaccz): Use CONST0_RTX.
        * config/rs6000/predicates.md: Recognize OOmode CONST0_RTX.
        * config/rs6000/rs6000.c (TARGET_OPAQUE_CONST0_RTX): Define.
        (rs6000_split_multireg_move): Handle splitting an OOmode register
        set to CONST0_RTX.
        (rs6000_opaque_const0_rtx): New function.
        * emit-rtl.c (init_emit_once): Initialize CONST0_RTX for opaque modes.
        * hooks.c (hook_rtx_mode_unreachable): New function.
        * hooks.h (hook_rtx_mode_unreachable): Declare
        * target.def (opaque_const0_rtx): New target hook.
        * doc/tm.texi.in: Document it.
        * doc/tm.texi: Regenerate.

gcc/testsuite/
        * gcc.target/powerpc/pr98872.c: New test.

diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md
index 87569f1c31d..fab849a4f12 100644
--- a/gcc/config/rs6000/mma.md
+++ b/gcc/config/rs6000/mma.md
@@ -272,7 +272,7 @@
 
 (define_insn_and_split "*movoo"
   [(set (match_operand:OO 0 "nonimmediate_operand" "=wa,m,wa")
-       (match_operand:OO 1 "input_operand" "m,wa,wa"))]
+       (match_operand:OO 1 "input_operand" "m,wa,waO"))]
   "TARGET_MMA
    && (gpc_reg_operand (operands[0], OOmode)
        || gpc_reg_operand (operands[1], OOmode))"
@@ -473,9 +473,7 @@
        (const_int 0))]
   "TARGET_MMA"
 {
-  rtx xo0 = gen_rtx_UNSPEC (XOmode, gen_rtvec (1, const0_rtx),
-                           UNSPEC_MMA_XXSETACCZ);
-  emit_insn (gen_rtx_SET (operands[0], xo0));
+  emit_insn (gen_rtx_SET (operands[0], CONST0_RTX (XOmode)));
   DONE;
 })
 
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 5d1952e59d3..30805ab0619 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -1081,6 +1081,10 @@
       && easy_vector_constant (op, mode))
     return 1;
 
+  /* For OOmode, zero is an easy constant.  */
+  if (mode == OOmode && op == CONST0_RTX (mode))
+    return 1;
+
   /* For floating-point or multi-word mode, the only remaining valid type
      is a register.  */
   if (SCALAR_FLOAT_MODE_P (mode)
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index f5565a1a253..c726aa09d26 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1752,6 +1752,10 @@ static const struct attribute_spec 
rs6000_attribute_table[] =
 
 #undef TARGET_INVALID_CONVERSION
 #define TARGET_INVALID_CONVERSION rs6000_invalid_conversion
+
+#undef TARGET_OPAQUE_CONST0_RTX
+#define TARGET_OPAQUE_CONST0_RTX rs6000_opaque_const0_rtx
+
 
 
 /* Processor table.  */
@@ -16624,6 +16628,19 @@ rs6000_split_multireg_move (rtx dst, rtx src)
          return;
        }
 
+      /* Split the clearing of an OOmode register pair into clearing
+        of its two constituent registers.  */
+      if (REG_P (dst) && mode == OOmode && src == CONST0_RTX (mode))
+       {
+         int regno = REGNO (dst);
+         gcc_assert (VSX_REGNO_P (regno));
+         emit_insn (gen_rtx_SET (gen_rtx_REG (reg_mode, regno),
+                                 CONST0_RTX (reg_mode)));
+         emit_insn (gen_rtx_SET (gen_rtx_REG (reg_mode, regno + 1),
+                                 CONST0_RTX (reg_mode)));
+         return;
+       }
+
       /* Register -> register moves can use common code.  */
     }
 
@@ -27477,6 +27494,25 @@ rs6000_output_addr_vec_elt (FILE *file, int value)
   fprintf (file, "\n");
 }
 
+/* Implement TARGET_OPAQUE_CONST0_RTX.  */
+
+rtx
+rs6000_opaque_const0_rtx (machine_mode mode)
+{
+  gcc_assert (OPAQUE_MODE_P (mode));
+
+  switch (mode)
+    {
+    case E_OOmode:
+      return const0_rtx;
+    case E_XOmode:
+      return gen_rtx_UNSPEC (XOmode, gen_rtvec (1, const0_rtx),
+                            UNSPEC_MMA_XXSETACCZ);
+    default:
+      gcc_unreachable ();
+    }
+}
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 #include "gt-rs6000.h"
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index b23284e5e56..4ac26491481 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -6408,6 +6408,11 @@ init_emit_once (void)
     if (GET_MODE_CLASS ((machine_mode) i) == MODE_CC)
       const_tiny_rtx[0][i] = const0_rtx;
 
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_OPAQUE)
+    {
+      const_tiny_rtx[0][(int) mode] = targetm.opaque_const0_rtx (mode);
+    }
+
   pc_rtx = gen_rtx_fmt_ (PC, VOIDmode);
   ret_rtx = gen_rtx_fmt_ (RETURN, VOIDmode);
   simple_return_rtx = gen_rtx_fmt_ (SIMPLE_RETURN, VOIDmode);
diff --git a/gcc/hooks.c b/gcc/hooks.c
index 680271f76a4..8e71105265a 100644
--- a/gcc/hooks.c
+++ b/gcc/hooks.c
@@ -380,6 +380,12 @@ hook_bool_wint_wint_uint_bool_true (const widest_int &, 
const widest_int &,
   return true;
 }
 
+rtx
+hook_rtx_mode_unreachable (machine_mode mode ATTRIBUTE_UNUSED)
+{
+  gcc_unreachable ();
+}
+
 /* Generic hook that takes an rtx and returns it.  */
 rtx
 hook_rtx_rtx_identity (rtx x)
diff --git a/gcc/hooks.h b/gcc/hooks.h
index add9a742e41..ba9b6d9ff75 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -119,6 +119,7 @@ extern unsigned int hook_uint_mode_0 (machine_mode);
 extern bool default_can_output_mi_thunk_no_vcall (const_tree, HOST_WIDE_INT,
                                                  HOST_WIDE_INT, const_tree);
 
+extern rtx hook_rtx_mode_unreachable (machine_mode);
 extern rtx hook_rtx_rtx_identity (rtx);
 extern rtx hook_rtx_rtx_null (rtx);
 extern rtx hook_rtx_tree_int_null (tree, int);
diff --git a/gcc/target.def b/gcc/target.def
index be7fcde961a..c026e584c78 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -3362,6 +3362,13 @@ constants can be done inline.  The function\n\
  HOST_WIDE_INT, (const_tree constant, HOST_WIDE_INT basic_align),
  default_constant_alignment)
 
+DEFHOOK
+(opaque_const0_rtx,
+ "Return an RTX representing the value @code{0} for opaque mode @var{mode}.\n\
+The default version of this hook always throws an error.",
+rtx, (machine_mode mode),
+hook_rtx_mode_unreachable)
+
 DEFHOOK
 (translate_mode_attribute,
  "Define this hook if during mode attribute processing, the port should\n\
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 3b19e6f4281..74f6626112b 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -3361,6 +3361,8 @@ stack.
 
 @hook TARGET_REF_MAY_ALIAS_ERRNO
 
+@hook TARGET_OPAQUE_CONST0_RTX
+
 @hook TARGET_TRANSLATE_MODE_ATTRIBUTE
 
 @hook TARGET_SCALAR_MODE_SUPPORTED_P
diff --git a/gcc/testsuite/gcc.target/powerpc/pr98872.c 
b/gcc/testsuite/gcc.target/powerpc/pr98872.c
new file mode 100644
index 00000000000..580b90de7dc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr98872.c
@@ -0,0 +1,20 @@
+/* PR target/98872 */
+/* { dg-do compile } */
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
+
+/* Verify we do not ICE on the tests below.  */
+
+void
+foo (__vector_quad *dst)
+{
+  __vector_quad acc;
+  *dst = acc;
+}
+
+void
+bar (__vector_pair *dst)
+{
+  __vector_pair pair;
+  *dst = pair;
+}

Reply via email to