From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 80640 invoked by alias); 25 Aug 2015 23:21:08 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 80630 invoked by uid 89); 25 Aug 2015 23:21:07 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.5 required=5.0 tests=AWL,BAYES_00,KAM_ASCII_DIVIDERS,KAM_LAZY_DOMAIN_SECURITY autolearn=no version=3.3.2 X-HELO: e38.co.us.ibm.com Received: from e38.co.us.ibm.com (HELO e38.co.us.ibm.com) (32.97.110.159) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Tue, 25 Aug 2015 23:21:05 +0000 Received: from /spool/local by e38.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 25 Aug 2015 17:21:03 -0600 Received: from d03dlp03.boulder.ibm.com (9.17.202.179) by e38.co.us.ibm.com (192.168.1.138) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 25 Aug 2015 17:21:01 -0600 X-MailFrom: meissner@ibm-tiger.the-meissners.org X-RcptTo: gcc-patches@gcc.gnu.org Received: from b03cxnp08025.gho.boulder.ibm.com (b03cxnp08025.gho.boulder.ibm.com [9.17.130.17]) by d03dlp03.boulder.ibm.com (Postfix) with ESMTP id C30A719D803F for ; Tue, 25 Aug 2015 17:11:56 -0600 (MDT) Received: from d03av04.boulder.ibm.com (d03av04.boulder.ibm.com [9.17.195.170]) by b03cxnp08025.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t7PNJxgH57671772 for ; Tue, 25 Aug 2015 16:19:59 -0700 Received: from d03av04.boulder.ibm.com (loopback [127.0.0.1]) by d03av04.boulder.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t7PNL0bt028368 for ; Tue, 25 Aug 2015 17:21:00 -0600 Received: from ibm-tiger.the-meissners.org (dhcp-9-32-77-111.usma.ibm.com [9.32.77.111]) by d03av04.boulder.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t7PNKxGC028357; Tue, 25 Aug 2015 17:21:00 -0600 Received: by ibm-tiger.the-meissners.org (Postfix, from userid 500) id 68A7E439CA; Tue, 25 Aug 2015 19:20:59 -0400 (EDT) Date: Tue, 25 Aug 2015 23:33:00 -0000 From: Michael Meissner To: Segher Boessenkool Cc: Michael Meissner , gcc-patches@gcc.gnu.org, dje.gcc@gmail.com Subject: Re: [PATCH], PowerPC IEEE 128-bit patch #5 Message-ID: <20150825232058.GA28175@ibm-tiger.the-meissners.org> Mail-Followup-To: Michael Meissner , Segher Boessenkool , gcc-patches@gcc.gnu.org, dje.gcc@gmail.com References: <20150729200428.GA30347@ibm-tiger.the-meissners.org> <20150814154603.GA20847@ibm-tiger.the-meissners.org> <20150819124124.GB8652@gate.crashing.org> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="VS++wcV0S1rZb1Fb" Content-Disposition: inline In-Reply-To: <20150819124124.GB8652@gate.crashing.org> User-Agent: Mutt/1.5.20 (2009-12-10) X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15082523-0029-0000-0000-00000C2E9FF5 X-IsSubscribed: yes X-SW-Source: 2015-08/txt/msg01569.txt.bz2 --VS++wcV0S1rZb1Fb Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 4444 On Wed, Aug 19, 2015 at 07:41:24AM -0500, Segher Boessenkool wrote: > On Fri, Aug 14, 2015 at 11:46:03AM -0400, Michael Meissner wrote: > > +;; Like int_reg_operand, but don't return true for pseudo registers > > +(define_predicate "int_reg_operand_not_pseudo" > > + (match_operand 0 "register_operand") > > +{ > > + if ((TARGET_E500_DOUBLE || TARGET_SPE) && invalid_e500_subreg (op, mode)) > > + return 0; > > + > > + if (GET_CODE (op) == SUBREG) > > + op = SUBREG_REG (op); > > + > > + if (!REG_P (op)) > > + return 0; > > + > > + if (REGNO (op) >= FIRST_PSEUDO_REGISTER) > > + return 0; > > + > > + return INT_REGNO_P (REGNO (op)); > > +}) > > Since you use this only once, maybe it is easier (to read, etc.) if you > just test it there? Hard regs do not get subregs. I was worried about hard regs appearing before reload, and possibly being subregs, so I'll remove the SUBREG test. > > +(define_insn_and_split "ieee_128bit_vsx_neg2" > > + [(set (match_operand:TFIFKF 0 "register_operand" "=wa") > > + (neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa"))) > > + (clobber (match_scratch:V16QI 2 "=v"))] > > + "TARGET_FLOAT128 && FLOAT128_IEEE_P (mode)" > > + "#" > > + "&& 1" > > + [(parallel [(set (match_dup 0) > > + (neg:TFIFKF (match_dup 1))) > > + (use (match_dup 2))])] > > +{ > > + if (GET_CODE (operands[2]) == SCRATCH) > > + operands[2] = gen_reg_rtx (V16QImode); > > + > > + operands[3] = gen_reg_rtx (V16QImode); > > + emit_insn (gen_ieee_128bit_negative_zero (operands[2])); > > +} > > + [(set_attr "length" "8") > > + (set_attr "type" "vecsimple")]) > > Where is operands[3] used? I guess that whole line should be deleted? Good catch. It was from the earlier patch before the fix for PR 67071, which added better support for vector constants that can be constructed with several vector operations, including a vector octet shift. > > +(define_insn "*ieee_128bit_vsx_neg2_internal" > > + [(set (match_operand:TFIFKF 0 "register_operand" "=wa") > > + (neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa"))) > > + (use (match_operand:V16QI 2 "register_operand" "=v"))] > > + "TARGET_FLOAT128" > > + "xxlxor %x0,%x1,%x2" > > + [(set_attr "length" "4") > > + (set_attr "type" "vecsimple")]) > > Length 4 is default, you can just leave it out (like we do for most > machine insns already). Ok, though I tend to always put them in. Here is the revised patch. Is it ok to install? 2015-08-25 Michael Meissner * config/rs6000/predicates.md (int_reg_operand_not_pseudo): New predicate for only GPR hard registers. * config/rs6000/rs6000.md (FP): Add IEEE 128-bit floating point modes to iterators. Add new iterators for moving 128-bit values in scalar FPR registers and VSX registers. (FMOVE128): Likewise. (FMOVE128_FPR): Likewise. (FMOVE128_GPR): Likewise. (FMOVE128_VSX): Likewise. (FLOAT128_SFDFTF): New iterators for IEEE 128-bit floating point in VSX registers. (IFKF): Likewise. (IBM128): Likewise. (TFIFKF): Likewise. (RELOAD): Add IEEE 128-bit floating point modes. (signbittf2): Convert TF insns to add support for new IEEE 128-bit floating point in VSX registers modes. (signbit2, IBM128 iterator): Likewise. (mov_64bit_dm, FMOVE128_FPR iterator): Likewise. (mov_32bit, FMOVE128_FPR iterator): Likewise. (negtf2): Likewise. (neg2, TFIFKF iterator): Likewise. (negtf2_internal): Likewise. (abstf2): Likewise. (abs2, TFIFKF iterator): Likewise. (ieee_128bit_negative_zero): New IEEE 128-bit floating point in VSX insn support for negate, absolute value, and negative absolute value. (ieee_128bit_vsx_neg2): Likewise. (ieee_128bit_vsx_neg2_internal): Likewise. (ieee_128bit_vsx_abs2): Likewise. (ieee_128bit_vsx_abs2_internal): Likewise. (ieee_128bit_vsx_nabs2): Likewise. (ieee_128bit_vsx_nabs2_internal): Likewise. (FP128_64): Update pack/unpack 128-bit insns for IEEE 128-bit floating point in VSX registers. (unpack_dm): Likewise. (unpack_nodm): Likewise. (pack): Likewise. (unpackv1ti): Likewise. (unpack, FMOVE128_VSX iterator): Likewise. (packv1ti): Likewise. (pack, FMOVE128_VSX iterator): Likewise. -- Michael Meissner, IBM IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797 --VS++wcV0S1rZb1Fb Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=ieee128-patch05d Content-length: 16181 Index: gcc/config/rs6000/predicates.md =================================================================== --- gcc/config/rs6000/predicates.md (revision 227180) +++ gcc/config/rs6000/predicates.md (working copy) @@ -239,6 +239,25 @@ (define_predicate "int_reg_operand" return INT_REGNO_P (REGNO (op)); }) +;; Like int_reg_operand, but don't return true for pseudo registers +(define_predicate "int_reg_operand_not_pseudo" + (match_operand 0 "register_operand") +{ + if ((TARGET_E500_DOUBLE || TARGET_SPE) && invalid_e500_subreg (op, mode)) + return 0; + + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + if (!REG_P (op)) + return 0; + + if (REGNO (op) >= FIRST_PSEUDO_REGISTER) + return 0; + + return INT_REGNO_P (REGNO (op)); +}) + ;; Like int_reg_operand, but only return true for base registers (define_predicate "base_reg_operand" (match_operand 0 "int_reg_operand") Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 227180) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -348,6 +348,8 @@ (define_mode_iterator FP [ && TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128") + (IF "TARGET_FLOAT128") + (KF "TARGET_FLOAT128") (DD "TARGET_DFP") (TD "TARGET_DFP")]) @@ -365,9 +367,14 @@ (define_mode_iterator FMA_F [ (define_mode_iterator FMOVE32 [SF SD]) (define_mode_iterator FMOVE64 [DF DD]) (define_mode_iterator FMOVE64X [DI DF DD]) -(define_mode_iterator FMOVE128 [(TF "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128") +(define_mode_iterator FMOVE128 [(TF "TARGET_LONG_DOUBLE_128") + (IF "TARGET_LONG_DOUBLE_128") (TD "TARGET_HARD_FLOAT && TARGET_FPRS")]) +(define_mode_iterator FMOVE128_FPR [(TF "FLOAT128_2REG_P (TFmode)") + (IF "FLOAT128_2REG_P (IFmode)") + (TD "TARGET_HARD_FLOAT && TARGET_FPRS")]) + ; Iterators for 128 bit types for direct move (define_mode_iterator FMOVE128_GPR [(TI "TARGET_VSX_TIMODE") (V16QI "") @@ -376,7 +383,13 @@ (define_mode_iterator FMOVE128_GPR [(TI (V4SF "") (V2DI "") (V2DF "") - (V1TI "")]) + (V1TI "") + (KF "") + (TF "") + (IF "")]) + +; Iterator for 128-bit VSX types for pack/unpack +(define_mode_iterator FMOVE128_VSX [V1TI KF]) ; Whether a floating point move is ok, don't allow SD without hardware FP (define_mode_attr fmove_ok [(SF "") @@ -432,6 +445,25 @@ (define_mode_iterator RECIPF [SF DF V4SF ; Iterator for just SF/DF (define_mode_iterator SFDF [SF DF]) +; Iterator for float128 floating conversions +(define_mode_iterator FLOAT128_SFDFTF [ + (SF "TARGET_FLOAT128") + (DF "TARGET_FLOAT128") + (TF "FLOAT128_IBM_P (TFmode)") + (IF "TARGET_FLOAT128")]) + +; Iterator for special 128-bit floating point. This is for non-default +; conversions, so TFmode is not used here. +(define_mode_iterator IFKF [IF KF]) + +; Iterator for 128-bit floating point that uses the IBM double-double format +(define_mode_iterator IBM128 [IF TF]) + +; Iterator for 128-bit floating point +(define_mode_iterator TFIFKF [(KF "TARGET_FLOAT128") + (IF "TARGET_FLOAT128") + (TF "TARGET_LONG_DOUBLE_128")]) + ; SF/DF suffix for traditional floating instructions (define_mode_attr Ftrad [(SF "s") (DF "")]) @@ -596,7 +628,7 @@ (define_mode_attr BOOL_REGS_UNARY [(TI " ;; Reload iterator for creating the function to allocate a base register to ;; supplement addressing modes. (define_mode_iterator RELOAD [V16QI V8HI V4SI V2DI V4SF V2DF V1TI - SF SD SI DF DD DI TI PTI]) + SF SD SI DF DD DI TI PTI KF IF TF]) ;; Start with fixed-point load and store insns. Here we put only the more @@ -4216,19 +4248,18 @@ (define_insn "*truncdfsf2_fpr" ;; This expander is here to avoid FLOAT_WORDS_BIGENDIAN tests in ;; builtins.c and optabs.c that are not correct for IBM long double ;; when little-endian. -(define_expand "signbittf2" +(define_expand "signbit2" [(set (match_dup 2) - (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" ""))) + (float_truncate:DF (match_operand:IBM128 1 "gpc_reg_operand" ""))) (set (match_dup 3) (subreg:DI (match_dup 2) 0)) (set (match_dup 4) (match_dup 5)) (set (match_operand:SI 0 "gpc_reg_operand" "") (match_dup 6))] - "!TARGET_IEEEQUAD + "FLOAT128_IBM_P (mode) && TARGET_HARD_FLOAT - && (TARGET_FPRS || TARGET_E500_DOUBLE) - && TARGET_LONG_DOUBLE_128" + && (TARGET_FPRS || TARGET_E500_DOUBLE)" { operands[2] = gen_reg_rtx (DFmode); operands[3] = gen_reg_rtx (DImode); @@ -6402,9 +6433,10 @@ (define_expand "mov" ;; problematical. Don't allow direct move for this case. (define_insn_and_split "*mov_64bit_dm" - [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r,r,wm") - (match_operand:FMOVE128 1 "input_operand" "d,m,d,j,r,jY,r,wm,r"))] + [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r,r,wm") + (match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,j,r,jY,r,wm,r"))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64 + && FLOAT128_2REG_P (mode) && (mode != TDmode || WORDS_BIG_ENDIAN) && (gpc_reg_operand (operands[0], mode) || gpc_reg_operand (operands[1], mode))" @@ -6427,9 +6459,12 @@ (define_insn_and_split "*movtd_64bit_nod [(set_attr "length" "8,8,8,8,12,12,8")]) (define_insn_and_split "*mov_32bit" - [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r") - (match_operand:FMOVE128 1 "input_operand" "d,m,d,j,r,jY,r"))] + [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r") + (match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,j,r,jY,r"))] "TARGET_HARD_FLOAT && TARGET_FPRS && !TARGET_POWERPC64 + && (FLOAT128_2REG_P (mode) + || int_reg_operand_not_pseudo (operands[0], mode) + || int_reg_operand_not_pseudo (operands[1], mode)) && (gpc_reg_operand (operands[0], mode) || gpc_reg_operand (operands[1], mode))" "#" @@ -6663,20 +6698,37 @@ (define_insn_and_split "*fix_trunctfsi2_ DONE; }) -(define_expand "negtf2" - [(set (match_operand:TF 0 "gpc_reg_operand" "") - (neg:TF (match_operand:TF 1 "gpc_reg_operand" "")))] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT - && (TARGET_FPRS || TARGET_E500_DOUBLE) - && TARGET_LONG_DOUBLE_128" - "") +(define_expand "neg2" + [(set (match_operand:TFIFKF 0 "gpc_reg_operand" "") + (neg:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))] + "FLOAT128_IEEE_P (mode) + || (FLOAT128_IBM_P (mode) + && TARGET_HARD_FLOAT + && (TARGET_FPRS || TARGET_E500_DOUBLE))" + " +{ + if (FLOAT128_IEEE_P (mode)) + { + if (TARGET_FLOAT128) + emit_insn (gen_ieee_128bit_vsx_neg2 (operands[0], operands[1])); + else + { + rtx libfunc = optab_libfunc (neg_optab, mode); + rtx target = emit_library_call_value (libfunc, operands[0], LCT_CONST, + mode, 1, + operands[1], mode); + + if (target && !rtx_equal_p (target, operands[0])) + emit_move_insn (operands[0], target); + } + DONE; + } +}") (define_insn "negtf2_internal" [(set (match_operand:TF 0 "gpc_reg_operand" "=d") (neg:TF (match_operand:TF 1 "gpc_reg_operand" "d")))] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128" + "TARGET_HARD_FLOAT && TARGET_FPRS && FLOAT128_IBM_P (TFmode)" "* { if (REGNO (operands[0]) == REGNO (operands[1]) + 1) @@ -6687,16 +6739,29 @@ (define_insn "negtf2_internal" [(set_attr "type" "fp") (set_attr "length" "8")]) -(define_expand "abstf2" - [(set (match_operand:TF 0 "gpc_reg_operand" "") - (abs:TF (match_operand:TF 1 "gpc_reg_operand" "")))] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT - && (TARGET_FPRS || TARGET_E500_DOUBLE) - && TARGET_LONG_DOUBLE_128" +(define_expand "abs2" + [(set (match_operand:TFIFKF 0 "gpc_reg_operand" "") + (abs:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))] + "FLOAT128_IEEE_P (mode) + || (FLOAT128_IBM_P (mode) + && TARGET_HARD_FLOAT + && (TARGET_FPRS || TARGET_E500_DOUBLE))" " { - rtx label = gen_label_rtx (); + rtx label; + + if (FLOAT128_IEEE_P (mode)) + { + if (TARGET_FLOAT128) + { + emit_insn (gen_ieee_128bit_vsx_abs2 (operands[0], operands[1])); + DONE; + } + else + FAIL; + } + + label = gen_label_rtx (); if (TARGET_E500_DOUBLE) { if (flag_finite_math_only && !flag_trapping_math) @@ -6732,6 +6797,126 @@ (define_expand "abstf2_internal" operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word); operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word); }") + + +;; Generate IEEE 128-bit -0.0 (0x80000000000000000000000000000000) in a vector +;; register + +(define_expand "ieee_128bit_negative_zero" + [(set (match_operand:V16QI 0 "register_operand" "") (match_dup 1))] + "TARGET_FLOAT128" +{ + rtvec v = rtvec_alloc (16); + int i, high; + + for (i = 0; i < 16; i++) + RTVEC_ELT (v, i) = const0_rtx; + + high = (BYTES_BIG_ENDIAN) ? 0 : 15; + RTVEC_ELT (v, high) = GEN_INT (0x80); + + rs6000_expand_vector_init (operands[0], gen_rtx_PARALLEL (V16QImode, v)); + DONE; +}) + +;; IEEE 128-bit negate + +;; We have 2 insns here for negate and absolute value. The first uses +;; match_scratch so that phases like combine can recognize neg/abs as generic +;; insns, and second insn after the first split pass loads up the bit to +;; twiddle the sign bit. Later GCSE passes can then combine multiple uses of +;; neg/abs to create the constant just once. + +(define_insn_and_split "ieee_128bit_vsx_neg2" + [(set (match_operand:TFIFKF 0 "register_operand" "=wa") + (neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa"))) + (clobber (match_scratch:V16QI 2 "=v"))] + "TARGET_FLOAT128 && FLOAT128_IEEE_P (mode)" + "#" + "&& 1" + [(parallel [(set (match_dup 0) + (neg:TFIFKF (match_dup 1))) + (use (match_dup 2))])] +{ + if (GET_CODE (operands[2]) == SCRATCH) + operands[2] = gen_reg_rtx (V16QImode); + + operands[3] = gen_reg_rtx (V16QImode); + emit_insn (gen_ieee_128bit_negative_zero (operands[2])); +} + [(set_attr "length" "8") + (set_attr "type" "vecsimple")]) + +(define_insn "*ieee_128bit_vsx_neg2_internal" + [(set (match_operand:TFIFKF 0 "register_operand" "=wa") + (neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa"))) + (use (match_operand:V16QI 2 "register_operand" "=v"))] + "TARGET_FLOAT128" + "xxlxor %x0,%x1,%x2" + [(set_attr "type" "vecsimple")]) + +;; IEEE 128-bit absolute value +(define_insn_and_split "ieee_128bit_vsx_abs2" + [(set (match_operand:TFIFKF 0 "register_operand" "=wa") + (abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa"))) + (clobber (match_scratch:V16QI 2 "=v"))] + "TARGET_FLOAT128 && FLOAT128_IEEE_P (mode)" + "#" + "&& 1" + [(parallel [(set (match_dup 0) + (abs:TFIFKF (match_dup 1))) + (use (match_dup 2))])] +{ + if (GET_CODE (operands[2]) == SCRATCH) + operands[2] = gen_reg_rtx (V16QImode); + + operands[3] = gen_reg_rtx (V16QImode); + emit_insn (gen_ieee_128bit_negative_zero (operands[2])); +} + [(set_attr "length" "8") + (set_attr "type" "vecsimple")]) + +(define_insn "*ieee_128bit_vsx_abs2_internal" + [(set (match_operand:TFIFKF 0 "register_operand" "=wa") + (abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa"))) + (use (match_operand:V16QI 2 "register_operand" "=v"))] + "TARGET_FLOAT128" + "xxlandc %x0,%x1,%x2" + [(set_attr "type" "vecsimple")]) + +;; IEEE 128-bit negative absolute value +(define_insn_and_split "*ieee_128bit_vsx_nabs2" + [(set (match_operand:TFIFKF 0 "register_operand" "=wa") + (neg:TFIFKF + (abs:TFIFKF + (match_operand:TFIFKF 1 "register_operand" "wa")))) + (clobber (match_scratch:V16QI 2 "=v"))] + "TARGET_FLOAT128 && FLOAT128_IEEE_P (mode)" + "#" + "&& 1" + [(parallel [(set (match_dup 0) + (abs:TFIFKF (match_dup 1))) + (use (match_dup 2))])] +{ + if (GET_CODE (operands[2]) == SCRATCH) + operands[2] = gen_reg_rtx (V16QImode); + + operands[3] = gen_reg_rtx (V16QImode); + emit_insn (gen_ieee_128bit_negative_zero (operands[2])); +} + [(set_attr "length" "8") + (set_attr "type" "vecsimple")]) + +(define_insn "*ieee_128bit_vsx_nabs2_internal" + [(set (match_operand:TFIFKF 0 "register_operand" "=wa") + (neg:TFIFKF + (abs:TFIFKF + (match_operand:TFIFKF 1 "register_operand" "wa")))) + (use (match_operand:V16QI 2 "register_operand" "=v"))] + "TARGET_FLOAT128" + "xxlor %x0,%x1,%x2" + [(set_attr "type" "vecsimple")]) + ;; Reload helper functions used by rs6000_secondary_reload. The patterns all ;; must have 3 arguments, and scratch register constraint must be a single @@ -12134,7 +12319,10 @@ (define_insn "div_" ;; Pack/unpack 128-bit floating point types that take 2 scalar registers ; Type of the 64-bit part when packing/unpacking 128-bit floating point types -(define_mode_attr FP128_64 [(TF "DF") (TD "DI")]) +(define_mode_attr FP128_64 [(TF "DF") + (IF "DF") + (TD "DI") + (KF "DI")]) (define_expand "unpack" [(set (match_operand: 0 "nonimmediate_operand" "") @@ -12142,7 +12330,7 @@ (define_expand "unpack" [(match_operand:FMOVE128 1 "register_operand" "") (match_operand:QI 2 "const_0_to_1_operand" "")] UNSPEC_UNPACK_128BIT))] - "" + "FLOAT128_2REG_P (mode)" "") (define_insn_and_split "unpack_dm" @@ -12151,7 +12339,7 @@ (define_insn_and_split "unpack_dm" [(match_operand:FMOVE128 1 "register_operand" "d,d,r,d,r") (match_operand:QI 2 "const_0_to_1_operand" "i,i,i,i,i")] UNSPEC_UNPACK_128BIT))] - "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE && FLOAT128_2REG_P (mode)" "#" "&& reload_completed" [(set (match_dup 0) (match_dup 3))] @@ -12175,7 +12363,7 @@ (define_insn_and_split "unpack_nod [(match_operand:FMOVE128 1 "register_operand" "d,d") (match_operand:QI 2 "const_0_to_1_operand" "i,i")] UNSPEC_UNPACK_128BIT))] - "!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE" + "(!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE) && FLOAT128_2REG_P (mode)" "#" "&& reload_completed" [(set (match_dup 0) (match_dup 3))] @@ -12199,7 +12387,7 @@ (define_insn_and_split "pack" [(match_operand: 1 "register_operand" "0,d") (match_operand: 2 "register_operand" "d,d")] UNSPEC_PACK_128BIT))] - "" + "FLOAT128_2REG_P (mode)" "@ fmr %L0,%2 #" @@ -12219,12 +12407,12 @@ (define_insn_and_split "pack" [(set_attr "type" "fp,fp") (set_attr "length" "4,8")]) -(define_insn "unpackv1ti" +(define_insn "unpack" [(set (match_operand:DI 0 "register_operand" "=d,d") - (unspec:DI [(match_operand:V1TI 1 "register_operand" "0,wa") + (unspec:DI [(match_operand:FMOVE128_VSX 1 "register_operand" "0,wa") (match_operand:QI 2 "const_0_to_1_operand" "O,i")] UNSPEC_UNPACK_128BIT))] - "TARGET_VSX" + "VECTOR_MEM_ALTIVEC_OR_VSX_P (mode)" { if (REGNO (operands[0]) == REGNO (operands[1]) && INTVAL (operands[2]) == 0) return ASM_COMMENT_START " xxpermdi to same register"; @@ -12232,19 +12420,17 @@ (define_insn "unpackv1ti" operands[3] = GEN_INT (INTVAL (operands[2]) == 0 ? 0 : 3); return "xxpermdi %x0,%x1,%x1,%3"; } - [(set_attr "type" "vecperm") - (set_attr "length" "4")]) + [(set_attr "type" "vecperm")]) -(define_insn "packv1ti" - [(set (match_operand:V1TI 0 "register_operand" "=wa") - (unspec:V1TI +(define_insn "pack" + [(set (match_operand:FMOVE128_VSX 0 "register_operand" "=wa") + (unspec:FMOVE128_VSX [(match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d")] UNSPEC_PACK_128BIT))] "TARGET_VSX" "xxpermdi %x0,%x1,%x2,0" - [(set_attr "type" "vecperm") - (set_attr "length" "4")]) + [(set_attr "type" "vecperm")]) --VS++wcV0S1rZb1Fb--