Message ID | f75fbd2a4ffe51e08451743d9bb94d8bfce497e5.1623941442.git.wschmidt@linux.ibm.com |
---|---|
State | New |
Headers | show |
Series | Replace the Power target-specific builtin machinery | expand |
On Thu, 2021-06-17 at 10:19 -0500, Bill Schmidt via Gcc-patches wrote: > 2021-06-17 Bill Schmidt <wschmidt@linux.ibm.com> > Hi, > gcc/ > * config/rs6000/rs6000-call.c (new_mma_expand_builtin): > Implement. Ok, > --- > gcc/config/rs6000/rs6000-call.c | 103 ++++++++++++++++++++++++++++++++ > 1 file changed, 103 insertions(+) > > diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c > index 981eabc1187..e1b685fb874 100644 > --- a/gcc/config/rs6000/rs6000-call.c > +++ b/gcc/config/rs6000/rs6000-call.c > @@ -14962,6 +14962,109 @@ static rtx > new_mma_expand_builtin (tree exp, rtx target, insn_code icode, > rs6000_gen_builtins fcode) > { > + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); > + tree arg; > + call_expr_arg_iterator iter; > + const struct insn_operand_data *insn_op; > + rtx op[MAX_MMA_OPERANDS]; > + unsigned nopnds = 0; > + bool void_func = TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node; > + machine_mode tmode = VOIDmode; > + > + if (!void_func) > + { > + 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; > + } > + > + 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: > + /* The ASSEMBLE builtin source operands are reversed in little-endian > + mode, so reorder them. */ > + if (fcode == RS6000_BIF_ASSEMBLE_PAIR_V_INTERNAL && !WORDS_BIG_ENDIAN) > + std::swap (op[1], op[2]); > + 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: > + /* The ASSEMBLE builtin source operands are reversed in little-endian > + mode, so reorder them. */ I'd be tempted to consolidate the source operand reversal comments for RS6000_BIF_ASSEMBLE_PAIR_V_INTERNAL and RS6000_BIF_ASSEMBLE_ACC_INTERNAL.. up at the start of the case statement.. but actually i think this makes sense as-is. Ok. > + if (fcode == RS6000_BIF_ASSEMBLE_ACC_INTERNAL && !WORDS_BIG_ENDIAN) > + { > + std::swap (op[1], op[4]); > + std::swap (op[2], op[3]); > + } > + 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); > + Ok, lgtm, thanks -Will > return target; > } >
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c index 981eabc1187..e1b685fb874 100644 --- a/gcc/config/rs6000/rs6000-call.c +++ b/gcc/config/rs6000/rs6000-call.c @@ -14962,6 +14962,109 @@ static rtx new_mma_expand_builtin (tree exp, rtx target, insn_code icode, rs6000_gen_builtins fcode) { + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); + tree arg; + call_expr_arg_iterator iter; + const struct insn_operand_data *insn_op; + rtx op[MAX_MMA_OPERANDS]; + unsigned nopnds = 0; + bool void_func = TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node; + machine_mode tmode = VOIDmode; + + if (!void_func) + { + 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; + } + + 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: + /* The ASSEMBLE builtin source operands are reversed in little-endian + mode, so reorder them. */ + if (fcode == RS6000_BIF_ASSEMBLE_PAIR_V_INTERNAL && !WORDS_BIG_ENDIAN) + std::swap (op[1], op[2]); + 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: + /* The ASSEMBLE builtin source operands are reversed in little-endian + mode, so reorder them. */ + if (fcode == RS6000_BIF_ASSEMBLE_ACC_INTERNAL && !WORDS_BIG_ENDIAN) + { + std::swap (op[1], op[4]); + std::swap (op[2], op[3]); + } + 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; }