Add two new builtins for extracting data from 1024-bit Dense Math
Registers (DMRs):
- __builtin_dmr_extract512 (void *, dmr1024 *, const int<2>):
extracts one 512-bit half of a DMR into four 128-bit vectors.
- __builtin_disassemble_dmr (void *, dmr1024 *):
extracts both 512-bit halves of a DMR into eight 128-bit vectors.
2026-07-16 Surya Kumari Jangala <[email protected]>
gcc:
* config/rs6000/rs6000-builtins.def (__builtin_dmr_extract512): New
built-in.
(__builtin_disassemble_dmr): Likewise.
(__builtin_dmr_extract512_internal): New internal built-in.
* config/rs6000/mma.md (UNSPEC_DMF_EXTRACT1024): New UNSPEC entry.
* config/rs6000/rs6000-builtin.cc (rs6000_gimple_fold_mma_builtin):
Exempt RS6000_BIF_DISASSEMBLE_DMR from the early-return guard.
Generate appropriate gimple code for the extract builtins.
gcc/testsuite:
* gcc.target/powerpc/dmf-extract512.c: New test.
* gcc.target/powerpc/dmf-disassemble-dmr.c: New test.
---
gcc/config/rs6000/mma.md | 1 +
gcc/config/rs6000/rs6000-builtin.cc | 71 ++++++++++++++++++-
gcc/config/rs6000/rs6000-builtins.def | 9 +++
.../gcc.target/powerpc/dmf-disassemble-dmr.c | 24 +++++++
.../gcc.target/powerpc/dmf-extract512.c | 20 ++++++
5 files changed, 124 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/powerpc/dmf-disassemble-dmr.c
create mode 100644 gcc/testsuite/gcc.target/powerpc/dmf-extract512.c
diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md
index 07dfb09fba0..01bd708fbdc 100644
--- a/gcc/config/rs6000/mma.md
+++ b/gcc/config/rs6000/mma.md
@@ -94,6 +94,7 @@ (define_c_enum "unspec"
UNSPEC_DMF_INSERT512
UNSPEC_DMF_EXTRACT512
UNSPEC_DMF_INSERT1024
+ UNSPEC_DMF_EXTRACT1024
UNSPEC_DMR_RELOAD_FROM_MEMORY
UNSPEC_DMR_RELOAD_TO_MEMORY
UNSPEC_DMF_DMXOR
diff --git a/gcc/config/rs6000/rs6000-builtin.cc
b/gcc/config/rs6000/rs6000-builtin.cc
index 0c6d961d7a7..c0aa885ac01 100644
--- a/gcc/config/rs6000/rs6000-builtin.cc
+++ b/gcc/config/rs6000/rs6000-builtin.cc
@@ -1131,7 +1131,8 @@ rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi,
if (rs6000_builtin_info[fncode].assoc_bif == RS6000_BIF_NONE
&& fncode != RS6000_BIF_LXVP
&& fncode != RS6000_BIF_STXVP
- && fncode != RS6000_BIF_DMMR)
+ && fncode != RS6000_BIF_DMMR
+ && fncode != RS6000_BIF_DISASSEMBLE_DMR)
return false;
bifdata *bd = &rs6000_builtin_info[fncode];
@@ -1139,6 +1140,74 @@ rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator
*gsi,
gimple *new_call;
tree new_decl;
+ if (fncode == RS6000_BIF_DMF_EXTRACT512
+ || fncode == RS6000_BIF_DISASSEMBLE_DMR)
+ {
+ unsigned num_extract512;
+ push_gimplify_context (true);
+ tree dst_ptr = gimple_call_arg (stmt, 0);
+ tree src_ptr = gimple_call_arg (stmt, 1);
+ tree src_type = build_pointer_type (dmr1024_type_node);
+
+ if (TREE_TYPE (src_ptr) != src_type)
+ src_ptr = build1 (NOP_EXPR, src_type, src_ptr);
+
+ /* The following code will ensure we are sending *src as parameter. */
+ tree src = make_ssa_name (TREE_TYPE (src_type));
+ gimplify_assign (src, build_simple_mem_ref (src_ptr), &new_seq);
+
+ /* Now we should call the internal builtin
RS6000_BIF_DM_EXTRACT512_INTERNAL. */
+ if (fncode == RS6000_BIF_DISASSEMBLE_DMR)
+ num_extract512 = 2;
+ else
+ num_extract512 = 1;
+
+ tree extract_decl =
rs6000_builtin_decls[RS6000_BIF_DMF_EXTRACT512_INTERNAL];
+
+ for (unsigned i = 0; i < num_extract512; i++)
+ {
+ tree const_arg;
+ if (fncode == RS6000_BIF_DISASSEMBLE_DMR)
+ const_arg = build_int_cstu (uint16_type_node, i);
+ else
+ const_arg = gimple_call_arg (stmt, 2);
+
+ /* Create call. */
+ new_call = gimple_build_call (extract_decl, 2, src, const_arg);
+ /* Create a tmp reg to denote lhs of call. */
+ tree lhs = make_ssa_name (vector_quad_type_node);
+
+ /* lhs = new_call */
+ gimple_call_set_lhs (new_call, lhs);
+
+ /* Add gimple stmt to gimple sequence. */
+ gimple_seq_add_stmt (&new_seq, new_call);
+
+ /* Now lhs contains the 512-bit value in vector_quad. We have to now
+ split up the vector_quad into individual vectors. */
+
+ new_decl = rs6000_builtin_decls[RS6000_BIF_DISASSEMBLE_ACC_INTERNAL];
+ tree dst_type = build_pointer_type_for_mode (unsigned_V16QI_type_node,
+ ptr_mode, true);
+
+ tree dst_base = build1 (NOP_EXPR, dst_type, dst_ptr);
+ for (unsigned j = 0; j < 4; j++)
+ {
+ tree dst = build2 (MEM_REF, unsigned_V16QI_type_node, dst_base,
+ build_int_cst (dst_type, j * 16 + i * 64));
+ tree dstssa = make_ssa_name (unsigned_V16QI_type_node);
+ new_call = gimple_build_call (new_decl, 2, lhs,
+ build_int_cstu (uint16_type_node,
j));
+ gimple_call_set_lhs (new_call, dstssa);
+ gimple_seq_add_stmt (&new_seq, new_call);
+ gimplify_assign (dst, dstssa, &new_seq);
+ }
+ }
+ pop_gimplify_context (NULL);
+ gsi_replace_with_seq (gsi, new_seq, true);
+ return true;
+ }
+
/* Compatibility built-ins; we used to call these
__builtin_mma_{dis,}assemble_pair, but now we call them
__builtin_vsx_{dis,}assemble_pair. Handle the old versions. */
diff --git a/gcc/config/rs6000/rs6000-builtins.def
b/gcc/config/rs6000/rs6000-builtins.def
index 2c0bc1d0119..f949db41063 100644
--- a/gcc/config/rs6000/rs6000-builtins.def
+++ b/gcc/config/rs6000/rs6000-builtins.def
@@ -4121,6 +4121,15 @@
dmr1024 __builtin_build_dmr_internal (vuc, vuc, vuc, vuc, vuc, vuc, vuc,
vuc);
BUILD_DMR_INTERNAL dmf_build_dmr {dm}
+ void __builtin_dmr_extract512 (void *, dmr1024 *, const int<2>);
+ DMF_EXTRACT512 nothing {dm,dmint}
+
+ v512 __builtin_dmr_extract512_internal (dmr1024, const int<2>);
+ DMF_EXTRACT512_INTERNAL dm_extract512 {dm}
+
+ void __builtin_disassemble_dmr (void *, dmr1024 *);
+ DISASSEMBLE_DMR nothing {dm}
+
void __builtin_mma_dmxvi8gerx4 (dmr1024 *, v256, vuc);
DMXVI8GERX4 nothing {dm,dmint}
diff --git a/gcc/testsuite/gcc.target/powerpc/dmf-disassemble-dmr.c
b/gcc/testsuite/gcc.target/powerpc/dmf-disassemble-dmr.c
new file mode 100644
index 00000000000..64a966ea61e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/dmf-disassemble-dmr.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_future_compile_ok } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-mdejagnu-cpu=future -O2" } */
+
+typedef unsigned char vec_t __attribute__((vector_size(16)));
+
+void
+bar (vec_t *dst, __dmr1024 *src)
+{
+ vec_t res[8];
+ __builtin_disassemble_dmr (res, src);
+ dst[0] = res[0];
+ dst[2] = res[1];
+ dst[4] = res[2];
+ dst[6] = res[3];
+ dst[8] = res[4];
+ dst[10] = res[5];
+ dst[12] = res[6];
+ dst[14] = res[7];
+}
+
+/* { dg-final { scan-assembler-times {\mdmxxextfdmr512\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mstxv\M} 8 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/dmf-extract512.c
b/gcc/testsuite/gcc.target/powerpc/dmf-extract512.c
new file mode 100644
index 00000000000..2b112c2725c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/dmf-extract512.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_future_compile_ok } */
+/* { dg-require-effective-target lp64 } */
+/* { dg-options "-mdejagnu-cpu=future -O2" } */
+
+typedef unsigned char vec_t __attribute__((vector_size(16)));
+
+void
+bar (vec_t *dst, __dmr1024 *src)
+{
+ vec_t res[4];
+ __builtin_dmr_extract512 (res, src, 0);
+ dst[0] = res[0];
+ dst[2] = res[1];
+ dst[4] = res[2];
+ dst[6] = res[3];
+}
+
+/* { dg-final { scan-assembler-times {\mdmxxextfdmr512\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mstxv\M} 4 } } */
--
2.52.0