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 } } */

Reply via email to