From patchwork Sun Apr 15 19:50:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Meissner X-Patchwork-Id: 898311 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-476404-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.vnet.ibm.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="G+HuN6Pk"; dkim-atps=neutral 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 40PMZf2V5zz9s0t for ; Mon, 16 Apr 2018 05:51:03 +1000 (AEST) 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=mc73NBUcXBPzt4c68aDe85FJ/4oLLYBsWov0439rGi+S5PDjgb5PM 4yu19uqt2WNYobCyk9HwwKqbhWsvijnd7lYJGzdOZ/aqvPmwD5MR49ldNJJdwOEw xbO9IaX4nY7wNWJKIGBrIHzReLIWjW8uu6Z4Zxz2N4BzFFvxaqbCK8= 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=DZ/5dVpfnP6KD33DMD7HN+gBFPo=; b=G+HuN6Pk6brzyxpLsQol IUOm+OSJdp2uDQHQ/Isvy8RwatCj/YEV2nope2aE1dWTOd9FcJ3cJr22T2Id2zb9 FaAIjq6so6lOglyGKxkWcykZIanuPdz9qKR/dYBnbekM7MK8WcvtixdaYod77RWN 7IOi5ODaYnE7kzGeUk1zGas= Received: (qmail 103671 invoked by alias); 15 Apr 2018 19:50:56 -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 103649 invoked by uid 89); 15 Apr 2018 19:50:55 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-10.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy=warned, 0d, King, king 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 ESMTP; Sun, 15 Apr 2018 19:50:52 +0000 Received: from pps.filterd (m0098416.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w3FJmdtj004102 for ; Sun, 15 Apr 2018 15:50:50 -0400 Received: from e34.co.us.ibm.com (e34.co.us.ibm.com [32.97.110.152]) by mx0b-001b2d01.pphosted.com with ESMTP id 2hcbrc25q4-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Sun, 15 Apr 2018 15:50:50 -0400 Received: from localhost by e34.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Sun, 15 Apr 2018 13:50:49 -0600 Received: from b03cxnp08025.gho.boulder.ibm.com (9.17.130.17) by e34.co.us.ibm.com (192.168.1.134) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Sun, 15 Apr 2018 13:50:46 -0600 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 w3FJojc112583374; Sun, 15 Apr 2018 12:50:45 -0700 Received: from b03ledav004.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 97C377803F; Sun, 15 Apr 2018 13:50:45 -0600 (MDT) Received: from ibm-tiger.the-meissners.org (unknown [9.32.77.111]) by b03ledav004.gho.boulder.ibm.com (Postfix) with ESMTP id 79FE378041; Sun, 15 Apr 2018 13:50:45 -0600 (MDT) Received: by ibm-tiger.the-meissners.org (Postfix, from userid 500) id CF2784AB4A; Sun, 15 Apr 2018 15:50:44 -0400 (EDT) Date: Sun, 15 Apr 2018 15:50:44 -0400 From: Michael Meissner To: Michael Meissner , GCC Patches , Segher Boessenkool , David Edelsohn , Bill Schmidt Subject: [PATCH] PR 85075, Fix PowerPC __float182/__ibm128 types and mangling Mail-Followup-To: Michael Meissner , GCC Patches , 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-cbid: 18041519-0016-0000-0000-0000088B18A4 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008862; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000257; SDB=6.01018398; UDB=6.00519462; IPR=6.00797636; MB=3.00020592; MTD=3.00000008; XFM=3.00000015; UTC=2018-04-15 19:50:47 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18041519-0017-0000-0000-00003E44E674 Message-Id: <20180415195044.GA2441@ibm-tiger.the-meissners.org> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-04-15_09:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1011 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1804150200 X-IsSubscribed: yes PR target/85075 shows that there are some problems with the types for the 3 128-bit floating point types on the PowerPC: __float128 (and _Float128 in C, IEEE 128-bit) __ieee128 (IBM extended double) long double (either IEEE 128-bit or IBM extended double) With GCC 8, we are beginning the transition of long double from the IBM extended double format to IEEE 128-bit. I implemented __float128 and __ieee128 initially as being separate types when the long double format was the other type, and mapped to long double when the long double format was the same as the type. However, the use of C++ templates and overloaded functions within classes shows that we really need to have 3 separate types. Each type needs to have different mangling. Since __float128 and __ibm128 are now always separate types, I relaxed the restriction that __ibm128 can only be used if -mlong-double-128. In developing this patch, Segher noticed that the mangling for __float128 violated the mangling standards. This patch includes a change to use a more official mangling (u10__float128). This means that GCC 8 will not be able to link with C++ functions that pass or return __float128 values compiled with GCC 6 or GCC 7. I have put in a warning if __float128 is mangled. The warning can be silenced by using -Wno-psabi. In addition, when I built this on big endian system, the changes exposed a latent bug with the way __builtin_packlongdouble was done when it tried to support the first argument overlapping with the result. I have removed the code to support overlapping input/output for this builtin. I imagine that we will need to add __builtin_packieee128 and __builtin_unpackieee128 as well in the future (or make __builtin_{,un}packlongdouble support all three types). The manglings that are now used are: For -mabi=ieeelongdouble: __float128 "u10__float128" __ibm128 "u8__ibm128" long double "u9__ieee128" For -mabi=ibmlongdouble: __float128 "u10__float128" __ibm128 "u8__ibm128" long double "g" For -mlong-double-64: __float128 "u10__float128" __ibm128 "u8__ibm128" long double "e" I have tested these patches on a little endian power8 system and a big endian power7 system (both 32/64-bit). I also tested a previous version of the patch on a big endian power8 system (both 32/64-bit). There were no regressions. Can I apply these patches to the GCC 8 trunk? [gcc] 2018-04-15 Michael Meissner PR target/85075 * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): __ibm128 is now a separate type, don't #define __ibm128 as long double. * config/rs6000/rs6000.c (rs6000_init_builtins): Make __ibm128 a separate type on systems that support IEEE 128-bit floating point. (rs6000_mangle_type): Use separate manglings for __ibm128 and __float128. Change __float128 mangling from U10__float128 to u10__float128. Issue a warning that the mangling has changed in GCC 8. * config/rs6000/rs6000.md (pack): Do not try handle a pack where the inputs overlap with the output. [gcc/testsuite] 2018-04-15 Michael Meissner PR target/85075 * g++.dg/pr85075-1.C: New tests. Make sure that __float128, __ibm128, and long double are different types, and that you can mix them in templates and with overloaded functions. Test all 3 different long dobule variants (IEEE 128 bit, IBM 128 bit, and 64 bit). * g++.dg/pr85075-2.C: Likewise. * g++.dg/pr85075-3.C: Likewise. Index: gcc/config/rs6000/rs6000-c.c =================================================================== --- gcc/config/rs6000/rs6000-c.c (revision 259376) +++ gcc/config/rs6000/rs6000-c.c (working copy) @@ -617,8 +617,6 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi builtin_define ("__RSQRTEF__"); if (TARGET_FLOAT128_TYPE) builtin_define ("__FLOAT128_TYPE__"); - if (TARGET_LONG_DOUBLE_128 && FLOAT128_IBM_P (TFmode)) - builtin_define ("__ibm128=long double"); #ifdef TARGET_LIBC_PROVIDES_HWCAP_IN_TCB builtin_define ("__BUILTIN_CPU_SUPPORTS__"); #endif Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 259376) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -16994,28 +16994,22 @@ rs6000_init_builtins (void) For IEEE 128-bit floating point, always create the type __ieee128. If the user used -mfloat128, rs6000-c.c will create a define from __float128 to __ieee128. */ - if (TARGET_LONG_DOUBLE_128 && FLOAT128_IEEE_P (TFmode)) + if (TARGET_FLOAT128_TYPE) { ibm128_float_type_node = make_node (REAL_TYPE); TYPE_PRECISION (ibm128_float_type_node) = 128; SET_TYPE_MODE (ibm128_float_type_node, IFmode); layout_type (ibm128_float_type_node); - lang_hooks.types.register_builtin_type (ibm128_float_type_node, "__ibm128"); - } - else - ibm128_float_type_node = long_double_type_node; - if (TARGET_FLOAT128_TYPE) - { ieee128_float_type_node = float128_type_node; lang_hooks.types.register_builtin_type (ieee128_float_type_node, "__ieee128"); } else - ieee128_float_type_node = long_double_type_node; + ieee128_float_type_node = ibm128_float_type_node = long_double_type_node; /* Initialize the modes for builtin_function_type, mapping a machine mode to tree type node. */ @@ -32902,24 +32896,32 @@ rs6000_mangle_type (const_tree type) if (type == bool_int_type_node) return "U6__booli"; if (type == bool_long_long_type_node) return "U6__boolx"; - /* Use a unique name for __float128 rather than trying to use "e" or "g". Use - "g" for IBM extended double, no matter whether it is long double (using - -mabi=ibmlongdouble) or the distinct __ibm128 type. */ - if (TARGET_FLOAT128_TYPE) - { - if (type == ieee128_float_type_node) - return "U10__float128"; + /* Use a unique name for __float128/__ibm128 rather than trying to use "e" or + "g". While, "g" in theory should be used for __float128, the PowerPC + compiler has used "g" for IBM extended double for a long time. Use + u10__float128 for the separate __float128 type (_Float128 in C), and + u9__ieee128 for long double when -mabi=ieeelongdouble is used. - if (TARGET_LONG_DOUBLE_128) + GCC 6/7 used U10__float128 instead of u10__float128. */ + if (type == ieee128_float_type_node) + { + static bool warned; + if (!warned && warn_psabi) { - if (type == long_double_type_node) - return (TARGET_IEEEQUAD) ? "U10__float128" : "g"; - - if (type == ibm128_float_type_node) - return "g"; + warned = true; + inform (input_location, + "the name mangling for __float128 types changed in GCC 8"); } + return "u10__float128"; } + if (type == ibm128_float_type_node) + return "u8__ibm128"; + + if (TARGET_FLOAT128_TYPE && TARGET_LONG_DOUBLE_128 + && type == long_double_type_node) + return (TARGET_IEEEQUAD) ? "u9__ieee128" : "g"; + /* Mangle IBM extended float long double as `g' (__float128) on powerpc*-linux where long-double-64 previously was the default. */ if (TYPE_MAIN_VARIANT (type) == long_double_type_node Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 259376) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -13934,16 +13934,14 @@ (define_insn_and_split "unpack_nod (set_attr "length" "4")]) (define_insn_and_split "pack" - [(set (match_operand:FMOVE128 0 "register_operand" "=d,&d") + [(set (match_operand:FMOVE128 0 "register_operand" "=&d") (unspec:FMOVE128 - [(match_operand: 1 "register_operand" "0,d") - (match_operand: 2 "register_operand" "d,d")] + [(match_operand: 1 "register_operand" "d") + (match_operand: 2 "register_operand" "d")] UNSPEC_PACK_128BIT))] "FLOAT128_2REG_P (mode)" - "@ - fmr %L0,%2 - #" - "&& reload_completed && REGNO (operands[0]) != REGNO (operands[1])" + "#" + "&& reload_completed" [(set (match_dup 3) (match_dup 1)) (set (match_dup 4) (match_dup 2))] { @@ -13956,8 +13954,8 @@ (define_insn_and_split "pack" operands[3] = gen_rtx_REG (mode, dest_hi); operands[4] = gen_rtx_REG (mode, dest_lo); } - [(set_attr "type" "fpsimple,fp") - (set_attr "length" "4,8")]) + [(set_attr "type" "fp") + (set_attr "length" "8")]) (define_insn "unpack" [(set (match_operand:DI 0 "register_operand" "=wa,wa") Index: gcc/testsuite/g++.dg/pr85075-1.C =================================================================== --- gcc/testsuite/g++.dg/pr85075-1.C (revision 0) +++ gcc/testsuite/g++.dg/pr85075-1.C (revision 0) @@ -0,0 +1,58 @@ +// { dg-do compile { target { powerpc*-*-linux* } } } +// { dg-require-effective-target ppc_float128_sw } +// { dg-options "-mvsx -mfloat128 -O2 -mabi=ieeelongdouble -Wno-psabi" } */ + +// PR 85075 +// If you used a template for both long double and __float128, it would +// complain that the same mangling was used for different types. Previously, +// __float128 was defined to __ieee128 (the keyword where the the _Float128 +// type is defined). Note, __float128 is defined to be 'long double' if +// -mabi=ieeelongdouble is used. + +template inline bool +iszero (__T __val) +{ + return __val == 0; +} + +#ifdef _ARCH_PWR7 +#ifdef __LONG_DOUBLE_IEEE128__ +#define LD_CONSTRAINT "wa" +#else +#define LD_CONSTRAINT "d" +#endif +#endif + +int +use_template (void) +{ + long double q1 = 0.0l; + __float128 q = 0.0q; + +#ifdef _ARCH_PWR7 + __asm__ (" # %x0, %x1" : "+" LD_CONSTRAINT (q1), "+wa" (q)); +#endif + + return iszero (q1) + iszero (q); +} + +class foo { +public: + foo () {} + ~foo () {} + inline bool iszero (long double ld) { return ld == 0.0L; } + inline bool iszero (__float128 f128) { return f128 == 0.0Q; } +} st; + +int +use_class (void) +{ + long double q1 = 0.0l; + __float128 q = 0.0q; + +#ifdef _ARCH_PWR7 + __asm__ (" # %x0, %x1" : "+" LD_CONSTRAINT (q1), "+wa" (q)); +#endif + + return st.iszero (q1) + st.iszero (q); +} Index: gcc/testsuite/g++.dg/pr85075-2.C =================================================================== --- gcc/testsuite/g++.dg/pr85075-2.C (revision 0) +++ gcc/testsuite/g++.dg/pr85075-2.C (revision 0) @@ -0,0 +1,58 @@ +// { dg-do compile { target { powerpc*-*-linux* } } } +// { dg-require-effective-target ppc_float128_sw } +// { dg-options "-mvsx -mfloat128 -O2 -mabi=ibmlongdouble -Wno-psabi" } */ + +// PR 85075 +// If you used a template for both long double and __float128, it would +// complain that the same mangling was used for different types. Previously, +// __float128 was defined to __ieee128 (the keyword where the the _Float128 +// type is defined). Note, __float128 is defined to be 'long double' if +// -mabi=ieeelongdouble is used. + +template inline bool +iszero (__T __val) +{ + return __val == 0; +} + +#ifdef _ARCH_PWR7 +#ifdef __LONG_DOUBLE_IEEE128__ +#define LD_CONSTRAINT "wa" +#else +#define LD_CONSTRAINT "d" +#endif +#endif + +int +use_template (void) +{ + long double q1 = 0.0l; + __float128 q = 0.0q; + +#ifdef _ARCH_PWR7 + __asm__ (" # %x0, %x1" : "+" LD_CONSTRAINT (q1), "+wa" (q)); +#endif + + return iszero (q1) + iszero (q); +} + +class foo { +public: + foo () {} + ~foo () {} + inline bool iszero (long double ld) { return ld == 0.0L; } + inline bool iszero (__float128 f128) { return f128 == 0.0Q; } +} st; + +int +use_class (void) +{ + long double q1 = 0.0l; + __float128 q = 0.0q; + +#ifdef _ARCH_PWR7 + __asm__ (" # %x0, %x1" : "+" LD_CONSTRAINT (q1), "+wa" (q)); +#endif + + return st.iszero (q1) + st.iszero (q); +} Index: gcc/testsuite/g++.dg/pr85075-3.C =================================================================== --- gcc/testsuite/g++.dg/pr85075-3.C (revision 0) +++ gcc/testsuite/g++.dg/pr85075-3.C (revision 0) @@ -0,0 +1,58 @@ +// { dg-do compile { target { powerpc*-*-linux* } } } +// { dg-require-effective-target ppc_float128_sw } +// { dg-options "-mvsx -mfloat128 -O2 -mlong-double-64 -Wno-psabi" } */ + +// PR 85075 +// If you used a template for both long double and __float128, it would +// complain that the same mangling was used for different types. Previously, +// __float128 was defined to __ieee128 (the keyword where the the _Float128 +// type is defined). Note, __float128 is defined to be 'long double' if +// -mabi=ieeelongdouble is used. + +template inline bool +iszero (__T __val) +{ + return __val == 0; +} + +#ifdef _ARCH_PWR7 +#ifdef __LONG_DOUBLE_IEEE128__ +#define LD_CONSTRAINT "wa" +#else +#define LD_CONSTRAINT "d" +#endif +#endif + +int +use_template (void) +{ + long double q1 = 0.0l; + __float128 q = 0.0q; + +#ifdef _ARCH_PWR7 + __asm__ (" # %x0, %x1" : "+" LD_CONSTRAINT (q1), "+wa" (q)); +#endif + + return iszero (q1) + iszero (q); +} + +class foo { +public: + foo () {} + ~foo () {} + inline bool iszero (long double ld) { return ld == 0.0L; } + inline bool iszero (__float128 f128) { return f128 == 0.0Q; } +} st; + +int +use_class (void) +{ + long double q1 = 0.0l; + __float128 q = 0.0q; + +#ifdef _ARCH_PWR7 + __asm__ (" # %x0, %x1" : "+" LD_CONSTRAINT (q1), "+wa" (q)); +#endif + + return st.iszero (q1) + st.iszero (q); +}