https://gcc.gnu.org/g:874b933495ade45b71d0801cc9acfb2c5ba6f817
commit 874b933495ade45b71d0801cc9acfb2c5ba6f817 Author: Michael Meissner <[email protected]> Date: Mon Oct 19 22:17:14 2026 -0400 Rework BFmode to V4SF mode code. 2026-10-19 Michael Meissner <[email protected]> * config/rs6000/float16.cc (fp16_vectorization): Add FP16_UNARY support. (bfloat16_operation_as_v4sf_inner): Likewise. (struct bfloat16_to_v4sf_stats): New structure. (zero_bfloat16_to_v4sf_stats): Likewise. (bfloat16_to_v4sf_inner): New function. (bfloat16_to_v4sf_p): Likewise. (bfloat16_to_v4sf_split): Likewise. * config/rs6000/float16.md (bfloat16_as_v4sf_1): New insn to support using V4SFmode to evaluate BFmode expressions. (bfloat16_as_v4sf_2): Likewise. (bfloat16_as_v4sf_3): Likewise. (bfloat16_binary_op_internal1): For now, keep old BFmode to V4SFmode code controlled by the -mno-float16-bf-v4sf switch. (bfloat16_binary_op_internal2): Likewise. (bfloat16_fma_internal1): Likewise. (bfloat16_fma_internal2): Likewise. (bfloat16_fms_internal1): Likewise. (bfloat16_fms_internal2): Likewise. (bfloat16_nfma_internal1): Likewise. (bfloat16_nfma_internal2): Likewise. (bfloat16_nfms_internal1): Likewise. (bfloat16_nfms_internal2): Likewise. * config/rs6000/predicates.md (bfloat16_to_v4sf_operand): New predicate. * config/rs6000/rs6000.h (enum fp16_operation): Add FP16_UNARY. * config/rs6000/rs6000-protos.h (bfloat16_to_v4sf_p): New prototype. (bfloat16_to_v4sf_split): Likewise. * config/rs6000/rs6000.opt (-mfloat16-bf-v4sf): New debug switch. Diff: --- gcc/config/rs6000/float16.cc | 399 ++++++++++++++++++++++++++++++++++++++ gcc/config/rs6000/float16.md | 67 +++++-- gcc/config/rs6000/predicates.md | 15 ++ gcc/config/rs6000/rs6000-protos.h | 3 + gcc/config/rs6000/rs6000.opt | 4 + 5 files changed, 476 insertions(+), 12 deletions(-) diff --git a/gcc/config/rs6000/float16.cc b/gcc/config/rs6000/float16.cc index d81c0f944b97..0cd8ce01e909 100644 --- a/gcc/config/rs6000/float16.cc +++ b/gcc/config/rs6000/float16.cc @@ -72,6 +72,10 @@ fp16_vectorization (enum rtx_code icode, switch (subtype) { + case FP16_UNARY: + n_opts = 1; + break; + case FP16_BINARY: n_opts = 2; break; @@ -123,6 +127,16 @@ fp16_vectorization (enum rtx_code icode, /* Do 2 sets of V4SFmode operations. */ switch (subtype) { + case FP16_UNARY: + emit_insn (gen_rtx_SET (result_hi, + gen_rtx_fmt_e (icode, V4SFmode, + op_hi[0]))); + + emit_insn (gen_rtx_SET (result_lo, + gen_rtx_fmt_e (icode, V4SFmode, + op_lo[0]))); + break; + case FP16_BINARY: emit_insn (gen_rtx_SET (result_hi, gen_rtx_fmt_ee (icode, V4SFmode, @@ -219,6 +233,11 @@ bfloat16_operation_as_v4sf_inner (enum rtx_code icode, switch (subtype) { + case FP16_UNARY: + n_opts = 1; + gcc_assert (op2 == NULL_RTX && op3 == NULL_RTX); + break; + case FP16_BINARY: n_opts = 2; gcc_assert (op3 == NULL_RTX); @@ -244,6 +263,15 @@ bfloat16_operation_as_v4sf_inner (enum rtx_code icode, switch (GET_CODE (op)) { + case NEG: + case ABS: + ops_v4sf[i] = bfloat16_operation_as_v4sf_inner (GET_CODE (op), + XEXP (op, 0), + NULL_RTX, + NULL_RTX, + FP16_UNARY); + continue; + /* Handle chained operations. */ case PLUS: case MINUS: @@ -317,6 +345,13 @@ bfloat16_operation_as_v4sf_inner (enum rtx_code icode, /* Do the operation in V4SFmode. */ switch (subtype) { + case FP16_UNARY: + emit_insn (gen_rtx_SET (result_v4sf, + gen_rtx_fmt_e (icode, V4SFmode, + ops_v4sf[0]))); + + break; + case FP16_BINARY: emit_insn (gen_rtx_SET (result_v4sf, gen_rtx_fmt_ee (icode, V4SFmode, @@ -396,3 +431,367 @@ bfloat16_operation_as_v4sf (enum rtx_code icode, else gcc_unreachable (); } + + +/* + * Recognize if can BFmode operations in V4SFmode. If the operation mostly + * involves BFmode values with some SFmode values. it is faster to convert the + * scalar code to vector and do the operation using one element of the vector, + * due to the lack of instructions to convert between BFmode and SFmode/DFmode + * scalars on power10. + * + * We allow multiple operations (a + b + c) to be folded together to try to do + * as much possible in the vector unit without having to convert back to scalar + * mode. + * + * We also fold in loads from memory to simplify the conversion. + * + * The expression that is combined is split before register allocation. + */ + +/* + * Stats for whole expression. + */ + +struct bfloat16_to_v4sf_stats +{ + unsigned num_bf_regs; // # of BF registers used + unsigned num_bf_loads; // # of BF values loaded from memory + unsigned num_sf_regs; // # of SF registers used + unsigned num_const; // # of constants used + unsigned num_binary; // # of binary operations done + unsigned num_fma; // # of FMA (fused multiply-adds) done + unsigned num_unary; // # of unary ops not folded into FMA/ABS + unsigned num_neg_folded; // # of negates folded into a FMA/ABS insn + unsigned num_extend; // # of FLOAT_EXTENDs +}; + +/* Initialize the bfloat16_to_v4sf_stats structure. */ +static struct bfloat16_to_v4sf_stats zero_bfloat16_to_v4sf_stats; + +/* + * Recursively evaluate whether a RTX expression can be optimized to use + * V4SFmode operations. Return true if the expression might be able to be + * optimized, and update the stats. + */ + +static bool +bfloat16_to_v4sf_inner (rtx op, struct bfloat16_to_v4sf_stats *stats) +{ + machine_mode mode = GET_MODE (op); + rtx arg; + rtx_code code; + bool ret = true; + bool update_stats = false; + +#ifdef TARGET_DEBUG_EXTRA1 + if (TARGET_DEBUG_EXTRA1) + update_stats = true; +#endif + + if (mode != BFmode && mode != SFmode) + ret = false; + + else + { + switch (GET_CODE (op)) + { + default: + ret = false; + break; + + // Update register counts. + case REG: + case SUBREG: + if (mode == BFmode) + stats->num_bf_regs++; + else + stats->num_sf_regs++; + + break; + + // Update memory counts. + case MEM: + if (mode != BFmode) + ret = false; + else + stats->num_bf_loads++; + + break; + + // Update constants + case CONST_DOUBLE: + stats->num_const++; + break; + + // Process absolute value + case ABS: + stats->num_unary++; + if (!bfloat16_to_v4sf_inner (XEXP (op, 0), stats)) + ret = false; + + break; + + // Process negation, deal with negate being folded into FMA or ABS. + case NEG: + arg = XEXP (op, 0); + code = GET_CODE (arg); + + if (code == FMA || code == ABS) + stats->num_neg_folded++; + else + stats->num_unary++; + + if (!bfloat16_to_v4sf_inner (arg, stats)) + ret = false; + + break; + + // Process binary operations + case PLUS: + case MINUS: + case MULT: + case SMIN: + case SMAX: + stats->num_binary++; + + if (update_stats) + { + bool ret1 = bfloat16_to_v4sf_inner (XEXP (op, 0), stats); + bool ret2 = bfloat16_to_v4sf_inner (XEXP (op, 1), stats); + if (!ret1 || !ret2) + ret = false; + } + else if (!bfloat16_to_v4sf_inner (XEXP (op, 0), stats) + || !bfloat16_to_v4sf_inner (XEXP (op, 1), stats)) + ret = false; + + break; + + // Process fused multiply-adds + case FMA: + stats->num_fma++; + + if (update_stats) + { + bool ret1 = bfloat16_to_v4sf_inner (XEXP (op, 0), stats); + bool ret2 = bfloat16_to_v4sf_inner (XEXP (op, 1), stats); + bool ret3 = bfloat16_to_v4sf_inner (XEXP (op, 2), stats); + if (!ret1 || !ret2 || !ret3) + ret = false; + } + else + if (!bfloat16_to_v4sf_inner (XEXP (op, 0), stats) + || !bfloat16_to_v4sf_inner (XEXP (op, 1), stats) + || !bfloat16_to_v4sf_inner (XEXP (op, 2), stats)) + ret = false; + + break; + + // Process extend BF -> SF + case FLOAT_EXTEND: + stats->num_extend++; + arg = XEXP (op, 0); + if (mode != SFmode || GET_MODE (arg) != BFmode) + ret = false;; + + if (!bfloat16_to_v4sf_inner (arg, stats)) + ret = false; + } + } + + return ret; +} + +/* + * Decide whether an expression can optimize BFmode to use V4SFmode. + */ + +bool +bfloat16_to_v4sf_p (rtx op, machine_mode mode) +{ + if (mode != BFmode && mode != SFmode) + return false; + +#ifdef TARGET_DEBUG_EXTRA1 + rtx orig_op = op; +#endif + + struct bfloat16_to_v4sf_stats stats = zero_bfloat16_to_v4sf_stats; + + // Handle top level FLOAT_TRUNCATE + if (GET_CODE (op) == FLOAT_TRUNCATE + && mode == BFmode + && GET_MODE (XEXP (op, 0)) == SFmode) + op = XEXP (op, 0); + + bool ret = bfloat16_to_v4sf_inner (op, &stats); + + // Make sure we had enough BFmode operations to do the optimization + if (ret) + { + unsigned num_bf = stats.num_bf_regs + stats.num_bf_loads; + + // If we had no BFmode values, don't do the optimization. + if (!num_bf) + ret = false; + + // If we had no binary or fma opertors, don't do the optimization. + else if (!stats.num_binary && !stats.num_fma) + ret = false; + + // If the expression has much more SFmode elements than BFmode, prefer + // converting BFmode to SFmode instead of using V4SFmode. + else if (stats.num_sf_regs > (num_bf + 2)) + ret = false; + } + + // Debugging. +#ifdef TARGET_DEBUG_EXTRA1 + if (TARGET_DEBUG_EXTRA1) + { + fprintf (stderr, "\n========== bfloat16_to_v4sf_p, return = %s", + ret ? "true" : "false"); + + if (stats.num_bf_regs) + fprintf (stderr, ", # BF regs = %u", stats.num_bf_regs); + + if (stats.num_bf_loads) + fprintf (stderr, ", # BF values loaded = %u", stats.num_bf_loads); + + if (stats.num_sf_regs) + fprintf (stderr, ", # SF regs = %u", stats.num_sf_regs); + + if (stats.num_const) + fprintf (stderr, ", # constants = %u", stats.num_const); + + if (stats.num_extend) + fprintf (stderr, ", # extends = %u", stats.num_extend); + + if (stats.num_unary) + fprintf (stderr, ", # unary = %u", stats.num_unary); + + if (stats.num_binary) + fprintf (stderr, ", # binary = %u", stats.num_binary); + + if (stats.num_fma) + fprintf (stderr, ", # fma = %u", stats.num_fma); + + if (stats.num_neg_folded) + fprintf (stderr, ", # neg fold = %u", stats.num_neg_folded); + + fprintf (stderr, "\n"); + debug_rtx (orig_op); + } +#endif + + return ret; +} + +/* + * Split the isnsns tht optimize BFmode to use V4SFmode. + */ + +void +bfloat16_to_v4sf_split (rtx dest, rtx src) +{ + rtx orig_src = src; + enum rtx_code code = GET_CODE (src); + rtx arg, op0, op1, op2; + +#ifdef TARGET_DEBUG_EXTRA2 + if (TARGET_DEBUG_EXTRA2) + debug_rtx (gen_rtx_SET (dest, src)); +#endif + + if (code == FLOAT_EXTEND || code == FLOAT_TRUNCATE) + { + src = XEXP (src, 0); + code = GET_CODE (src); + } + + switch (code) + { + case ABS: + bfloat16_operation_as_v4sf (code, dest, + XEXP (src, 0), + NULL_RTX, + NULL_RTX, + FP16_UNARY); + break; + + case NEG: + arg = XEXP (src, 0); + if (GET_CODE (arg) == FMA) + { + op0 = XEXP (arg, 0); + op1 = XEXP (arg, 1); + op2 = XEXP (arg, 2); + if (GET_CODE (op2) == NEG) + { + op2 = XEXP (op2, 0); + bfloat16_operation_as_v4sf (code, dest, + op0, + op1, + op2, + FP16_NFMS); + } + + else + bfloat16_operation_as_v4sf (code, dest, + op0, + op1, + op2, + FP16_NFMA); + } + + else + bfloat16_operation_as_v4sf (code, dest, + XEXP (arg, 0), + NULL_RTX, + NULL_RTX, + FP16_UNARY); + + break; + + case PLUS: + case MINUS: + case MULT: + case SMIN: + case SMAX: + bfloat16_operation_as_v4sf (code, dest, + XEXP (src, 0), + XEXP (src, 1), + NULL_RTX, + FP16_BINARY); + break; + + case FMA: + op0 = XEXP (src, 0); + op1 = XEXP (src, 1); + op2 = XEXP (src, 2); + if (GET_CODE (op2) == NEG) + { + op2 = XEXP (op2, 0); + bfloat16_operation_as_v4sf (code, dest, + op0, + op1, + op2, + FP16_FMS); + } + + else + bfloat16_operation_as_v4sf (code, dest, + op0, + op1, + op2, + FP16_FMA); + + break; + + default: + fatal_insn_not_found (gen_rtx_SET (dest, orig_src)); + } + + return; +} diff --git a/gcc/config/rs6000/float16.md b/gcc/config/rs6000/float16.md index d3a31791f9bc..4f14862945f4 100644 --- a/gcc/config/rs6000/float16.md +++ b/gcc/config/rs6000/float16.md @@ -1283,12 +1283,55 @@ ;; uses -Ofast. Without -Ofast, it will always convert BFmode into ;; SFmode. +(define_insn_and_split "*bfloat16_as_v4sf_1" + [(set (match_operand:BF 0 "vsx_register_operand") + (match_operand:BF 1 "bfloat16_to_v4sf_operand"))] + "TARGET_BF_V4SF + && TARGET_BFLOAT16_HW + && can_create_pseudo_p ()" + "#" + "&& 1" + [(pc)] +{ + bfloat16_to_v4sf_split (operands[0], operands[1]); + DONE; +}) + +(define_insn_and_split "*bfloat16_as_v4sf_2" + [(set (match_operand:BF 0 "vsx_register_operand") + (float_truncate:BF + (match_operand:SF 1 "bfloat16_to_v4sf_operand")))] + "TARGET_BF_V4SF + && TARGET_BFLOAT16_HW + && can_create_pseudo_p ()" + "#" + "&& 1" + [(pc)] +{ + bfloat16_to_v4sf_split (operands[0], operands[1]); + DONE; +}) + +(define_insn_and_split "*bfloat16_as_v4sf_3" + [(set (match_operand:SF 0 "vsx_register_operand") + (match_operand:SF 1 "bfloat16_to_v4sf_operand"))] + "TARGET_BF_V4SF + && TARGET_BFLOAT16_HW + && can_create_pseudo_p ()" + "#" + "&& 1" + [(pc)] +{ + bfloat16_to_v4sf_split (operands[0], operands[1]); + DONE; +}) + (define_insn_and_split "*bfloat16_binary_op_internal1" [(set (match_operand:SF 0 "vsx_register_operand") (match_operator:SF 1 "fp16_binary_operator" [(match_operand:SF 2 "bfloat16_v4sf_operand") (match_operand:SF 3 "bfloat16_v4sf_operand")]))] - "TARGET_BFLOAT16_HW && can_create_pseudo_p () + "!TARGET_BF_V4SF && TARGET_BFLOAT16_HW && can_create_pseudo_p () && (bfloat16_bf_operand (operands[2], SFmode) || bfloat16_bf_operand (operands[3], SFmode))" "#" @@ -1306,7 +1349,7 @@ (match_operator:SF 1 "fp16_binary_operator" [(match_operand:SF 2 "bfloat16_v4sf_operand") (match_operand:SF 3 "bfloat16_v4sf_operand")])))] - "TARGET_BFLOAT16_HW && can_create_pseudo_p () + "!TARGET_BF_V4SF && TARGET_BFLOAT16_HW && can_create_pseudo_p () && (bfloat16_bf_operand (operands[2], SFmode) || bfloat16_bf_operand (operands[3], SFmode))" "#" @@ -1324,7 +1367,7 @@ (match_operand:SF 1 "bfloat16_v4sf_operand") (match_operand:SF 2 "bfloat16_v4sf_operand") (match_operand:SF 3 "bfloat16_v4sf_operand")))] - "TARGET_BFLOAT16_HW && can_create_pseudo_p () + "!TARGET_BF_V4SF && TARGET_BFLOAT16_HW && can_create_pseudo_p () && (bfloat16_bf_operand (operands[1], SFmode) + bfloat16_bf_operand (operands[2], SFmode) + bfloat16_bf_operand (operands[3], SFmode) >= 2)" @@ -1344,7 +1387,7 @@ (match_operand:SF 1 "bfloat16_v4sf_operand") (match_operand:SF 2 "bfloat16_v4sf_operand") (match_operand:SF 3 "bfloat16_v4sf_operand"))))] - "TARGET_BFLOAT16_HW && can_create_pseudo_p () + "!TARGET_BF_V4SF && TARGET_BFLOAT16_HW && can_create_pseudo_p () && (bfloat16_bf_operand (operands[1], SFmode) + bfloat16_bf_operand (operands[2], SFmode) + bfloat16_bf_operand (operands[3], SFmode) >= 2)" @@ -1364,7 +1407,7 @@ (match_operand:SF 2 "bfloat16_v4sf_operand") (neg:SF (match_operand:SF 3 "bfloat16_v4sf_operand"))))] - "TARGET_BFLOAT16_HW && can_create_pseudo_p () + "!TARGET_BF_V4SF && TARGET_BFLOAT16_HW && can_create_pseudo_p () && (bfloat16_bf_operand (operands[1], SFmode) + bfloat16_bf_operand (operands[2], SFmode) + bfloat16_bf_operand (operands[3], SFmode) >= 2)" @@ -1385,7 +1428,7 @@ (match_operand:SF 2 "bfloat16_v4sf_operand") (neg:SF (match_operand:SF 3 "bfloat16_v4sf_operand")))))] - "TARGET_BFLOAT16_HW && can_create_pseudo_p () + "!TARGET_BF_V4SF && TARGET_BFLOAT16_HW && can_create_pseudo_p () && (bfloat16_bf_operand (operands[1], SFmode) + bfloat16_bf_operand (operands[2], SFmode) + bfloat16_bf_operand (operands[3], SFmode) >= 2)" @@ -1405,7 +1448,7 @@ (match_operand:SF 1 "bfloat16_v4sf_operand") (match_operand:SF 2 "bfloat16_v4sf_operand") (match_operand:SF 3 "bfloat16_v4sf_operand"))))] - "TARGET_BFLOAT16_HW && can_create_pseudo_p () + "!TARGET_BF_V4SF && TARGET_BFLOAT16_HW && can_create_pseudo_p () && (bfloat16_bf_operand (operands[1], SFmode) + bfloat16_bf_operand (operands[2], SFmode) + bfloat16_bf_operand (operands[3], SFmode) >= 2)" @@ -1426,7 +1469,7 @@ (match_operand:SF 1 "bfloat16_v4sf_operand") (match_operand:SF 2 "bfloat16_v4sf_operand") (match_operand:SF 3 "bfloat16_v4sf_operand")))))] - "TARGET_BFLOAT16_HW && can_create_pseudo_p () + "!TARGET_BF_V4SF && TARGET_BFLOAT16_HW && can_create_pseudo_p () && (bfloat16_bf_operand (operands[1], SFmode) + bfloat16_bf_operand (operands[2], SFmode) + bfloat16_bf_operand (operands[3], SFmode) >= 2)" @@ -1447,7 +1490,7 @@ (match_operand:SF 1 "bfloat16_v4sf_operand") (match_operand:SF 2 "bfloat16_v4sf_operand") (match_operand:SF 3 "bfloat16_v4sf_operand")))))] - "TARGET_BFLOAT16_HW && can_create_pseudo_p () + "!TARGET_BF_V4SF && TARGET_BFLOAT16_HW && can_create_pseudo_p () && (bfloat16_bf_operand (operands[1], SFmode) + bfloat16_bf_operand (operands[2], SFmode) + bfloat16_bf_operand (operands[3], SFmode) >= 2)" @@ -1468,7 +1511,7 @@ (match_operand:SF 2 "bfloat16_v4sf_operand") (neg:SF (match_operand:SF 3 "bfloat16_v4sf_operand")))))] - "TARGET_BFLOAT16_HW && can_create_pseudo_p () + "!TARGET_BF_V4SF && TARGET_BFLOAT16_HW && can_create_pseudo_p () && (bfloat16_bf_operand (operands[1], SFmode) + bfloat16_bf_operand (operands[2], SFmode) + bfloat16_bf_operand (operands[3], SFmode) >= 2)" @@ -1490,7 +1533,7 @@ (match_operand:SF 2 "bfloat16_v4sf_operand") (neg:SF (match_operand:SF 3 "bfloat16_v4sf_operand"))))))] - "TARGET_BFLOAT16_HW && can_create_pseudo_p () + "!TARGET_BF_V4SF && TARGET_BFLOAT16_HW && can_create_pseudo_p () && (bfloat16_bf_operand (operands[1], SFmode) + bfloat16_bf_operand (operands[2], SFmode) + bfloat16_bf_operand (operands[3], SFmode) >= 2)" @@ -1512,7 +1555,7 @@ (match_operand:SF 2 "bfloat16_v4sf_operand") (neg:SF (match_operand:SF 3 "bfloat16_v4sf_operand"))))))] - "TARGET_BFLOAT16_HW && can_create_pseudo_p () + "!TARGET_BF_V4SF && TARGET_BFLOAT16_HW && can_create_pseudo_p () && (bfloat16_bf_operand (operands[1], SFmode) + bfloat16_bf_operand (operands[2], SFmode) + bfloat16_bf_operand (operands[3], SFmode) >= 2)" diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index afe63447eb0d..70a927940b10 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -2315,6 +2315,21 @@ (define_predicate "fp16_binary_operator" (match_code "plus,minus,mult,smax,smin")) + +;; Match bfloat16/float operands that can be optimized to do the +;; operation in V4SFmode. +(define_predicate "bfloat16_to_v4sf_operand" + (match_code "reg,subreg,const_double,float_extend,plus,minus,mult,fma,neg,abs") +{ + if (mode != BFmode && mode != SFmode) + return false; + + if (mode != GET_MODE (op)) + return false; + + return bfloat16_to_v4sf_p (op, mode); +}) + ;; Match bfloat16/float operands that can be optimized to do the ;; operation in V4SFmode. (define_predicate "bfloat16_v4sf_operand" diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 3691b522f42c..1f8f75201461 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -262,6 +262,7 @@ extern unsigned constant_generates_xxspltidp (vec_const_128bit_type *); /* From float16.cc. */ /* Optimize bfloat16 and float16 operations. */ enum fp16_operation { + FP16_UNARY, /* Bfloat16/float16 unary op. */ FP16_BINARY, /* Bfloat16/float16 binary op. */ FP16_FMA, /* (a * b) + c. */ FP16_FMS, /* (a * b) - c. */ @@ -273,6 +274,8 @@ extern void fp16_vectorization (enum rtx_code, rtx, rtx, rtx, rtx, enum fp16_operation); extern void bfloat16_operation_as_v4sf (enum rtx_code, rtx, rtx, rtx, rtx, enum fp16_operation); +extern bool bfloat16_to_v4sf_p (rtx, machine_mode); +extern void bfloat16_to_v4sf_split (rtx, rtx); #endif /* RTX_CODE */ #ifdef TREE_CODE diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index 973051afc350..47a705a20dbc 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -650,6 +650,10 @@ mfloat16-gpr-convert Target Undocumented Var(TARGET_FLOAT16_GPR_CONVERT) Init(1) Save Pass/return (do not pass/return) 16-it float conversions in GPR registers. +mfloat16-bf-v4sf +Target Undocumented Var(TARGET_BF_V4SF) Init(1) Save +Optimize bfloat16 to use float vector instructions. + ; Documented parameters -param=rs6000-vect-unroll-limit=
