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