From: Peter Bergner Date: Sun, 21 Jun 2020 04:23:02 +0000 (-0500) Subject: rs6000: Add MMA built-in function definitions and test cases. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8ee2640bfdc62f835ec9740278f948034bc7d9f1;p=gcc.git rs6000: Add MMA built-in function definitions and test cases. Add the Matrix-Multiply Assist (MMA) built-ins. The MMA accumulators are INOUT operands for most MMA instructions, but they are also very expensive to move around. For this reason, we have implemented a built-in API where the accumulators are passed using pass-by-reference/pointers, so the user won't use one accumulator as input and another as output, which wouldentail a lot of copies. However, using pointers gives us poor code generation when we expand the built-ins at normal expand time. We therefore expand the MMA built-ins early into gimple, converting the pass-by-reference calls to an internal built-in that uses pass-by-value calling convention, where we can enforce the input and output accumulators are the same. This gives us much better code generation. 2020-06-20 Peter Bergner gcc/ * config/rs6000/predicates.md (mma_assemble_input_operand): New. * config/rs6000/rs6000-builtin.def (BU_MMA_1, BU_MMA_V2, BU_MMA_3, BU_MMA_5, BU_MMA_6, BU_VSX_1): Add support macros for defining MMA built-in functions. (ASSEMBLE_ACC, ASSEMBLE_PAIR, DISASSEMBLE_ACC, DISASSEMBLE_PAIR, PMXVBF16GER2, PMXVBF16GER2NN, PMXVBF16GER2NP, PMXVBF16GER2PN, PMXVBF16GER2PP, PMXVF16GER2, PMXVF16GER2NN, PMXVF16GER2NP, PMXVF16GER2PN, PMXVF16GER2PP, PMXVF32GER, PMXVF32GERNN, PMXVF32GERNP, PMXVF32GERPN, PMXVF32GERPP, PMXVF64GER, PMXVF64GERNN, PMXVF64GERNP, PMXVF64GERPN, PMXVF64GERPP, PMXVI16GER2, PMXVI16GER2PP, PMXVI16GER2S, PMXVI16GER2SPP, PMXVI4GER8, PMXVI4GER8PP, PMXVI8GER4, PMXVI8GER4PP, PMXVI8GER4SPP, XVBF16GER2, XVBF16GER2NN, XVBF16GER2NP, XVBF16GER2PN, XVBF16GER2PP, XVCVBF16SP, XVCVSPBF16, XVF16GER2, XVF16GER2NN, XVF16GER2NP, XVF16GER2PN, XVF16GER2PP, XVF32GER, XVF32GERNN, XVF32GERNP, XVF32GERPN, XVF32GERPP, XVF64GER, XVF64GERNN, XVF64GERNP, XVF64GERPN, XVF64GERPP, XVI16GER2, XVI16GER2PP, XVI16GER2S, XVI16GER2SPP, XVI4GER8, XVI4GER8PP, XVI8GER4, XVI8GER4PP, XVI8GER4SPP, XXMFACC, XXMTACC, XXSETACCZ): Add MMA built-ins. * config/rs6000/rs6000.c (rs6000_emit_move): Use CONST_INT_P. Allow zero constants. (print_operand) : New output modifier. (rs6000_split_multireg_move): Add support for inserting accumulator priming and depriming instructions. Add support for splitting an assemble accumulator pattern. * config/rs6000/rs6000-call.c (mma_init_builtins, mma_expand_builtin, rs6000_gimple_fold_mma_builtin): New functions. (RS6000_BUILTIN_M): New macro. (def_builtin): Handle RS6000_BTC_QUAD and RS6000_BTC_PAIR attributes. (bdesc_mma): Add new MMA built-in support. (htm_expand_builtin): Use RS6000_BTC_OPND_MASK. (rs6000_invalid_builtin): Add handling of RS6000_BTM_FUTURE and RS6000_BTM_MMA. (rs6000_builtin_valid_without_lhs): Handle RS6000_BTC_VOID attribute. (rs6000_gimple_fold_builtin): Call rs6000_builtin_is_supported_p and rs6000_gimple_fold_mma_builtin. (rs6000_expand_builtin): Call mma_expand_builtin. Use RS6000_BTC_OPND_MASK. (rs6000_init_builtins): Adjust comment. Call mma_init_builtins. (htm_init_builtins): Use RS6000_BTC_OPND_MASK. (builtin_function_type): Handle VSX_BUILTIN_XVCVSPBF16 and VSX_BUILTIN_XVCVBF16SP. * config/rs6000/rs6000.h (RS6000_BTC_QUINARY, RS6000_BTC_SENARY, RS6000_BTC_OPND_MASK, RS6000_BTC_QUAD, RS6000_BTC_PAIR, RS6000_BTC_QUADPAIR, RS6000_BTC_GIMPLE): New defines. (RS6000_BTC_PREDICATE, RS6000_BTC_ABS, RS6000_BTC_DST, RS6000_BTC_TYPE_MASK, RS6000_BTC_ATTR_MASK): Adjust values. * config/rs6000/mma.md (MAX_MMA_OPERANDS): New define_constant. (UNSPEC_MMA_ASSEMBLE_ACC, UNSPEC_MMA_PMXVBF16GER2, UNSPEC_MMA_PMXVBF16GER2NN, UNSPEC_MMA_PMXVBF16GER2NP, UNSPEC_MMA_PMXVBF16GER2PN, UNSPEC_MMA_PMXVBF16GER2PP, UNSPEC_MMA_PMXVF16GER2, UNSPEC_MMA_PMXVF16GER2NN, UNSPEC_MMA_PMXVF16GER2NP, UNSPEC_MMA_PMXVF16GER2PN, UNSPEC_MMA_PMXVF16GER2PP, UNSPEC_MMA_PMXVF32GER, UNSPEC_MMA_PMXVF32GERNN, UNSPEC_MMA_PMXVF32GERNP, UNSPEC_MMA_PMXVF32GERPN, UNSPEC_MMA_PMXVF32GERPP, UNSPEC_MMA_PMXVF64GER, UNSPEC_MMA_PMXVF64GERNN, UNSPEC_MMA_PMXVF64GERNP, UNSPEC_MMA_PMXVF64GERPN, UNSPEC_MMA_PMXVF64GERPP, UNSPEC_MMA_PMXVI16GER2, UNSPEC_MMA_PMXVI16GER2PP, UNSPEC_MMA_PMXVI16GER2S, UNSPEC_MMA_PMXVI16GER2SPP, UNSPEC_MMA_PMXVI4GER8, UNSPEC_MMA_PMXVI4GER8PP, UNSPEC_MMA_PMXVI8GER4, UNSPEC_MMA_PMXVI8GER4PP, UNSPEC_MMA_PMXVI8GER4SPP, UNSPEC_MMA_XVBF16GER2, UNSPEC_MMA_XVBF16GER2NN, UNSPEC_MMA_XVBF16GER2NP, UNSPEC_MMA_XVBF16GER2PN, UNSPEC_MMA_XVBF16GER2PP, UNSPEC_MMA_XVF16GER2, UNSPEC_MMA_XVF16GER2NN, UNSPEC_MMA_XVF16GER2NP, UNSPEC_MMA_XVF16GER2PN, UNSPEC_MMA_XVF16GER2PP, UNSPEC_MMA_XVF32GER, UNSPEC_MMA_XVF32GERNN, UNSPEC_MMA_XVF32GERNP, UNSPEC_MMA_XVF32GERPN, UNSPEC_MMA_XVF32GERPP, UNSPEC_MMA_XVF64GER, UNSPEC_MMA_XVF64GERNN, UNSPEC_MMA_XVF64GERNP, UNSPEC_MMA_XVF64GERPN, UNSPEC_MMA_XVF64GERPP, UNSPEC_MMA_XVI16GER2, UNSPEC_MMA_XVI16GER2PP, UNSPEC_MMA_XVI16GER2S, UNSPEC_MMA_XVI16GER2SPP, UNSPEC_MMA_XVI4GER8, UNSPEC_MMA_XVI4GER8PP, UNSPEC_MMA_XVI8GER4, UNSPEC_MMA_XVI8GER4PP, UNSPEC_MMA_XVI8GER4SPP, UNSPEC_MMA_XXMFACC, UNSPEC_MMA_XXMTACC): New. (MMA_ACC, MMA_VV, MMA_AVV, MMA_PV, MMA_APV, MMA_VVI4I4I8, MMA_AVVI4I4I8, MMA_VVI4I4I2, MMA_AVVI4I4I2, MMA_VVI4I4, MMA_AVVI4I4, MMA_PVI4I2, MMA_APVI4I2, MMA_VVI4I4I4, MMA_AVVI4I4I4): New define_int_iterator. (acc, vv, avv, pv, apv, vvi4i4i8, avvi4i4i8, vvi4i4i2, avvi4i4i2, vvi4i4, avvi4i4, pvi4i2, apvi4i2, vvi4i4i4, avvi4i4i4): New define_int_attr. (*movpxi): Add zero constant alternative. (mma_assemble_pair, mma_assemble_acc): New define_expand. (*mma_assemble_acc): New define_insn_and_split. (mma_, mma_xxsetaccz, mma_, mma_, mma_, mma_, mma_, mma_, mma_, mma_, mma_, mma_, mma_, mma_, mma_, mma_): New define_insn. * config/rs6000/rs6000.md (define_attr "type"): New type mma. * config/rs6000/vsx.md (UNSPEC_VSX_XVCVBF16SP): New. (UNSPEC_VSX_XVCVSPBF16): Likewise. (XVCVBF16): New define_int_iterator. (xvcvbf16): New define_int_attr. (vsx_): New define_insn. * doc/extend.texi: Document the mma built-ins. --- diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md index 6e4cfcaeebc..15cacfb7fc1 100644 --- a/gcc/config/rs6000/mma.md +++ b/gcc/config/rs6000/mma.md @@ -31,6 +31,240 @@ ;; therefore, we define the XImode and OImode move patterns, but we ;; disable their use with a "false" condition flag. +(define_constants [(MAX_MMA_OPERANDS 7)]) + +;; Constants for creating unspecs + +(define_c_enum "unspec" + [UNSPEC_MMA_ASSEMBLE_ACC + UNSPEC_MMA_PMXVBF16GER2 + UNSPEC_MMA_PMXVBF16GER2NN + UNSPEC_MMA_PMXVBF16GER2NP + UNSPEC_MMA_PMXVBF16GER2PN + UNSPEC_MMA_PMXVBF16GER2PP + UNSPEC_MMA_PMXVF16GER2 + UNSPEC_MMA_PMXVF16GER2NN + UNSPEC_MMA_PMXVF16GER2NP + UNSPEC_MMA_PMXVF16GER2PN + UNSPEC_MMA_PMXVF16GER2PP + UNSPEC_MMA_PMXVF32GER + UNSPEC_MMA_PMXVF32GERNN + UNSPEC_MMA_PMXVF32GERNP + UNSPEC_MMA_PMXVF32GERPN + UNSPEC_MMA_PMXVF32GERPP + UNSPEC_MMA_PMXVF64GER + UNSPEC_MMA_PMXVF64GERNN + UNSPEC_MMA_PMXVF64GERNP + UNSPEC_MMA_PMXVF64GERPN + UNSPEC_MMA_PMXVF64GERPP + UNSPEC_MMA_PMXVI16GER2 + UNSPEC_MMA_PMXVI16GER2PP + UNSPEC_MMA_PMXVI16GER2S + UNSPEC_MMA_PMXVI16GER2SPP + UNSPEC_MMA_PMXVI4GER8 + UNSPEC_MMA_PMXVI4GER8PP + UNSPEC_MMA_PMXVI8GER4 + UNSPEC_MMA_PMXVI8GER4PP + UNSPEC_MMA_PMXVI8GER4SPP + UNSPEC_MMA_XVBF16GER2 + UNSPEC_MMA_XVBF16GER2NN + UNSPEC_MMA_XVBF16GER2NP + UNSPEC_MMA_XVBF16GER2PN + UNSPEC_MMA_XVBF16GER2PP + UNSPEC_MMA_XVF16GER2 + UNSPEC_MMA_XVF16GER2NN + UNSPEC_MMA_XVF16GER2NP + UNSPEC_MMA_XVF16GER2PN + UNSPEC_MMA_XVF16GER2PP + UNSPEC_MMA_XVF32GER + UNSPEC_MMA_XVF32GERNN + UNSPEC_MMA_XVF32GERNP + UNSPEC_MMA_XVF32GERPN + UNSPEC_MMA_XVF32GERPP + UNSPEC_MMA_XVF64GER + UNSPEC_MMA_XVF64GERNN + UNSPEC_MMA_XVF64GERNP + UNSPEC_MMA_XVF64GERPN + UNSPEC_MMA_XVF64GERPP + UNSPEC_MMA_XVI16GER2 + UNSPEC_MMA_XVI16GER2PP + UNSPEC_MMA_XVI16GER2S + UNSPEC_MMA_XVI16GER2SPP + UNSPEC_MMA_XVI4GER8 + UNSPEC_MMA_XVI4GER8PP + UNSPEC_MMA_XVI8GER4 + UNSPEC_MMA_XVI8GER4PP + UNSPEC_MMA_XVI8GER4SPP + UNSPEC_MMA_XXMFACC + UNSPEC_MMA_XXMTACC + ]) + +;; MMA instructions with 1 accumulator argument +(define_int_iterator MMA_ACC [UNSPEC_MMA_XXMFACC + UNSPEC_MMA_XXMTACC]) + +;; MMA instructions with 2 vector arguments +(define_int_iterator MMA_VV [UNSPEC_MMA_XVI4GER8 + UNSPEC_MMA_XVI8GER4 + UNSPEC_MMA_XVI16GER2 + UNSPEC_MMA_XVI16GER2S + UNSPEC_MMA_XVF16GER2 + UNSPEC_MMA_XVBF16GER2 + UNSPEC_MMA_XVF32GER]) + +;; MMA instructions with 1 accumulator and 2 vector arguments +(define_int_iterator MMA_AVV [UNSPEC_MMA_XVI4GER8PP + UNSPEC_MMA_XVI8GER4PP + UNSPEC_MMA_XVI8GER4SPP + UNSPEC_MMA_XVI16GER2PP + UNSPEC_MMA_XVI16GER2SPP + UNSPEC_MMA_XVF16GER2PP + UNSPEC_MMA_XVF16GER2PN + UNSPEC_MMA_XVF16GER2NP + UNSPEC_MMA_XVF16GER2NN + UNSPEC_MMA_XVBF16GER2PP + UNSPEC_MMA_XVBF16GER2PN + UNSPEC_MMA_XVBF16GER2NP + UNSPEC_MMA_XVBF16GER2NN + UNSPEC_MMA_XVF32GERPP + UNSPEC_MMA_XVF32GERPN + UNSPEC_MMA_XVF32GERNP + UNSPEC_MMA_XVF32GERNN]) + +;; MMA instructions with 1 vector pair and 1 vector arguments +(define_int_iterator MMA_PV [UNSPEC_MMA_XVF64GER]) + +;; MMA instructions with 1 accumulator, 1 vector pair and 1 vector arguments +(define_int_iterator MMA_APV [UNSPEC_MMA_XVF64GERPP + UNSPEC_MMA_XVF64GERPN + UNSPEC_MMA_XVF64GERNP + UNSPEC_MMA_XVF64GERNN]) + +;; MMA instructions with 2 vector, 2 4-bit and 1 8-bit arguments +(define_int_iterator MMA_VVI4I4I8 [UNSPEC_MMA_PMXVI4GER8]) + +;; MMA instructions with 1 accumulator, 2 vector, 2 4-bit and 1 8-bit arguments +(define_int_iterator MMA_AVVI4I4I8 [UNSPEC_MMA_PMXVI4GER8PP]) + +;; MMA instructions with 2 vector, 2 4-bit and 1 2-bit arguments +(define_int_iterator MMA_VVI4I4I2 [UNSPEC_MMA_PMXVI16GER2 + UNSPEC_MMA_PMXVI16GER2S + UNSPEC_MMA_PMXVF16GER2 + UNSPEC_MMA_PMXVBF16GER2]) + +;; MMA instructions with 1 accumulator, 2 vector, 2 4-bit and 1 2-bit arguments +(define_int_iterator MMA_AVVI4I4I2 [UNSPEC_MMA_PMXVI16GER2PP + UNSPEC_MMA_PMXVI16GER2SPP + UNSPEC_MMA_PMXVF16GER2PP + UNSPEC_MMA_PMXVF16GER2PN + UNSPEC_MMA_PMXVF16GER2NP + UNSPEC_MMA_PMXVF16GER2NN + UNSPEC_MMA_PMXVBF16GER2PP + UNSPEC_MMA_PMXVBF16GER2PN + UNSPEC_MMA_PMXVBF16GER2NP + UNSPEC_MMA_PMXVBF16GER2NN]) + +;; MMA instructions with 2 vector and 2 4-bit arguments +(define_int_iterator MMA_VVI4I4 [UNSPEC_MMA_PMXVF32GER]) + +;; MMA instructions with 1 accumulator, 2 vector and 2 4-bit arguments +(define_int_iterator MMA_AVVI4I4 [UNSPEC_MMA_PMXVF32GERPP + UNSPEC_MMA_PMXVF32GERPN + UNSPEC_MMA_PMXVF32GERNP + UNSPEC_MMA_PMXVF32GERNN]) + +;; MMA instructions with 2 vector, 1 4-bit and 1 2-bit arguments +(define_int_iterator MMA_PVI4I2 [UNSPEC_MMA_PMXVF64GER]) + +;; MMA instructions with 1 accumulator, 2 vector, 1 4-bit and 1 2-bit arguments +(define_int_iterator MMA_APVI4I2 [UNSPEC_MMA_PMXVF64GERPP + UNSPEC_MMA_PMXVF64GERPN + UNSPEC_MMA_PMXVF64GERNP + UNSPEC_MMA_PMXVF64GERNN]) + +;; MMA instructions with 2 vector and 3 4-bit arguments +(define_int_iterator MMA_VVI4I4I4 [UNSPEC_MMA_PMXVI8GER4]) + +;; MMA instructions with 1 accumulator, 2 vector and 3 4-bit arguments +(define_int_iterator MMA_AVVI4I4I4 [UNSPEC_MMA_PMXVI8GER4PP + UNSPEC_MMA_PMXVI8GER4SPP]) + +(define_int_attr acc [(UNSPEC_MMA_XXMFACC "xxmfacc") + (UNSPEC_MMA_XXMTACC "xxmtacc")]) + +(define_int_attr vv [(UNSPEC_MMA_XVI4GER8 "xvi4ger8") + (UNSPEC_MMA_XVI8GER4 "xvi8ger4") + (UNSPEC_MMA_XVI16GER2 "xvi16ger2") + (UNSPEC_MMA_XVI16GER2S "xvi16ger2s") + (UNSPEC_MMA_XVF16GER2 "xvf16ger2") + (UNSPEC_MMA_XVBF16GER2 "xvbf16ger2") + (UNSPEC_MMA_XVF32GER "xvf32ger")]) + +(define_int_attr avv [(UNSPEC_MMA_XVI4GER8PP "xvi4ger8pp") + (UNSPEC_MMA_XVI8GER4PP "xvi8ger4pp") + (UNSPEC_MMA_XVI8GER4SPP "xvi8ger4spp") + (UNSPEC_MMA_XVI16GER2PP "xvi16ger2pp") + (UNSPEC_MMA_XVI16GER2SPP "xvi16ger2spp") + (UNSPEC_MMA_XVF16GER2PP "xvf16ger2pp") + (UNSPEC_MMA_XVF16GER2PN "xvf16ger2pn") + (UNSPEC_MMA_XVF16GER2NP "xvf16ger2np") + (UNSPEC_MMA_XVF16GER2NN "xvf16ger2nn") + (UNSPEC_MMA_XVBF16GER2PP "xvbf16ger2pp") + (UNSPEC_MMA_XVBF16GER2PN "xvbf16ger2pn") + (UNSPEC_MMA_XVBF16GER2NP "xvbf16ger2np") + (UNSPEC_MMA_XVBF16GER2NN "xvbf16ger2nn") + (UNSPEC_MMA_XVF32GERPP "xvf32gerpp") + (UNSPEC_MMA_XVF32GERPN "xvf32gerpn") + (UNSPEC_MMA_XVF32GERNP "xvf32gernp") + (UNSPEC_MMA_XVF32GERNN "xvf32gernn")]) + +(define_int_attr pv [(UNSPEC_MMA_XVF64GER "xvf64ger")]) + +(define_int_attr apv [(UNSPEC_MMA_XVF64GERPP "xvf64gerpp") + (UNSPEC_MMA_XVF64GERPN "xvf64gerpn") + (UNSPEC_MMA_XVF64GERNP "xvf64gernp") + (UNSPEC_MMA_XVF64GERNN "xvf64gernn")]) + +(define_int_attr vvi4i4i8 [(UNSPEC_MMA_PMXVI4GER8 "pmxvi4ger8")]) + +(define_int_attr avvi4i4i8 [(UNSPEC_MMA_PMXVI4GER8PP "pmxvi4ger8pp")]) + +(define_int_attr vvi4i4i2 [(UNSPEC_MMA_PMXVI16GER2 "pmxvi16ger2") + (UNSPEC_MMA_PMXVI16GER2S "pmxvi16ger2s") + (UNSPEC_MMA_PMXVF16GER2 "pmxvf16ger2") + (UNSPEC_MMA_PMXVBF16GER2 "pmxvbf16ger2")]) + +(define_int_attr avvi4i4i2 [(UNSPEC_MMA_PMXVI16GER2PP "pmxvi16ger2pp") + (UNSPEC_MMA_PMXVI16GER2SPP "pmxvi16ger2spp") + (UNSPEC_MMA_PMXVF16GER2PP "pmxvf16ger2pp") + (UNSPEC_MMA_PMXVF16GER2PN "pmxvf16ger2pn") + (UNSPEC_MMA_PMXVF16GER2NP "pmxvf16ger2np") + (UNSPEC_MMA_PMXVF16GER2NN "pmxvf16ger2nn") + (UNSPEC_MMA_PMXVBF16GER2PP "pmxvbf16ger2pp") + (UNSPEC_MMA_PMXVBF16GER2PN "pmxvbf16ger2pn") + (UNSPEC_MMA_PMXVBF16GER2NP "pmxvbf16ger2np") + (UNSPEC_MMA_PMXVBF16GER2NN "pmxvbf16ger2nn")]) + +(define_int_attr vvi4i4 [(UNSPEC_MMA_PMXVF32GER "pmxvf32ger")]) + +(define_int_attr avvi4i4 [(UNSPEC_MMA_PMXVF32GERPP "pmxvf32gerpp") + (UNSPEC_MMA_PMXVF32GERPN "pmxvf32gerpn") + (UNSPEC_MMA_PMXVF32GERNP "pmxvf32gernp") + (UNSPEC_MMA_PMXVF32GERNN "pmxvf32gernn")]) + +(define_int_attr pvi4i2 [(UNSPEC_MMA_PMXVF64GER "pmxvf64ger")]) + +(define_int_attr apvi4i2 [(UNSPEC_MMA_PMXVF64GERPP "pmxvf64gerpp") + (UNSPEC_MMA_PMXVF64GERPN "pmxvf64gerpn") + (UNSPEC_MMA_PMXVF64GERNP "pmxvf64gernp") + (UNSPEC_MMA_PMXVF64GERNN "pmxvf64gernn")]) + +(define_int_attr vvi4i4i4 [(UNSPEC_MMA_PMXVI8GER4 "pmxvi8ger4")]) + +(define_int_attr avvi4i4i4 [(UNSPEC_MMA_PMXVI8GER4PP "pmxvi8ger4pp") + (UNSPEC_MMA_PMXVI8GER4SPP "pmxvi8ger4spp")]) + + ;; Define a disabled OImode move pattern, so we can use POImode. (define_expand "movoi" [(set (match_operand:OI 0 "nonimmediate_operand") @@ -91,10 +325,11 @@ }) (define_insn_and_split "*movpxi" - [(set (match_operand:PXI 0 "nonimmediate_operand" "=d,m,d") - (match_operand:PXI 1 "input_operand" "m,d,d"))] + [(set (match_operand:PXI 0 "nonimmediate_operand" "=d,m,d,d") + (match_operand:PXI 1 "input_operand" "m,d,d,O"))] "TARGET_MMA - && (gpc_reg_operand (operands[0], PXImode) + && ((gpc_reg_operand (operands[0], PXImode) + && !(CONST_INT_P (operands[1]) && INTVAL (operands[1]) == 0)) || gpc_reg_operand (operands[1], PXImode))" "#" "&& reload_completed" @@ -103,6 +338,249 @@ rs6000_split_multireg_move (operands[0], operands[1]); DONE; } - [(set_attr "type" "vecload,vecstore,veclogical") - (set_attr "length" "8,8,16") - (set_attr "max_prefixed_insns" "2,2,*")]) + [(set_attr "type" "vecload,vecstore,veclogical,mma") + (set_attr "length" "8,8,16,*") + (set_attr "max_prefixed_insns" "2,2,*,*")]) + +(define_expand "mma_assemble_pair" + [(match_operand:POI 0 "vsx_register_operand") + (match_operand:V16QI 1 "input_operand") + (match_operand:V16QI 2 "input_operand")] + "TARGET_MMA" +{ + rtx dst; + + /* Let the compiler know the code below fully defines our output value. */ + emit_clobber (operands[0]); + + dst = simplify_gen_subreg (V16QImode, operands[0], POImode, 0); + emit_move_insn (dst, operands[1]); + dst = simplify_gen_subreg (V16QImode, operands[0], POImode, 16); + emit_move_insn (dst, operands[2]); + DONE; +}) + +(define_expand "mma_assemble_acc" + [(match_operand:PXI 0 "fpr_reg_operand") + (match_operand:V16QI 1 "input_operand") + (match_operand:V16QI 2 "input_operand") + (match_operand:V16QI 3 "input_operand") + (match_operand:V16QI 4 "input_operand")] + "TARGET_MMA" +{ + rtx src = gen_rtx_UNSPEC (PXImode, + gen_rtvec (4, operands[1], operands[2], + operands[3], operands[4]), + UNSPEC_MMA_ASSEMBLE_ACC); + emit_move_insn (operands[0], src); + DONE; +}) + +(define_insn_and_split "*mma_assemble_acc" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=d") + (unspec:PXI [(match_operand:V16QI 1 "mma_assemble_input_operand" "mwa") + (match_operand:V16QI 2 "mma_assemble_input_operand" "mwa") + (match_operand:V16QI 3 "mma_assemble_input_operand" "mwa") + (match_operand:V16QI 4 "mma_assemble_input_operand" "mwa")] + UNSPEC_MMA_ASSEMBLE_ACC))] + "TARGET_MMA + && fpr_reg_operand (operands[0], PXImode)" + "#" + "&& reload_completed" + [(const_int 0)] +{ + rtx src = gen_rtx_UNSPEC (PXImode, + gen_rtvec (4, operands[1], operands[2], + operands[3], operands[4]), + UNSPEC_MMA_ASSEMBLE_ACC); + rs6000_split_multireg_move (operands[0], src); + 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_" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d") + (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0")] + MMA_ACC))] + "TARGET_MMA" + " %A0" + [(set_attr "type" "mma")]) + +(define_insn "mma_xxsetaccz" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=d") + (const_int 0))] + "TARGET_MMA" + "xxsetaccz %A0" + [(set_attr "type" "mma")]) + +(define_insn "mma_" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d") + (unspec:PXI [(match_operand:V16QI 1 "vsx_register_operand" "wa") + (match_operand:V16QI 2 "vsx_register_operand" "wa")] + MMA_VV))] + "TARGET_MMA" + " %A0,%x1,%x2" + [(set_attr "type" "mma")]) + +(define_insn "mma_" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d") + (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0") + (match_operand:V16QI 2 "vsx_register_operand" "wa") + (match_operand:V16QI 3 "vsx_register_operand" "wa")] + MMA_AVV))] + "TARGET_MMA" + " %A0,%x2,%x3" + [(set_attr "type" "mma")]) + +(define_insn "mma_" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d") + (unspec:PXI [(match_operand:POI 1 "vsx_register_operand" "wa") + (match_operand:V16QI 2 "vsx_register_operand" "wa")] + MMA_PV))] + "TARGET_MMA" + " %A0,%x1,%x2" + [(set_attr "type" "mma")]) + +(define_insn "mma_" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d") + (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0") + (match_operand:POI 2 "vsx_register_operand" "wa") + (match_operand:V16QI 3 "vsx_register_operand" "wa")] + MMA_APV))] + "TARGET_MMA" + " %A0,%x2,%x3" + [(set_attr "type" "mma")]) + +(define_insn "mma_" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d") + (unspec:PXI [(match_operand:V16QI 1 "vsx_register_operand" "wa") + (match_operand:V16QI 2 "vsx_register_operand" "wa") + (match_operand:SI 3 "const_0_to_15_operand" "n") + (match_operand:SI 4 "const_0_to_15_operand" "n") + (match_operand:SI 5 "u8bit_cint_operand" "n")] + MMA_VVI4I4I8))] + "TARGET_MMA" + " %A0,%x1,%x2,%3,%4,%5" + [(set_attr "type" "mma") + (set_attr "length" "8")]) + +(define_insn "mma_" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d") + (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0") + (match_operand:V16QI 2 "vsx_register_operand" "wa") + (match_operand:V16QI 3 "vsx_register_operand" "wa") + (match_operand:SI 4 "const_0_to_15_operand" "n") + (match_operand:SI 5 "const_0_to_15_operand" "n") + (match_operand:SI 6 "u8bit_cint_operand" "n")] + MMA_AVVI4I4I8))] + "TARGET_MMA" + " %A0,%x2,%x3,%4,%5,%6" + [(set_attr "type" "mma") + (set_attr "length" "8")]) + +(define_insn "mma_" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d") + (unspec:PXI [(match_operand:V16QI 1 "vsx_register_operand" "wa") + (match_operand:V16QI 2 "vsx_register_operand" "wa") + (match_operand:SI 3 "const_0_to_15_operand" "n") + (match_operand:SI 4 "const_0_to_15_operand" "n") + (match_operand:SI 5 "const_0_to_3_operand" "n")] + MMA_VVI4I4I2))] + "TARGET_MMA" + " %A0,%x1,%x2,%3,%4,%5" + [(set_attr "type" "mma") + (set_attr "length" "8")]) + +(define_insn "mma_" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d") + (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0") + (match_operand:V16QI 2 "vsx_register_operand" "wa") + (match_operand:V16QI 3 "vsx_register_operand" "wa") + (match_operand:SI 4 "const_0_to_15_operand" "n") + (match_operand:SI 5 "const_0_to_15_operand" "n") + (match_operand:SI 6 "const_0_to_3_operand" "n")] + MMA_AVVI4I4I2))] + "TARGET_MMA" + " %A0,%x2,%x3,%4,%5,%6" + [(set_attr "type" "mma") + (set_attr "length" "8")]) + +(define_insn "mma_" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d") + (unspec:PXI [(match_operand:V16QI 1 "vsx_register_operand" "wa") + (match_operand:V16QI 2 "vsx_register_operand" "wa") + (match_operand:SI 3 "const_0_to_15_operand" "n") + (match_operand:SI 4 "const_0_to_15_operand" "n")] + MMA_VVI4I4))] + "TARGET_MMA" + " %A0,%x1,%x2,%3,%4" + [(set_attr "type" "mma") + (set_attr "length" "8")]) + +(define_insn "mma_" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d") + (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0") + (match_operand:V16QI 2 "vsx_register_operand" "wa") + (match_operand:V16QI 3 "vsx_register_operand" "wa") + (match_operand:SI 4 "const_0_to_15_operand" "n") + (match_operand:SI 5 "const_0_to_15_operand" "n")] + MMA_AVVI4I4))] + "TARGET_MMA" + " %A0,%x2,%x3,%4,%5" + [(set_attr "type" "mma") + (set_attr "length" "8")]) + +(define_insn "mma_" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d") + (unspec:PXI [(match_operand:POI 1 "vsx_register_operand" "wa") + (match_operand:V16QI 2 "vsx_register_operand" "wa") + (match_operand:SI 3 "const_0_to_15_operand" "n") + (match_operand:SI 4 "const_0_to_3_operand" "n")] + MMA_PVI4I2))] + "TARGET_MMA" + " %A0,%x1,%x2,%3,%4" + [(set_attr "type" "mma") + (set_attr "length" "8")]) + +(define_insn "mma_" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d") + (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0") + (match_operand:POI 2 "vsx_register_operand" "wa") + (match_operand:V16QI 3 "vsx_register_operand" "wa") + (match_operand:SI 4 "const_0_to_15_operand" "n") + (match_operand:SI 5 "const_0_to_3_operand" "n")] + MMA_APVI4I2))] + "TARGET_MMA" + " %A0,%x2,%x3,%4,%5" + [(set_attr "type" "mma") + (set_attr "length" "8")]) + +(define_insn "mma_" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d") + (unspec:PXI [(match_operand:V16QI 1 "vsx_register_operand" "wa") + (match_operand:V16QI 2 "vsx_register_operand" "wa") + (match_operand:SI 3 "const_0_to_15_operand" "n") + (match_operand:SI 4 "const_0_to_15_operand" "n") + (match_operand:SI 5 "const_0_to_15_operand" "n")] + MMA_VVI4I4I4))] + "TARGET_MMA" + " %A0,%x1,%x2,%3,%4,%5" + [(set_attr "type" "mma") + (set_attr "length" "8")]) + +(define_insn "mma_" + [(set (match_operand:PXI 0 "fpr_reg_operand" "=&d") + (unspec:PXI [(match_operand:PXI 1 "fpr_reg_operand" "0") + (match_operand:V16QI 2 "vsx_register_operand" "wa") + (match_operand:V16QI 3 "vsx_register_operand" "wa") + (match_operand:SI 4 "const_0_to_15_operand" "n") + (match_operand:SI 5 "const_0_to_15_operand" "n") + (match_operand:SI 6 "const_0_to_15_operand" "n")] + MMA_AVVI4I4I4))] + "TARGET_MMA" + " %A0,%x2,%x3,%4,%5,%6" + [(set_attr "type" "mma") + (set_attr "length" "8")]) diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index c3f460face2..9762855d76d 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -1119,6 +1119,11 @@ return gpc_reg_operand (op, mode); }) +;; Return 1 if this operand is valid for a MMA assemble accumulator insn. +(define_special_predicate "mma_assemble_input_operand" + (match_test "(mode == V16QImode + && (vsx_register_operand (op, mode) || MEM_P (op)))")) + ;; Return true if operand is an operator used in rotate-and-mask instructions. (define_predicate "rotate_mask_operator" (match_code "rotate,ashift,lshiftrt")) diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def index 8b1ddb00045..968c46cc36f 100644 --- a/gcc/config/rs6000/rs6000-builtin.def +++ b/gcc/config/rs6000/rs6000-builtin.def @@ -32,6 +32,7 @@ RS6000_BUILTIN_A -- ABS builtins RS6000_BUILTIN_D -- DST builtins RS6000_BUILTIN_H -- HTM builtins + RS6000_BUILTIN_M -- MMA builtins RS6000_BUILTIN_P -- Altivec, VSX, ISA 2.07 vector predicate builtins RS6000_BUILTIN_X -- special builtins @@ -74,6 +75,10 @@ #error "RS6000_BUILTIN_H is not defined." #endif +#ifndef RS6000_BUILTIN_M + #error "RS6000_BUILTIN_M is not defined." +#endif + #ifndef RS6000_BUILTIN_P #error "RS6000_BUILTIN_P is not defined." #endif @@ -329,6 +334,82 @@ | RS6000_BTC_SPECIAL), \ CODE_FOR_nothing) /* ICODE */ +/* MMA convenience macros. */ + +#define BU_MMA_1(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_M (MMA_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_mma_" NAME, /* NAME */ \ + RS6000_BTM_MMA, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_UNARY \ + | RS6000_BTC_VOID \ + | RS6000_BTC_GIMPLE), \ + CODE_FOR_nothing) /* ICODE */ \ + RS6000_BUILTIN_M (MMA_BUILTIN_ ## ENUM ## _INTERNAL, /* ENUM */ \ + "__builtin_mma_" NAME "_internal", /* NAME */ \ + RS6000_BTM_MMA, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_UNARY), \ + CODE_FOR_ ## ICODE) /* ICODE */ + +#define BU_MMA_V2(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_M (MMA_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_mma_" NAME, /* NAME */ \ + RS6000_BTM_MMA, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_BINARY \ + | RS6000_BTC_VOID \ + | RS6000_BTC_GIMPLE), \ + CODE_FOR_nothing) /* ICODE */ + +#define BU_MMA_3(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_M (MMA_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_mma_" NAME, /* NAME */ \ + RS6000_BTM_MMA, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_TERNARY \ + | RS6000_BTC_VOID \ + | RS6000_BTC_GIMPLE), \ + CODE_FOR_nothing) /* ICODE */ \ + RS6000_BUILTIN_M (MMA_BUILTIN_ ## ENUM ## _INTERNAL, /* ENUM */ \ + "__builtin_mma_" NAME "_internal", /* NAME */ \ + RS6000_BTM_MMA, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_TERNARY), \ + CODE_FOR_ ## ICODE) /* ICODE */ + +#define BU_MMA_5(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_M (MMA_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_mma_" NAME, /* NAME */ \ + RS6000_BTM_MMA, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_QUINARY \ + | RS6000_BTC_VOID \ + | RS6000_BTC_GIMPLE), \ + CODE_FOR_nothing) /* ICODE */ \ + RS6000_BUILTIN_M (MMA_BUILTIN_ ## ENUM ## _INTERNAL, /* ENUM */ \ + "__builtin_mma_" NAME "_internal", /* NAME */ \ + RS6000_BTM_MMA, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_QUINARY), \ + CODE_FOR_ ## ICODE) /* ICODE */ + +#define BU_MMA_6(ENUM, NAME, ATTR, ICODE) \ + RS6000_BUILTIN_M (MMA_BUILTIN_ ## ENUM, /* ENUM */ \ + "__builtin_mma_" NAME, /* NAME */ \ + RS6000_BTM_MMA, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_SENARY \ + | RS6000_BTC_VOID \ + | RS6000_BTC_GIMPLE), \ + CODE_FOR_nothing) /* ICODE */ \ + RS6000_BUILTIN_M (MMA_BUILTIN_ ## ENUM ## _INTERNAL, /* ENUM */ \ + "__builtin_mma_" NAME "_internal", /* NAME */ \ + RS6000_BTM_MMA, /* MASK */ \ + (RS6000_BTC_ ## ATTR /* ATTR */ \ + | RS6000_BTC_SENARY), \ + CODE_FOR_ ## ICODE) /* ICODE */ + /* ISA 2.05 (power6) convenience macros. */ /* For functions that depend on the CMPB instruction */ #define BU_P6_2(ENUM, NAME, ATTR, ICODE) \ @@ -2785,3 +2866,77 @@ BU_SPECIAL_X (RS6000_BUILTIN_CPU_SUPPORTS, "__builtin_cpu_supports", /* Darwin CfString builtin. */ BU_SPECIAL_X (RS6000_BUILTIN_CFSTRING, "__builtin_cfstring", RS6000_BTM_ALWAYS, RS6000_BTC_MISC) + +/* FUTURE MMA builtins. */ +BU_VSX_1 (XVCVBF16SP, "xvcvbf16sp", MISC, vsx_xvcvbf16sp) +BU_VSX_1 (XVCVSPBF16, "xvcvspbf16", MISC, vsx_xvcvspbf16) + +BU_MMA_1 (XXMFACC, "xxmfacc", QUAD, mma_xxmfacc) +BU_MMA_1 (XXMTACC, "xxmtacc", QUAD, mma_xxmtacc) +BU_MMA_1 (XXSETACCZ, "xxsetaccz", MISC, mma_xxsetaccz) + +BU_MMA_V2 (DISASSEMBLE_ACC, "disassemble_acc", QUAD, nothing) +BU_MMA_V2 (DISASSEMBLE_PAIR,"disassemble_pair", PAIR, nothing) + +BU_MMA_3 (ASSEMBLE_PAIR, "assemble_pair", MISC, mma_assemble_pair) +BU_MMA_3 (XVBF16GER2, "xvbf16ger2", MISC, mma_xvbf16ger2) +BU_MMA_3 (XVF16GER2, "xvf16ger2", MISC, mma_xvf16ger2) +BU_MMA_3 (XVF32GER, "xvf32ger", MISC, mma_xvf32ger) +BU_MMA_3 (XVF64GER, "xvf64ger", PAIR, mma_xvf64ger) +BU_MMA_3 (XVI4GER8, "xvi4ger8", MISC, mma_xvi4ger8) +BU_MMA_3 (XVI8GER4, "xvi8ger4", MISC, mma_xvi8ger4) +BU_MMA_3 (XVI16GER2, "xvi16ger2", MISC, mma_xvi16ger2) +BU_MMA_3 (XVI16GER2S, "xvi16ger2s", MISC, mma_xvi16ger2s) +BU_MMA_3 (XVBF16GER2NN, "xvbf16ger2nn", QUAD, mma_xvbf16ger2nn) +BU_MMA_3 (XVBF16GER2NP, "xvbf16ger2np", QUAD, mma_xvbf16ger2np) +BU_MMA_3 (XVBF16GER2PN, "xvbf16ger2pn", QUAD, mma_xvbf16ger2pn) +BU_MMA_3 (XVBF16GER2PP, "xvbf16ger2pp", QUAD, mma_xvbf16ger2pp) +BU_MMA_3 (XVF16GER2NN, "xvf16ger2nn", QUAD, mma_xvf16ger2nn) +BU_MMA_3 (XVF16GER2NP, "xvf16ger2np", QUAD, mma_xvf16ger2np) +BU_MMA_3 (XVF16GER2PN, "xvf16ger2pn", QUAD, mma_xvf16ger2pn) +BU_MMA_3 (XVF16GER2PP, "xvf16ger2pp", QUAD, mma_xvf16ger2pp) +BU_MMA_3 (XVF32GERNN, "xvf32gernn", QUAD, mma_xvf32gernn) +BU_MMA_3 (XVF32GERNP, "xvf32gernp", QUAD, mma_xvf32gernp) +BU_MMA_3 (XVF32GERPN, "xvf32gerpn", QUAD, mma_xvf32gerpn) +BU_MMA_3 (XVF32GERPP, "xvf32gerpp", QUAD, mma_xvf32gerpp) +BU_MMA_3 (XVF64GERNN, "xvf64gernn", QUADPAIR, mma_xvf64gernn) +BU_MMA_3 (XVF64GERNP, "xvf64gernp", QUADPAIR, mma_xvf64gernp) +BU_MMA_3 (XVF64GERPN, "xvf64gerpn", QUADPAIR, mma_xvf64gerpn) +BU_MMA_3 (XVF64GERPP, "xvf64gerpp", QUADPAIR, mma_xvf64gerpp) +BU_MMA_3 (XVI4GER8PP, "xvi4ger8pp", QUAD, mma_xvi4ger8pp) +BU_MMA_3 (XVI8GER4PP, "xvi8ger4pp", QUAD, mma_xvi8ger4pp) +BU_MMA_3 (XVI8GER4SPP, "xvi8ger4spp", QUAD, mma_xvi8ger4spp) +BU_MMA_3 (XVI16GER2PP, "xvi16ger2pp", QUAD, mma_xvi16ger2pp) +BU_MMA_3 (XVI16GER2SPP, "xvi16ger2spp", QUAD, mma_xvi16ger2spp) + +BU_MMA_5 (ASSEMBLE_ACC, "assemble_acc", MISC, mma_assemble_acc) +BU_MMA_5 (PMXVF32GER, "pmxvf32ger", MISC, mma_pmxvf32ger) +BU_MMA_5 (PMXVF64GER, "pmxvf64ger", PAIR, mma_pmxvf64ger) +BU_MMA_5 (PMXVF32GERNN, "pmxvf32gernn", QUAD, mma_pmxvf32gernn) +BU_MMA_5 (PMXVF32GERNP, "pmxvf32gernp", QUAD, mma_pmxvf32gernp) +BU_MMA_5 (PMXVF32GERPN, "pmxvf32gerpn", QUAD, mma_pmxvf32gerpn) +BU_MMA_5 (PMXVF32GERPP, "pmxvf32gerpp", QUAD, mma_pmxvf32gerpp) +BU_MMA_5 (PMXVF64GERNN, "pmxvf64gernn", QUADPAIR, mma_pmxvf64gernn) +BU_MMA_5 (PMXVF64GERNP, "pmxvf64gernp", QUADPAIR, mma_pmxvf64gernp) +BU_MMA_5 (PMXVF64GERPN, "pmxvf64gerpn", QUADPAIR, mma_pmxvf64gerpn) +BU_MMA_5 (PMXVF64GERPP, "pmxvf64gerpp", QUADPAIR, mma_pmxvf64gerpp) + +BU_MMA_6 (PMXVBF16GER2, "pmxvbf16ger2", MISC, mma_pmxvbf16ger2) +BU_MMA_6 (PMXVF16GER2, "pmxvf16ger2", MISC, mma_pmxvf16ger2) +BU_MMA_6 (PMXVI4GER8, "pmxvi4ger8", MISC, mma_pmxvi4ger8) +BU_MMA_6 (PMXVI8GER4, "pmxvi8ger4", MISC, mma_pmxvi8ger4) +BU_MMA_6 (PMXVI16GER2, "pmxvi16ger2", MISC, mma_pmxvi16ger2) +BU_MMA_6 (PMXVI16GER2S, "pmxvi16ger2s", MISC, mma_pmxvi16ger2s) +BU_MMA_6 (PMXVBF16GER2NN, "pmxvbf16ger2nn", QUAD, mma_pmxvbf16ger2nn) +BU_MMA_6 (PMXVBF16GER2NP, "pmxvbf16ger2np", QUAD, mma_pmxvbf16ger2np) +BU_MMA_6 (PMXVBF16GER2PN, "pmxvbf16ger2pn", QUAD, mma_pmxvbf16ger2pn) +BU_MMA_6 (PMXVBF16GER2PP, "pmxvbf16ger2pp", QUAD, mma_pmxvbf16ger2pp) +BU_MMA_6 (PMXVF16GER2NN, "pmxvf16ger2nn", QUAD, mma_pmxvf16ger2nn) +BU_MMA_6 (PMXVF16GER2NP, "pmxvf16ger2np", QUAD, mma_pmxvf16ger2np) +BU_MMA_6 (PMXVF16GER2PN, "pmxvf16ger2pn", QUAD, mma_pmxvf16ger2pn) +BU_MMA_6 (PMXVF16GER2PP, "pmxvf16ger2pp", QUAD, mma_pmxvf16ger2pp) +BU_MMA_6 (PMXVI4GER8PP, "pmxvi4ger8pp", QUAD, mma_pmxvi4ger8pp) +BU_MMA_6 (PMXVI8GER4PP, "pmxvi8ger4pp", QUAD, mma_pmxvi8ger4pp) +BU_MMA_6 (PMXVI8GER4SPP, "pmxvi8ger4spp", QUAD, mma_pmxvi8ger4spp) +BU_MMA_6 (PMXVI16GER2PP, "pmxvi16ger2pp", QUAD, mma_pmxvi16ger2pp) +BU_MMA_6 (PMXVI16GER2SPP, "pmxvi16ger2spp", QUAD, mma_pmxvi16ger2spp) diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c index 088264bab90..fdf136faf29 100644 --- a/gcc/config/rs6000/rs6000-call.c +++ b/gcc/config/rs6000/rs6000-call.c @@ -183,6 +183,7 @@ static tree builtin_function_type (machine_mode, machine_mode, enum rs6000_builtins, const char *name); static void rs6000_common_init_builtins (void); static void htm_init_builtins (void); +static void mma_init_builtins (void); /* Hash table to keep track of the argument types for builtin functions. */ @@ -243,6 +244,7 @@ builtin_hasher::equal (builtin_hash_struct *p1, builtin_hash_struct *p2) #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_M #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_X @@ -270,6 +272,9 @@ builtin_hasher::equal (builtin_hash_struct *p1, builtin_hash_struct *p2) #define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) \ { NAME, ICODE, MASK, ATTR }, +#define RS6000_BUILTIN_M(ENUM, NAME, MASK, ATTR, ICODE) \ + { NAME, ICODE, MASK, ATTR }, + #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) \ { NAME, ICODE, MASK, ATTR }, @@ -296,6 +301,7 @@ static const struct rs6000_builtin_info_type rs6000_builtin_info[] = #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_M #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_X @@ -8354,6 +8360,9 @@ def_builtin (const char *name, tree type, enum rs6000_builtins code) attr_string = ", fp, const"; } } + else if ((classify & (RS6000_BTC_QUAD | RS6000_BTC_PAIR)) != 0) + /* The function uses a register quad and/or pair. Nothing to do. */ + ; else if ((classify & RS6000_BTC_ATTR_MASK) != 0) gcc_unreachable (); @@ -8372,6 +8381,7 @@ def_builtin (const char *name, tree type, enum rs6000_builtins code) #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_M #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_X @@ -8385,6 +8395,7 @@ def_builtin (const char *name, tree type, enum rs6000_builtins code) #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_M(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) @@ -8403,6 +8414,7 @@ static const struct builtin_description bdesc_3arg[] = #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_M #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_X @@ -8416,6 +8428,7 @@ static const struct builtin_description bdesc_3arg[] = #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_M(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) @@ -8434,6 +8447,7 @@ static const struct builtin_description bdesc_4arg[] = #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_M #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_X @@ -8447,6 +8461,7 @@ static const struct builtin_description bdesc_4arg[] = { MASK, ICODE, NAME, ENUM }, #define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_M(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) @@ -8465,6 +8480,7 @@ static const struct builtin_description bdesc_dst[] = #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_M #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_X @@ -8478,6 +8494,7 @@ static const struct builtin_description bdesc_dst[] = #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_M(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) @@ -8494,6 +8511,7 @@ static const struct builtin_description bdesc_2arg[] = #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_M #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_X @@ -8505,6 +8523,7 @@ static const struct builtin_description bdesc_2arg[] = #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_M(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) \ { MASK, ICODE, NAME, ENUM }, @@ -8527,6 +8546,7 @@ static const struct builtin_description bdesc_altivec_preds[] = #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_M #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_X @@ -8540,6 +8560,7 @@ static const struct builtin_description bdesc_altivec_preds[] = #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_M(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) @@ -8559,6 +8580,7 @@ static const struct builtin_description bdesc_abs[] = #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_M #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_X @@ -8572,6 +8594,7 @@ static const struct builtin_description bdesc_abs[] = #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_M(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) @@ -8590,6 +8613,7 @@ static const struct builtin_description bdesc_1arg[] = #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_M #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_X @@ -8603,6 +8627,7 @@ static const struct builtin_description bdesc_1arg[] = #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_M(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) @@ -8620,6 +8645,7 @@ static const struct builtin_description bdesc_0arg[] = #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_M #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_X @@ -8633,6 +8659,7 @@ static const struct builtin_description bdesc_0arg[] = #define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) \ { MASK, ICODE, NAME, ENUM }, +#define RS6000_BUILTIN_M(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) #define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) @@ -8641,6 +8668,7 @@ static const struct builtin_description bdesc_htm[] = #include "rs6000-builtin.def" }; +/* MMA builtins. */ #undef RS6000_BUILTIN_0 #undef RS6000_BUILTIN_1 #undef RS6000_BUILTIN_2 @@ -8649,7 +8677,40 @@ static const struct builtin_description bdesc_htm[] = #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_M #undef RS6000_BUILTIN_P +#undef RS6000_BUILTIN_X + +#define RS6000_BUILTIN_0(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_1(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_2(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_3(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_4(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_M(ENUM, NAME, MASK, ATTR, ICODE) \ + { MASK, ICODE, NAME, ENUM }, + +#define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) +#define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) + +static const struct builtin_description bdesc_mma[] = +{ +#include "rs6000-builtin.def" +}; + +#undef RS6000_BUILTIN_0 +#undef RS6000_BUILTIN_1 +#undef RS6000_BUILTIN_2 +#undef RS6000_BUILTIN_3 +#undef RS6000_BUILTIN_4 +#undef RS6000_BUILTIN_A +#undef RS6000_BUILTIN_D +#undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_M +#undef RS6000_BUILTIN_P +#undef RS6000_BUILTIN_X /* Return true if a builtin function is overloaded. */ bool @@ -9393,6 +9454,133 @@ altivec_expand_stv_builtin (enum insn_code icode, tree exp) return NULL_RTX; } +/* Expand the MMA built-in in EXP. + Store true in *EXPANDEDP if we found a built-in to expand. */ + +static rtx +mma_expand_builtin (tree exp, rtx target, bool *expandedp) +{ + unsigned i; + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); + enum rs6000_builtins fcode + = (enum rs6000_builtins) DECL_MD_FUNCTION_CODE (fndecl); + const struct builtin_description *d = bdesc_mma; + + /* Expand the MMA built-in. */ + for (i = 0; i < ARRAY_SIZE (bdesc_mma); i++, d++) + if (d->code == fcode) + break; + + if (i >= ARRAY_SIZE (bdesc_mma)) + { + *expandedp = false; + return NULL_RTX; + } + + *expandedp = true; + + tree arg; + call_expr_arg_iterator iter; + enum insn_code icode = d->icode; + const struct insn_operand_data *insn_op; + rtx op[MAX_MMA_OPERANDS]; + unsigned nopnds = 0; + unsigned attr = rs6000_builtin_info[fcode].attr; + bool void_func = (attr & RS6000_BTC_VOID); + machine_mode tmode = VOIDmode; + + if (TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node) + { + tmode = insn_data[icode].operand[0].mode; + if (!target + || GET_MODE (target) != tmode + || !(*insn_data[icode].operand[0].predicate) (target, tmode)) + target = gen_reg_rtx (tmode); + op[nopnds++] = target; + } + else + target = const0_rtx; + + FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) + { + if (arg == error_mark_node) + return const0_rtx; + + rtx opnd; + insn_op = &insn_data[icode].operand[nopnds]; + if (TREE_CODE (arg) == ADDR_EXPR + && MEM_P (DECL_RTL (TREE_OPERAND (arg, 0)))) + opnd = DECL_RTL (TREE_OPERAND (arg, 0)); + else + opnd = expand_normal (arg); + + if (!(*insn_op->predicate) (opnd, insn_op->mode)) + { + if (!strcmp (insn_op->constraint, "n")) + { + if (!CONST_INT_P (opnd)) + error ("argument %d must be an unsigned literal", nopnds); + else + error ("argument %d is an unsigned literal that is " + "out of range", nopnds); + return const0_rtx; + } + opnd = copy_to_mode_reg (insn_op->mode, opnd); + } + + /* Some MMA instructions have INOUT accumulator operands, so force + their target register to be the same as their input register. */ + if (!void_func + && nopnds == 1 + && !strcmp (insn_op->constraint, "0") + && insn_op->mode == tmode + && REG_P (opnd) + && (*insn_data[icode].operand[0].predicate) (opnd, tmode)) + target = op[0] = opnd; + + op[nopnds++] = opnd; + } + + unsigned attr_args = attr & RS6000_BTC_OPND_MASK; + if (attr & RS6000_BTC_QUAD) + attr_args++; + + gcc_assert (nopnds == attr_args); + + rtx pat; + switch (nopnds) + { + case 1: + pat = GEN_FCN (icode) (op[0]); + break; + case 2: + pat = GEN_FCN (icode) (op[0], op[1]); + break; + case 3: + pat = GEN_FCN (icode) (op[0], op[1], op[2]); + break; + case 4: + pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]); + break; + case 5: + pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]); + break; + case 6: + pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5]); + break; + case 7: + pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5], op[6]); + break; + default: + gcc_unreachable (); + } + if (!pat) + return NULL_RTX; + emit_insn (pat); + + return target; +} + /* Return the appropriate SPR number associated with the given builtin. */ static inline HOST_WIDE_INT htm_spr_num (enum rs6000_builtins code) @@ -9539,11 +9727,11 @@ htm_expand_builtin (tree exp, rtx target, bool * expandedp) if (flag_checking) { int expected_nopnds = 0; - if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_UNARY) + if ((attr & RS6000_BTC_OPND_MASK) == RS6000_BTC_UNARY) expected_nopnds = 1; - else if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_BINARY) + else if ((attr & RS6000_BTC_OPND_MASK) == RS6000_BTC_BINARY) expected_nopnds = 2; - else if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_TERNARY) + else if ((attr & RS6000_BTC_OPND_MASK) == RS6000_BTC_TERNARY) expected_nopnds = 3; else if ((attr & RS6000_BTC_TYPE_MASK) == RS6000_BTC_QUATERNARY) expected_nopnds = 4; @@ -10647,6 +10835,10 @@ rs6000_invalid_builtin (enum rs6000_builtins fncode) "-m64"); else if ((fnmask & RS6000_BTM_P9_MISC) == RS6000_BTM_P9_MISC) error ("%qs requires the %qs option", name, "-mcpu=power9"); + else if ((fnmask & RS6000_BTM_FUTURE) != 0) + error ("%qs requires the %qs option", name, "-mcpu=future"); + else if ((fnmask & RS6000_BTM_MMA) != 0) + error ("%qs requires the %qs option", name, "-mmma"); else if ((fnmask & RS6000_BTM_LDBL128) == RS6000_BTM_LDBL128) { if (!TARGET_HARD_FLOAT) @@ -10690,6 +10882,10 @@ rs6000_fold_builtin (tree fndecl ATTRIBUTE_UNUSED, static bool rs6000_builtin_valid_without_lhs (enum rs6000_builtins fn_code) { + /* Check for built-ins explicitly marked as a void function. */ + if (rs6000_builtin_info[fn_code].attr & RS6000_BTC_VOID) + return true; + switch (fn_code) { case ALTIVEC_BUILTIN_STVX_V16QI: @@ -10836,6 +11032,156 @@ fold_mergeeo_helper (gimple_stmt_iterator *gsi, gimple *stmt, int use_odd) gsi_replace (gsi, g, true); } +/* Expand the MMA built-ins early, so that we can convert the pass-by-reference + __vector_quad arguments into pass-by-value arguments, leading to more + efficient code generation. */ + +bool +rs6000_gimple_fold_mma_builtin (gimple_stmt_iterator *gsi) +{ + gimple *stmt = gsi_stmt (*gsi); + tree fndecl = gimple_call_fndecl (stmt); + enum rs6000_builtins fncode + = (enum rs6000_builtins) DECL_MD_FUNCTION_CODE (fndecl); + unsigned attr = rs6000_builtin_info[fncode].attr; + + if ((attr & RS6000_BTC_GIMPLE) == 0) + return false; + + unsigned nopnds = (attr & RS6000_BTC_OPND_MASK); + gimple_seq new_seq = NULL; + gimple *new_call; + tree new_decl; + + if (rs6000_builtin_info[fncode + 1].icode == CODE_FOR_nothing) + { + /* This is an MMA disassemble built-in function. */ + gcc_assert (fncode == MMA_BUILTIN_DISASSEMBLE_ACC + || fncode == MMA_BUILTIN_DISASSEMBLE_PAIR); + + push_gimplify_context (true); + tree dst_ptr = gimple_call_arg (stmt, 0); + tree src_ptr = gimple_call_arg (stmt, 1); + tree src_type = TREE_TYPE (src_ptr); + tree src = make_ssa_name (TREE_TYPE (src_type)); + gimplify_assign (src, build_simple_mem_ref (src_ptr), &new_seq); + + /* If we are not disassembling an accumulator or our destination is + another accumulator, then just copy the entire thing as is. */ + if (fncode != MMA_BUILTIN_DISASSEMBLE_ACC + || TREE_TYPE (TREE_TYPE (dst_ptr)) == vector_quad_type_node) + { + tree dst = build_simple_mem_ref (build1 (VIEW_CONVERT_EXPR, + src_type, dst_ptr)); + gimplify_assign (dst, src, &new_seq); + pop_gimplify_context (NULL); + gsi_replace_with_seq (gsi, new_seq, true); + return true; + } + + /* We're disassembling an accumulator into a different type, so we need + to emit a xxmfacc instruction now, since we cannot do it later. */ + new_decl = rs6000_builtin_decls[MMA_BUILTIN_XXMFACC_INTERNAL]; + new_call = gimple_build_call (new_decl, 1, src); + src = make_ssa_name (vector_quad_type_node); + gimple_call_set_lhs (new_call, src); + gimple_seq_add_stmt (&new_seq, new_call); + + /* Copy the accumulator vector by vector. */ + tree dst_type = build_pointer_type_for_mode (unsigned_V16QI_type_node, + ptr_mode, true); + tree dst_base = build1 (VIEW_CONVERT_EXPR, dst_type, dst_ptr); + tree array_type = build_array_type_nelts (unsigned_V16QI_type_node, 4); + tree src_array = build1 (VIEW_CONVERT_EXPR, array_type, src); + for (unsigned i = 0; i < 4; i++) + { + tree ref = build4 (ARRAY_REF, unsigned_V16QI_type_node, src_array, + build_int_cst (size_type_node, i), + NULL_TREE, NULL_TREE); + tree dst = build2 (MEM_REF, unsigned_V16QI_type_node, dst_base, + build_int_cst (dst_type, i * 16)); + gimplify_assign (dst, ref, &new_seq); + } + pop_gimplify_context (NULL); + gsi_replace_with_seq (gsi, new_seq, true); + return true; + } + + /* Convert this built-in into an internal version that uses pass-by-value + arguments. The internal built-in follows immediately after this one. */ + new_decl = rs6000_builtin_decls[fncode + 1]; + tree lhs, mem, op[MAX_MMA_OPERANDS]; + tree acc = gimple_call_arg (stmt, 0); + if (TREE_CODE (acc) == PARM_DECL) + mem = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (acc)), acc); + else + mem = build_simple_mem_ref (acc); + push_gimplify_context (true); + + if ((attr & RS6000_BTC_QUAD) != 0) + { + /* This built-in has a pass-by-reference accumulator input, so load it + into a temporary accumulator for use as a pass-by-value input. */ + op[0] = make_ssa_name (vector_quad_type_node); + for (unsigned i = 1; i < nopnds; i++) + op[i] = gimple_call_arg (stmt, i); + gimplify_assign (op[0], mem, &new_seq); + } + else + { + /* This built-in does not use its pass-by-reference accumulator argument + as an input argument, so remove it from the input list. */ + nopnds--; + for (unsigned i = 0; i < nopnds; i++) + op[i] = gimple_call_arg (stmt, i + 1); + } + + switch (nopnds) + { + case 0: + new_call = gimple_build_call (new_decl, 0); + break; + case 1: + new_call = gimple_build_call (new_decl, 1, op[0]); + break; + case 2: + new_call = gimple_build_call (new_decl, 2, op[0], op[1]); + break; + case 3: + new_call = gimple_build_call (new_decl, 3, op[0], op[1], op[2]); + break; + case 4: + new_call = gimple_build_call (new_decl, 4, op[0], op[1], op[2], op[3]); + break; + case 5: + new_call = gimple_build_call (new_decl, 5, op[0], op[1], op[2], op[3], + op[4]); + break; + case 6: + new_call = gimple_build_call (new_decl, 6, op[0], op[1], op[2], op[3], + op[4], op[5]); + break; + case 7: + new_call = gimple_build_call (new_decl, 7, op[0], op[1], op[2], op[3], + op[4], op[5], op[6]); + break; + default: + gcc_unreachable (); + } + + if (fncode == MMA_BUILTIN_ASSEMBLE_PAIR) + lhs = make_ssa_name (vector_pair_type_node); + else + lhs = make_ssa_name (vector_quad_type_node); + gimple_call_set_lhs (new_call, lhs); + gimple_seq_add_stmt (&new_seq, new_call); + gimplify_assign (mem, lhs, &new_seq); + pop_gimplify_context (NULL); + gsi_replace_with_seq (gsi, new_seq, true); + + return true; +} + /* Fold a machine-dependent built-in in GIMPLE. (For folding into a constant, use rs6000_fold_builtin.) */ @@ -10871,11 +11217,12 @@ rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi) return false; /* Don't fold invalid builtins, let rs6000_expand_builtin diagnose it. */ - HOST_WIDE_INT mask = rs6000_builtin_info[uns_fncode].mask; - bool func_valid_p = (rs6000_builtin_mask & mask) == mask; - if (!func_valid_p) + if (!rs6000_builtin_is_supported_p (fn_code)) return false; + if (rs6000_gimple_fold_mma_builtin (gsi)) + return true; + switch (fn_code) { /* Flavors of vec_add. We deliberately don't expand @@ -12010,6 +12357,13 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, break; } + if (TARGET_MMA) + { + ret = mma_expand_builtin (exp, target, &success); + + if (success) + return ret; + } if (TARGET_ALTIVEC) { ret = altivec_expand_builtin (exp, target, &success); @@ -12025,7 +12379,7 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, return ret; } - unsigned attr = rs6000_builtin_info[uns_fcode].attr & RS6000_BTC_TYPE_MASK; + unsigned attr = rs6000_builtin_info[uns_fcode].attr & RS6000_BTC_OPND_MASK; /* RS6000_BTC_SPECIAL represents no-operand operators. */ gcc_assert (attr == RS6000_BTC_UNARY || attr == RS6000_BTC_BINARY @@ -12208,7 +12562,7 @@ rs6000_init_builtins (void) else ieee128_float_type_node = ibm128_float_type_node = long_double_type_node; - /* Vector paired and vector quad support. */ + /* Vector pair and vector quad support. */ if (TARGET_MMA) { tree oi_uns_type = make_unsigned_type (256); @@ -12290,6 +12644,8 @@ rs6000_init_builtins (void) the target attribute. */ if (TARGET_EXTRA_BUILTINS) altivec_init_builtins (); + if (TARGET_MMA) + mma_init_builtins (); if (TARGET_HTM) htm_init_builtins (); @@ -13015,6 +13371,119 @@ altivec_init_builtins (void) } +static void +mma_init_builtins (void) +{ + const struct builtin_description *d = bdesc_mma; + + for (unsigned i = 0; i < ARRAY_SIZE (bdesc_mma); i++, d++) + { + tree op[MAX_MMA_OPERANDS], type; + HOST_WIDE_INT mask = d->mask; + unsigned icode = (unsigned) d->icode; + unsigned attr = rs6000_builtin_info[d->code].attr; + int attr_args = (attr & RS6000_BTC_OPND_MASK); + bool gimple_func = (attr & RS6000_BTC_GIMPLE); + unsigned nopnds = 0; + + if ((mask & rs6000_builtin_mask) != mask) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "mma_builtin, skip binary %s\n", d->name); + continue; + } + + if (d->name == 0) + { + if (TARGET_DEBUG_BUILTIN) + fprintf (stderr, "mma_builtin, bdesc_mma[%ld] no name\n", + (long unsigned) i); + continue; + } + + if (gimple_func) + { + gcc_assert (icode == CODE_FOR_nothing); + op[nopnds++] = void_type_node; + /* Some MMA built-ins that are expanded into gimple are converted + into internal MMA built-ins that are expanded into rtl. + The internal built-in follows immediately after this built-in. */ + icode = d[1].icode; + } + else + { + if ((attr & RS6000_BTC_QUAD) == 0) + attr_args--; + + /* Ensure we have the correct number and type of operands. */ + gcc_assert (attr_args == insn_data[icode].n_operands - 1); + } + + if (icode == CODE_FOR_nothing) + { + /* This is a disassemble MMA built-in function. */ + gcc_assert (attr_args == RS6000_BTC_BINARY + && (d->code == MMA_BUILTIN_DISASSEMBLE_ACC + || d->code == MMA_BUILTIN_DISASSEMBLE_PAIR)); + op[nopnds++] = build_pointer_type (void_type_node); + if (attr & RS6000_BTC_QUAD) + op[nopnds++] = build_pointer_type (vector_quad_type_node); + else + op[nopnds++] = build_pointer_type (vector_pair_type_node); + } + else + { + /* This is a normal MMA built-in function. */ + unsigned j = (attr & RS6000_BTC_QUAD) ? 1 : 0; + for (; j < insn_data[icode].n_operands; j++) + { + machine_mode mode = insn_data[icode].operand[j].mode; + if (gimple_func && mode == PXImode) + op[nopnds++] = build_pointer_type (vector_quad_type_node); + else if (gimple_func && mode == POImode + && d->code == MMA_BUILTIN_ASSEMBLE_PAIR) + op[nopnds++] = build_pointer_type (vector_pair_type_node); + else + /* MMA uses unsigned types. */ + op[nopnds++] = builtin_mode_to_type[mode][1]; + } + } + + switch (nopnds) + { + case 1: + type = build_function_type_list (op[0], NULL_TREE); + break; + case 2: + type = build_function_type_list (op[0], op[1], NULL_TREE); + break; + case 3: + type = build_function_type_list (op[0], op[1], op[2], NULL_TREE); + break; + case 4: + type = build_function_type_list (op[0], op[1], op[2], op[3], + NULL_TREE); + break; + case 5: + type = build_function_type_list (op[0], op[1], op[2], op[3], op[4], + NULL_TREE); + break; + case 6: + type = build_function_type_list (op[0], op[1], op[2], op[3], op[4], + op[5], NULL_TREE); + break; + case 7: + type = build_function_type_list (op[0], op[1], op[2], op[3], op[4], + op[5], op[6], NULL_TREE); + break; + default: + gcc_unreachable (); + } + + def_builtin (d->name, type, d->code); + } +} + static void htm_init_builtins (void) { @@ -13029,7 +13498,7 @@ htm_init_builtins (void) HOST_WIDE_INT mask = d->mask; unsigned attr = rs6000_builtin_info[d->code].attr; bool void_func = (attr & RS6000_BTC_VOID); - int attr_args = (attr & RS6000_BTC_TYPE_MASK); + int attr_args = (attr & RS6000_BTC_OPND_MASK); int nopnds = 0; tree gpr_type_node; tree rettype; @@ -13195,6 +13664,8 @@ builtin_function_type (machine_mode mode_ret, machine_mode mode_arg0, case P8V_BUILTIN_VGBBD: case MISC_BUILTIN_CDTBCD: case MISC_BUILTIN_CBCDTD: + case VSX_BUILTIN_XVCVSPBF16: + case VSX_BUILTIN_XVCVBF16SP: h.uns_p[0] = 1; h.uns_p[1] = 1; break; diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 8f06080821a..6bc070f9a3c 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -9941,7 +9941,7 @@ rs6000_emit_move (rtx dest, rtx source, machine_mode mode) case E_POImode: case E_PXImode: - if (CONSTANT_P (operands[1])) + if (CONST_INT_P (operands[1]) && INTVAL (operands[1]) != 0) error ("%qs is an opaque type, and you can't set it to other values.", (mode == POImode) ? "__vector_pair" : "__vector_quad"); break; @@ -12853,6 +12853,14 @@ print_operand (FILE *file, rtx x, int code) /* %c is output_addr_const if a CONSTANT_ADDRESS_P, otherwise output_operand. */ + case 'A': + /* Write the MMA accumulator number associated with VSX register X. */ + if (!REG_P (x) || !FP_REGNO_P (REGNO (x)) || (REGNO (x) % 4) != 0) + output_operand_lossage ("invalid %%A value"); + else + fprintf (file, "%d", (REGNO (x) - FIRST_FPR_REGNO) / 4); + return; + case 'D': /* Like 'J' but get to the GT bit only. */ if (!REG_P (x) || !CR_REGNO_P (REGNO (x))) @@ -15963,6 +15971,12 @@ rs6000_split_multireg_move (rtx dst, rtx src) unsigned offset = 0; 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 + && GET_MODE (src) == PXImode && FP_REGNO_P (REGNO (src))) + emit_insn (gen_mma_xxmfacc (src, src)); + for (int i = 0; i < nregs; i++) { unsigned subreg = (WORDS_BIG_ENDIAN) @@ -15991,6 +16005,32 @@ rs6000_split_multireg_move (rtx dst, rtx src) emit_insn (gen_rtx_SET (dst2, src2)); } + /* If we are writing an accumulator register, we have to + prime it after we've written it. */ + if (TARGET_MMA + && GET_MODE (dst) == PXImode && FP_REGNO_P (REGNO (dst))) + emit_insn (gen_mma_xxmtacc (dst, dst)); + + return; + } + + if (GET_CODE (src) == UNSPEC) + { + gcc_assert (REG_P (dst) + && FP_REGNO_P (REGNO (dst)) + && XINT (src, 1) == UNSPEC_MMA_ASSEMBLE_ACC); + + reg_mode = GET_MODE (XVECEXP (src, 0, 0)); + for (int i = 0; i < XVECLEN (src, 0); i++) + { + rtx dst_i = gen_rtx_REG (reg_mode, reg + i); + emit_insn (gen_rtx_SET (dst_i, XVECEXP (src, 0, i))); + } + + /* We are writing an accumulator register, so we have to + prime it after we've written it. */ + emit_insn (gen_mma_xxmtacc (dst, dst)); + return; } @@ -15999,6 +16039,12 @@ 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 + && GET_MODE (src) == PXImode && FP_REGNO_P (REGNO (src))) + emit_insn (gen_mma_xxmfacc (src, src)); + /* Move register range backwards, if we might have destructive overlap. */ int i; @@ -16007,6 +16053,12 @@ rs6000_split_multireg_move (rtx dst, rtx src) i * reg_mode_size), simplify_gen_subreg (reg_mode, src, mode, i * reg_mode_size))); + + /* If we are writing an accumulator register, we have to + prime it after we've written it. */ + if (TARGET_MMA + && GET_MODE (dst) == PXImode && FP_REGNO_P (REGNO (dst))) + emit_insn (gen_mma_xxmtacc (dst, dst)); } else { @@ -16139,6 +16191,12 @@ rs6000_split_multireg_move (rtx dst, rtx src) gcc_assert (rs6000_offsettable_memref_p (dst, reg_mode, true)); } + /* If we are reading an accumulator register, we have to + deprime it before we can access it. */ + if (TARGET_MMA && REG_P (src) + && GET_MODE (src) == PXImode && FP_REGNO_P (REGNO (src))) + emit_insn (gen_mma_xxmfacc (src, src)); + for (i = 0; i < nregs; i++) { /* Calculate index to next subword. */ @@ -16156,6 +16214,13 @@ rs6000_split_multireg_move (rtx dst, rtx src) simplify_gen_subreg (reg_mode, src, mode, j * reg_mode_size))); } + + /* If we are writing an accumulator register, we have to + prime it after we've written it. */ + if (TARGET_MMA && REG_P (dst) + && GET_MODE (dst) == PXImode && FP_REGNO_P (REGNO (dst))) + emit_insn (gen_mma_xxmtacc (dst, dst)); + if (restore_basereg != NULL_RTX) emit_insn (restore_basereg); } diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 188f49ca1f3..eb22d5e4f01 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -2251,20 +2251,24 @@ extern int frame_pointer_needed; flags macros, but we've run out of bits, so we now map the options into new settings used here. */ -/* Builtin attributes. */ -#define RS6000_BTC_SPECIAL 0x00000000 /* Special function. */ +/* Builtin operand count. */ #define RS6000_BTC_UNARY 0x00000001 /* normal unary function. */ #define RS6000_BTC_BINARY 0x00000002 /* normal binary function. */ #define RS6000_BTC_TERNARY 0x00000003 /* normal ternary function. */ #define RS6000_BTC_QUATERNARY 0x00000004 /* normal quaternary function. */ +#define RS6000_BTC_QUINARY 0x00000005 /* normal quinary function. */ +#define RS6000_BTC_SENARY 0x00000006 /* normal senary function. */ +#define RS6000_BTC_OPND_MASK 0x00000007 /* Mask to isolate operands. */ -#define RS6000_BTC_PREDICATE 0x00000005 /* predicate function. */ -#define RS6000_BTC_ABS 0x00000006 /* Altivec/VSX ABS +/* Builtin attributes. */ +#define RS6000_BTC_SPECIAL 0x00000000 /* Special function. */ +#define RS6000_BTC_PREDICATE 0x00000008 /* predicate function. */ +#define RS6000_BTC_ABS 0x00000010 /* Altivec/VSX ABS function. */ -#define RS6000_BTC_DST 0x00000007 /* Altivec DST function. */ +#define RS6000_BTC_DST 0x00000020 /* Altivec DST function. */ -#define RS6000_BTC_TYPE_MASK 0x0000000f /* Mask to isolate types */ +#define RS6000_BTC_TYPE_MASK 0x0000003f /* Mask to isolate types */ #define RS6000_BTC_MISC 0x00000000 /* No special attributes. */ #define RS6000_BTC_CONST 0x00000100 /* Neither uses, nor @@ -2273,13 +2277,18 @@ extern int frame_pointer_needed; state/mem and does not modify global state. */ #define RS6000_BTC_FP 0x00000400 /* depends on rounding mode. */ -#define RS6000_BTC_ATTR_MASK 0x00000700 /* Mask of the attributes. */ +#define RS6000_BTC_QUAD 0x00000800 /* Uses a register quad. */ +#define RS6000_BTC_PAIR 0x00001000 /* Uses a register pair. */ +#define RS6000_BTC_QUADPAIR 0x00001800 /* Uses a quad and a pair. */ +#define RS6000_BTC_ATTR_MASK 0x00001f00 /* Mask of the attributes. */ /* Miscellaneous information. */ #define RS6000_BTC_SPR 0x01000000 /* function references SPRs. */ #define RS6000_BTC_VOID 0x02000000 /* function has no return value. */ #define RS6000_BTC_CR 0x04000000 /* function references a CR. */ #define RS6000_BTC_OVERLOADED 0x08000000 /* function is overloaded. */ +#define RS6000_BTC_GIMPLE 0x10000000 /* function should be expanded + into gimple. */ #define RS6000_BTC_MISC_MASK 0x1f000000 /* Mask of the misc info. */ /* Convenience macros to document the instruction type. */ @@ -2348,6 +2357,7 @@ extern int frame_pointer_needed; #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_M #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_X @@ -2359,6 +2369,7 @@ extern int frame_pointer_needed; #define RS6000_BUILTIN_A(ENUM, NAME, MASK, ATTR, ICODE) ENUM, #define RS6000_BUILTIN_D(ENUM, NAME, MASK, ATTR, ICODE) ENUM, #define RS6000_BUILTIN_H(ENUM, NAME, MASK, ATTR, ICODE) ENUM, +#define RS6000_BUILTIN_M(ENUM, NAME, MASK, ATTR, ICODE) ENUM, #define RS6000_BUILTIN_P(ENUM, NAME, MASK, ATTR, ICODE) ENUM, #define RS6000_BUILTIN_X(ENUM, NAME, MASK, ATTR, ICODE) ENUM, @@ -2377,6 +2388,7 @@ enum rs6000_builtins #undef RS6000_BUILTIN_A #undef RS6000_BUILTIN_D #undef RS6000_BUILTIN_H +#undef RS6000_BUILTIN_M #undef RS6000_BUILTIN_P #undef RS6000_BUILTIN_X diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index f577bb0e823..67d7f38e5d0 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -203,7 +203,7 @@ vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm, vecfloat,vecfdiv,vecdouble,mffgpr,mftgpr,crypto, veclogical,veccmpfx,vecexts,vecmove, - htm,htmsimple,dfp" + htm,htmsimple,dfp,mma" (const_string "integer")) ;; What data size does this instruction work on? diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index 2a28215ac5b..342927abeda 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -296,6 +296,8 @@ UNSPEC_VSX_DIVUD UNSPEC_VSX_MULSD UNSPEC_VSX_SIGN_EXTEND + UNSPEC_VSX_XVCVBF16SP + UNSPEC_VSX_XVCVSPBF16 UNSPEC_VSX_XVCVSPSXDS UNSPEC_VSX_VSLO UNSPEC_VSX_EXTRACT @@ -346,6 +348,12 @@ UNSPEC_XXGENPCV ]) +(define_int_iterator XVCVBF16 [UNSPEC_VSX_XVCVSPBF16 + UNSPEC_VSX_XVCVBF16SP]) + +(define_int_attr xvcvbf16 [(UNSPEC_VSX_XVCVSPBF16 "xvcvspbf16") + (UNSPEC_VSX_XVCVBF16SP "xvcvbf16sp")]) + ;; VSX moves ;; The patterns for LE permuted loads and stores come before the general @@ -5676,3 +5684,10 @@ DONE; }) +(define_insn "vsx_" + [(set (match_operand:V16QI 0 "vsx_register_operand" "=wa") + (unspec:V16QI [(match_operand:V16QI 1 "vsx_register_operand" "wa")] + XVCVBF16))] + "TARGET_FUTURE" + " %x0,%x1" + [(set_attr "type" "vecfloat")]) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 10dc32e6d2d..95f7192e41e 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -13858,6 +13858,7 @@ instructions, but allow the compiler to schedule those calls. * PowerPC AltiVec/VSX Built-in Functions:: * PowerPC Hardware Transactional Memory Built-in Functions:: * PowerPC Atomic Memory Operation Functions:: +* PowerPC Matrix-Multiply Assist Built-in Functions:: * RX Built-in Functions:: * S/390 System z Built-in Functions:: * SH Built-in Functions:: @@ -21359,6 +21360,100 @@ void amo_stdat_smax (int64_t *, int64_t); void amo_stdat_smin (int64_t *, int64_t); @end smallexample +@node PowerPC Matrix-Multiply Assist Built-in Functions +@subsection PowerPC Matrix-Multiply Assist Built-in Functions +ISA 3.1 of the PowerPC added new Matrix-Multiply Assist (MMA) instructions. +GCC provides support for these instructions through the following built-in +functions which are enabled with the @code{-mmma} option. The vec_t type +below is defined to be a normal vector unsigned char type.  The uint2, uint4 +and uint8 parameters are 2-bit, 4-bit and 8-bit unsigned integer constants +respectively.  The compiler will verify that they are constants and that +their values are within range.  + +The built-in functions supported are: + +@smallexample +void __builtin_mma_xvi4ger8 (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvi8ger4 (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvi16ger2 (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvi16ger2s (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvf16ger2 (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvbf16ger2 (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvf32ger (__vector_quad *, vec_t, vec_t); + +void __builtin_mma_xvi4ger8pp (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvi8ger4pp (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvi8ger4spp(__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvi16ger2pp (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvi16ger2spp (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvf16ger2pp (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvf16ger2pn (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvf16ger2np (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvf16ger2nn (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvbf16ger2pp (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvbf16ger2pn (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvbf16ger2np (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvbf16ger2nn (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvf32gerpp (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvf32gerpn (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvf32gernp (__vector_quad *, vec_t, vec_t); +void __builtin_mma_xvf32gernn (__vector_quad *, vec_t, vec_t); + +void __builtin_mma_pmxvi4ger8 (__vector_quad *, vec_t, vec_t, uint4, uint4, uint8); +void __builtin_mma_pmxvi4ger8pp (__vector_quad *, vec_t, vec_t, uint4, uint4, uint8); + +void __builtin_mma_pmxvi8ger4 (__vector_quad *, vec_t, vec_t, uint4, uint4, uint4); +void __builtin_mma_pmxvi8ger4pp (__vector_quad *, vec_t, vec_t, uint4, uint4, uint4); +void __builtin_mma_pmxvi8ger4spp(__vector_quad *, vec_t, vec_t, uint4, uint4, uint4); + +void __builtin_mma_pmxvi16ger2 (__vector_quad *, vec_t, vec_t, uint4, uint4, uint2); +void __builtin_mma_pmxvi16ger2s (__vector_quad *, vec_t, vec_t, uint4, uint4, uint2); +void __builtin_mma_pmxvf16ger2 (__vector_quad *, vec_t, vec_t, uint4, uint4, uint2); +void __builtin_mma_pmxvbf16ger2 (__vector_quad *, vec_t, vec_t, uint4, uint4, uint2); + +void __builtin_mma_pmxvi16ger2pp (__vector_quad *, vec_t, vec_t, uint4, uint4, uint2); +void __builtin_mma_pmxvi16ger2spp (__vector_quad *, vec_t, vec_t, uint4, uint4, uint2); +void __builtin_mma_pmxvf16ger2pp (__vector_quad *, vec_t, vec_t, uint4, uint4, uint2); +void __builtin_mma_pmxvf16ger2pn (__vector_quad *, vec_t, vec_t, uint4, uint4, uint2); +void __builtin_mma_pmxvf16ger2np (__vector_quad *, vec_t, vec_t, uint4, uint4, uint2); +void __builtin_mma_pmxvf16ger2nn (__vector_quad *, vec_t, vec_t, uint4, uint4, uint2); +void __builtin_mma_pmxvbf16ger2pp (__vector_quad *, vec_t, vec_t, uint4, uint4, uint2); +void __builtin_mma_pmxvbf16ger2pn (__vector_quad *, vec_t, vec_t, uint4, uint4, uint2); +void __builtin_mma_pmxvbf16ger2np (__vector_quad *, vec_t, vec_t, uint4, uint4, uint2); +void __builtin_mma_pmxvbf16ger2nn (__vector_quad *, vec_t, vec_t, uint4, uint4, uint2); + +void __builtin_mma_pmxvf32ger (__vector_quad *, vec_t, vec_t, uint4, uint4); +void __builtin_mma_pmxvf32gerpp (__vector_quad *, vec_t, vec_t, uint4, uint4); +void __builtin_mma_pmxvf32gerpn (__vector_quad *, vec_t, vec_t, uint4, uint4); +void __builtin_mma_pmxvf32gernp (__vector_quad *, vec_t, vec_t, uint4, uint4); +void __builtin_mma_pmxvf32gernn (__vector_quad *, vec_t, vec_t, uint4, uint4); + +void __builtin_mma_xvf64ger (__vector_quad *, __vector_pair, vec_t); +void __builtin_mma_xvf64gerpp (__vector_quad *, __vector_pair, vec_t); +void __builtin_mma_xvf64gerpn (__vector_quad *, __vector_pair, vec_t); +void __builtin_mma_xvf64gernp (__vector_quad *, __vector_pair, vec_t); +void __builtin_mma_xvf64gernn (__vector_quad *, __vector_pair, vec_t); + +void __builtin_mma_pmxvf64ger (__vector_quad *, __vector_pair, vec_t, uint4, uint2); +void __builtin_mma_pmxvf64gerpp (__vector_quad *, __vector_pair, vec_t, uint4, uint2); +void __builtin_mma_pmxvf64gerpn (__vector_quad *, __vector_pair, vec_t, uint4, uint2); +void __builtin_mma_pmxvf64gernp (__vector_quad *, __vector_pair, vec_t, uint4, uint2); +void __builtin_mma_pmxvf64gernn (__vector_quad *, __vector_pair, vec_t, uint4, uint2); + +void __builtin_mma_xxmtacc (__vector_quad *); +void __builtin_mma_xxmfacc (__vector_quad *); +void __builtin_mma_xxsetaccz (__vector_quad *); + +void __builtin_mma_assemble_acc (__vector_quad *, vec_t, vec_t, vec_t, vec_t); +void __builtin_mma_disassemble_acc (void *, __vector_quad *); + +void __builtin_mma_assemble_pair (__vector_pair *, vec_t, vec_t); +void __builtin_mma_disassemble_pair (void *, __vector_pair *); + +vec_t __builtin_vsx_xvcvspbf16 (vec_t); +vec_t __builtin_vsx_xvcvbf16sp (vec_t); +@end smallexample + @node RX Built-in Functions @subsection RX Built-in Functions GCC supports some of the RX instructions which cannot be expressed in diff --git a/gcc/testsuite/gcc.target/powerpc/mma-builtin-1.c b/gcc/testsuite/gcc.target/powerpc/mma-builtin-1.c new file mode 100644 index 00000000000..a971c869095 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/mma-builtin-1.c @@ -0,0 +1,313 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_future_ok } */ +/* { dg-options "-Wno-psabi -mdejagnu-cpu=future -O2" } */ + +typedef unsigned char vec_t __attribute__((vector_size(16))); + +void +foo0 (__vector_quad *dst, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + __builtin_mma_xvi4ger8 (&acc, vec0, vec1); + __builtin_mma_xvi4ger8pp (&acc, vec0, vec1); + dst[0] = acc; +} + +void +foo1 (__vector_quad *dst, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + __builtin_mma_xvi8ger4 (&acc, vec0, vec1); + __builtin_mma_xvi8ger4pp (&acc, vec0, vec1); + __builtin_mma_xvi8ger4spp(&acc, vec0, vec1); + dst[1] = acc; +} + +void +foo2 (__vector_quad *dst, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + __builtin_mma_xvi16ger2 (&acc, vec0, vec1); + __builtin_mma_xvi16ger2pp (&acc, vec0, vec1); + dst[2] = acc; +} + +void +foo3 (__vector_quad *dst, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + __builtin_mma_xvi16ger2s (&acc, vec0, vec1); + __builtin_mma_xvi16ger2spp (&acc, vec0, vec1); + dst[3] = acc; +} + +void +foo4 (__vector_quad *dst, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + __builtin_mma_xvf16ger2 (&acc, vec0, vec1); + __builtin_mma_xvf16ger2pp (&acc, vec0, vec1); + __builtin_mma_xvf16ger2pn (&acc, vec0, vec1); + dst[4] = acc; +} + +void +foo4b (__vector_quad *dst, __vector_quad *src, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + acc = src[0]; + __builtin_mma_xvf16ger2np (&acc, vec0, vec1); + __builtin_mma_xvf16ger2nn (&acc, vec0, vec1); + dst[4] = acc; +} + +void +foo5 (__vector_quad *dst, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + __builtin_mma_xvbf16ger2 (&acc, vec0, vec1); + __builtin_mma_xvbf16ger2pp (&acc, vec0, vec1); + __builtin_mma_xvbf16ger2pn (&acc, vec0, vec1); + dst[5] = acc; +} + +void +foo5b (__vector_quad *dst, __vector_quad *src, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + acc = src[0]; + __builtin_mma_xvbf16ger2np (&acc, vec0, vec1); + __builtin_mma_xvbf16ger2nn (&acc, vec0, vec1); + dst[5] = acc; +} + +void +foo6 (__vector_quad *dst, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + __builtin_mma_xvf32ger (&acc, vec0, vec1); + __builtin_mma_xvf32gerpp (&acc, vec0, vec1); + __builtin_mma_xvf32gerpn (&acc, vec0, vec1); + dst[6] = acc; +} + +void +foo6b (__vector_quad *dst, __vector_quad *src, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + acc = src[0]; + __builtin_mma_xvf32gernp (&acc, vec0, vec1); + __builtin_mma_xvf32gernn (&acc, vec0, vec1); + dst[6] = acc; +} + +void +foo7 (__vector_quad *dst, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + __builtin_mma_pmxvi4ger8 (&acc, vec0, vec1, 15, 15, 255); + __builtin_mma_pmxvi4ger8pp (&acc, vec0, vec1, 15, 15, 255); + dst[7] = acc; +} + +void +foo8 (__vector_quad *dst, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + __builtin_mma_pmxvi8ger4 (&acc, vec0, vec1, 15, 15, 15); + __builtin_mma_pmxvi8ger4pp (&acc, vec0, vec1, 15, 15, 15); + __builtin_mma_pmxvi8ger4spp(&acc, vec0, vec1, 15, 15, 15); + dst[8] = acc; +} + +void +foo9 (__vector_quad *dst, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + __builtin_mma_pmxvi16ger2 (&acc, vec0, vec1, 15, 15, 3); + __builtin_mma_pmxvi16ger2pp (&acc, vec0, vec1, 15, 15, 3); + dst[9] = acc; +} + +void +foo10 (__vector_quad *dst, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + __builtin_mma_pmxvi16ger2s (&acc, vec0, vec1, 15, 15, 3); + __builtin_mma_pmxvi16ger2spp (&acc, vec0, vec1, 15, 15, 3); + dst[10] = acc; +} + +void +foo11 (__vector_quad *dst, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + __builtin_mma_pmxvf16ger2 (&acc, vec0, vec1, 15, 15, 3); + __builtin_mma_pmxvf16ger2pp (&acc, vec0, vec1, 15, 15, 3); + __builtin_mma_pmxvf16ger2pn (&acc, vec0, vec1, 15, 15, 3); + dst[11] = acc; +} + +void +foo11b (__vector_quad *dst, __vector_quad *src, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + acc = src[0]; + __builtin_mma_pmxvf16ger2np (&acc, vec0, vec1, 15, 15, 3); + __builtin_mma_pmxvf16ger2nn (&acc, vec0, vec1, 15, 15, 3); + dst[11] = acc; +} + +void +foo12 (__vector_quad *dst, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + __builtin_mma_pmxvbf16ger2 (&acc, vec0, vec1, 15, 15, 3); + __builtin_mma_pmxvbf16ger2pp (&acc, vec0, vec1, 15, 15, 3); + __builtin_mma_pmxvbf16ger2pn (&acc, vec0, vec1, 15, 15, 3); + dst[12] = acc; +} + +void +foo12b (__vector_quad *dst, __vector_quad *src, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + acc = src[0]; + __builtin_mma_pmxvbf16ger2np (&acc, vec0, vec1, 15, 15, 3); + __builtin_mma_pmxvbf16ger2nn (&acc, vec0, vec1, 15, 15, 3); + dst[12] = acc; +} + +void +foo13 (__vector_quad *dst, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + __builtin_mma_pmxvf32ger (&acc, vec0, vec1, 15, 15); + __builtin_mma_pmxvf32gerpp (&acc, vec0, vec1, 15, 15); + __builtin_mma_pmxvf32gerpn (&acc, vec0, vec1, 15, 15); + dst[13] = acc; +} + +void +foo13b (__vector_quad *dst, __vector_quad *src, vec_t *vec) +{ + __vector_quad acc; + vec_t vec0 = vec[0]; + vec_t vec1 = vec[1]; + + acc = src[0]; + __builtin_mma_pmxvf32gernp (&acc, vec0, vec1, 15, 15); + __builtin_mma_pmxvf32gernn (&acc, vec0, vec1, 15, 15); + dst[13] = acc; +} + +/* { dg-final { scan-assembler-times {\mlxv\M} 40 } } */ +/* { dg-final { scan-assembler-times {\mlxvp\M} 12 } } */ +/* { dg-final { scan-assembler-times {\mstxvp\M} 40 } } */ +/* { dg-final { scan-assembler-times {\mxxmfacc\M} 20 } } */ +/* { dg-final { scan-assembler-times {\mxxmtacc\M} 6 } } */ +/* { dg-final { scan-assembler-times {\mxvbf16ger2\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvbf16ger2nn\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvbf16ger2np\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvbf16ger2pn\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvbf16ger2pp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvf16ger2\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvf16ger2nn\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvf16ger2np\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvf16ger2pn\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvf16ger2pp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvf32ger\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvf32gernn\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvf32gernp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvf32gerpn\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvf32gerpp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvi16ger2\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvi16ger2pp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvi16ger2s\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvi16ger2spp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvi4ger8\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvi4ger8pp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvi8ger4\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvi8ger4pp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvi8ger4spp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvbf16ger2\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvbf16ger2nn\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvbf16ger2np\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvbf16ger2pn\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvbf16ger2pp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvf16ger2\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvf16ger2nn\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvf16ger2np\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvf16ger2pn\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvf16ger2pp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvf32ger\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvf32gernn\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvf32gernp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvf32gerpn\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvf32gerpp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvi16ger2\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvi16ger2pp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvi16ger2s\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvi16ger2spp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvi4ger8\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvi4ger8pp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvi8ger4\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvi8ger4pp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvi8ger4spp\M} 1 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/mma-builtin-2.c b/gcc/testsuite/gcc.target/powerpc/mma-builtin-2.c new file mode 100644 index 00000000000..cb8b30dd992 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/mma-builtin-2.c @@ -0,0 +1,72 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_future_ok } */ +/* { dg-options "-Wno-psabi -mdejagnu-cpu=future -O2" } */ + +typedef unsigned char vec_t __attribute__((vector_size(16))); + +void +foo0 (__vector_quad *dst, vec_t *vec, __vector_pair *pvecp) +{ + __vector_quad acc; + __vector_pair vecp0 = *pvecp; + vec_t vec1 = vec[1]; + + __builtin_mma_xvf64ger (&acc, vecp0, vec1); + __builtin_mma_xvf64gerpp (&acc, vecp0, vec1); + __builtin_mma_xvf64gerpn (&acc, vecp0, vec1); + dst[0] = acc; +} + +void +foo1 (__vector_quad *dst, __vector_quad *src, vec_t *vec, __vector_pair *pvecp) +{ + __vector_quad acc; + __vector_pair vecp0 = *pvecp; + vec_t vec1 = vec[1]; + + acc = src[0]; + __builtin_mma_xvf64gernp (&acc, vecp0, vec1); + __builtin_mma_xvf64gernn (&acc, vecp0, vec1); + dst[0] = acc; +} + +void +foo2 (__vector_quad *dst, vec_t *vec, __vector_pair *pvecp) +{ + __vector_quad acc; + __vector_pair vecp0 = *pvecp; + vec_t vec1 = vec[1]; + __builtin_mma_pmxvf64ger (&acc, vecp0, vec1, 15, 3); + __builtin_mma_pmxvf64gerpp (&acc, vecp0, vec1, 15, 3); + __builtin_mma_pmxvf64gerpn (&acc, vecp0, vec1, 15, 3); + dst[1] = acc; +} + +void +foo3 (__vector_quad *dst, __vector_quad *src, vec_t *vec, __vector_pair *pvecp) +{ + __vector_quad acc; + __vector_pair vecp0 = *pvecp; + vec_t vec1 = vec[1]; + + acc = src[0]; + __builtin_mma_pmxvf64gernp (&acc, vecp0, vec1, 15, 3); + __builtin_mma_pmxvf64gernn (&acc, vecp0, vec1, 15, 3); + dst[1] = acc; +} + +/* { dg-final { scan-assembler-times {\mxxmfacc\M} 4 } } */ +/* { dg-final { scan-assembler-times {\mxxmtacc\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mlxv\M} 4 } } */ +/* { dg-final { scan-assembler-times {\mlxvp\M} 8 } } */ +/* { dg-final { scan-assembler-times {\mstxvp\M} 8 } } */ +/* { dg-final { scan-assembler-times {\mxvf64ger\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvf64gerpp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvf64gerpn\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvf64gernp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvf64gernn\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvf64ger\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvf64gerpp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvf64gerpn\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvf64gernp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mpmxvf64gernn\M} 1 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/mma-builtin-3.c b/gcc/testsuite/gcc.target/powerpc/mma-builtin-3.c new file mode 100644 index 00000000000..5406707061e --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/mma-builtin-3.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_future_ok } */ +/* { dg-options "-Wno-psabi -mdejagnu-cpu=future -O2" } */ + +void +foo0 (void) +{ + __vector_quad acc; + asm ("#..." : "=d" (acc)); + __builtin_mma_xxmtacc (&acc); + __builtin_mma_xxmfacc (&acc); + asm ("#..." :: "d" (acc)); +} + +typedef unsigned char vec_t __attribute__((vector_size(16))); + +void +foo1 (vec_t *vec) +{ + vec[1] = __builtin_vsx_xvcvspbf16 (vec[0]); + vec[3] = __builtin_vsx_xvcvbf16sp (vec[2]); +} + +/* { dg-final { scan-assembler-times {\mxxmtacc\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxxmfacc\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mlxv\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mstxv\M} 2 } } */ +/* { dg-final { scan-assembler-not {\mlxvp\M} } } */ +/* { dg-final { scan-assembler-not {\mstxvp\M} } } */ +/* { dg-final { scan-assembler-times {\mxvcvspbf16\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxvcvbf16sp\M} 1 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/mma-builtin-4.c b/gcc/testsuite/gcc.target/powerpc/mma-builtin-4.c new file mode 100644 index 00000000000..138d1b46bc4 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/mma-builtin-4.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_future_ok } */ +/* { dg-options "-Wno-psabi -mdejagnu-cpu=future -O2" } */ + +typedef unsigned char vec_t __attribute__((vector_size(16))); + +void +foo (__vector_pair *dst, vec_t *src) +{ + __vector_pair pair; + __builtin_mma_assemble_pair (&pair, src[0], src[4]); + *dst = pair; +} + +void +bar (vec_t *dst, __vector_pair *src) +{ + vec_t res[2]; + __builtin_mma_disassemble_pair (res, src); + dst[0] = res[0]; + dst[4] = res[1]; +} + +/* { dg-final { scan-assembler-times {\mlxv\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mlxvp\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mstxv\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mstxvp\M} 1 } } */ + diff --git a/gcc/testsuite/gcc.target/powerpc/mma-builtin-5.c b/gcc/testsuite/gcc.target/powerpc/mma-builtin-5.c new file mode 100644 index 00000000000..0ee45b6bdfd --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/mma-builtin-5.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_future_ok } */ +/* { dg-options "-Wno-psabi -mdejagnu-cpu=future -O2" } */ + +typedef unsigned char vec_t __attribute__((vector_size(16))); + +void +foo (__vector_quad *dst, vec_t *src) +{ + __vector_quad acc; + __builtin_mma_assemble_acc (&acc, src[0], src[4], src[8], src[12]); + *dst = acc; +} + +void +bar (vec_t *dst, __vector_quad *src) +{ + vec_t res[4]; + __builtin_mma_disassemble_acc (res, src); + dst[0] = res[0]; + dst[4] = res[1]; + dst[8] = res[2]; + dst[12] = res[3]; +} + +/* { dg-final { scan-assembler-times {\mlxv\M} 4 } } */ +/* { dg-final { scan-assembler-times {\mlxvp\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mstxv\M} 4 } } */ +/* { dg-final { scan-assembler-times {\mstxvp\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mxxmfacc\M} 2 } } */ +/* { dg-final { scan-assembler-times {\mxxmtacc\M} 2 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/mma-builtin-6.c b/gcc/testsuite/gcc.target/powerpc/mma-builtin-6.c new file mode 100644 index 00000000000..c0b5eedd3d1 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/mma-builtin-6.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_future_ok } */ +/* { dg-options "-Wno-psabi -mdejagnu-cpu=future -O2" } */ + +void +foo (__vector_quad *dst) +{ + __vector_quad acc; + __builtin_mma_xxsetaccz (&acc); + *dst = acc; +} + +/* { dg-final { scan-assembler-not {\mlxv\M} } } */ +/* { dg-final { scan-assembler-not {\mlxvp\M} } } */ +/* { dg-final { scan-assembler-not {\mxxmtacc\M} } } */ +/* { dg-final { scan-assembler-times {\mxxsetaccz\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mxxmfacc\M} 1 } } */ +/* { dg-final { scan-assembler-times {\mstxvp\M} 2 } } */