https://gcc.gnu.org/g:49cd06eb5c818776cc59125b6f1e42f58310b07b
commit 49cd06eb5c818776cc59125b6f1e42f58310b07b Author: Kishan Parmar <[email protected]> Date: Tue Jul 7 12:44:49 2026 +0530 rs6000: Treat xxmtacc/xxmfacc as no-ops and build accumulators via DMR for DMF When the Dense Math Facility (DMF) is enabled, accumulators are backed by dedicated Dense Math Registers (DMRs) instead of aliased VSX/FPR registers. In this mode, xxmtacc/xxmfacc do not require explicit prime/deprime operations, so treat them as no-ops. Update accumulator assembly to construct accumulators in DMRs using DMR insert operations rather than relying on aliased VSX/FPR registers. Also switch the relevant patterns to use accumulator_operand/"wD" so they correctly support both conventional and DMF-backed accumulators, and avoid emitting xxmtacc/xxmfacc during internal accumulator moves when DMF is enabled. Diff: --- gcc/config/rs6000/mma.md | 70 ++++++++++++++++++----- gcc/config/rs6000/rs6000.cc | 35 +++++++----- gcc/testsuite/gcc.target/powerpc/future-xxacc-1.c | 18 ++++++ gcc/testsuite/gcc.target/powerpc/future-xxacc-2.c | 18 ++++++ 4 files changed, 114 insertions(+), 27 deletions(-) diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md index 1103f1fc0375..a31ac8b3bac3 100644 --- a/gcc/config/rs6000/mma.md +++ b/gcc/config/rs6000/mma.md @@ -91,6 +91,7 @@ UNSPEC_MMA_XVI8GER4SPP UNSPEC_MMA_XXMFACC UNSPEC_MMA_XXMTACC + UNSPEC_DM_INSERT512 ]) (define_c_enum "unspecv" @@ -425,19 +426,42 @@ DONE; }) +;; Move from VSX registers to DMR registers via two insert 512 bit +;; instructions. +(define_insn "dm_insert512" + [(set (match_operand:XO 0 "dmr_register_operand" "=wD") + (unspec:XO [(match_operand:OO 1 "vsx_register_operand" "wa") + (match_operand:OO 2 "vsx_register_operand" "wa") + (match_operand 3 "const_0_to_1_operand")] + UNSPEC_DM_INSERT512))] + "TARGET_DMF" + "dmxxinstdmr512 %0,%x1,%x2,%3" + [(set_attr "type" "mma")]) + (define_expand "mma_assemble_acc" - [(match_operand:XO 0 "fpr_reg_operand") + [(match_operand:XO 0 "accumulator_operand") (match_operand:V16QI 1 "mma_assemble_input_operand") (match_operand:V16QI 2 "mma_assemble_input_operand") (match_operand:V16QI 3 "mma_assemble_input_operand") (match_operand:V16QI 4 "mma_assemble_input_operand")] "TARGET_MMA" { - rtx src = gen_rtx_UNSPEC_VOLATILE (XOmode, - gen_rtvec (4, operands[1], operands[2], - operands[3], operands[4]), - UNSPECV_MMA_ASSEMBLE); - emit_move_insn (operands[0], src); + if (TARGET_DMF) + { + rtx vp0 = gen_reg_rtx (OOmode); + rtx vp1 = gen_reg_rtx (OOmode); + emit_insn (gen_vsx_assemble_pair (vp0, operands[1], operands[2])); + emit_insn (gen_vsx_assemble_pair (vp1, operands[3], operands[4])); + emit_insn (gen_dm_insert512 (operands[0], vp0, vp1, const0_rtx)); + } + else + { + rtx src = gen_rtx_UNSPEC_VOLATILE (XOmode, + gen_rtvec (4, operands[1], operands[2], + operands[3], operands[4]), + UNSPECV_MMA_ASSEMBLE); + emit_move_insn (operands[0], src); + } DONE; }) @@ -445,7 +469,7 @@ ;; as an early clobber so we don't accidentally clobber the input operands. */ (define_insn_and_split "*mma_assemble_acc" - [(set (match_operand:XO 0 "fpr_reg_operand" "=&d") + [(set (match_operand:XO 0 "accumulator_operand" "=&wD") (unspec_volatile:XO [(match_operand:V16QI 1 "mma_assemble_input_operand" "mwa") (match_operand:V16QI 2 "mma_assemble_input_operand" "mwa") @@ -453,7 +477,7 @@ (match_operand:V16QI 4 "mma_assemble_input_operand" "mwa")] UNSPECV_MMA_ASSEMBLE))] "TARGET_MMA - && fpr_reg_operand (operands[0], XOmode)" + && accumulator_operand (operands[0], XOmode)" "#" "&& reload_completed" [(const_int 0)] @@ -468,7 +492,7 @@ (define_expand "mma_disassemble_acc" [(match_operand:V16QI 0 "mma_disassemble_output_operand") - (match_operand:XO 1 "fpr_reg_operand") + (match_operand:XO 1 "accumulator_operand") (match_operand 2 "const_0_to_3_operand")] "TARGET_MMA" { @@ -499,15 +523,35 @@ DONE; }) +;; xxmtacc/xxmfacc prime/deprime an accumulator that lives in 4 adjacent +;; FPRs -- they reformat that shared FPR/accumulator storage in place. On +;; TARGET_DMF, DMRs are a register file entirely separate from the FPRs, +;; so there is no such format to convert and these are a nop. This expand +;; only exists so __builtin_mma_xxmfacc/xxmtacc (which always resolve to +;; this icode, regardless of register class) correctly do nothing on +;; TARGET_DMF instead of failing to match any insn. +(define_expand "mma_<acc>" + [(set (match_operand:XO 0 "accumulator_operand") + (unspec:XO [(match_operand:XO 1 "accumulator_operand")] + MMA_ACC))] + "TARGET_MMA" +{ + if (TARGET_DMF) + { + emit_move_insn (operands[0], operands[1]); + DONE; + } +}) + ;; MMA instructions that do not use their accumulators as an input, still ;; must not allow their vector operands to overlap the registers used by ;; the accumulator. We enforce this by marking the output as early clobber. -(define_insn "mma_<acc>" - [(set (match_operand:XO 0 "fpr_reg_operand" "=&d") - (unspec:XO [(match_operand:XO 1 "fpr_reg_operand" "0")] +(define_insn "*mma_<acc>" + [(set (match_operand:XO 0 "accumulator_operand" "=&wD") + (unspec:XO [(match_operand:XO 1 "accumulator_operand" "0")] MMA_ACC))] - "TARGET_MMA" + "TARGET_MMA && !TARGET_DMF" "<acc> %A0" [(set_attr "type" "mma")]) diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index c2302a253379..49695dfbc163 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -27587,8 +27587,9 @@ rs6000_split_multireg_move (rtx dst, rtx src) unsigned size = GET_MODE_SIZE (reg_mode); /* If we are reading an accumulator register, we have to - deprime it before we can access it. */ - if (TARGET_MMA + deprime it before we can access it, unless we have dense math + registers, which do not need priming/depriming. */ + if (TARGET_MMA && !TARGET_DMF && GET_MODE (src) == XOmode && FP_REGNO_P (REGNO (src))) emit_insn (gen_mma_xxmfacc (src, src)); @@ -27621,8 +27622,9 @@ rs6000_split_multireg_move (rtx dst, rtx src) } /* If we are writing an accumulator register, we have to - prime it after we've written it. */ - if (TARGET_MMA + prime it after we've written it, unless we have dense math + registers, which do not need priming/depriming. */ + if (TARGET_MMA && !TARGET_DMF && GET_MODE (dst) == XOmode && FP_REGNO_P (REGNO (dst))) emit_insn (gen_mma_xxmtacc (dst, dst)); @@ -27690,8 +27692,9 @@ rs6000_split_multireg_move (rtx dst, rtx src) } /* We are writing an accumulator register, so we have to - prime it after we've written it. */ - if (GET_MODE (src) == XOmode) + prime it after we've written it, unless we have dense math + registers, which do not need priming/depriming. */ + if (GET_MODE (src) == XOmode && !TARGET_DMF) emit_insn (gen_mma_xxmtacc (dst, dst)); return; @@ -27703,8 +27706,9 @@ rs6000_split_multireg_move (rtx dst, rtx src) if (REG_P (src) && REG_P (dst) && (REGNO (src) < REGNO (dst))) { /* If we are reading an accumulator register, we have to - deprime it before we can access it. */ - if (TARGET_MMA + deprime it before we can access it, unless we have dense math + registers, which do not need priming/depriming. */ + if (TARGET_MMA && !TARGET_DMF && GET_MODE (src) == XOmode && FP_REGNO_P (REGNO (src))) emit_insn (gen_mma_xxmfacc (src, src)); @@ -27731,8 +27735,9 @@ rs6000_split_multireg_move (rtx dst, rtx src) } /* If we are writing an accumulator register, we have to - prime it after we've written it. */ - if (TARGET_MMA + prime it after we've written it, unless we have dense math + registers, which do not need priming/depriming. */ + if (TARGET_MMA && !TARGET_DMF && GET_MODE (dst) == XOmode && FP_REGNO_P (REGNO (dst))) emit_insn (gen_mma_xxmtacc (dst, dst)); } @@ -27868,8 +27873,9 @@ rs6000_split_multireg_move (rtx dst, rtx src) } /* If we are reading an accumulator register, we have to - deprime it before we can access it. */ - if (TARGET_MMA && REG_P (src) + deprime it before we can access it, unless we have dense math + registers, which do not need priming/depriming. */ + if (TARGET_MMA && !TARGET_DMF && REG_P (src) && GET_MODE (src) == XOmode && FP_REGNO_P (REGNO (src))) emit_insn (gen_mma_xxmfacc (src, src)); @@ -27900,8 +27906,9 @@ rs6000_split_multireg_move (rtx dst, rtx src) } /* If we are writing an accumulator register, we have to - prime it after we've written it. */ - if (TARGET_MMA && REG_P (dst) + prime it after we've written it, unless we have dense math + registers, which do not need priming/depriming. */ + if (TARGET_MMA && !TARGET_DMF && REG_P (dst) && GET_MODE (dst) == XOmode && FP_REGNO_P (REGNO (dst))) emit_insn (gen_mma_xxmtacc (dst, dst)); diff --git a/gcc/testsuite/gcc.target/powerpc/future-xxacc-1.c b/gcc/testsuite/gcc.target/powerpc/future-xxacc-1.c new file mode 100644 index 000000000000..2242f6693d02 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/future-xxacc-1.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-mdejagnu-cpu=future -O2" } */ +/* { dg-require-effective-target powerpc_future_compile_ok } */ + +void +foo (__vector_quad *acc) +{ + __builtin_mma_xxmtacc (acc); +} + +void +bar (__vector_quad *acc) +{ + __builtin_mma_xxmfacc (acc); +} + +/* { dg-final { scan-assembler-not {\mxxmtacc\M} } } */ +/* { dg-final { scan-assembler-not {\mxxmfacc\M} } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/future-xxacc-2.c b/gcc/testsuite/gcc.target/powerpc/future-xxacc-2.c new file mode 100644 index 000000000000..a643dc5f6380 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/future-xxacc-2.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-mdejagnu-cpu=future -O2 -mno-dense-math" } */ +/* { dg-require-effective-target powerpc_future_compile_ok } */ + +void +foo (__vector_quad *acc) +{ + __builtin_mma_xxmtacc (acc); +} + +void +bar (__vector_quad *acc) +{ + __builtin_mma_xxmfacc (acc); +} + +/* { dg-final { scan-assembler {\mxxmtacc\M} } } */ +/* { dg-final { scan-assembler {\mxxmfacc\M} } } */
