https://gcc.gnu.org/g:aa8dd49c88ea0150478c2ab0597c151f4fbd4b4a
commit aa8dd49c88ea0150478c2ab0597c151f4fbd4b4a Author: Michael Meissner <[email protected]> Date: Tue Sep 15 18:51:25 2026 -0400 Do BF to SF converts on p9; Remove int conversions; Add BF debug switches. 2026-09-15 Michael Meissner <[email protected]> gcc/ * config/rs6000/float16.md (extendbf<mode>2): On power9, convert BFmode to SFmode or DFmode by shifting. (extendbf<mode>2_p1): Likewise. (extendbf<mode>2_not_p10): Likewise. (extendbfsf2_memory): Rename from convert_bf_to_sf_store. (float<GPR:mode><FP16_HW:mode>2): Delete integer conversion insns. (floatuns<GPR:mode><FP16_HW:mode>2): Likewise. (fix_trunc<FP16_HW:mode><GPR:mode): Likewise. (fixuns_trunc<FP16_HW:mode><GPR:mode>2): Likewise. * config/rs6000/rs6000.h (TARGET_BFLOAT16_CVT): New macro. * config/rs6000/rs6000.opt (-mbfloat16-convert): New debug switch. (mbfloat16-p10-convert): Likewise. Diff: --- gcc/config/rs6000/float16.md | 124 +++++++++++++++++++++++-------------------- gcc/config/rs6000/rs6000.h | 6 +++ gcc/config/rs6000/rs6000.opt | 8 +++ 3 files changed, 81 insertions(+), 57 deletions(-) diff --git a/gcc/config/rs6000/float16.md b/gcc/config/rs6000/float16.md index 672effc6d019..e16853292735 100644 --- a/gcc/config/rs6000/float16.md +++ b/gcc/config/rs6000/float16.md @@ -233,16 +233,40 @@ [(set_attr "type" "fpsimple")]) ;; Convert BFmode to SFmode/DFmode. -;; 3 instructions are generated: +;; 3 instructions are generated on power10: ;; XXSPLTW -- duplicate BFmode into all even elements ;; XVCVBF16SPN -- convert even BFmode elements to SFmode ;; XSCVSPNDP -- convert memory format of SFmode to DFmode. -(define_insn_and_split "extendbf<mode>2" +;; +;; 3 instructions are generated on power8/power9 +;; SLDI -- shift left 48 bits +;; MTVSRD -- move to VSX register +;; XSCVSPNDP -- convert memory format of SFmode to DFmode. +;; +;; We have 2 variants for testing. One that uses the xvcvbf16spn +;; instruction on power10, and one that does not. + +(define_expand "extendbf<mode>2" + [(set (match_operand:SFDF 0 "vsx_register_operand") + (float_extend:SFDF + (match_operand:BF 1 "gpc_reg_operand")))] + "TARGET_BFLOAT16_CVT" +{ + if (TARGET_BFLOAT16_HW && TARGET_BFLOAT16_P10_CONVERT) + emit_insn (gen_extendbf<mode>2_p10 (operands[0], operands[1])); + else + emit_insn (gen_extendbf<mode>2_not_p10 (operands[0], operands[1])); + + DONE; +}) + +(define_insn_and_split "extendbf<mode>2_p10" [(set (match_operand:SFDF 0 "vsx_register_operand" "=wa") (float_extend:SFDF - (match_operand:BF 1 "vsx_register_operand" "v"))) + (match_operand:BF 1 "vsx_register_operand" "wa"))) (clobber (match_scratch:V4SF 2 "=wa"))] - "TARGET_BFLOAT16_HW" + "TARGET_BFLOAT16_HW && TARGET_BFLOAT16_CONVERT + && TARGET_BFLOAT16_P10_CONVERT" "#" "&& 1" [(pc)] @@ -254,8 +278,9 @@ if (GET_CODE (op2) == SCRATCH) op2 = gen_reg_rtx (V4SFmode); - /* XXSPLTW -- duplicate BFmode element into all of the even elements. We - can use splat words because we won't be using the odd elements */ + /* XXSPLTW -- duplicate BFmode element into all of the even elements. + We can use splat words because we won't be using the odd + elements. */ emit_insn (gen_xxspltw_bf (op2, op1)); /* XVCVBF16SPN -- convert even V8BFmode elements to V4SFmode. */ @@ -272,6 +297,41 @@ [(set_attr "type" "fpsimple") (set_attr "length" "12")]) +(define_insn_and_split "extendbf<mode>2_not_p10" + [(set (match_operand:SFDF 0 "vsx_register_operand" "=wa") + (float_extend:SFDF + (match_operand:BF 1 "int_reg_operand" "r"))) + (clobber (match_scratch:V4SF 2 "=wa")) + (clobber (match_scratch:DI 3 "=r"))] + "TARGET_BFLOAT16_CVT + && (!TARGET_BFLOAT16_HW || !TARGET_BFLOAT16_P10_CONVERT)" + "#" + "&& reload_completed" + [(pc)] +{ + rtx op0 = operands[0]; + rtx op1 = operands[1]; + rtx op2 = operands[2]; + rtx op3 = operands[3]; + rtx op1_di = gen_rtx_REG (DImode, reg_or_subregno (op1)); + rtx op2_di = gen_rtx_REG (DImode, reg_or_subregno (op2)); + + /* The shift left of 48 combines a shift left of 16 bits to + convert a BFmode to a SFmode with shift left of 32 bits + to do the xscvspdpn instruction. */ + emit_insn (gen_ashldi3 (op3, op1_di, GEN_INT (48))); + emit_move_insn (op2_di, op3); + + /* XSCVSPNDP -- convert single V4SFmode element to DFmode. */ + emit_insn (GET_MODE (op0) == SFmode + ? gen_xscvspdpn_sf (op0, op2) + : gen_vsx_xscvspdpn (op0, op2)); + + DONE; +} + [(set_attr "type" "fpsimple") + (set_attr "length" "12")]) + ;; Convert a SFmode scalar represented as DFmode to elements 0 and 1 of ;; V4SFmode. (define_insn "xscvdpspn_sf" @@ -294,7 +354,7 @@ ;; Optimize storing the conversion of BFmode to SFmode by shifting the ;; BFmode left 16 bits. -(define_insn_and_split "*convert_bf_to_sf_store" +(define_insn_and_split "*extendbfsf2_memory" [(set (match_operand:SF 0 "memory_operand" "=m") (float_extend:SF (match_operand:BF 1 "int_reg_operand" "r"))) @@ -618,56 +678,6 @@ convert_move (operands[0], df_tmp, 0); DONE; }) - -;; Convert integers to 16-bit floating point modes. -(define_expand "float<GPR:mode><FP16_HW:mode>2" - [(use (match_operand:FP16_HW 0 "vsx_register_operand")) - (use (match_operand:GPR 1 "vsx_register_operand"))] - "can_create_pseudo_p ()" -{ - rtx df_tmp = gen_reg_rtx (DFmode); - - convert_move (df_tmp, operands[1], 0); - convert_move (operands[0], df_tmp, 0); - DONE; -}) - -(define_expand "floatuns<GPR:mode><FP16_HW:mode>2" - [(use (match_operand:FP16_HW 0 "vsx_register_operand")) - (use (match_operand:GPR 1 "vsx_register_operand"))] - "can_create_pseudo_p ()" -{ - rtx df_tmp = gen_reg_rtx (DFmode); - - convert_move (df_tmp, operands[1], 1); - convert_move (operands[0], df_tmp, 0); - DONE; -}) - -;; Convert 16-bit floating point modes to integers -(define_expand "fix_trunc<FP16_HW:mode><GPR:mode>2" - [(use (match_operand:GPR 0 "vsx_register_operand")) - (use (match_operand:FP16_HW 1 "vsx_register_operand"))] - "can_create_pseudo_p ()" -{ - rtx df_tmp = gen_reg_rtx (DFmode); - - convert_move (df_tmp, operands[1], 0); - convert_move (operands[0], df_tmp, 0); - DONE; -}) - -(define_expand "fixuns_trunc<FP16_HW:mode><GPR:mode>2" - [(use (match_operand:GPR 0 "vsx_register_operand")) - (use (match_operand:FP16_HW 1 "vsx_register_operand"))] - "can_create_pseudo_p ()" -{ - rtx df_tmp = gen_reg_rtx (DFmode); - - convert_move (df_tmp, operands[1], 0); - convert_move (operands[0], df_tmp, 1); - DONE; -}) ;; Negate 16-bit floating point by XOR with -0.0. diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 1d88e0a46df3..d91b2a564998 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -355,6 +355,12 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); #define TARGET_BFLOAT16_HW (TARGET_FLOAT16 && TARGET_POWER10) #define TARGET_FLOAT16_HW (TARGET_FLOAT16 && TARGET_P9_VECTOR) +/* Mode iterator for conversions from 16-bit floating point. Unlike + TARGET_BFLOAT16_HW, this specifically allows converting from BFmode even if + we don't have the bfloat16 conversion. We do this conversion */ +#define TARGET_BFLOAT16_CVT \ + (TARGET_FLOAT16 && TARGET_BFLOAT16_CONVERT && TARGET_P9_VECTOR) + /* Do we have conversion support in hardware for the 16-bit floating point and also enable the 16-bit floating point vector optimizations? */ #define TARGET_BFLOAT16_HW_VECTOR \ diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index 231a5121f9e9..f28dd3e6f1f1 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -646,6 +646,14 @@ mfloat16 Target Mask(FLOAT16) Var(rs6000_isa_flags) Enable or disable 16-bit floating point. +mbfloat16-convert +Target Undocumented Var(TARGET_BFLOAT16_CONVERT) Init(1) Save +Generate (do not generate) __bf16 to float/double conversions. + +mbfloat16-p10-convert +Target Undocumented Var(TARGET_BFLOAT16_P10_CONVERT) Init(1) Save +Generate (do not generate) xvcvbf16spn to do __bf16 to float/double conversions. + mfloat16-convert-in-gprs Target Undocumented Var(TARGET_FLOAT16_CONVERT_IN_GPRS) Init(0) Save Pass/return (do not pass/return) 16-it float conversions in GPR registers.
