[12/12] rs6000: Add DMR extract builtins for Dense Math support

Message ID 282a1016-8c97-4bc2-9847-6deed321bab0@linux.ibm.com
State New
Headers
Series rs6000: Add support for Dense Math Facility (DMF) |

Commit Message

Surya Kumari Jangala July 16, 2026, 5:09 p.m. UTC
  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  <jskumari@linux.ibm.com>

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
  

Comments

Michael Meissner July 18, 2026, 4:35 a.m. UTC | #1
On Thu, Jul 16, 2026 at 10:39:19PM +0530, Surya Kumari Jangala wrote:
> 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  <jskumari@linux.ibm.com>
> 
> 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.

I applied the patches in order.  One part did not apply.

> ---
>  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

This patch does not apply.  Since nothing else uses
UNSPEC_DMF_EXTRACT1024, this part of the patch should be deleted.
  
Michael Meissner July 21, 2026, 7:12 a.m. UTC | #2
On Thu, Jul 16, 2026 at 10:39:19PM +0530, Surya Kumari Jangala wrote:
> 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  <jskumari@linux.ibm.com>
> 
> 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.

As I said in another message, you need to delete the change in mma.md
that isn't used elsewhere in this patch and it won't apply after the 11
previous patches are applied.  If you delete that patch, you change
commit the change without have to resend the patch out.

And please change the ChangeLog commit to something like:

2026-07-16  Surya Kumari Jangala  <jskumari@linux.ibm.com>

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.
  
Michael Meissner July 21, 2026, 10:54 p.m. UTC | #3
On Thu, Jul 16, 2026 at 10:39:19PM +0530, Surya Kumari Jangala wrote:
> 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  <jskumari@linux.ibm.com>
> 
> 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.

All of these patches are cleared to be back ported to the GCC 16 branch
after a short delay to make sure the master branch was not broken,
given they only modify PowerPC specific files or documentation files.
  

Patch

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