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