The changes have been bootstrapped and regression tested on
powerpc64le-linux.

Register __dmr1024 as a new 1024-bit opaque built-in type, following
the same pattern as the existing __vector_pair (OOmode) and
__vector_quad (XOmode) opaque types.  __dmr1024 uses TDOmode, which
was already added in a previous commit ("rs6000: Add TDOmode
support"), and is intended to hold the contents of a Dense Math
Register (DMR) when the Dense Math Facility (-mdense-math) is
enabled.

Note there is no __dmr1024 move pattern (movtdo) yet, so none of
these tests perform an actual load/store/copy of a __dmr1024 value;
that is left for a follow-on patch that adds the Dense Math move
support.

2026-07-13  Manjunath Matti  <[email protected]>

gcc/ChangeLog:
        * config/rs6000/rs6000.h (RS6000_BTI_dmr1024): New enumerator.
        (RS6000_BTI_ptr_dmr1024): New enumerator.
        (dmr1024_type_node): New macro.
        (ptr_dmr1024_type_node): New macro.
        * config/rs6000/rs6000-builtin.cc (rs6000_type_string): Handle
        dmr1024_type_node.
        (rs6000_init_builtins): Register the __dmr1024 opaque type and
        its pointer-to-const variant, with 512-bit alignment.
        * config/rs6000/rs6000.cc (rs6000_mangle_type): Handle
        dmr1024_type_node.
        (rs6000_invalid_conversion): Reject conversions to/from TDOmode.
        (rs6000_opaque_type_invalid_use_p): Gate __vector_quad and
        __vector_pair on TARGET_MMA and __dmr1024 on TARGET_DMF
        independently, and require -mdense-math for __dmr1024.

gcc/testsuite/ChangeLog:
        * gcc.target/powerpc/dmr1024-alignment.c: New test case.
        * gcc.target/powerpc/dmr1024-compile.c: Likewise.
        * gcc/testsuite/gcc.target/powerpc/dmr1024-invalid-use-1.c: Likewise.
        * gcc/testsuite/gcc.target/powerpc/dmr1024-invalid-use-2.c: Likewise.
        * gcc/testsuite/gcc.target/powerpc/dmf-no-mma.c: Likewise.

diff --git a/gcc/config/rs6000/rs6000-builtin.cc 
b/gcc/config/rs6000/rs6000-builtin.cc
index e3aab2b6ef1..1a949b4412c 100644
--- a/gcc/config/rs6000/rs6000-builtin.cc
+++ b/gcc/config/rs6000/rs6000-builtin.cc
@@ -512,6 +512,8 @@ const char *rs6000_type_string (tree type_node)
     return "__vector_pair";
   else if (type_node == vector_quad_type_node)
     return "__vector_quad";
+  else if (type_node == dmr1024_type_node)
+    return "__dmr1024";
 
   return "unknown";
 }
@@ -813,6 +815,21 @@ rs6000_init_builtins (void)
   t = build_qualified_type (vector_quad_type_node, TYPE_QUAL_CONST);
   ptr_vector_quad_type_node = build_pointer_type (t);
 
+  /* For TDOmode (1024-bit dense math registers), don't use an alignment
+     of 1024, use 512.  TDOmode loads and stores are always broken up
+     into two vector pair loads or stores.  In addition, we don't have
+     support for aligning the stack to 1024 bits.  */
+  dmr1024_type_node = make_node (OPAQUE_TYPE);
+  SET_TYPE_MODE (dmr1024_type_node, TDOmode);
+  TYPE_SIZE (dmr1024_type_node) = bitsize_int (GET_MODE_BITSIZE (TDOmode));
+  TYPE_PRECISION (dmr1024_type_node) = GET_MODE_BITSIZE (TDOmode);
+  TYPE_SIZE_UNIT (dmr1024_type_node) = size_int (GET_MODE_SIZE (TDOmode));
+  SET_TYPE_ALIGN (dmr1024_type_node, 512);
+  TYPE_USER_ALIGN (dmr1024_type_node) = 0;
+  lang_hooks.types.register_builtin_type (dmr1024_type_node, "__dmr1024");
+  t = build_qualified_type (dmr1024_type_node, TYPE_QUAL_CONST);
+  ptr_dmr1024_type_node = build_pointer_type (t);
+
   tdecl = add_builtin_type ("__bool char", bool_char_type_node);
   TYPE_NAME (bool_char_type_node) = tdecl;
 
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 7743c9cdc4a..bd605d8c66d 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -20649,6 +20649,8 @@ rs6000_mangle_type (const_tree type)
     return "u13__vector_pair";
   if (type == vector_quad_type_node)
     return "u13__vector_quad";
+  if (type == dmr1024_type_node)
+    return "u9__dmr1024";
 
   /* For all other types, use the default mangling.  */
   return NULL;
@@ -28819,7 +28821,8 @@ rs6000_invalid_conversion (const_tree fromtype, 
const_tree totype)
 
   if (frommode != tomode)
     {
-      /* Do not allow conversions to/from XOmode and OOmode types.  */
+      /* Do not allow conversions to/from XOmode, OOmode and TDOmode
+        types.  */
       if (frommode == XOmode)
        return N_("invalid conversion from type %<__vector_quad%>");
       if (tomode == XOmode)
@@ -28828,6 +28831,10 @@ rs6000_invalid_conversion (const_tree fromtype, 
const_tree totype)
        return N_("invalid conversion from type %<__vector_pair%>");
       if (tomode == OOmode)
        return N_("invalid conversion to type %<__vector_pair%>");
+      if (frommode == TDOmode)
+       return N_("invalid conversion from type %<__dmr1024%>");
+      if (tomode == TDOmode)
+       return N_("invalid conversion to type %<__dmr1024%>");
     }
 
   /* Conversion allowed.  */
@@ -29309,33 +29316,44 @@ constant_generates_xxspltidp (vec_const_128bit_type 
*vsx_const)
   return sf_value;
 }
 
-/* Now we have only two opaque types, they are __vector_quad and
-   __vector_pair built-in types.  They are target specific and
-   only available when MMA is supported.  With MMA supported, it
-   simply returns true, otherwise it checks if the given gimple
-   STMT is an assignment, asm or call stmt and uses either of
-   these two opaque types unexpectedly, if yes, it would raise
-   an error message and returns true, otherwise it returns false.  */
+/* Now we have three opaque types: the __vector_quad, __vector_pair and
+   __dmr1024 built-in types.  They are target specific and each one is
+   only available when its required ISA support is enabled:
+   __vector_pair requires MMA or DMF (vector pairs are used by both),
+   __vector_quad requires MMA, and __dmr1024 requires DMF.  Note that
+   DMF does not imply MMA (e.g. -mcpu=future -mno-mma).  With both MMA
+   and DMF enabled, all three types are usable and this simply returns
+   false, otherwise it checks if the given gimple STMT is an
+   assignment, asm or call stmt and uses one of these opaque types
+   whose ISA support is missing, if yes, it would raise an error
+   message and returns true, otherwise it returns false.  */
 
 bool
 rs6000_opaque_type_invalid_use_p (gimple *stmt)
 {
-  if (TARGET_MMA)
+  if (TARGET_MMA && TARGET_DMF)
     return false;
 
-  /* If the given TYPE is one MMA opaque type, emit the corresponding
-     error messages and return true, otherwise return false.  */
+  /* If the given TYPE is one MMA/DMF opaque type whose required ISA
+     support is missing, emit the corresponding error message and
+     return true, otherwise return false.  */
   auto check_and_error_invalid_use = [](tree type)
   {
     tree mv = TYPE_MAIN_VARIANT (type);
-    if (mv == vector_quad_type_node)
+    if (!TARGET_MMA && mv == vector_quad_type_node)
       {
        error ("type %<__vector_quad%> requires the %qs option", "-mmma");
        return true;
       }
-    else if (mv == vector_pair_type_node)
+    else if (!TARGET_MMA && !TARGET_DMF && mv == vector_pair_type_node)
+      {
+       error ("type %<__vector_pair%> requires the %qs or %qs option", "-mmma"
+              , "-mdense-math");
+       return true;
+      }
+    else if (!TARGET_DMF && mv == dmr1024_type_node)
       {
-       error ("type %<__vector_pair%> requires the %qs option", "-mmma");
+       error ("type %<__dmr1024%> requires the %qs option", "-mdense-math");
        return true;
       }
     return false;
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 8235e095bcc..5afca1bfb48 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -2247,6 +2247,7 @@ enum rs6000_builtin_type_index
   RS6000_BTI_const_str,                 /* pointer to const char * */
   RS6000_BTI_vector_pair,       /* unsigned 256-bit types (vector pair).  */
   RS6000_BTI_vector_quad,       /* unsigned 512-bit types (vector quad).  */
+  RS6000_BTI_dmr1024,            /* unsigned 1024-bit type (dmr1024).  */
   RS6000_BTI_const_ptr_void,     /* const pointer to void */
   RS6000_BTI_ptr_V16QI,
   RS6000_BTI_ptr_V1TI,
@@ -2285,6 +2286,7 @@ enum rs6000_builtin_type_index
   RS6000_BTI_ptr_dfloat128,
   RS6000_BTI_ptr_vector_pair,
   RS6000_BTI_ptr_vector_quad,
+  RS6000_BTI_ptr_dmr1024,
   RS6000_BTI_ptr_long_long,
   RS6000_BTI_ptr_long_long_unsigned,
   RS6000_BTI_INTPTI,
@@ -2346,6 +2348,7 @@ enum rs6000_builtin_type_index
 #define const_str_type_node             
(rs6000_builtin_types[RS6000_BTI_const_str])
 #define vector_pair_type_node           
(rs6000_builtin_types[RS6000_BTI_vector_pair])
 #define vector_quad_type_node           
(rs6000_builtin_types[RS6000_BTI_vector_quad])
+#define dmr1024_type_node                
(rs6000_builtin_types[RS6000_BTI_dmr1024])
 #define pcvoid_type_node                
(rs6000_builtin_types[RS6000_BTI_const_ptr_void])
 #define ptr_V16QI_type_node             
(rs6000_builtin_types[RS6000_BTI_ptr_V16QI])
 #define ptr_V1TI_type_node              
(rs6000_builtin_types[RS6000_BTI_ptr_V1TI])
@@ -2384,6 +2387,7 @@ enum rs6000_builtin_type_index
 #define ptr_dfloat128_type_node                 
(rs6000_builtin_types[RS6000_BTI_ptr_dfloat128])
 #define ptr_vector_pair_type_node       
(rs6000_builtin_types[RS6000_BTI_ptr_vector_pair])
 #define ptr_vector_quad_type_node       
(rs6000_builtin_types[RS6000_BTI_ptr_vector_quad])
+#define ptr_dmr1024_type_node            
(rs6000_builtin_types[RS6000_BTI_ptr_dmr1024])
 #define ptr_long_long_integer_type_node         
(rs6000_builtin_types[RS6000_BTI_ptr_long_long])
 #define ptr_long_long_unsigned_type_node 
(rs6000_builtin_types[RS6000_BTI_ptr_long_long_unsigned])
 
diff --git a/gcc/testsuite/gcc.target/powerpc/dmf-no-mma.c 
b/gcc/testsuite/gcc.target/powerpc/dmf-no-mma.c
new file mode 100644
index 00000000000..3da0c8c601e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/dmf-no-mma.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_future_compile_ok } */
+/* { dg-options "-mdejagnu-cpu=future -mdense-math -mno-mma -O2" } */
+
+/* Dense Math (-mdense-math) without MMA supports __vector_pair and
+   __dmr1024 (see dmf-no-mma-1.c), but __vector_quad moves still
+   require MMA.  Verify that a __vector_quad copy under -mno-mma is
+   diagnosed with a proper error message via the movxo expander
+   instead of ICEing.  The error is emitted during RTL expansion, so
+   its reported location can be fragile; match it anywhere in the
+   output.  */
+
+void
+copy_quad (__vector_quad *dst, __vector_quad *src)
+{
+  *dst = *src;
+}
+
+/* { dg-error "type '__vector_quad' requires the '-mmma' option" "" { target 
*-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.target/powerpc/dmr1024-alignment.c 
b/gcc/testsuite/gcc.target/powerpc/dmr1024-alignment.c
new file mode 100644
index 00000000000..147556c90e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/dmr1024-alignment.c
@@ -0,0 +1,33 @@
+/* { dg-do run } */
+/* { dg-require-effective-target hard_float } */
+/* { dg-options "-O2 -mhard-float" } */
+
+/* Verify the __dmr1024 opaque type is always registered (regardless of
+   whether -mdense-math is enabled) and has the expected size and
+   alignment, following the same model as __vector_pair and
+   __vector_quad in mma-alignment.c.  */
+
+#include <stdlib.h>
+
+struct
+{
+  int __attribute__ ((__aligned__)) ivar;
+  __dmr1024 dmr;
+} s;
+
+int
+main (void)
+{
+  /* __dmr1024 holds the contents of a 1,024-bit Dense Math Register.  */
+  if (sizeof (__dmr1024) != 128)
+    abort ();
+
+  /* __dmr1024 loads/stores are always broken into two vector-pair
+     transfers, and there is no support for aligning the stack to
+     1,024 bits, so the type alignment is 512 bits (64 bytes), matching
+     __vector_quad rather than its own 1,024-bit size.  */
+  if (__alignof__ (s.dmr) != 64)
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/dmr1024-compile.c 
b/gcc/testsuite/gcc.target/powerpc/dmr1024-compile.c
new file mode 100644
index 00000000000..2ae66738f02
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/dmr1024-compile.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_future_compile_ok } */
+/* { dg-options "-mdejagnu-cpu=future -mdense-math -O2" } */
+
+/* Verify that __dmr1024 is accepted as a type with the expected size
+   and alignment, and that it can be used through pointers without
+   triggering any diagnostics.  Only pointers are passed around here;
+   actual __dmr1024 value copies are covered by dmr1024-copy.c.  */
+
+typedef __dmr1024 dmr_t;
+
+_Static_assert (sizeof (__dmr1024) == 128, "__dmr1024 must be 128 bytes");
+_Static_assert (__alignof__ (__dmr1024) == 64,
+                "__dmr1024 alignment must be 64 bytes");
+
+struct dmr_holder
+{
+  __dmr1024 dmr;
+};
+
+extern __dmr1024 global_dmr;
+extern const dmr_t *global_dmr_ptr;
+
+__dmr1024 *
+identity (__dmr1024 *p)
+{
+  return p;
+}
+
+const dmr_t *
+identity_const (const dmr_t *p)
+{
+  return p;
+}
+
+void *
+as_void_ptr (__dmr1024 *p)
+{
+  return (void *) p;
+}
+
+__dmr1024 *
+holder_dmr (struct dmr_holder *h)
+{
+  return &h->dmr;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/dmr1024-invalid-use-1.c 
b/gcc/testsuite/gcc.target/powerpc/dmr1024-invalid-use-1.c
new file mode 100644
index 00000000000..dfd72bded7a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/dmr1024-invalid-use-1.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_future_compile_ok } */
+/* { dg-options "-mdejagnu-cpu=future -mdense-math -O2 -std=gnu17" } */
+
+/* The __dmr1024 opaque type, like __vector_quad and __vector_pair
+   (see pr96506-1.c), may not be used as a function parameter.  Verify
+   we flag errors on these uses rather than ICE.
+
+   This must be kept separate from the return-value test
+   (dmr1024-invalid-use-2.c): the parameter diagnostics below are only
+   emitted during RTL expansion, which is skipped entirely once a
+   parse-time error (such as the return-value diagnostic) has been
+   emitted.  */
+
+extern void bar0 ();
+extern void bar1 ();
+
+typedef __dmr1024 dmr_t;
+
+void
+foo0 (void)
+{
+  __dmr1024 v;
+  bar0 (v); /* { dg-error "invalid use of Dense Math operand of type 
.__dmr1024. as a function parameter" } */
+}
+
+void
+foo1 (void)
+{
+  dmr_t v;
+  bar1 (v); /* { dg-error "invalid use of Dense Math operand of type 
.__dmr1024. as a function parameter" } */
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/dmr1024-invalid-use-2.c 
b/gcc/testsuite/gcc.target/powerpc/dmr1024-invalid-use-2.c
new file mode 100644
index 00000000000..c814cf78827
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/dmr1024-invalid-use-2.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_future_compile_ok } */
+/* { dg-options "-mdejagnu-cpu=future -mdense-math -O2" } */
+
+/* The __dmr1024 opaque type, like __vector_quad and __vector_pair
+   (see pr96506-2.c), may not be used as a function return value.
+   Verify we flag errors on these uses rather than ICE.  Kept separate
+   from the function-parameter test (dmr1024-invalid-use-1.c); see the
+   comment there.  */
+
+typedef __dmr1024 dmr_t;
+
+__dmr1024
+foo0 (__dmr1024 *src)
+{ /* { dg-error "invalid use of Dense Math type .__dmr1024. as a function 
return value" } */
+  return *src;
+}
+
+dmr_t
+foo1 (dmr_t *src)
+{ /* { dg-error "invalid use of Dense Math type .__dmr1024. as a function 
return value" } */
+  return *src;
+}
-- 
2.52.0

Reply via email to