From patchwork Tue Jul 26 20:09:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Meissner X-Patchwork-Id: 652903 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 3rzTjl3wblz9t0X for ; Wed, 27 Jul 2016 06:09:30 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=Hy6xKt8L; 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:cc:subject:references:mime-version:content-type :in-reply-to:message-id; q=dns; s=default; b=QFEpqjKSlGWiLn96U2Y PsR5uvPeO7WF3JZfoPvpV+thOLK7/9VJg3rdVP9N0YqxdzFqJ+tW+EHEeW03EPtJ PYVKeIUNnq9Y/2rB1OUjdzTU/hOu4cggxbh+v/+3Pzgkape7EL0nSmz8sMQUQHNr y+I8hb3uiJOD7fvgfD9Opv54= 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:cc:subject:references:mime-version:content-type :in-reply-to:message-id; s=default; bh=9sXiJUMixz9tpaQQ9++ecBZ3u wA=; b=Hy6xKt8LxM+60INKxBBdY7Ll88kMF3ZCLPxfirTz788s43KUQ0Cad/9mD TFHEpdEBqpMVjq+cXhbqU60DRT+FDF3+iNzXnuALFz/rphRlQHAH2cJO7BiCns33 5vZyqbETAyLhVqNXs8wCIX1axrqEBYfkZNzisU+dpY2go6O4X4= Received: (qmail 37460 invoked by alias); 26 Jul 2016 20:09:21 -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 37445 invoked by uid 89); 26 Jul 2016 20:09:21 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.4 required=5.0 tests=AWL, BAYES_50, KAM_ASCII_DIVIDERS, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 spammy=King, Join, emit_jump_insn, 978 X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0b-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.158.5) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Tue, 26 Jul 2016 20:09:13 +0000 Received: from pps.filterd (m0098420.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id u6QJxuUh024115 for ; Tue, 26 Jul 2016 16:09:10 -0400 Received: from e38.co.us.ibm.com (e38.co.us.ibm.com [32.97.110.159]) by mx0b-001b2d01.pphosted.com with ESMTP id 24e5wc8c9c-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Tue, 26 Jul 2016 16:09:10 -0400 Received: from localhost by e38.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 26 Jul 2016 14:09:09 -0600 Received: from d03dlp02.boulder.ibm.com (9.17.202.178) by e38.co.us.ibm.com (192.168.1.138) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 26 Jul 2016 14:09:05 -0600 X-IBM-Helo: d03dlp02.boulder.ibm.com X-IBM-MailFrom: meissner@ibm-tiger.the-meissners.org 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 9E2A13E4006F; Tue, 26 Jul 2016 14:09:04 -0600 (MDT) Received: from b03ledav004.gho.boulder.ibm.com (b03ledav004.gho.boulder.ibm.com [9.17.130.235]) by b03cxnp08025.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u6QK94Fe15204702; Tue, 26 Jul 2016 13:09:04 -0700 Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 76B8278011; Tue, 26 Jul 2016 14:09:04 -0600 (MDT) Received: from ibm-tiger.the-meissners.org (unknown [9.32.77.111]) by b03ledav004.gho.boulder.ibm.com (Postfix) with ESMTP id 5AC5A90002; Tue, 26 Jul 2016 14:09:04 -0600 (MDT) Received: by ibm-tiger.the-meissners.org (Postfix, from userid 500) id EF9A846CF2; Tue, 26 Jul 2016 16:09:01 -0400 (EDT) Date: Tue, 26 Jul 2016 16:09:01 -0400 From: Michael Meissner To: Segher Boessenkool Cc: Michael Meissner , gcc-patches@gcc.gnu.org, David Edelsohn , Bill Schmidt , Richard Biener , Jakub Jelinek , murphyp@linux.vnet.ibm.com Subject: Re: [PATCH], Fix PR 71869, Correctly implement isgreater, etc. on PowerPC __float128 Mail-Followup-To: Michael Meissner , Segher Boessenkool , gcc-patches@gcc.gnu.org, David Edelsohn , Bill Schmidt , Richard Biener , Jakub Jelinek , murphyp@linux.vnet.ibm.com References: <20160726152338.GA7191@ibm-tiger.the-meissners.org> <20160726160532.GA12959@gate.crashing.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20160726160532.GA12959@gate.crashing.org> User-Agent: Mutt/1.5.20 (2009-12-10) X-TM-AS-GCONF: 00 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16072620-0028-0000-0000-0000053F3F6E X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16072620-0029-0000-0000-00002DDE949D Message-Id: <20160726200901.GA655@ibm-tiger.the-meissners.org> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-07-26_14:, , 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-1604210000 definitions=main-1607260214 X-IsSubscribed: yes On Tue, Jul 26, 2016 at 11:05:32AM -0500, Segher Boessenkool wrote: > > --- gcc/testsuite/gcc.target/powerpc/float128-cmp.c (revision 0) > > +++ gcc/testsuite/gcc.target/powerpc/float128-cmp.c (revision 0) > > @@ -0,0 +1,17 @@ > > +/* { dg-do compile { target { powerpc*-*-linux* } } } */ > > +/* { dg-require-effective-target powerpc_float128_sw_ok } */ > > +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */ > > +/* { dg-options "-O2 -mcpu=power7 -mfloat128" } */ > > + > > +#ifndef __FLOAT128__ > > +#error "-mfloat128 is not supported." > > +#endif > > This should never trigger, it is only there for debug, right? > > > +int > > +test_isgreater (__float128 a, __float128 b) > > +{ > > + return __builtin_isgreater (a, b); > > +} > > + > > +/* { dg-final { scan-assembler "bl __\[gl\]ekf2" } } */ > > +/* { dg-final { scan-assembler "bl __unordkf2" } } */ > > There are some extra spaces in that [gl]ekf2 line. > > Could you test all five functions please? Use multiple testcases, maybe. I decided to write an executable test rather than do more assembly tests. The patch to rs6000.c is unchanged, and the test now tests all of the comparison operators and functions with various values including quiet NaNs and signalling NaNs. It passes on power7 big endian 64-bit, power7 big endian 32-bit, power8 little endian 64-bit, and I ran it on the power9 simulator with hardware float128 support. [gcc] 2016-07-26 Michael Meissner PR target/71869 * config/rs6000/rs6000.c (rs6000_generate_compare): Rework __float128 support when we don't have hardware support, so that the IEEE built-in functions like isgreater, first call __unordkf3 to make sure neither operand is a NaN, and if both operands are ordered, do the normal comparison. [gcc/testsuite] 2016-07-26 Michael Meissner PR target/71869 * gcc.target/powerpc/float128-cmp.c: New test to make sure that IEEE built-in functions handle quiet and signalling NaNs correctly. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 238730) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -21755,8 +21755,8 @@ rs6000_generate_compare (rtx cmp, machin else if (!TARGET_FLOAT128_HW && FLOAT128_VECTOR_P (mode)) { rtx libfunc = NULL_RTX; - bool uneq_or_ltgt = false; - rtx dest = gen_reg_rtx (SImode); + bool check_nan = false; + rtx dest; switch (code) { @@ -21783,21 +21783,23 @@ rs6000_generate_compare (rtx cmp, machin case UNGE: case UNGT: - libfunc = optab_libfunc (le_optab, mode); + check_nan = true; + libfunc = optab_libfunc (ge_optab, mode); code = (code == UNGE) ? GE : GT; break; case UNLE: case UNLT: - libfunc = optab_libfunc (ge_optab, mode); + check_nan = true; + libfunc = optab_libfunc (le_optab, mode); code = (code == UNLE) ? LE : LT; break; case UNEQ: case LTGT: - libfunc = optab_libfunc (le_optab, mode); - uneq_or_ltgt = true; - code = (code = UNEQ) ? NE : EQ; + check_nan = true; + libfunc = optab_libfunc (eq_optab, mode); + code = (code = UNEQ) ? EQ : NE; break; default: @@ -21805,21 +21807,56 @@ rs6000_generate_compare (rtx cmp, machin } gcc_assert (libfunc); - dest = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, - SImode, 2, op0, mode, op1, mode); - /* If this is UNEQ or LTGT, we call __lekf2, which returns -1 for less - than, 0 for equal, +1 for greater, and +2 for nan. We add 1, to give - a value of 0..3, and then do and AND immediate of 1 to isolate whether - it is 0/Nan (i.e. bottom bit is 0), or less than/greater than - (i.e. bottom bit is 1). */ - if (uneq_or_ltgt) - { - rtx add_result = gen_reg_rtx (SImode); - rtx and_result = gen_reg_rtx (SImode); - emit_insn (gen_addsi3 (add_result, dest, GEN_INT (1))); - emit_insn (gen_andsi3 (and_result, add_result, GEN_INT (1))); - dest = and_result; + if (!check_nan) + dest = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, + SImode, 2, op0, mode, op1, mode); + + /* The library signals an exception for signalling NaNs, so we need to + handle isgreater, etc. by first checking isordered. */ + else + { + rtx ne_rtx, normal_dest, unord_dest; + rtx unord_func = optab_libfunc (unord_optab, mode); + rtx join_label = gen_label_rtx (); + rtx join_ref = gen_rtx_LABEL_REF (VOIDmode, join_label); + rtx unord_cmp = gen_reg_rtx (comp_mode); + + + /* Test for either value being a NaN. */ + gcc_assert (unord_func); + unord_dest = emit_library_call_value (unord_func, NULL_RTX, LCT_CONST, + SImode, 2, op0, mode, op1, + mode); + + /* Set value (0) if either value is a NaN, and jump to the join + label. */ + dest = gen_reg_rtx (SImode); + emit_move_insn (dest, const1_rtx); + emit_insn (gen_rtx_SET (unord_cmp, + gen_rtx_COMPARE (comp_mode, unord_dest, + const0_rtx))); + + ne_rtx = gen_rtx_NE (comp_mode, unord_cmp, const0_rtx); + emit_jump_insn (gen_rtx_SET (pc_rtx, + gen_rtx_IF_THEN_ELSE (VOIDmode, ne_rtx, + join_ref, + pc_rtx))); + + /* Do the normal comparison, knowing that the values are not + NaNs. */ + normal_dest = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, + SImode, 2, op0, mode, op1, + mode); + + emit_insn (gen_cstoresi4 (dest, + gen_rtx_fmt_ee (code, SImode, normal_dest, + const0_rtx), + normal_dest, const0_rtx)); + + /* Join NaN and non-Nan paths. Compare dest against 0. */ + emit_label (join_label); + code = NE; } emit_insn (gen_rtx_SET (compare_result, Index: gcc/testsuite/gcc.target/powerpc/float128-cmp.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-cmp.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/float128-cmp.c (revision 0) @@ -0,0 +1,106 @@ +/* { dg-do compile { target { powerpc*-*-linux* } } } */ +/* { dg-require-effective-target ppc_float128_sw } */ +/* { dg-options "-mvsx -O2 -mfloat128" } */ + +#include +#include + +#ifndef TYPE +#define TYPE __float128 +#define NAN __builtin_nanq ("") +#define SNAN __builtin_nansq ("") +#else +#define NAN __builtin_nan ("") +#define SNAN __builtin_nans ("") +#endif + +extern void check (TYPE a, + TYPE b, + int eq, + int ne, + int lt, + int le, + int gt, + int ge, + int i_lt, + int i_le, + int i_gt, + int i_ge, + int i_lg, + int i_un) __attribute__((__noinline__)); + +void +check (TYPE a, + TYPE b, + int eq, + int ne, + int lt, + int le, + int gt, + int ge, + int i_lt, + int i_le, + int i_gt, + int i_ge, + int i_lg, + int i_un) +{ + if (eq != (a == b)) + abort (); + + if (ne != (a != b)) + abort (); + + if (lt != (a < b)) + abort (); + + if (le != (a <= b)) + abort (); + + if (gt != (a > b)) + abort (); + + if (ge != (a >= b)) + abort (); + + if (i_lt != __builtin_isless (a, b)) + abort (); + + if (i_le != __builtin_islessequal (a, b)) + abort (); + + if (i_gt != __builtin_isgreater (a, b)) + abort (); + + if (i_ge != __builtin_isgreaterequal (a, b)) + abort (); + + if (i_lg != __builtin_islessgreater (a, b)) + abort (); + + if (i_un != __builtin_isunordered (a, b)) + abort (); +} + +int main (void) +{ + TYPE one = (TYPE) +1.0; + TYPE two = (TYPE) +2.0; + TYPE pzero = (TYPE) +0.0; + TYPE mzero = (TYPE) -0.0; + TYPE nan = (TYPE) NAN; + TYPE snan = (TYPE) SNAN; + + check (one, two, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0); + check (one, one, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0); + check (one, pzero, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0); + check (mzero, pzero, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0); + check (nan, one, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); + check (one, nan, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); + check (nan, nan, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); + check (snan, one, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); + check (one, snan, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); + check (snan, nan, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); + check (nan, snan, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); + return 0; +}