https://gcc.gnu.org/g:8ace490930721016c9302059be3ea27720e4e17c
commit 8ace490930721016c9302059be3ea27720e4e17c Author: Michael Meissner <[email protected]> Date: Fri Oct 3 13:32:16 2025 -0400 Attempt to add support for adding BFmode constants. 2025-10-03 Michael Meissner <[email protected]> gcc/ * config/rs6000/float16.md (mov<mode>_xxspltiw): Add specific 0.0 support. (<BF_OPS_NAME>bf3): Allow operand2 to be a constant. * config/rs6000/predicates.md (fp16_reg_or_constant_operand): New predicate. Diff: --- gcc/config/rs6000/float16.md | 56 ++++++++++++++++++++++++++++++----------- gcc/config/rs6000/predicates.md | 16 ++++++++++++ 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/gcc/config/rs6000/float16.md b/gcc/config/rs6000/float16.md index e9d3572e5898..e0a946d6c6d9 100644 --- a/gcc/config/rs6000/float16.md +++ b/gcc/config/rs6000/float16.md @@ -65,22 +65,27 @@ ;; On power10, we can load up HFmode and BFmode constants with xxspltiw ;; or pli. (define_insn "*mov<mode>_xxspltiw" - [(set (match_operand:FP16 0 "gpc_reg_operand" "=wa,r") - (match_operand:FP16 1 "fp16_xxspltiw_constant" "eP,eP"))] + [(set (match_operand:FP16 0 "gpc_reg_operand" "=wa,r,wa,r") + (match_operand:FP16 1 "fp16_xxspltiw_constant" "j,j,eP,eP"))] "TARGET_POWER10 && TARGET_PREFIXED" { rtx op1 = operands[1]; const REAL_VALUE_TYPE *rtype = CONST_DOUBLE_REAL_VALUE (op1); long real_words[1]; + if (op1 == CONST0_RTX (<MODE>mode)) + return (vsx_register_operand (operands[0], <MODE>mode) + ? "xxspltib %x0,0" + : "li %0,0"); + real_to_target (real_words, rtype, <MODE>mode); operands[2] = GEN_INT (real_words[0]); return (vsx_register_operand (operands[0], <MODE>mode) ? "xxspltiw %x0,%2" : "li %0,%2"); } - [(set_attr "type" "vecperm,*") - (set_attr "prefixed" "yes")]) + [(set_attr "type" "vecsimple,*,vecperm,*") + (set_attr "prefixed" "no,no,yes,no")]) (define_insn "*mov<mode>_internal" [(set (match_operand:FP16 0 "nonimmediate_operand" @@ -311,12 +316,13 @@ ;; dividing by 0. (define_insn_and_split "<BF_OPS_NAME>bf3" - [(set (match_operand:BF 0 "vsx_register_operand" "=wa") - (BF_OPS:BF (match_operand:BF 1 "vsx_register_operand" "wa") - (match_operand:BF 2 "vsx_register_operand" "wa"))) - (clobber (match_scratch:V4SF 3 "=&wa")) - (clobber (match_scratch:V4SF 4 "=&wa")) - (clobber (match_scratch:V4SF 5 "=&wa"))] + [(set (match_operand:BF 0 "vsx_register_operand" "=wa,wa,wa") + (BF_OPS:BF + (match_operand:BF 1 "vsx_register_operand" "wa,wa,wa") + (match_operand:BF 2 "fp16_reg_or_constant_operand" "wa,j,eP"))) + (clobber (match_scratch:V4SF 3 "=&wa,&wa,&wa")) + (clobber (match_scratch:V4SF 4 "=&wa,&wa,&wa")) + (clobber (match_scratch:V4SF 5 "=&wa,&wa,&wa"))] "TARGET_BFLOAT16_HW" "#" "&& 1" @@ -338,12 +344,34 @@ if (GET_CODE (tmp2) == SCRATCH) tmp2 = gen_reg_rtx (V4SFmode); - /* Convert operand1 to V4SFmode format. */ + /* Convert operand1 and operand2 to V4SFmode format. We use SPLAT for + registers to get the value into the upper 32-bits. We can use XXSPLTW + to splat words instead of VSPLTIH since the XVCVBF16SPN instruction + ignores the odd half-words, and XXSPLTW can operate on all VSX registers + instead of just the Altivec registers. Using SPLAT instead of a shift + also insure that other bits are not a signalling NaN. If we are using + XXSPLTIW or XXSPLTIB to load the constant the other bits are duplicated. */ + + /* Operand1. */ emit_insn (gen_xxspltw_bf (tmp1, op1)); emit_insn (gen_xvcvbf16spn_bf (tmp1, tmp1)); - /* Convert operand2 to V4SFmode format. */ - emit_insn (gen_xxspltw_bf (tmp2, op2)); + /* Operand2. */ + if (REG_P (op2) || SUBREG_P (op2)) + emit_insn (gen_xxspltw_bf (tmp2, op2)); + + else if (op2 == CONST0_RTX (BFmode)) + emit_move_insn (tmp2, CONST0_RTX (V4SFmode)); + + else if (fp16_xxspltiw_constant (op2, BFmode)) + { + rtx op2_bf = gen_lowpart (BFmode, tmp2); + emit_move_insn (op2_bf, op2); + } + + else + gcc_unreachable (); + emit_insn (gen_xvcvbf16spn_bf (tmp2, tmp2)); /* Do the operation in V4SFmode. */ @@ -354,7 +382,7 @@ DONE; } [(set_attr "type" "vecperm") - (set_attr "length" "24")]) + (set_attr "length" "24,24,32")]) ;; Duplicate a BF value so it can be used for xvcvbf16spn. Because ;; xvcvbf16spn only uses the even elements, we can use xxspltw instead diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 3dc9e020fd71..4f7d1dd0be5a 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -2186,3 +2186,19 @@ return constant_generates_xxspltiw (&vsx_const); }) + +;; Return 1 if this is a 16-bit floating point operand that can be used +;; in an add, subtract, or multiply operation that uses the vector +;; conversion function. +(define_predicate "fp16_reg_or_constant_operand" + (match_code "reg,subreg,const_double") +{ + if (REG_P (op) || SUBREG_P (op)) + return vsx_register_operand (op, mode); + + if (CONST_DOUBLE_P (op)) + return (op == CONST0_RTX (mode) + || fp16_xxspltiw_constant (op, mode)); + + return false; +})
