[gcc(refs/vendors/ibm/heads/dmr-mainline)] 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:faff3ec7888532565d75d6dd4abb03afee118d9f

commit faff3ec7888532565d75d6dd4abb03afee118d9f
Author: Surya Kumari Jangala <[email protected]>
Date:   Thu Jul 16 10:47:02 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_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.

Diff:
---
 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/testsuite/gcc.target/powerpc/dmf-extract512.c  | 20 ++++++
 5 files changed, 124 insertions(+), 1 deletion(-)

diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md
index 07dfb09fba05..01bd708fbdc7 100644
--- a/gcc/config/rs6000/mma.md
+++ b/gcc/config/rs6000/mma.md
@@ -94,6 +94,7 @@
    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 0c6d961d7a7d..c0aa885ac019 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 2c0bc1d0119b..f949db410634 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 000000000000..64a966ea61e6
--- /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 000000000000..2b112c2725cc
--- /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 } } */
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.