From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1005) id 88116385840A; Wed, 11 Jan 2023 03:20:13 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 88116385840A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1673407213; bh=2/9QHWeqk3qHWjJT1ZntLotpMOfAjm3cU2BWxJiGXBE=; h=From:To:Subject:Date:From; b=wAfTPhwK0QICElaiQWSIk920pH5YiWoYM8BdT9Tb6O85HLbT4HPJVPinCPX5vx/HV gGjZSGEDdH0SeoBSgtDxtqMz8ptnJ5WQ+ZxwNmaU92THMDtlaOARzD+5QnRkcPhauQ 9LtPai7/JgjSOznnSsEdpWI02rIoeapnuLrvC3x0= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Michael Meissner To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/users/meissner/heads/work105)] Improve PowerPC 128-bit floating point precision support. X-Act-Checkin: gcc X-Git-Author: Michael Meissner X-Git-Refname: refs/users/meissner/heads/work105 X-Git-Oldrev: 5974cd0030da2ac202b3d0bf796d825e6283471b X-Git-Newrev: 8be98ddf50b3252565b73e9e23be11fbea97388e Message-Id: <20230111032013.88116385840A@sourceware.org> Date: Wed, 11 Jan 2023 03:20:13 +0000 (GMT) List-Id: https://gcc.gnu.org/g:8be98ddf50b3252565b73e9e23be11fbea97388e commit 8be98ddf50b3252565b73e9e23be11fbea97388e Author: Michael Meissner Date: Tue Jan 10 22:14:43 2023 -0500 Improve PowerPC 128-bit floating point precision support. This patch improves the code for the 3 PowerPC 128-bit floating point types. There are two main additions with this patch: 1) Allow the backend to adjust the precision of the 3 types at runtime. This allows us to use the same precision for both long double and for either __float128 or __ibm128 types. By having the same precision, it makes it easier for the machine independent part of the compiler to realize that these modes are talking to the same representation. 2) Prevent __ibm128 and __float128 from being considered in the automatic widening that the compiler does. This way, you don't have the possibility that IFmode (__ibm128) will be widened to TFmode or KFmode, even there is hardware to support the IEEE 128-bit operations. Fortran depends on the current precision values to identify whether the current floating point type is IBM extended double or IEEE 128-bit. While it might be nice to fix this in the future so that can just set the precision of all 3 modes to be 128, I decided to not make this incompatible change and break Fortran. I also moved changing the TFmode format from ieee to ibm to rs6000-modes.def from rs6000.cc. 2022-01-10 Michael Meissner gcc/ * config/rs6000/rs6000-modes.def (IFmode): Rework to use FRACTIONAL_FLOAT_MODE_NO_WIDEN. Adjust the precision if long double uses the same representation. (KFmode): Likewise. (TFmode): Rework to use FRACTIONAL_FLOAT_MODE_NO_WIDEN. Adjust the format of TFmode based on the -mabi={ibm,ieee}longdouble option. * expr.cc (convert_mode_scalar): Don't abort if we are converting floating point modes that are the same precision but use different encodings. * genmodes.cc (struct mode_data): Add support for no widening and adjusting precision. (blank_mode): Likewise. (FRACTIONAL_FLOAT_MODE): Add support for no widening capability. (FRACTIONAL_FLOAT_MODE_NO_WIDEN): New macro. (make_float_mode): Add support for no widening capability. (cmp_modes): Likewise. (emit_mode_unit_precision_inline): Add support for adjusting the precision. (emit_insn_modes_h): Likewise. (emit_mode_wider): Add support for no widening capability. (emit_mode_unit_precision): Add support for adjusting the precision. (emit_mode_adjustments): Likewise. * machmode.def (FRACTIONAL_FLOAT_MODE_NO_WIDEN): Document. * machmode.h (mode_unit_precision): Add suport for adjusting the precision. Diff: --- gcc/config/rs6000/rs6000.cc | 2 +- gcc/config/rs6000/rs6000.md | 177 ++++++++++++-------------------------------- 2 files changed, 49 insertions(+), 130 deletions(-) diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index c508e891413..b64ebeb1a4c 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -11182,7 +11182,7 @@ init_float128_ieee (machine_mode mode) if (mode != TFmode && FLOAT128_IBM_P (TFmode)) set_conv_libfunc (sext_optab, mode, TFmode, "__trunctfkf2"); - set_conv_libfunc (trunc_optab, IFmode, mode, "__extendkftf2"); + set_conv_libfunc (sext_optab, IFmode, mode, "__extendkftf2"); if (mode != TFmode && FLOAT128_IBM_P (TFmode)) set_conv_libfunc (trunc_optab, TFmode, mode, "__extendkftf2"); diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 3cae64a264a..203d0ba6a7f 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -543,12 +543,6 @@ ; Iterator for 128-bit VSX types for pack/unpack (define_mode_iterator FMOVE128_VSX [V1TI KF]) -; Iterators for converting to/from TFmode -(define_mode_iterator IFKF [IF KF]) - -; Constraints for moving IF/KFmode. -(define_mode_attr IFKF_reg [(IF "d") (KF "wa")]) - ; Whether a floating point move is ok, don't allow SD without hardware FP (define_mode_attr fmove_ok [(SF "") (DF "") @@ -9161,106 +9155,65 @@ "xxlor %x0,%x1,%x2" [(set_attr "type" "veclogical")]) -;; Float128 conversion functions. These expand to library function calls. -;; We use expand to convert from IBM double double to IEEE 128-bit -;; and trunc for the opposite. -(define_expand "extendiftf2" - [(set (match_operand:TF 0 "gpc_reg_operand") - (float_extend:TF (match_operand:IF 1 "gpc_reg_operand")))] - "TARGET_FLOAT128_TYPE" -{ - rs6000_expand_float128_convert (operands[0], operands[1], false); - DONE; -}) - -(define_expand "extendifkf2" - [(set (match_operand:KF 0 "gpc_reg_operand") - (float_extend:KF (match_operand:IF 1 "gpc_reg_operand")))] - "TARGET_FLOAT128_TYPE" -{ - rs6000_expand_float128_convert (operands[0], operands[1], false); - DONE; -}) - -(define_expand "extendtfkf2" - [(set (match_operand:KF 0 "gpc_reg_operand") - (float_extend:KF (match_operand:TF 1 "gpc_reg_operand")))] - "TARGET_FLOAT128_TYPE" -{ - rs6000_expand_float128_convert (operands[0], operands[1], false); - DONE; -}) - -(define_expand "extendtfif2" - [(set (match_operand:IF 0 "gpc_reg_operand") - (float_extend:IF (match_operand:TF 1 "gpc_reg_operand")))] - "TARGET_FLOAT128_TYPE" -{ - rs6000_expand_float128_convert (operands[0], operands[1], false); - DONE; -}) - -(define_expand "trunciftf2" - [(set (match_operand:TF 0 "gpc_reg_operand") - (float_truncate:TF (match_operand:IF 1 "gpc_reg_operand")))] - "TARGET_FLOAT128_TYPE" -{ - rs6000_expand_float128_convert (operands[0], operands[1], false); - DONE; -}) - -(define_expand "truncifkf2" - [(set (match_operand:KF 0 "gpc_reg_operand") - (float_truncate:KF (match_operand:IF 1 "gpc_reg_operand")))] - "TARGET_FLOAT128_TYPE" -{ - rs6000_expand_float128_convert (operands[0], operands[1], false); - DONE; -}) - -(define_expand "trunckftf2" - [(set (match_operand:TF 0 "gpc_reg_operand") - (float_truncate:TF (match_operand:KF 1 "gpc_reg_operand")))] - "TARGET_FLOAT128_TYPE" +;; Float128 conversion functions. We only define the 'conversions' between two +;; formats that use the same representation. We call the library function to +;; convert between IEEE 128-bit and IBM 128-bit. We can't do these moves by +;; using a SUBREG before register allocation. We set up the moves to prefer +;; the output register being the same as the input register, which would enable +;; the move to be deleted completely. +(define_insn_and_split "extendkftf2" + [(set (match_operand:TF 0 "gpc_reg_operand" "=wa,wa") + (float_extend:TF (match_operand:KF 1 "gpc_reg_operand" "0,wa")))] + "TARGET_FLOAT128_TYPE && FLOAT128_IEEE_P (TFmode)" + "#" + "&& reload_completed" + [(set (match_dup 0) + (match_dup 2))] { - rs6000_expand_float128_convert (operands[0], operands[1], false); - DONE; -}) + operands[2] = gen_lowpart (TFmode, operands[1]); +} + [(set_attr "type" "veclogical")]) -(define_expand "trunctfif2" - [(set (match_operand:IF 0 "gpc_reg_operand") - (float_truncate:IF (match_operand:TF 1 "gpc_reg_operand")))] - "TARGET_FLOAT128_TYPE" +(define_insn_and_split "trunctfkf2" + [(set (match_operand:KF 0 "gpc_reg_operand" "=wa,wa") + (float_truncate:KF (match_operand:TF 1 "gpc_reg_operand" "0,wa")))] + "TARGET_FLOAT128_TYPE && FLOAT128_IEEE_P (TFmode)" + "#" + "&& reload_completed" + [(set (match_dup 0) + (match_dup 2))] { - rs6000_expand_float128_convert (operands[0], operands[1], false); - DONE; -}) + operands[2] = gen_lowpart (KFmode, operands[1]); +} + [(set_attr "type" "veclogical")]) -(define_insn_and_split "*extendtf2_internal" - [(set (match_operand:TF 0 "gpc_reg_operand" "=") - (float_extend:TF - (match_operand:IFKF 1 "gpc_reg_operand" "")))] - "TARGET_FLOAT128_TYPE - && FLOAT128_IBM_P (TFmode) == FLOAT128_IBM_P (mode)" +(define_insn_and_split "extendtfif2" + [(set (match_operand:IF 0 "gpc_reg_operand" "=wa,wa,r,r") + (float_extend:IF (match_operand:TF 1 "gpc_reg_operand" "0,wa,0,r")))] + "TARGET_HARD_FLOAT && FLOAT128_IBM_P (TFmode)" "#" "&& reload_completed" - [(set (match_dup 0) (match_dup 2))] + [(set (match_dup 0) + (match_dup 2))] { - operands[2] = gen_rtx_REG (TFmode, REGNO (operands[1])); -}) + operands[2] = gen_lowpart (IFmode, operands[1]); +} + [(set_attr "num_insns" "2") + (set_attr "length" "8")]) -(define_insn_and_split "*extendtf2_internal" - [(set (match_operand:IFKF 0 "gpc_reg_operand" "=") - (float_extend:IFKF - (match_operand:TF 1 "gpc_reg_operand" "")))] - "TARGET_FLOAT128_TYPE - && FLOAT128_IBM_P (TFmode) == FLOAT128_IBM_P (mode)" +(define_insn_and_split "extendiftf2" + [(set (match_operand:TF 0 "gpc_reg_operand" "=wa,wa,r,r") + (float_extend:TF (match_operand:IF 1 "gpc_reg_operand" "0,wa,0,r")))] + "TARGET_HARD_FLOAT && FLOAT128_IBM_P (TFmode)" "#" "&& reload_completed" - [(set (match_dup 0) (match_dup 2))] + [(set (match_dup 0) + (match_dup 2))] { - operands[2] = gen_rtx_REG (mode, REGNO (operands[1])); -}) + operands[2] = gen_lowpart (TFmode, operands[1]); +} + [(set_attr "num_insns" "2") + (set_attr "length" "8")]) ;; Reload helper functions used by rs6000_secondary_reload. The patterns all @@ -14983,40 +14936,6 @@ [(set_attr "type" "vecfloat") (set_attr "size" "128")]) -;; Conversion between KFmode and TFmode if TFmode is ieee 128-bit floating -;; point is a simple copy. -(define_insn_and_split "extendkftf2" - [(set (match_operand:TF 0 "vsx_register_operand" "=wa,?wa") - (float_extend:TF (match_operand:KF 1 "vsx_register_operand" "0,wa")))] - "TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD" - "@ - # - xxlor %x0,%x1,%x1" - "&& reload_completed && REGNO (operands[0]) == REGNO (operands[1])" - [(const_int 0)] -{ - emit_note (NOTE_INSN_DELETED); - DONE; -} - [(set_attr "type" "*,veclogical") - (set_attr "length" "0,4")]) - -(define_insn_and_split "trunctfkf2" - [(set (match_operand:KF 0 "vsx_register_operand" "=wa,?wa") - (float_extend:KF (match_operand:TF 1 "vsx_register_operand" "0,wa")))] - "TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD" - "@ - # - xxlor %x0,%x1,%x1" - "&& reload_completed && REGNO (operands[0]) == REGNO (operands[1])" - [(const_int 0)] -{ - emit_note (NOTE_INSN_DELETED); - DONE; -} - [(set_attr "type" "*,veclogical") - (set_attr "length" "0,4")]) - (define_insn "truncdf2_hw" [(set (match_operand:DF 0 "altivec_register_operand" "=v") (float_truncate:DF