From patchwork Tue Jan 31 01:21:00 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Meissner X-Patchwork-Id: 721775 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3vC7l11YSTz9t0q for ; Tue, 31 Jan 2017 12:21:31 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="oRlfuL9F"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:mime-version:content-type:message-id; q=dns; s= default; b=mOPfillr66ZxDbppjxp4TUiVW0MJPhhqgykTn2ldOzP3biyLBVlI3 IsJDxMN+tCN7AUsud8ufhwwCXXWA2aEGoPqtTPAwcdllBfvRQCiBQPAWJgYv31yN RqPDfvLoV5+n36YDiHc2ivke1lXTXN4Js589X+i7O+JFh1rzvQeWqg= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:mime-version:content-type:message-id; s= default; bh=h6B6t907kT+JrWkHCpWlSf66FAs=; b=oRlfuL9FVxgnQ9g3uBkS kFc7C/zkMOimdfnhP+JIScG6rfhwgey1/H1AXW59vXBtp3OgBhK45RntegO/MX/d aqxonFyy+z7/HfS08YtCus0TcDR1Ju7VYxGVevvwkaAEiCxcDHRRsPVTV6oMCwJD nBqtTpPr0OApy1kKp+m+HzY= Received: (qmail 73321 invoked by alias); 31 Jan 2017 01:21:18 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 73306 invoked by uid 89); 31 Jan 2017 01:21:18 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.7 required=5.0 tests=AWL, BAYES_00, KAM_ASCII_DIVIDERS, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 spammy=IEEE128, ieee128, zwi, King X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0a-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.156.1) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 31 Jan 2017 01:21:08 +0000 Received: from pps.filterd (m0098394.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.20/8.16.0.20) with SMTP id v0V1J6m1028985 for ; Mon, 30 Jan 2017 20:21:06 -0500 Received: from e34.co.us.ibm.com (e34.co.us.ibm.com [32.97.110.152]) by mx0a-001b2d01.pphosted.com with ESMTP id 28ads2dpew-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 30 Jan 2017 20:21:05 -0500 Received: from localhost by e34.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 30 Jan 2017 18:21:05 -0700 Received: from d03dlp02.boulder.ibm.com (9.17.202.178) by e34.co.us.ibm.com (192.168.1.134) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 30 Jan 2017 18:21:02 -0700 Received: from b03cxnp08025.gho.boulder.ibm.com (b03cxnp08025.gho.boulder.ibm.com [9.17.130.17]) by d03dlp02.boulder.ibm.com (Postfix) with ESMTP id 1883D3E40030; Mon, 30 Jan 2017 18:21:02 -0700 (MST) Received: from b03ledav002.gho.boulder.ibm.com (b03ledav002.gho.boulder.ibm.com [9.17.130.233]) by b03cxnp08025.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v0V1JO2011665872; Mon, 30 Jan 2017 18:21:02 -0700 Received: from b03ledav002.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id EBA6813603A; Mon, 30 Jan 2017 18:21:01 -0700 (MST) Received: from ibm-tiger.the-meissners.org (unknown [9.32.77.111]) by b03ledav002.gho.boulder.ibm.com (Postfix) with ESMTP id C5A4C136046; Mon, 30 Jan 2017 18:21:01 -0700 (MST) Received: by ibm-tiger.the-meissners.org (Postfix, from userid 500) id EFA6448307; Mon, 30 Jan 2017 20:21:00 -0500 (EST) Date: Mon, 30 Jan 2017 20:21:00 -0500 From: Michael Meissner To: gcc-patches@gcc.gnu.org, Segher Boessenkool , David Edelsohn , Bill Schmidt Subject: [PATCH], PR target/78597, Fix PowerPC fp-int-convert-{float128-ieee, float64x} Mail-Followup-To: Michael Meissner , gcc-patches@gcc.gnu.org, Segher Boessenkool , David Edelsohn , Bill Schmidt MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-12-10) X-TM-AS-GCONF: 00 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 17013101-0016-0000-0000-000006051E66 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00006528; HX=3.00000240; KW=3.00000007; PH=3.00000004; SC=3.00000201; SDB=6.00814978; UDB=6.00397820; IPR=6.00592419; BA=6.00005100; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00014113; XFM=3.00000011; UTC=2017-01-31 01:21:04 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17013101-0017-0000-0000-000036F6ACBD Message-Id: <20170131012100.GA28913@ibm-tiger.the-meissners.org> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-01-30_11:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=0 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1612050000 definitions=main-1701310011 X-IsSubscribed: yes This patch fixes PR target/78597 on PowerPC. The basic problem is conversion between unsigned int and _Float128 fails for 0x80000000. Both power{7,8} using simulated IEEE 128-bit floating point and power9 using hardware IEEE 128-bit failed in the same test. I cut down the patches I had developed for 79038 that are waiting for GCC 8 to open up to include the patches that fix the problem, but don't do additional improvements (optimizing conversions between char/short and _Float128, and optimizing converting _Float128 to int/short/char and storing the result). This patch is a little on the big side, because I deleted the two functions (convert_float128_to_int and (convert_int_to_float128) that were doing the integer/_Float128 conversions, and instead implemented them directly. I also deleted the various insns that those two functions called. It only affects _Float128/__float128 conversions. I have tested this on a little endian power8 system. Bootstrap passes, and the only changes in the test suite runs were the following tests now pass: gcc.dg/torture/fp-int-convert-float128-ieee.c gcc.dg/torture/fp-int-convert-float64x.c I did not add any tests, because it was covered by existing tests. Can I check this into trunk? 2017-01-30 Michael Meissner PR target/78597 PR target/79038 * config/rs6000/rs6000-protos.h (convert_float128_to_int): Delete, no longer used. (convert_int_to_float128): Likewise. * config/rs6000/rs6000.c (convert_float128_to_int): Likewise. (convert_int_to_float128): Likewise. * config/rs6000/rs6000.md (UNSPEC_IEEE128_MOVE): Likewise. (UNSPEC_IEEE128_CONVERT): Likewise. (floatsi2, FLOAT128 iterator): Bypass calling rs6000_expand_float128_convert if we have IEEE 128-bit hardware. Use local variables for IBM extended format. (fix_truncsi2, FLOAT128 iterator): Likewise. (fix_truncsi2_fprs): Likewise. (fixuns_trunc2): Likewise. (floatuns2, IEEE128 iterator): Likewise. (fix_si2_hw): Rework the IEEE 128-bt hardware support to know that we can now have integers of all sizes in vector registers. (fix_di2_hw): Likewise. (float_si2_hw): Likewise. (fix_si2_hw): Likewise. (fixuns_si2_hw): Likewise. (float_di2_hw): Likewise. (float_di2_hw): Likewise. (float_si2_hw): Likewise. (floatuns_di2_hw): Likewise. (floatuns_si2_hw): Likewise. (xscvqpwz_): Delete, no longer used. (xscvqpdz_): Likewise. (xscvdqp_): Likewise. (ieee128_mfvsrd_64bit): Likewise. (ieee128_mfvsrd_32bit): Likewise. (ieee128_mfvsrwz): Likewise. (ieee128_mtvsrw): Likewise. (ieee128_mtvsrd_64bit): Likewise. (ieee128_mtvsrd_32bit): Likewise. Index: gcc/config/rs6000/rs6000-protos.h =================================================================== --- gcc/config/rs6000/rs6000-protos.h (revision 245036) +++ gcc/config/rs6000/rs6000-protos.h (working copy) @@ -57,8 +57,6 @@ extern const char *rs6000_output_move_12 extern bool rs6000_move_128bit_ok_p (rtx []); extern bool rs6000_split_128bit_ok_p (rtx []); extern void rs6000_expand_float128_convert (rtx, rtx, bool); -extern void convert_float128_to_int (rtx *, enum rtx_code); -extern void convert_int_to_float128 (rtx *, enum rtx_code); extern void rs6000_expand_vector_init (rtx, rtx); extern void paired_expand_vector_init (rtx, rtx); extern void rs6000_expand_vector_set (rtx, rtx, int); Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 245036) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -24609,92 +24609,6 @@ rs6000_expand_float128_convert (rtx dest return; } -/* Split a conversion from __float128 to an integer type into separate insns. - OPERANDS points to the destination, source, and V2DI temporary - register. CODE is either FIX or UNSIGNED_FIX. */ - -void -convert_float128_to_int (rtx *operands, enum rtx_code code) -{ - rtx dest = operands[0]; - rtx src = operands[1]; - rtx tmp = operands[2]; - rtx cvt; - rtvec cvt_vec; - rtx cvt_unspec; - rtvec move_vec; - rtx move_unspec; - - if (GET_CODE (tmp) == SCRATCH) - tmp = gen_reg_rtx (V2DImode); - - if (MEM_P (dest)) - dest = rs6000_address_for_fpconvert (dest); - - /* Generate the actual convert insn of the form: - (set (tmp) (unspec:V2DI [(fix:SI (reg:KF))] UNSPEC_IEEE128_CONVERT)). */ - cvt = gen_rtx_fmt_e (code, GET_MODE (dest), src); - cvt_vec = gen_rtvec (1, cvt); - cvt_unspec = gen_rtx_UNSPEC (V2DImode, cvt_vec, UNSPEC_IEEE128_CONVERT); - emit_insn (gen_rtx_SET (tmp, cvt_unspec)); - - /* Generate the move insn of the form: - (set (dest:SI) (unspec:SI [(tmp:V2DI))] UNSPEC_IEEE128_MOVE)). */ - move_vec = gen_rtvec (1, tmp); - move_unspec = gen_rtx_UNSPEC (GET_MODE (dest), move_vec, UNSPEC_IEEE128_MOVE); - emit_insn (gen_rtx_SET (dest, move_unspec)); -} - -/* Split a conversion from an integer type to __float128 into separate insns. - OPERANDS points to the destination, source, and V2DI temporary - register. CODE is either FLOAT or UNSIGNED_FLOAT. */ - -void -convert_int_to_float128 (rtx *operands, enum rtx_code code) -{ - rtx dest = operands[0]; - rtx src = operands[1]; - rtx tmp = operands[2]; - rtx cvt; - rtvec cvt_vec; - rtx cvt_unspec; - rtvec move_vec; - rtx move_unspec; - rtx unsigned_flag; - - if (GET_CODE (tmp) == SCRATCH) - tmp = gen_reg_rtx (V2DImode); - - if (MEM_P (src)) - src = rs6000_address_for_fpconvert (src); - - /* Generate the move of the integer into the Altivec register of the form: - (set (tmp:V2DI) (unspec:V2DI [(src:SI) - (const_int 0)] UNSPEC_IEEE128_MOVE)). - - or: - (set (tmp:V2DI) (unspec:V2DI [(src:DI)] UNSPEC_IEEE128_MOVE)). */ - - if (GET_MODE (src) == SImode) - { - unsigned_flag = (code == UNSIGNED_FLOAT) ? const1_rtx : const0_rtx; - move_vec = gen_rtvec (2, src, unsigned_flag); - } - else - move_vec = gen_rtvec (1, src); - - move_unspec = gen_rtx_UNSPEC (V2DImode, move_vec, UNSPEC_IEEE128_MOVE); - emit_insn (gen_rtx_SET (tmp, move_unspec)); - - /* Generate the actual convert insn of the form: - (set (dest:KF) (float:KF (unspec:DI [(tmp:V2DI)] - UNSPEC_IEEE128_CONVERT))). */ - cvt_vec = gen_rtvec (1, tmp); - cvt_unspec = gen_rtx_UNSPEC (DImode, cvt_vec, UNSPEC_IEEE128_CONVERT); - cvt = gen_rtx_fmt_e (code, GET_MODE (dest), cvt_unspec); - emit_insn (gen_rtx_SET (dest, cvt)); -} - /* Emit the RTL for an sISEL pattern. */ Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 245036) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -146,8 +146,6 @@ (define_c_enum "unspec" UNSPEC_FUSION_P9 UNSPEC_FUSION_ADDIS UNSPEC_ROUND_TO_ODD - UNSPEC_IEEE128_MOVE - UNSPEC_IEEE128_CONVERT UNSPEC_SIGNBIT UNSPEC_SF_FROM_SI UNSPEC_SI_FROM_SF @@ -7661,26 +7659,35 @@ (define_insn_and_split "truncsf2_f "") (define_expand "floatsi2" - [(set (match_operand:FLOAT128 0 "gpc_reg_operand" "") - (float:FLOAT128 (match_operand:SI 1 "gpc_reg_operand" "")))] + [(parallel [(set (match_operand:FLOAT128 0 "gpc_reg_operand") + (float:FLOAT128 (match_operand:SI 1 "gpc_reg_operand"))) + (clobber (match_scratch:DI 2))])] "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128" { - if (FLOAT128_IEEE_P (mode)) - rs6000_expand_float128_convert (operands[0], operands[1], false); + rtx op0 = operands[0]; + rtx op1 = operands[1]; + + if (TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)) + ; + else if (FLOAT128_IEEE_P (mode)) + { + rs6000_expand_float128_convert (op0, op1, false); + DONE; + } else { rtx tmp = gen_reg_rtx (DFmode); - expand_float (tmp, operands[1], false); + expand_float (tmp, op1, false); if (mode == TFmode) - emit_insn (gen_extenddftf2 (operands[0], tmp)); + emit_insn (gen_extenddftf2 (op0, tmp)); else if (mode == IFmode) - emit_insn (gen_extenddfif2 (operands[0], tmp)); + emit_insn (gen_extenddfif2 (op0, tmp)); else gcc_unreachable (); + DONE; } - DONE; }) ; fadd, but rounding towards zero. @@ -7702,17 +7709,25 @@ (define_expand "fix_truncsi2" "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128" { - if (FLOAT128_IEEE_P (mode)) - rs6000_expand_float128_convert (operands[0], operands[1], false); - else if (TARGET_E500_DOUBLE && mode == TFmode) - emit_insn (gen_spe_fix_trunctfsi2 (operands[0], operands[1])); - else if (mode == TFmode) - emit_insn (gen_fix_trunctfsi2_fprs (operands[0], operands[1])); - else if (mode == IFmode) - emit_insn (gen_fix_truncifsi2_fprs (operands[0], operands[1])); + rtx op0 = operands[0]; + rtx op1 = operands[1]; + + if (TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)) + ; else - gcc_unreachable (); - DONE; + { + if (FLOAT128_IEEE_P (mode)) + rs6000_expand_float128_convert (op0, op1, false); + else if (TARGET_E500_DOUBLE && mode == TFmode) + emit_insn (gen_spe_fix_trunctfsi2 (op0, op1)); + else if (mode == TFmode) + emit_insn (gen_fix_trunctfsi2_fprs (op0, op1)); + else if (mode == IFmode) + emit_insn (gen_fix_truncifsi2_fprs (op0, op1)); + else + gcc_unreachable (); + DONE; + } }) (define_expand "fix_truncsi2_fprs" @@ -7760,8 +7775,11 @@ (define_expand "fix_truncdi2" (fix:DI (match_operand:IEEE128 1 "gpc_reg_operand" "")))] "TARGET_FLOAT128_TYPE" { - rs6000_expand_float128_convert (operands[0], operands[1], false); - DONE; + if (!TARGET_FLOAT128_HW) + { + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; + } }) (define_expand "fixuns_trunc2" @@ -7778,16 +7796,37 @@ (define_expand "floatdi2" (float:IEEE128 (match_operand:DI 1 "gpc_reg_operand" "")))] "TARGET_FLOAT128_TYPE" { - rs6000_expand_float128_convert (operands[0], operands[1], false); - DONE; + if (!TARGET_FLOAT128_HW) + { + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; + } }) -(define_expand "floatuns2" +(define_expand "floatunsdi2" [(set (match_operand:IEEE128 0 "gpc_reg_operand" "") - (unsigned_float:IEEE128 (match_operand:SDI 1 "gpc_reg_operand" "")))] + (unsigned_float:IEEE128 (match_operand:DI 1 "gpc_reg_operand" "")))] "TARGET_FLOAT128_TYPE" { - rs6000_expand_float128_convert (operands[0], operands[1], true); + if (!TARGET_FLOAT128_HW) + { + rs6000_expand_float128_convert (operands[0], operands[1], true); + DONE; + } +}) + +(define_expand "floatuns2" + [(set (match_operand:IEEE128 0 "gpc_reg_operand" "") + (unsigned_float:IEEE128 (match_operand:SI 1 "gpc_reg_operand" "")))] + "TARGET_FLOAT128_TYPE" +{ + rtx op0 = operands[0]; + rtx op1 = operands[1]; + + if (TARGET_FLOAT128_HW) + emit_insn (gen_floatuns_si2_hw (op0, op1)); + else + rs6000_expand_float128_convert (op0, op1, true); DONE; }) @@ -14321,170 +14360,102 @@ (define_insn_and_split "truncsf2_h [(set_attr "type" "vecfloat") (set_attr "length" "8")]) -;; At present SImode is not allowed in VSX registers at all, and DImode is only -;; allowed in the traditional floating point registers. Use V2DImode so that -;; we can get a value in an Altivec register. - -(define_insn_and_split "fix_si2_hw" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,Z") - (any_fix:SI (match_operand:IEEE128 1 "altivec_register_operand" "v,v"))) - (clobber (match_scratch:V2DI 2 "=v,v"))] +;; Conersion between IEEE 128-bit and integer types +(define_insn "fix_di2_hw" + [(set (match_operand:DI 0 "altivec_register_operand" "=v") + (fix:DI (match_operand:IEEE128 1 "altivec_register_operand" "v")))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" - "#" - "&& 1" - [(pc)] -{ - convert_float128_to_int (operands, ); - DONE; -} - [(set_attr "length" "8") - (set_attr "type" "mftgpr,fpstore")]) + "xscvqpsdz %0,%1" + [(set_attr "type" "vecfloat") + (set_attr "size" "128")]) -(define_insn_and_split "fix_di2_hw" - [(set (match_operand:DI 0 "nonimmediate_operand" "=wr,wi,Z") - (any_fix:DI (match_operand:IEEE128 1 "altivec_register_operand" "v,v,v"))) - (clobber (match_scratch:V2DI 2 "=v,v,v"))] +(define_insn "fixuns_di2_hw" + [(set (match_operand:DI 0 "altivec_register_operand" "=v") + (unsigned_fix:DI (match_operand:IEEE128 1 "altivec_register_operand" "v")))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" - "#" - "&& 1" - [(pc)] -{ - convert_float128_to_int (operands, ); - DONE; -} - [(set_attr "length" "8") - (set_attr "type" "mftgpr,vecsimple,fpstore")]) + "xscvqpudz %0,%1" + [(set_attr "type" "vecfloat") + (set_attr "size" "128")]) -(define_insn_and_split "float_si2_hw" - [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v,v") - (any_float:IEEE128 (match_operand:SI 1 "nonimmediate_operand" "r,Z"))) - (clobber (match_scratch:V2DI 2 "=v,v"))] +(define_insn "fix_si2_hw" + [(set (match_operand:SI 0 "altivec_register_operand" "=v") + (fix:SI (match_operand:IEEE128 1 "altivec_register_operand" "v")))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" - "#" - "&& 1" - [(pc)] -{ - convert_int_to_float128 (operands, ); - DONE; -} - [(set_attr "length" "8") - (set_attr "type" "vecfloat")]) + "xscvqpswz %0,%1" + [(set_attr "type" "vecfloat") + (set_attr "size" "128")]) + +(define_insn "fixuns_si2_hw" + [(set (match_operand:SI 0 "altivec_register_operand" "=v") + (unsigned_fix:SI (match_operand:IEEE128 1 "altivec_register_operand" "v")))] + "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" + "xscvqpuwz %0,%1" + [(set_attr "type" "vecfloat") + (set_attr "size" "128")]) -(define_insn_and_split "float_di2_hw" - [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v,v,v") - (any_float:IEEE128 (match_operand:DI 1 "nonimmediate_operand" "wi,wr,Z"))) - (clobber (match_scratch:V2DI 2 "=v,v,v"))] +;; Combiner pattern to prevent moving the result of converting an IEEE 128-bit +;; floating point value to 32-bit integer to GPR in order to save it. +(define_insn_and_split "*fix__mem" + [(set (match_operand:SI 0 "memory_operand" "=Z") + (any_fix:SI (match_operand:IEEE128 1 "altivec_register_operand" "v"))) + (clobber (match_scratch:SI 2 "=v"))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" "#" - "&& 1" - [(pc)] -{ - convert_int_to_float128 (operands, ); - DONE; -} - [(set_attr "length" "8") - (set_attr "type" "vecfloat")]) + "&& reload_completed" + [(set (match_dup 2) + (any_fix:SI (match_dup 1))) + (set (match_dup 0) + (match_dup 2))]) -;; Integer conversion instructions, using V2DImode to get an Altivec register -(define_insn "*xscvqpwz_" - [(set (match_operand:V2DI 0 "altivec_register_operand" "=v") - (unspec:V2DI - [(any_fix:SI - (match_operand:IEEE128 1 "altivec_register_operand" "v"))] - UNSPEC_IEEE128_CONVERT))] +(define_insn "float_di2_hw" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") + (float:IEEE128 (match_operand:DI 1 "altivec_register_operand" "v")))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" - "xscvqpwz %0,%1" + "xscvsdqp %0,%1" [(set_attr "type" "vecfloat") (set_attr "size" "128")]) -(define_insn "*xscvqpdz_" - [(set (match_operand:V2DI 0 "altivec_register_operand" "=v") - (unspec:V2DI - [(any_fix:DI - (match_operand:IEEE128 1 "altivec_register_operand" "v"))] - UNSPEC_IEEE128_CONVERT))] +(define_insn_and_split "float_si2_hw" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") + (float:IEEE128 (match_operand:SI 1 "nonimmediate_operand" "vrZ"))) + (clobber (match_scratch:DI 2 "=v"))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" - "xscvqpdz %0,%1" - [(set_attr "type" "vecfloat") - (set_attr "size" "128")]) + "#" + "&& 1" + [(set (match_dup 2) + (sign_extend:DI (match_dup 1))) + (set (match_dup 0) + (float:IEEE128 (match_dup 2)))] +{ + if (GET_CODE (operands[2]) == SCRATCH) + operands[2] = gen_reg_rtx (DImode); +}) -(define_insn "*xscvdqp_" +(define_insn "floatuns_di2_hw" [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") - (any_float:IEEE128 - (unspec:DI [(match_operand:V2DI 1 "altivec_register_operand" "v")] - UNSPEC_IEEE128_CONVERT)))] + (unsigned_float:IEEE128 + (match_operand:DI 1 "altivec_register_operand" "v")))] "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" - "xscvdqp %0,%1" + "xscvudqp %0,%1" [(set_attr "type" "vecfloat") (set_attr "size" "128")]) -(define_insn "*ieee128_mfvsrd_64bit" - [(set (match_operand:DI 0 "reg_or_indexed_operand" "=wr,Z,wi") - (unspec:DI [(match_operand:V2DI 1 "altivec_register_operand" "v,v,v")] - UNSPEC_IEEE128_MOVE))] - "TARGET_FLOAT128_HW && TARGET_POWERPC64" - "@ - mfvsrd %0,%x1 - stxsdx %x1,%y0 - xxlor %x0,%x1,%x1" - [(set_attr "type" "mftgpr,fpstore,veclogical")]) - - -(define_insn "*ieee128_mfvsrd_32bit" - [(set (match_operand:DI 0 "reg_or_indexed_operand" "=Z,wi") - (unspec:DI [(match_operand:V2DI 1 "altivec_register_operand" "v,v")] - UNSPEC_IEEE128_MOVE))] - "TARGET_FLOAT128_HW && !TARGET_POWERPC64" - "@ - stxsdx %x1,%y0 - xxlor %x0,%x1,%x1" - [(set_attr "type" "fpstore,veclogical")]) - -(define_insn "*ieee128_mfvsrwz" - [(set (match_operand:SI 0 "reg_or_indexed_operand" "=r,Z") - (unspec:SI [(match_operand:V2DI 1 "altivec_register_operand" "v,v")] - UNSPEC_IEEE128_MOVE))] - "TARGET_FLOAT128_HW" - "@ - mfvsrwz %0,%x1 - stxsiwx %x1,%y0" - [(set_attr "type" "mftgpr,fpstore")]) - -;; 0 says do sign-extension, 1 says zero-extension -(define_insn "*ieee128_mtvsrw" - [(set (match_operand:V2DI 0 "altivec_register_operand" "=v,v,v,v") - (unspec:V2DI [(match_operand:SI 1 "nonimmediate_operand" "r,Z,r,Z") - (match_operand:SI 2 "const_0_to_1_operand" "O,O,n,n")] - UNSPEC_IEEE128_MOVE))] - "TARGET_FLOAT128_HW" - "@ - mtvsrwa %x0,%1 - lxsiwax %x0,%y1 - mtvsrwz %x0,%1 - lxsiwzx %x0,%y1" - [(set_attr "type" "mffgpr,fpload,mffgpr,fpload")]) - - -(define_insn "*ieee128_mtvsrd_64bit" - [(set (match_operand:V2DI 0 "altivec_register_operand" "=v,v,v") - (unspec:V2DI [(match_operand:DI 1 "nonimmediate_operand" "wr,Z,wi")] - UNSPEC_IEEE128_MOVE))] - "TARGET_FLOAT128_HW && TARGET_POWERPC64" - "@ - mtvsrd %x0,%1 - lxsdx %x0,%y1 - xxlor %x0,%x1,%x1" - [(set_attr "type" "mffgpr,fpload,veclogical")]) - -(define_insn "*ieee128_mtvsrd_32bit" - [(set (match_operand:V2DI 0 "altivec_register_operand" "=v,v") - (unspec:V2DI [(match_operand:DI 1 "nonimmediate_operand" "Z,wi")] - UNSPEC_IEEE128_MOVE))] - "TARGET_FLOAT128_HW && !TARGET_POWERPC64" - "@ - lxsdx %x0,%y1 - xxlor %x0,%x1,%x1" - [(set_attr "type" "fpload,veclogical")]) +(define_insn_and_split "floatuns_si2_hw" + [(set (match_operand:IEEE128 0 "altivec_register_operand" "=v") + (unsigned_float:IEEE128 + (match_operand:SI 1 "nonimmediate_operand" "vrZ"))) + (clobber (match_scratch:DI 2 "=v"))] + "TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)" + "#" + "&& 1" + [(set (match_dup 2) + (zero_extend:DI (match_dup 1))) + (set (match_dup 0) + (float:IEEE128 (match_dup 2)))] +{ + if (GET_CODE (operands[2]) == SCRATCH) + operands[2] = gen_reg_rtx (DImode); +}) ;; IEEE 128-bit instructions with round to odd semantics (define_insn "*truncdf2_odd"