[gcc(refs/vendors/ibm/heads/dmr-support)] rs6000: Add DMR extract builtins for Dense Math support

Surya Kumari Jangala via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:be3af1c57c71a884f10da4f999ccb204123a5d15

commit be3af1c57c71a884f10da4f999ccb204123a5d15
Author: Surya Kumari Jangala <[email protected]>
Date:   Wed Jul 8 05:20:19 2026 -0500

    rs6000: Add DMR extract builtins for Dense Math support
    
    Add two new builtins for extracting data from 1024-bit Dense Math
    Registers (DMRs):
    
      - __builtin_mma_dmr_extract512 (void *, dm1024 *, const int<2>):
        extracts one 512-bit half of a DMR into four 128-bit vectors.
      - __builtin_mma_disassemble_dmr (void *, dm1024 *):
        extracts both 512-bit halves of a DMR into eight 128-bit vectors.
    
    2026-07-08  Surya Kumari Jangala  <[email protected]>
    
    gcc:
            * config/rs6000/rs6000-builtins.def (__builtin_mma_dmr_extract512): New
            built-in.
            (__builtin_mma_disassemble_dmr): Likewise.
            (__builtin_mma_dmr_extract512_internal): New internal built-in.
            * config/rs6000/mma.md (UNSPEC_DM_EXTRACT1024): New UNSPEC entry.
            * config/rs6000/rs6000-builtin.cc (rs6000_gimple_fold_mma_builtin):
            Exempt RS6000_BIF_DISASSEMBLE_DMR from the early-return guard.
            Handle RS6000_BIF_DM_EXTRACT512 and RS6000_BIF_DISASSEMBLE_DMR.
    
    gcc/testsuite:
            * gcc.target/powerpc/dmf-extract512.c: New test.
            * gcc.target/powerpc/dmf-disassemble-dmr.c: New test.

Diff:
---
 gcc/config/rs6000/mma.md                           |  1 +
 gcc/config/rs6000/rs6000-builtin.cc                | 73 +++++++++++++++++++++-
 gcc/config/rs6000/rs6000-builtins.def              |  9 +++
 .../gcc.target/powerpc/dmf-disassemble-dmr.c       | 24 +++++++
 gcc/testsuite/gcc.target/powerpc/dmf-extract512.c  | 20 ++++++
 5 files changed, 125 insertions(+), 2 deletions(-)

diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md
index 07274bc54d05..3328105fcd57 100644
--- a/gcc/config/rs6000/mma.md
+++ b/gcc/config/rs6000/mma.md
@@ -94,6 +94,7 @@
    UNSPEC_DM_INSERT512
    UNSPEC_DMF_EXTRACT512
    UNSPEC_DMF_INSERT1024
+   UNSPEC_DM_EXTRACT1024
    UNSPEC_DMF_DMXOR
    UNSPEC_DMF_DMXVI8GERX4
    UNSPEC_DMF_DMXVI8GERX4PP
diff --git a/gcc/config/rs6000/rs6000-builtin.cc b/gcc/config/rs6000/rs6000-builtin.cc
index e16ebb54065b..a9814aa62ffa 100644
--- a/gcc/config/rs6000/rs6000-builtin.cc
+++ b/gcc/config/rs6000/rs6000-builtin.cc
@@ -1127,11 +1127,12 @@ rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi,
 
   /* Each call that can be gimple-expanded has an associated built-in
      function that it will expand into.  If this one doesn't, we have
-     already expanded it!  Exceptions: lxvp and stxvp.  */
+     already expanded it!  Exceptions: lxvp, stxvp and disassemble_dmr.  */
   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_DM_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_DM_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 dc39ef2e5262..a6ba2f869cbb 100644
--- a/gcc/config/rs6000/rs6000-builtins.def
+++ b/gcc/config/rs6000/rs6000-builtins.def
@@ -4056,6 +4056,12 @@
   dmr1024 __builtin_dmmr_internal (dmr1024);
     DMMR_INTERNAL movtdo {dm}
 
+  void __builtin_mma_dmr_extract512 (void *, dmr1024 *, const int<2>);
+    DM_EXTRACT512 nothing {dm,dmint}
+
+  v512 __builtin_mma_dmr_extract512_internal (dmr1024, const int<2>);
+    DM_EXTRACT512_INTERNAL dm_extract512 {dm}
+
   void __builtin_dmxor (dmr1024 *, dmr1024 *);
     DMXOR nothing {dm,dmint,dmr}
 
@@ -4068,6 +4074,9 @@
   dmr1024 __builtin_build_dmr_internal (vuc, vuc, vuc, vuc, vuc, vuc, vuc, vuc);
     BUILD_DMR_INTERNAL dmf_build_dmr {dm}
 
+  void __builtin_mma_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 000000000000..3ad2dc43bdef
--- /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_mma_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 000000000000..cf4163d9b058
--- /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_mma_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 } } */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.