From patchwork Tue Aug 24 18:53:38 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Meissner X-Patchwork-Id: 62619 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]) by ozlabs.org (Postfix) with SMTP id 9A749B70CE for ; Wed, 25 Aug 2010 04:53:58 +1000 (EST) Received: (qmail 29991 invoked by alias); 24 Aug 2010 18:53:57 -0000 Received: (qmail 29979 invoked by uid 22791); 24 Aug 2010 18:53:54 -0000 X-SWARE-Spam-Status: No, hits=-0.9 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from caiajhbdcbef.dreamhost.com (HELO homiemail-a33.g.dreamhost.com) (208.97.132.145) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 24 Aug 2010 18:53:44 +0000 Received: from homiemail-a33.g.dreamhost.com (localhost [127.0.0.1]) by homiemail-a33.g.dreamhost.com (Postfix) with ESMTP id A61C3594093; Tue, 24 Aug 2010 11:53:42 -0700 (PDT) Received: from hungry-tiger.westford.ibm.com (bi01pt1.ct.us.ibm.com [129.33.1.37]) (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) (Authenticated sender: gnu@the-meissners.org) by homiemail-a33.g.dreamhost.com (Postfix) with ESMTPSA id 803C2594084; Tue, 24 Aug 2010 11:53:41 -0700 (PDT) Date: Tue, 24 Aug 2010 14:53:38 -0400 From: Michael Meissner To: gcc-patches@gcc.gnu.org, dje.gcc@gmail.com Subject: [PATCH, powerpc] Improve floating point to integer conversions on powerpc Message-ID: <20100824185338.GA24317@hungry-tiger.westford.ibm.com> Mail-Followup-To: Michael Meissner , gcc-patches@gcc.gnu.org, dje.gcc@gmail.com MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-08-17) X-IsSubscribed: yes 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 This is the second patch in terms improving floating point conversions on the powerpc. The changes here include: 1) Merge SF/DF patterns into a single combined insn; 2) Add missing power7 conversions; 3) Add combiner insns to reduce the cases where the target of the conversion is going to be stored in memory to prevent the compiler from storing the value into the stack, reloading it into a GPR, and then storing it to the destination. 4) Eliminate another case of pre-IRA register allocator constraints that doesn't work as well with IRA, and add extra round trips through memory and GPRs. 5) Generate code for the lrint builtin funciton (on 64-bit) and llrint (on both 32 and 64-bit). As before, I bootstraped and did make check with no regressions. I built SPE code for -mcpu=e500mc and -mcpu=e500mc64 with no differences. I added 5 tests to test the basic functionality for different code models. [gcc] 2010-08-24 Michael Meissner * config/rs6000/rs6000.md (fixuns_truncsfsi2): Delete, merge into common pattern for both SF/DF. Add power7 support. (fix_truncsfsi2): Ditto. (fixuns_truncdfsi2): Ditto. (fixuns_truncdfdi2): Ditto. (fix_truncdfsi2): Ditto. (fix_truncdfsi2_internal): Ditto. (fix_truncdfsi2_internal_gfxopt): Ditto. (fix_truncdfsi2_mfpgpr): Ditto. (fctiwz): Ditto. (btruncdf2): Ditto. (btruncdf2_fpr): Ditto. (btructsf2): Ditto. (ceildf2): Ditto. (ceildf2_fpr): Ditto. (ceilsf2): Ditto. (floordf2): Ditto. (floordf2_fpr): Ditto. (floorsf2): Ditto. (rounddf2): Ditto. (rounddf2_fpr): Ditto. (roundsf2): Ditto. (fix_truncsi2): Combine SF/DF conversion into one insn. (fix_truncdi2): Ditto. (fixuns_truncsi2): Ditto. (fixuns_truncdi2): Ditto. (fctiwz_): Ditto. (btrunc2): Ditto. (btrunc2_fpr): Ditto. (ceil2): Ditto. (ceil2_fpr): Ditto. (floor2): Ditto. (float2_fpr): Ditto. (round2): Ditto. (round2_fpr): Ditto. (fix_truncsi2_stfiwx): New insn for machines with STFIWX. (fixuns_truncsi2_stfiwx): Ditto. (fix_truncdfsi2_internal): Ditto. (fix_truncsi2_mem): Combiner pattern to eliminate storing converted value on stack, loaded into GPR, and then stored into the final destination. (fix_truncdi2_fctidz): New pattern for targets supporting FCTIDZ. (lrintdi2): New insn, provide the lrint builtin functions. (ftruncdf2): Delete, unused. (fix_trunctfsi2_internal): Use gen_fctiwz_df, not gen_fctiwz. * config/rs6000/vsx.md (toplevel): Update copyright year. (VSr2): Use "ws" contraint for DFmode, not "!r#r". (VSr3): Ditto. [gcc/testsuite] 2010-08-24 Michael Meissner * gcc.target/powerpc/ppc-fpconv-5.c: New test for floating point to integer conversion code generation. * gcc.target/powerpc/ppc-fpconv-6.c: Ditto. * gcc.target/powerpc/ppc-fpconv-7.c: Ditto. * gcc.target/powerpc/ppc-fpconv-8.c: Ditto. * gcc.target/powerpc/ppc-fpconv-9.c: Ditto. Index: gcc/config/rs6000/vsx.md =================================================================== --- gcc/config/rs6000/vsx.md (revision 163480) +++ gcc/config/rs6000/vsx.md (working copy) @@ -1,5 +1,5 @@ ;; VSX patterns. -;; Copyright (C) 2009 +;; Copyright (C) 2009, 2010 ;; Free Software Foundation, Inc. ;; Contributed by Michael Meissner @@ -73,11 +73,11 @@ (define_mode_attr VSr [(V16QI "v") ;; Map the register class used for float<->int conversions (define_mode_attr VSr2 [(V2DF "wd") (V4SF "wf") - (DF "!f#r")]) + (DF "ws")]) (define_mode_attr VSr3 [(V2DF "wa") (V4SF "wa") - (DF "!f#r")]) + (DF "ws")]) ;; Map the register class for sp<->dp float conversions, destination (define_mode_attr VSr4 [(SF "ws") Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 163480) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -6435,30 +6435,6 @@ (define_insn "*fselsfdf4" ;; Conversions to and from floating-point. -(define_expand "fixuns_truncsfsi2" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (unsigned_fix:SI (match_operand:SF 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT" - "") - -(define_expand "fix_truncsfsi2" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (fix:SI (match_operand:SF 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && !TARGET_FPRS && TARGET_SINGLE_FLOAT" - "") - -(define_expand "fixuns_truncdfsi2" - [(set (match_operand:SI 0 "gpc_reg_operand" "") - (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE" - "") - -(define_expand "fixuns_truncdfdi2" - [(set (match_operand:DI 0 "register_operand" "") - (unsigned_fix:DI (match_operand:DF 1 "register_operand" "")))] - "TARGET_HARD_FLOAT && TARGET_VSX" - "") - ; We don't define lfiwax/lfiwzx with the normal definition, because we ; don't want to support putting SImode in FPR registers. (define_insn "lfiwax" @@ -6793,46 +6769,85 @@ (define_insn_and_split "*floatunssidf2_i }" [(set_attr "length" "20")]) -(define_expand "fix_truncdfsi2" - [(parallel [(set (match_operand:SI 0 "fix_trunc_dest_operand" "") - (fix:SI (match_operand:DF 1 "gpc_reg_operand" ""))) - (clobber (match_dup 2)) - (clobber (match_dup 3))])] - "(TARGET_POWER2 || TARGET_POWERPC) - && TARGET_HARD_FLOAT && ((TARGET_FPRS && TARGET_DOUBLE_FLOAT) || TARGET_E500_DOUBLE)" +(define_expand "fix_truncsi2" + [(set (match_operand:SI 0 "gpc_reg_operand" "") + (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))] + "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT + && ((TARGET_FPRS && ) || )" " { - if (TARGET_E500_DOUBLE) + if (!) { - emit_insn (gen_spe_fix_truncdfsi2 (operands[0], operands[1])); - DONE; - } - operands[2] = gen_reg_rtx (DImode); - if (TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS - && gpc_reg_operand(operands[0], GET_MODE (operands[0]))) - { - operands[3] = gen_reg_rtx (DImode); - emit_insn (gen_fix_truncdfsi2_mfpgpr (operands[0], operands[1], - operands[2], operands[3])); + rtx tmp, stack; + + if (TARGET_STFIWX) + { + tmp = gen_reg_rtx (DImode); + stack = rs6000_allocate_stack_temp (SImode, false, true); + emit_insn (gen_fix_truncsi2_stfiwx (operands[0], operands[1], + tmp, stack)); + } + else + { + tmp = gen_reg_rtx (DImode); + stack = rs6000_allocate_stack_temp (DImode, true, false); + emit_insn (gen_fix_truncsi2_internal (operands[0], operands[1], + tmp, stack)); + } DONE; } - if (TARGET_PPC_GFXOPT) +}") + +(define_insn_and_split "fix_truncsi2_stfiwx" + [(set (match_operand:SI 0 "gpc_reg_operand" "=r") + (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" ""))) + (clobber (match_operand:DI 2 "gpc_reg_operand" "=d")) + (clobber (match_operand:SI 3 "indexed_or_indirect_operand" "=Z"))] + "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT + && (mode != SFmode || TARGET_SINGLE_FLOAT) + && TARGET_STFIWX" + "#" + "&& reload_completed" + [(pc)] + " +{ + emit_insn (gen_fctiwz_ (operands[2], operands[1])); + if (TARGET_MFPGPR && TARGET_POWERPC64 && REG_P (operands[0]) + && INT_REGNO_P (REGNO (operands[0]))) { - rtx orig_dest = operands[0]; - if (! memory_operand (orig_dest, GET_MODE (orig_dest))) - operands[0] = assign_stack_temp (SImode, GET_MODE_SIZE (SImode), 0); - emit_insn (gen_fix_truncdfsi2_internal_gfxopt (operands[0], operands[1], - operands[2])); - if (operands[0] != orig_dest) - emit_move_insn (orig_dest, operands[0]); - DONE; + rtx reg = gen_lowpart (DImode, operands[0]); + emit_move_insn (reg, operands[2]); } - operands[3] = assign_stack_temp (DImode, GET_MODE_SIZE (DImode), 0); -}") + else + { + emit_insn (gen_stfiwx (operands[3], operands[2])); + emit_move_insn (operands[0], operands[3]); + } + DONE; +}" + [(set_attr "length" "12")]) + +(define_insn_and_split "*fix_truncsi2_mem" + [(set (match_operand:SI 0 "memory_operand" "=Z") + (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" ""))) + (clobber (match_scratch:DI 2 "=d"))] + "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT + && (mode != SFmode || TARGET_SINGLE_FLOAT) + && TARGET_STFIWX" + "#" + "&& reload_completed" + [(pc)] + " +{ + emit_insn (gen_fctiwz_ (operands[2], operands[1])); + emit_insn (gen_stfiwx (operands[0], operands[2])); + DONE; +}" + [(set_attr "length" "8")]) -(define_insn_and_split "*fix_truncdfsi2_internal" +(define_insn_and_split "fix_truncsi2_internal" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (fix:SI (match_operand:DF 1 "gpc_reg_operand" "d"))) + (fix:SI (match_operand:SFDF 1 "gpc_reg_operand" ""))) (clobber (match_operand:DI 2 "gpc_reg_operand" "=d")) (clobber (match_operand:DI 3 "offsettable_mem_operand" "=o"))] "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS @@ -6846,143 +6861,194 @@ (define_insn_and_split "*fix_truncdfsi2_ gcc_assert (MEM_P (operands[3])); lowword = adjust_address (operands[3], SImode, WORDS_BIG_ENDIAN ? 4 : 0); - emit_insn (gen_fctiwz (operands[2], operands[1])); + emit_insn (gen_fctiwz_ (operands[2], operands[1])); emit_move_insn (operands[3], operands[2]); emit_move_insn (operands[0], lowword); DONE; }" [(set_attr "length" "16")]) -(define_insn_and_split "fix_truncdfsi2_internal_gfxopt" +(define_expand "fix_truncdi2" + [(set (match_operand:DI 0 "gpc_reg_operand" "") + (fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "")))] + "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS + && TARGET_FCFID" + "") + +(define_insn "*fix_truncdi2_fctidz" + [(set (match_operand:DI 0 "gpc_reg_operand" "=d") + (fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "d")))] + "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS + && TARGET_FCFID && !VECTOR_UNIT_VSX_P (mode)" + "fctidz %0,%1" + [(set_attr "type" "fp")]) + +(define_expand "fixuns_truncsi2" + [(set (match_operand:SI 0 "gpc_reg_operand" "") + (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "")))] + "TARGET_HARD_FLOAT + && ((TARGET_FPRS && && TARGET_FCTIWUZ && TARGET_STFIWX) + || )" + " +{ + if (!) + { + rtx tmp = gen_reg_rtx (DImode); + rtx stack = rs6000_allocate_stack_temp (SImode, false, true); + emit_insn (gen_fixuns_truncsi2_stfiwx (operands[0], operands[1], + tmp, stack)); + DONE; + } +}") + +(define_insn_and_split "fixuns_truncsi2_stfiwx" + [(set (match_operand:SI 0 "gpc_reg_operand" "=r") + (unsigned_fix:SI + (match_operand:SFDF 1 "gpc_reg_operand" ""))) + (clobber (match_operand:DI 2 "gpc_reg_operand" "=d")) + (clobber (match_operand:SI 3 "indexed_or_indirect_operand" "=Z"))] + "TARGET_HARD_FLOAT && TARGET_FPRS && && TARGET_FCTIWUZ + && TARGET_STFIWX" + "#" + "&& reload_completed" + [(pc)] + " +{ + emit_insn (gen_fctiwuz_ (operands[2], operands[1])); + if (TARGET_MFPGPR && TARGET_POWERPC64 && REG_P (operands[0]) + && INT_REGNO_P (REGNO (operands[0]))) + { + rtx reg = gen_lowpart (DImode, operands[0]); + emit_move_insn (reg, operands[2]); + } + else + { + emit_insn (gen_stfiwx (operands[3], operands[2])); + emit_move_insn (operands[0], operands[3]); + } + DONE; +}" + [(set_attr "length" "12")]) + +(define_insn_and_split "*fixuns_truncsi2_mem" [(set (match_operand:SI 0 "memory_operand" "=Z") - (fix:SI (match_operand:DF 1 "gpc_reg_operand" "d"))) - (clobber (match_operand:DI 2 "gpc_reg_operand" "=d"))] - "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS - && TARGET_DOUBLE_FLOAT - && TARGET_PPC_GFXOPT" + (unsigned_fix:SI (match_operand:SFDF 1 "gpc_reg_operand" ""))) + (clobber (match_scratch:DI 2 "=d"))] + "TARGET_HARD_FLOAT && TARGET_FPRS && && TARGET_FCTIWUZ + && TARGET_STFIWX" "#" - "&& 1" + "&& reload_completed" [(pc)] " { - emit_insn (gen_fctiwz (operands[2], operands[1])); + emit_insn (gen_fctiwuz_ (operands[2], operands[1])); emit_insn (gen_stfiwx (operands[0], operands[2])); DONE; }" - [(set_attr "length" "16")]) + [(set_attr "length" "8")]) -(define_insn_and_split "fix_truncdfsi2_mfpgpr" - [(set (match_operand:SI 0 "gpc_reg_operand" "=r") - (fix:SI (match_operand:DF 1 "gpc_reg_operand" "d"))) - (clobber (match_operand:DI 2 "gpc_reg_operand" "=d")) - (clobber (match_operand:DI 3 "gpc_reg_operand" "=r"))] - "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS - && TARGET_DOUBLE_FLOAT" - "#" - "&& 1" - [(set (match_dup 2) (unspec:DI [(fix:SI (match_dup 1))] UNSPEC_FCTIWZ)) - (set (match_dup 3) (match_dup 2)) - (set (match_dup 0) (subreg:SI (match_dup 3) 4))] - "" - [(set_attr "length" "12")]) +(define_expand "fixuns_truncdi2" + [(set (match_operand:DI 0 "register_operand" "") + (unsigned_fix:DI (match_operand:SFDF 1 "register_operand" "")))] + "TARGET_HARD_FLOAT && (TARGET_FCTIDUZ || VECTOR_UNIT_VSX_P (mode))" + "") + +(define_insn "*fixuns_truncdi2_fctiduz" + [(set (match_operand:DI 0 "gpc_reg_operand" "=d") + (unsigned_fix:DI (match_operand:SFDF 1 "gpc_reg_operand" "d")))] + "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_FPRS + && TARGET_FCTIDUZ && !VECTOR_UNIT_VSX_P (mode)" + "fctiduz %0,%1" + [(set_attr "type" "fp")]) ; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ)) ; rather than (set (subreg:SI (reg)) (fix:SI ...)) ; because the first makes it clear that operand 0 is not live ; before the instruction. -(define_insn "fctiwz" +(define_insn "fctiwz_" [(set (match_operand:DI 0 "gpc_reg_operand" "=d") - (unspec:DI [(fix:SI (match_operand:DF 1 "gpc_reg_operand" "d"))] + (unspec:DI [(fix:SI (match_operand:SFDF 1 "gpc_reg_operand" "d"))] UNSPEC_FCTIWZ))] "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" "{fcirz|fctiwz} %0,%1" [(set_attr "type" "fp")]) -(define_expand "btruncdf2" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIZ))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" - "") - -(define_insn "*btruncdf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=f") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && !VECTOR_UNIT_VSX_P (DFmode)" - "friz %0,%1" +(define_insn "fctiwuz_" + [(set (match_operand:DI 0 "gpc_reg_operand" "=d") + (unspec:DI [(unsigned_fix:SI + (match_operand:SFDF 1 "gpc_reg_operand" ""))] + UNSPEC_FCTIWUZ))] + "TARGET_HARD_FLOAT && TARGET_FPRS && && TARGET_FCTIWUZ" + "fctiwuz %0,%1" [(set_attr "type" "fp")]) -(define_insn "btruncsf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT" - "friz %0,%1" +;; No VSX equivalent to fctid +(define_insn "lrintdi2" + [(set (match_operand:DI 0 "gpc_reg_operand" "=d") + (unspec:DI [(match_operand:SFDF 1 "gpc_reg_operand" "")] + UNSPEC_FCTID))] + "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && " + "fctid %0,%1" [(set_attr "type" "fp")]) -(define_expand "ceildf2" - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "")] UNSPEC_FRIP))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" +(define_expand "btrunc2" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "") + (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")] + UNSPEC_FRIZ))] + "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && " "") -(define_insn "*ceildf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIP))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && !VECTOR_UNIT_VSX_P (DFmode)" - "frip %0,%1" +(define_insn "*btrunc2_fpr" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=") + (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")] + UNSPEC_FRIZ))] + "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && + && !VECTOR_UNIT_VSX_P (mode)" + "friz %0,%1" [(set_attr "type" "fp")]) -(define_insn "ceilsf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIP))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT " +(define_expand "ceil2" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "") + (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")] + UNSPEC_FRIP))] + "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && " + "") + +(define_insn "*ceil2_fpr" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=") + (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")] + UNSPEC_FRIP))] + "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && + && !VECTOR_UNIT_VSX_P (mode)" "frip %0,%1" [(set_attr "type" "fp")]) -(define_expand "floordf2" - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "")] UNSPEC_FRIM))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" +(define_expand "floor2" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "") + (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")] + UNSPEC_FRIM))] + "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && " "") -(define_insn "*floordf2_fpr" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIM))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT - && !VECTOR_UNIT_VSX_P (DFmode)" - "frim %0,%1" - [(set_attr "type" "fp")]) - -(define_insn "floorsf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIM))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT " +(define_insn "*floor2_fpr" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=") + (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")] + UNSPEC_FRIM))] + "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && + && !VECTOR_UNIT_VSX_P (mode)" "frim %0,%1" [(set_attr "type" "fp")]) ;; No VSX equivalent to frin -(define_insn "rounddf2" - [(set (match_operand:DF 0 "gpc_reg_operand" "=d") - (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "d")] UNSPEC_FRIN))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT" - "frin %0,%1" - [(set_attr "type" "fp")]) - -(define_insn "roundsf2" - [(set (match_operand:SF 0 "gpc_reg_operand" "=f") - (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIN))] - "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT " +(define_insn "round2" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=") + (unspec:SFDF [(match_operand:SFDF 1 "gpc_reg_operand" "")] + UNSPEC_FRIN))] + "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS && " "frin %0,%1" [(set_attr "type" "fp")]) -(define_expand "ftruncdf2" - [(set (match_operand:DF 0 "gpc_reg_operand" "") - (fix:DF (match_operand:DF 1 "gpc_reg_operand" "")))] - "VECTOR_UNIT_VSX_P (DFmode)" - "") - ; An UNSPEC is used so we don't have to support SImode in FP registers. (define_insn "stfiwx" [(set (match_operand:SI 0 "memory_operand" "=Z") @@ -9860,7 +9926,7 @@ (define_insn_and_split "*fix_trunctfsi2_ gcc_assert (MEM_P (operands[5])); lowword = adjust_address (operands[5], SImode, WORDS_BIG_ENDIAN ? 4 : 0); - emit_insn (gen_fctiwz (operands[4], operands[2])); + emit_insn (gen_fctiwz_df (operands[4], operands[2])); emit_move_insn (operands[5], operands[4]); emit_move_insn (operands[0], lowword); DONE; Index: gcc/testsuite/gcc.target/powerpc/ppc-fpconv-7.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/ppc-fpconv-7.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/ppc-fpconv-7.c (revision 0) @@ -0,0 +1,22 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O3 -mcpu=power5 -ffast-math" } */ +/* { dg-final { scan-assembler-times "fctiwz" 2 } } */ +/* { dg-final { scan-assembler-not "fctiwuz" } } */ +/* { dg-final { scan-assembler-times "fctidz" 8 } } */ +/* { dg-final { scan-assembler-not "fctiduz" } } */ +/* { dg-final { scan-assembler-not "xscvdpsxds" } } */ +/* { dg-final { scan-assembler-not "xscvdpuxds" } } */ + +void float_to_int (int *dest, float src) { *dest = (int) src; } +void double_to_int (int *dest, double src) { *dest = (int) src; } + +void float_to_uint (int *dest, float src) { *dest = (unsigned int) src; } +void double_to_uint (int *dest, double src) { *dest = (unsigned int) src; } + +void float_to_llong (long long *dest, float src) { *dest = (long long) src; } +void double_to_llong (long long *dest, double src) { *dest = (long long) src; } + +void float_to_ullong (unsigned long long *dest, float src) { *dest = (unsigned long long) src; } +void double_to_ullong (unsigned long long *dest, double src) { *dest = (unsigned long long) src; } Index: gcc/testsuite/gcc.target/powerpc/ppc-fpconv-8.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/ppc-fpconv-8.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/ppc-fpconv-8.c (revision 0) @@ -0,0 +1,22 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O3 -mcpu=750 -ffast-math" } */ +/* { dg-final { scan-assembler-times "fctiwz" 6 } } */ +/* { dg-final { scan-assembler-not "fctiwuz" } } */ +/* { dg-final { scan-assembler-not "fctidz" } } */ +/* { dg-final { scan-assembler-not "fctiduz" } } */ +/* { dg-final { scan-assembler-not "xscvdpsxds" } } */ +/* { dg-final { scan-assembler-not "xscvdpuxds" } } */ + +void float_to_int (int *dest, float src) { *dest = (int) src; } +void double_to_int (int *dest, double src) { *dest = (int) src; } + +void float_to_uint (int *dest, float src) { *dest = (unsigned int) src; } +void double_to_uint (int *dest, double src) { *dest = (unsigned int) src; } + +void float_to_llong (long long *dest, float src) { *dest = (long long) src; } +void double_to_llong (long long *dest, double src) { *dest = (long long) src; } + +void float_to_ullong (unsigned long long *dest, float src) { *dest = (unsigned long long) src; } +void double_to_ullong (unsigned long long *dest, double src) { *dest = (unsigned long long) src; } Index: gcc/testsuite/gcc.target/powerpc/ppc-fpconv-9.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/ppc-fpconv-9.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/ppc-fpconv-9.c (revision 0) @@ -0,0 +1,11 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-options "-O3 -mcpu=power7 -ffast-math" } */ +/* { dg-final { scan-assembler-not "lwz" } } */ +/* { dg-final { scan-assembler-not "stw" } } */ +/* { dg-final { scan-assembler-not "ld " } } */ +/* { dg-final { scan-assembler-not "std" } } */ + +void float_to_llong (long long *dest, float src) { *dest = (long long) src; } +void double_to_llong (long long *dest, double src) { *dest = (long long) src; } Index: gcc/testsuite/gcc.target/powerpc/ppc-fpconv-5.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/ppc-fpconv-5.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/ppc-fpconv-5.c (revision 0) @@ -0,0 +1,22 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-options "-O3 -mcpu=power7 -ffast-math" } */ +/* { dg-final { scan-assembler-times "fctiwz" 2 } } */ +/* { dg-final { scan-assembler-times "fctiwuz" 2 } } */ +/* { dg-final { scan-assembler-times "fctidz" 1 } } */ +/* { dg-final { scan-assembler-times "fctiduz" 1 } } */ +/* { dg-final { scan-assembler-times "xscvdpsxds" 1 } } */ +/* { dg-final { scan-assembler-times "xscvdpuxds" 1 } } */ + +void float_to_int (int *dest, float src) { *dest = (int) src; } +void double_to_int (int *dest, double src) { *dest = (int) src; } + +void float_to_uint (int *dest, float src) { *dest = (unsigned int) src; } +void double_to_uint (int *dest, double src) { *dest = (unsigned int) src; } + +void float_to_llong (long long *dest, float src) { *dest = (long long) src; } +void double_to_llong (long long *dest, double src) { *dest = (long long) src; } + +void float_to_ullong (unsigned long long *dest, float src) { *dest = (unsigned long long) src; } +void double_to_ullong (unsigned long long *dest, double src) { *dest = (unsigned long long) src; } Index: gcc/testsuite/gcc.target/powerpc/ppc-fpconv-6.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/ppc-fpconv-6.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/ppc-fpconv-6.c (revision 0) @@ -0,0 +1,22 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_vsx_ok } */ +/* { dg-options "-O3 -mcpu=power6 -ffast-math" } */ +/* { dg-final { scan-assembler-times "fctiwz" 2 } } */ +/* { dg-final { scan-assembler-not "fctiwuz" } } */ +/* { dg-final { scan-assembler-times "fctidz" 8 } } */ +/* { dg-final { scan-assembler-not "fctiduz" } } */ +/* { dg-final { scan-assembler-not "xscvdpsxds" } } */ +/* { dg-final { scan-assembler-not "xscvdpuxds" } } */ + +void float_to_int (int *dest, float src) { *dest = (int) src; } +void double_to_int (int *dest, double src) { *dest = (int) src; } + +void float_to_uint (int *dest, float src) { *dest = (unsigned int) src; } +void double_to_uint (int *dest, double src) { *dest = (unsigned int) src; } + +void float_to_llong (long long *dest, float src) { *dest = (long long) src; } +void double_to_llong (long long *dest, double src) { *dest = (long long) src; } + +void float_to_ullong (unsigned long long *dest, float src) { *dest = (unsigned long long) src; } +void double_to_ullong (unsigned long long *dest, double src) { *dest = (unsigned long long) src; }