From patchwork Thu Jan 4 23:05:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Meissner X-Patchwork-Id: 855848 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-470190-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="Cm+vcz4Q"; 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 3zCNhY65lKz9s7h for ; Fri, 5 Jan 2018 10:06:20 +1100 (AEDT) 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=VNrbF8mEFr/bOYhZ+FKEIegbDLhvCBVdDIYnBpk3wFLeaXP66aB4P ibbMvfFYc/Lan0iGKKMz6PNEyEswuRu6O/DTF3pdIXUGn1XXY36A0xz8vG1zzpY3 fSLGCuKLpmqY1M/YNUe3ubD+j+/q82n4fxBu3n5MXVUVb5zwiwO6ag= 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=odUf7UAe85W2Iff34WxZ21WPBtY=; b=Cm+vcz4QP4h+BM1bfzbk rxyjacEHVDtE0625ExlVj28W6DtGCrRJhgEiveuWquDcSM0fHZdde5yvmsFZDdJ6 gMDM3PW3Ndln2aCZZoC4G4Svg8g8qau73Lq8e5kb3XIQLHazxc7McrtyBhdUXh8w PyiGBcFpyBE9ei1ESijFTYY= Received: (qmail 118305 invoked by alias); 4 Jan 2018 23:06:11 -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 118288 invoked by uid 89); 4 Jan 2018 23:06:10 -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, KAM_SHORT, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy=1102, mn 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; Thu, 04 Jan 2018 23:06:02 +0000 Received: from pps.filterd (m0098413.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.21/8.16.0.21) with SMTP id w04MxDKA080410 for ; Thu, 4 Jan 2018 18:06:00 -0500 Received: from e32.co.us.ibm.com (e32.co.us.ibm.com [32.97.110.150]) by mx0b-001b2d01.pphosted.com with ESMTP id 2f9pe0jf96-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Thu, 04 Jan 2018 18:06:00 -0500 Received: from localhost by e32.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 4 Jan 2018 16:05:59 -0700 Received: from b03cxnp07029.gho.boulder.ibm.com (9.17.130.16) by e32.co.us.ibm.com (192.168.1.132) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 4 Jan 2018 16:05:57 -0700 Received: from b03ledav006.gho.boulder.ibm.com (b03ledav006.gho.boulder.ibm.com [9.17.130.237]) by b03cxnp07029.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w04N5vDj59638010; Thu, 4 Jan 2018 16:05:57 -0700 Received: from b03ledav006.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id F1C01C603C; Thu, 4 Jan 2018 16:05:56 -0700 (MST) Received: from ibm-tiger.the-meissners.org (unknown [9.32.77.111]) by b03ledav006.gho.boulder.ibm.com (Postfix) with ESMTP id C1926C6037; Thu, 4 Jan 2018 16:05:56 -0700 (MST) Received: by ibm-tiger.the-meissners.org (Postfix, from userid 500) id 13366496AE; Thu, 4 Jan 2018 18:05:55 -0500 (EST) Date: Thu, 4 Jan 2018 18:05:55 -0500 From: Michael Meissner To: GCC Patches , Segher Boessenkool , David Edelsohn , Bill Schmidt Subject: [PATCH], Add optional IEEE/IBM long double multilib support 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: 18010423-0004-0000-0000-0000137930EA X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008319; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000244; SDB=6.00970318; UDB=6.00491423; IPR=6.00750289; BA=6.00005765; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00018878; XFM=3.00000015; UTC=2018-01-04 23:05:59 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18010423-0005-0000-0000-00008584D94F Message-Id: <20180104230555.GA4847@ibm-tiger.the-meissners.org> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-01-04_10:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=2 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-1801040314 X-IsSubscribed: yes This patch is the beginning step to switching the PowerPC long double support from IBM extended double to IEEE 128-bit floating point on PowerPC servers. It will be necessary to have this patch or a similar patch to allow the GLIBC team to begin their modifications in GLIBC 2.28, so that by the time GCC 9 comes out, we can decide to switch the default. It is likely, the default will only be switched on the 64-bit little endian PowerPC systems, when a distribution goes through a major level, such that they can contemplate major changes. If you do not use the configuration option --with-long-double-format=ieee or --with-long-double-format=ibm, the system will not build multilibs, and just build normal libraries with the default set to IBM extended double. If you do use either of the switches, and allow multilibs, it will build two sets of multilibs, one for -mabi=ieeelongdouble and one for -mabi=ibmlongdouble. Now, to build a compiler with multilibs, you need to do the following steps: 1) Install the IBM Advance Toolchain AT 11.0-2. 2) Clone the AT directory: # rsync -aH /opt/at11.0/ /opt/at11.0-ieee/ 3) Go into the new directory and add a symlink from lib64 to ieee64. Eventually once we have versions of the libraries compiled for -mabi=ieeelongdouble, these libraries and objects would go into the ieee64 directory. However, to do a build, you need the crt files in order to build the shared libraries. 4) Configure the compiler with these options: --with-long-double-128 # should be default --with-cpu=power8 # or power9 --with-long-double-format=ibm # specify long double format --enable-multilib # enable multilibs --with-system-libz # do not build our own libz --with-advance-toolchain=at11.0-ieee # use the special AT library # Use the AT library's includes --with-native-system-header-dir=/opt/at11.0-ieee/include --with-gnu-ld=/opt/at11.0-ieee/bin/ld # specify as/ld locations --with-gnu-as=/opt/at11.0-ieee/bin/as --with-ld=/opt/at11.0-ieee/bin/ld --with-as=/opt/at11.0-ieee/bin/as The libgcc changes were changes that show up when you build libgcc with the default set to IEEE 128-bit. There is a work around in rs6000-c.c to allow the AT 11.0-2 include files to be used as is. Otherwise, we need to modify /opt/at11.0/include/bits/floatn.h to specify the correct IEEE 128-bit complex type in C++ (C++ does not support the _Float128 keyword, and __float128 _Complex does not work, so we have to use the mode attribute to declare the type). When -mabi=ieeelongdouble is used, the default Float128 types are TFmode for scalar and TCmode for complex. With the default -mabi=ibmlongdouble is used, the default Float128 types are KFmode and KCmode. It is hoped that in AT 11.0-3, we can fix floatn.h to declare the appropriate type. I have built bootstrap builds on a little endian power8 system without using the --with-long-double-format switch and it runs the same as the unpatched compiler. I have also built bootstrap builds on a little endian power8 system with the switches listed above, and the tests for the default long double format are the same. Obviously, we can't run multilib make checks until the necessary work has been done in GLIBC. I will do a big endian build shortly to make sure it builds normally. What changes or additional tests do you feel I need to make before checking this into the trunk? [gcc] 2018-01-04 Michael Meissner * configure.ac (--with-long-double-format): Add support for configuration option to change the default long double format in PowerPC Linux systems. * configure: Regenerate. * config.gcc (powerpc*-linux*-*): Add support for --with-long-double-format={ieee,ibm}. If the format is explicit set, also set up IBM and IEEE multilibs. * config/rs6000/rs6000.h (FLOAT128_IEEE_P): Explicitly check for 128-bit long doubles before checking TFmode or TCmode. (FLOAT128_IBM_P): Likewise. (TARGET_IEEEQUAD_MULTILIB): Set to 0 if not already defined. * config/rs6000/rs6000.c (rs6000_option_override_internal): If we have IBM/IEEE multilibs, don't give a warning if the user chagnes the long double format. (is_complex_IBM_long_double): Explicitly check for 128-bit long doubles before checking TCmode. * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): If long double is IEEE, define __KC__ and __KF__ to allow floatn.h to be used without modification. * config/rs6000/linux64.h (MULTILIB_DEFAULTS_IEEE): Specify the -mabi={ieee,ibm}longdouble default for multilibs. (MULTILIB_DEFAULTS): Likewise. * config/rs6000/t-ldouble: New file, add IEEE/IBM long double multilibs. [libgcc] 2018-01-04 Michael Meissner * config/rs6000/quad-float128.h (IBM128_TYPE): Explicitly use __ibm128, instead of trying to use long double. (CVT_FLOAT128_TO_IBM128): Use TFtype instead of __float128 to accomidate -mabi=ieeelongdouble multilibs. (CVT_IBM128_TO_FLOAT128): Likewise. * config/rs6000/ibm-ldouble.c (IBM128_TYPE): New macro to define the appropriate IBM extended double type. (__gcc_qadd): Change all occurances of long double to IBM128_TYPE. (__gcc_qsub): Likewise. (__gcc_qmul): Likewise. (__gcc_qdiv): Likewise. (pack_ldouble): Likewise. (__gcc_qneg): Likewise. (__gcc_qeq): Likewise. (__gcc_qne): Likewise. (__gcc_qge): Likewise. (__gcc_qle): Likewise. (__gcc_stoq): Likewise. (__gcc_dtoq): Likewise. (__gcc_itoq): Likewise. (__gcc_utoq): Likewise. (__gcc_qunord): Likewise. * config/rs6000/_mulkc3.c (toplevel): Include soft-fp.h and quad-float128.h for the definitions. (COPYSIGN): Use the f128 version instead of the q version. (INFINITY): Likewise. (__mulkc3): Use TFmode/TCmode for float128 scalar/complex types. * config/rs6000/_divkc3.c (toplevel): Include soft-fp.h and quad-float128.h for the definitions. (COPYSIGN): Use the f128 version instead of the q version. (INFINITY): Likewise. (FABS): Likewise. (__divkc3): Use TFmode/TCmode for float128 scalar/complex types. * config/rs6000/extendkftf2-sw.c (__extendkftf2_sw): Likewise. * config/rs6000/trunctfkf2-sw.c (__trunctfkf2_sw): Likewise. Index: gcc/configure.ac =================================================================== --- gcc/configure.ac (revision 256120) +++ gcc/configure.ac (working copy) @@ -5885,6 +5885,30 @@ if test x$gcc_cv_target_ldbl128 = xyes; [Define if TFmode long double should be the default]) fi +# Check if TFmode long double target should use the IBM extended double or IEEE +# 128-bit floating point formats if long doubles are 128-bits long. The long +# double type can only be switched on powerpc64 bit Linux systems where VSX is +# supported. Other PowerPC systems do not build the IEEE 128-bit emulator in +# liggcc. +AC_ARG_WITH([long-double-format], + [AS_HELP_STRING([--with-long-double-format={ieee,ibm}] + [Specify whether PowerPC long double uses IEEE or IBM format])],[ +case "$target:$with_cpu:$with_long_double_format" in + powerpc*-*-linux*:power[789]:ieee | powerpc*-*-linux*:power[1-9][0-9]+:ieee | \ + powerpc*-*-linux*:power[789]:ibm | powerpc*-*-linux*:power[1-9][0-9]+:ibm | \ + powerpc64le-*-linux*:*:ieee | powerpc64le-*-linux*:*:ibm) + ;; + powerpc*-*-linux*:power[789]:* | powerpc*-*-linux*:power[1-9][0-9]+:* | \ + powerpc64le-*-linux*:*:*) + AC_MSG_ERROR([--with-long-double-format argument should be ibm or ieee]) + ;; + *) + AC_MSG_ERROR([Configure option --with-long-double-format is only supported \ +for PowerPC VSX Linux systems]) + ;; +esac], + []) + # Check if the target LIBC supports exporting the AT_PLATFORM and AT_HWCAP # values in the TCB. Currently, only GLIBC 2.23 and later support this. gcc_cv_libc_provides_hwcap_in_tcb=no Index: gcc/configure =================================================================== --- gcc/configure (revision 256120) +++ gcc/configure (working copy) @@ -945,6 +945,7 @@ enable_linker_build_id enable_libssp enable_default_ssp with_long_double_128 +with_long_double_format with_gc with_system_zlib enable_maintainer_mode @@ -1738,6 +1739,9 @@ Optional Packages: --with-glibc-version=M.N assume GCC used with glibc version M.N or later --with-long-double-128 use 128-bit long double by default + --with-long-double-format={ieee,ibm} + Specify whether PowerPC long double uses IEEE or IBM format + --with-gc={page,zone} this option is not supported anymore. It used to choose the garbage collection mechanism to use with the compiler @@ -18442,7 +18446,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 18445 "configure" +#line 18449 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -18548,7 +18552,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 18551 "configure" +#line 18555 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -29185,6 +29189,32 @@ $as_echo "#define TARGET_DEFAULT_LONG_DO fi +# Check if TFmode long double target should use the IBM extended double or IEEE +# 128-bit floating point formats if long doubles are 128-bits long. The long +# double type can only be switched on powerpc64 bit Linux systems where VSX is +# supported. Other PowerPC systems do not build the IEEE 128-bit emulator in +# liggcc. + +# Check whether --with-long-double-format was given. +if test "${with_long_double_format+set}" = set; then : + withval=$with_long_double_format; +case "$target:$with_cpu:$with_long_double_format" in + powerpc*-*-linux*:power789:ieee | powerpc*-*-linux*:power1-90-9+:ieee | \ + powerpc*-*-linux*:power789:ibm | powerpc*-*-linux*:power1-90-9+:ibm | \ + powerpc64le-*-linux*:*:ieee | powerpc64le-*-linux*:*:ibm) + ;; + powerpc*-*-linux*:power789:* | powerpc*-*-linux*:power1-90-9+:* | \ + powerpc64le-*-linux*:*:*) + as_fn_error "--with-long-double-format argument should be ibm or ieee" "$LINENO" 5 + ;; + *) + as_fn_error "Configure option --with-long-double-format is only supported \ +for PowerPC VSX Linux systems" "$LINENO" 5 + ;; +esac +fi + + # Check if the target LIBC supports exporting the AT_PLATFORM and AT_HWCAP # values in the TCB. Currently, only GLIBC 2.23 and later support this. gcc_cv_libc_provides_hwcap_in_tcb=no Index: gcc/config.gcc =================================================================== --- gcc/config.gcc (revision 256120) +++ gcc/config.gcc (working copy) @@ -4392,6 +4392,24 @@ case "${target}" in exit 1 fi fi + + # Set up the default long double format. Only enable the + # IEEE/IBM multilibs if the user explicitly set the long double + # format and did not do --disable-multilib. + if test x$with_long_double_format = xieee; then + tm_defines="${tm_defines} TARGET_IEEEQUAD_DEFAULT=1" + if test x$enable_multilib = xyes; then + tm_defines="${tm_defines} TARGET_IEEEQUAD_MULTILIB=1" + tmake_file="${tmake_file} rs6000/t-ldouble" + fi + + elif test x$with_long_double_format = xibm; then + tm_defines="${tm_defines} TARGET_IEEEQUAD_DEFAULT=0" + if test x$enable_multilib = xyes; then + tm_defines="${tm_defines} TARGET_IEEEQUAD_MULTILIB=1" + tmake_file="${tmake_file} rs6000/t-ldouble" + fi + fi ;; s390*-*-*) Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 256120) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -437,11 +437,13 @@ extern const char *host_detect_local_cpu Similarly IFmode is the IBM long double format even if the default is IEEE 128-bit. Don't allow IFmode if -msoft-float. */ #define FLOAT128_IEEE_P(MODE) \ - ((TARGET_IEEEQUAD && ((MODE) == TFmode || (MODE) == TCmode)) \ + ((TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128 \ + && ((MODE) == TFmode || (MODE) == TCmode)) \ || ((MODE) == KFmode) || ((MODE) == KCmode)) #define FLOAT128_IBM_P(MODE) \ - ((!TARGET_IEEEQUAD && ((MODE) == TFmode || (MODE) == TCmode)) \ + ((!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128 \ + && ((MODE) == TFmode || (MODE) == TCmode)) \ || (TARGET_HARD_FLOAT && ((MODE) == IFmode || (MODE) == ICmode))) /* Helper macros to say whether a 128-bit floating point type can go in a @@ -562,6 +564,12 @@ extern int rs6000_vector_align[]; #define TARGET_ALTIVEC_ABI rs6000_altivec_abi #define TARGET_LDBRX (TARGET_POPCNTD || rs6000_cpu == PROCESSOR_CELL) +/* Define as 1 if we support multilibs for switching long double between IEEE + 128-bit floating point and IBM extended double. */ +#ifndef TARGET_IEEEQUAD_MULTILIB +#define TARGET_IEEEQUAD_MULTILIB 0 +#endif + /* ISA 2.01 allowed FCFID to be done in 32-bit, previously it was 64-bit only. Enable 32-bit fcfid's on any of the switches for newer ISA machines or XILINX. */ Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 256120) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -4600,11 +4600,15 @@ rs6000_option_override_internal (bool gl systems will also set long double to be IEEE 128-bit. AIX and Darwin explicitly redefine TARGET_IEEEQUAD and TARGET_IEEEQUAD_DEFAULT to 0, so those systems will not pick up this default. Warn if the user changes the - default unless -Wno-psabi. */ + default unless either the user used the -Wno-psabi option, or the compiler + was built to enable multilibs to switch between the two long double + types. */ if (!global_options_set.x_rs6000_ieeequad) rs6000_ieeequad = TARGET_IEEEQUAD_DEFAULT; - else if (rs6000_ieeequad != TARGET_IEEEQUAD_DEFAULT && TARGET_LONG_DOUBLE_128) + else if (!TARGET_IEEEQUAD_MULTILIB + && rs6000_ieeequad != TARGET_IEEEQUAD_DEFAULT + && TARGET_LONG_DOUBLE_128) { static bool warned_change_long_double; if (!warned_change_long_double) @@ -11424,7 +11428,9 @@ rs6000_must_pass_in_stack (machine_mode static inline bool is_complex_IBM_long_double (machine_mode mode) { - return mode == ICmode || (!TARGET_IEEEQUAD && mode == TCmode); + return mode == ICmode || (!TARGET_IEEEQUAD + && TARGET_LONG_DOUBLE_128 + && mode == TCmode); } /* Whether ABI_V4 passes MODE args to a function in floating point Index: gcc/config/rs6000/rs6000-c.c =================================================================== --- gcc/config/rs6000/rs6000-c.c (revision 256120) +++ gcc/config/rs6000/rs6000-c.c (working copy) @@ -708,7 +708,18 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi builtin_define ("__LONGDOUBLE128"); if (TARGET_IEEEQUAD) - builtin_define ("__LONG_DOUBLE_IEEE128__"); + { + /* Older versions of GLIBC used __attribute__((__KC__)) to create the + IEEE 128-bit floating point complex type for C++ (which does not + support _Float128 _Complex). If the default for long double is + IEEE 128-bit mode, the library would need to use + __attribute__((__TC__)) instead. Defining __KF__ and __KC__ + is a stop-gap to build with the older libraries, until we + get an updated library. */ + builtin_define ("__LONG_DOUBLE_IEEE128__"); + builtin_define ("__KF__=__TF__"); + builtin_define ("__KC__=__TC__"); + } else builtin_define ("__LONG_DOUBLE_IBM128__"); } Index: gcc/config/rs6000/linux64.h =================================================================== --- gcc/config/rs6000/linux64.h (revision 256120) +++ gcc/config/rs6000/linux64.h (working copy) @@ -245,11 +245,23 @@ extern int dot_symbols; #define DYNAMIC_LINKER_PREFIX "" #endif +#if TARGET_IEEEQUAD_MULTILIB +#if TARGET_IEEEQUAD_DEFAULT +#define MULTILIB_DEFAULTS_IEEE , "mabi=ieeelongdouble" + +#else /* TARGET_IEEEQUAD_DEFAULT. */ +#define MULTILIB_DEFAULTS_IEEE , "mabi=ibmlongdouble" +#endif /* TARGET_IEEEQUAD_DEFAULT. */ + +#else /* TARGET_IEEEQUAD_MULTILIB. */ +#define MULTILIB_DEFAULTS_IEEE +#endif /* TARGET_IEEEQUAD_MULTILIB. */ + #undef MULTILIB_DEFAULTS #if DEFAULT_ARCH64_P -#define MULTILIB_DEFAULTS { "m64" } +#define MULTILIB_DEFAULTS { "m64" MULTILIB_DEFAULTS_IEEE } #else -#define MULTILIB_DEFAULTS { "m32" } +#define MULTILIB_DEFAULTS { "m32" MULTILIB_DEFAULTS_IEEE } #endif /* Split stack is only supported for 64 bit, and requires glibc >= 2.18. */ Index: gcc/config/rs6000/t-ldouble =================================================================== --- gcc/config/rs6000/t-ldouble (revision 0) +++ gcc/config/rs6000/t-ldouble (revision 0) @@ -0,0 +1,24 @@ +# Copyright (C) 2017 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# . + +# Enable building IEEE 128-bit floating point multilibs on a system that +# defaults to IBM extended double floating point. +MULTILIB_OPTIONS += mabi=ibmlongdouble/mabi=ieeelongdouble +MULTILIB_DIRNAMES += ibm128 ieee128 +MULTILIB_OSDIRNAMES += mabi.ibmlongdouble=../lib64 mabi.ieeelongdouble=../ieee64 ../lib64 + Index: libgcc/config/rs6000/quad-float128.h =================================================================== --- libgcc/config/rs6000/quad-float128.h (revision 256120) +++ libgcc/config/rs6000/quad-float128.h (working copy) @@ -51,12 +51,7 @@ typedef __complex float TCtype __attribu #include -#ifdef __LONG_DOUBLE_IEEE128__ -#define IBM128_TYPE __ibm128 - -#else -#define IBM128_TYPE long double -#endif +#define IBM128_TYPE __ibm128 /* Add prototypes of the library functions created. In case the appropriate int/long types are not declared in scope by the time quad.h is included, @@ -185,7 +180,7 @@ union ibm128_union { #define CVT_FLOAT128_TO_IBM128(RESULT, VALUE) \ { \ double __high, __low; \ - __float128 __value = (VALUE); \ + TFtype __value = (VALUE); \ union ibm128_union u; \ \ __high = (double) __value; \ @@ -196,7 +191,7 @@ union ibm128_union { { \ double __high_temp; \ \ - __low = (double) (__value - (__float128) __high); \ + __low = (double) (__value - (TFtype) __high); \ /* Renormalize low/high and move them into canonical IBM long \ double form. */ \ __high_temp = __high + __low; \ @@ -220,13 +215,13 @@ union ibm128_union { \ /* Handle the special cases of NAN and infinity. */ \ if (__builtin_isnan (__high) || __builtin_isinf (__high)) \ - RESULT = (__float128) __high; \ + RESULT = (TFtype) __high; \ \ /* If low is 0.0, there no need to do the add. In addition, \ avoiding the add produces the correct sign if high is -0.0. */ \ else if (__low == 0.0) \ - RESULT = (__float128) __high; \ + RESULT = (TFtype) __high; \ \ else \ - RESULT = ((__float128) __high) + ((__float128) __low); \ + RESULT = ((TFtype) __high) + ((TFtype) __low); \ } Index: libgcc/config/rs6000/ibm-ldouble.c =================================================================== --- libgcc/config/rs6000/ibm-ldouble.c (revision 256120) +++ libgcc/config/rs6000/ibm-ldouble.c (working copy) @@ -56,6 +56,15 @@ see the files COPYING3 and COPYING.RUNTI #define nonfinite(a) unlikely (! isless (fabs (a), inf ())) +/* If we have __float128/_Float128, use __ibm128 instead of long double. On + other systems, use long double, because __ibm128 might not have been + created. */ +#ifdef __FLOAT128__ +#define IBM128_TYPE __ibm128 +#else +#define IBM128_TYPE long double +#endif + /* Define ALIASNAME as a strong alias for NAME. */ # define strong_alias(name, aliasname) _strong_alias(name, aliasname) # define _strong_alias(name, aliasname) \ @@ -65,10 +74,10 @@ see the files COPYING3 and COPYING.RUNTI but GCC currently generates poor code when a union is used to turn a long double into a pair of doubles. */ -long double __gcc_qadd (double, double, double, double); -long double __gcc_qsub (double, double, double, double); -long double __gcc_qmul (double, double, double, double); -long double __gcc_qdiv (double, double, double, double); +IBM128_TYPE __gcc_qadd (double, double, double, double); +IBM128_TYPE __gcc_qsub (double, double, double, double); +IBM128_TYPE __gcc_qmul (double, double, double, double); +IBM128_TYPE __gcc_qdiv (double, double, double, double); #if defined __ELF__ && defined SHARED \ && (defined __powerpc64__ || !(defined __linux__ || defined __gnu_hurd__)) @@ -88,17 +97,17 @@ __asm__ (".symver __gcc_qadd,_xlqadd@GCC ".symver .__gcc_qdiv,._xlqdiv@GCC_3.4"); #endif -/* Combine two 'double' values into one 'long double' and return the result. */ -static inline long double +/* Combine two 'double' values into one 'IBM128_TYPE' and return the result. */ +static inline IBM128_TYPE pack_ldouble (double dh, double dl) { -#if defined (__LONG_DOUBLE_128__) \ +#if defined (__LONG_DOUBLE_128__) && defined (__LONG_DOUBLE_IBM128__) \ && !(defined (_SOFT_FLOAT) || defined (__NO_FPRS__)) return __builtin_pack_longdouble (dh, dl); #else union { - long double ldval; + IBM128_TYPE ldval; double dval[2]; } x; x.dval[0] = dh; @@ -107,8 +116,8 @@ pack_ldouble (double dh, double dl) #endif } -/* Add two 'long double' values and return the result. */ -long double +/* Add two 'IBM128_TYPE' values and return the result. */ +IBM128_TYPE __gcc_qadd (double a, double aa, double c, double cc) { double xh, xl, z, q, zz; @@ -147,7 +156,7 @@ __gcc_qadd (double a, double aa, double return pack_ldouble (xh, xl); } -long double +IBM128_TYPE __gcc_qsub (double a, double b, double c, double d) { return __gcc_qadd (a, b, -c, -d); @@ -157,7 +166,7 @@ __gcc_qsub (double a, double b, double c static double fmsub (double, double, double); #endif -long double +IBM128_TYPE __gcc_qmul (double a, double b, double c, double d) { double xh, xl, t, tau, u, v, w; @@ -181,7 +190,7 @@ __gcc_qmul (double a, double b, double c tau += v + w; /* Add in other second-order terms. */ u = t + tau; - /* Construct long double result. */ + /* Construct IBM128_TYPE result. */ if (nonfinite (u)) return u; xh = u; @@ -189,7 +198,7 @@ __gcc_qmul (double a, double b, double c return pack_ldouble (xh, xl); } -long double +IBM128_TYPE __gcc_qdiv (double a, double b, double c, double d) { double xh, xl, s, sigma, t, tau, u, v, w; @@ -226,7 +235,7 @@ __gcc_qdiv (double a, double b, double c tau = ((v-sigma)+w)/c; /* Correction to t. */ u = t + tau; - /* Construct long double result. */ + /* Construct IBM128_TYPE result. */ if (nonfinite (u)) return u; xh = u; @@ -236,32 +245,32 @@ __gcc_qdiv (double a, double b, double c #if defined (_SOFT_DOUBLE) && defined (__LONG_DOUBLE_128__) -long double __gcc_qneg (double, double); +IBM128_TYPE __gcc_qneg (double, double); int __gcc_qeq (double, double, double, double); int __gcc_qne (double, double, double, double); int __gcc_qge (double, double, double, double); int __gcc_qle (double, double, double, double); -long double __gcc_stoq (float); -long double __gcc_dtoq (double); +IBM128_TYPE __gcc_stoq (float); +IBM128_TYPE __gcc_dtoq (double); float __gcc_qtos (double, double); double __gcc_qtod (double, double); int __gcc_qtoi (double, double); unsigned int __gcc_qtou (double, double); -long double __gcc_itoq (int); -long double __gcc_utoq (unsigned int); +IBM128_TYPE __gcc_itoq (int); +IBM128_TYPE __gcc_utoq (unsigned int); extern int __eqdf2 (double, double); extern int __ledf2 (double, double); extern int __gedf2 (double, double); -/* Negate 'long double' value and return the result. */ -long double +/* Negate 'IBM128_TYPE' value and return the result. */ +IBM128_TYPE __gcc_qneg (double a, double aa) { return pack_ldouble (-a, -aa); } -/* Compare two 'long double' values for equality. */ +/* Compare two 'IBM128_TYPE' values for equality. */ int __gcc_qeq (double a, double aa, double c, double cc) { @@ -272,7 +281,7 @@ __gcc_qeq (double a, double aa, double c strong_alias (__gcc_qeq, __gcc_qne); -/* Compare two 'long double' values for less than or equal. */ +/* Compare two 'IBM128_TYPE' values for less than or equal. */ int __gcc_qle (double a, double aa, double c, double cc) { @@ -283,7 +292,7 @@ __gcc_qle (double a, double aa, double c strong_alias (__gcc_qle, __gcc_qlt); -/* Compare two 'long double' values for greater than or equal. */ +/* Compare two 'IBM128_TYPE' values for greater than or equal. */ int __gcc_qge (double a, double aa, double c, double cc) { @@ -294,35 +303,35 @@ __gcc_qge (double a, double aa, double c strong_alias (__gcc_qge, __gcc_qgt); -/* Convert single to long double. */ -long double +/* Convert single to IBM128_TYPE. */ +IBM128_TYPE __gcc_stoq (float a) { return pack_ldouble ((double) a, 0.0); } -/* Convert double to long double. */ -long double +/* Convert double to IBM128_TYPE. */ +IBM128_TYPE __gcc_dtoq (double a) { return pack_ldouble (a, 0.0); } -/* Convert long double to single. */ +/* Convert IBM128_TYPE to single. */ float __gcc_qtos (double a, double aa __attribute__ ((__unused__))) { return (float) a; } -/* Convert long double to double. */ +/* Convert IBM128_TYPE to double. */ double __gcc_qtod (double a, double aa __attribute__ ((__unused__))) { return a; } -/* Convert long double to int. */ +/* Convert IBM128_TYPE to int. */ int __gcc_qtoi (double a, double aa) { @@ -330,7 +339,7 @@ __gcc_qtoi (double a, double aa) return (int) z; } -/* Convert long double to unsigned int. */ +/* Convert IBM128_TYPE to unsigned int. */ unsigned int __gcc_qtou (double a, double aa) { @@ -338,15 +347,15 @@ __gcc_qtou (double a, double aa) return (unsigned int) z; } -/* Convert int to long double. */ -long double +/* Convert int to IBM128_TYPE. */ +IBM128_TYPE __gcc_itoq (int a) { return __gcc_dtoq ((double) a); } -/* Convert unsigned int to long double. */ -long double +/* Convert unsigned int to IBM128_TYPE. */ +IBM128_TYPE __gcc_utoq (unsigned int a) { return __gcc_dtoq ((double) a); @@ -361,7 +370,7 @@ int __gcc_qunord (double, double, double extern int __eqdf2 (double, double); extern int __unorddf2 (double, double); -/* Compare two 'long double' values for unordered. */ +/* Compare two 'IBM128_TYPE' values for unordered. */ int __gcc_qunord (double a, double aa, double c, double cc) { @@ -389,7 +398,7 @@ fmsub (double a, double b, double c) FP_DECL_Q(V); FP_DECL_D(R); double r; - long double u, x, y, z; + IBM128_TYPE u, x, y, z; FP_INIT_ROUNDMODE; FP_UNPACK_RAW_D (A, a); Index: libgcc/config/rs6000/_mulkc3.c =================================================================== --- libgcc/config/rs6000/_mulkc3.c (revision 256120) +++ libgcc/config/rs6000/_mulkc3.c (working copy) @@ -23,11 +23,11 @@ see the files COPYING3 and COPYING.RUNTI /* This is a temporary specialization of code from libgcc/libgcc2.c. */ -typedef float KFtype __attribute__ ((mode (KF))); -typedef __complex float KCtype __attribute__ ((mode (KC))); +#include "soft-fp.h" +#include "quad-float128.h" -#define COPYSIGN(x,y) __builtin_copysignq (x, y) -#define INFINITY __builtin_infq () +#define COPYSIGN(x,y) __builtin_copysignf128 (x, y) +#define INFINITY __builtin_inff128 () #define isnan __builtin_isnan #define isinf __builtin_isinf @@ -35,13 +35,11 @@ typedef __complex float KCtype __attribu #define __mulkc3 __mulkc3_sw #endif -extern KCtype __mulkc3 (KFtype, KFtype, KFtype, KFtype); - -KCtype -__mulkc3 (KFtype a, KFtype b, KFtype c, KFtype d) +TCtype +__mulkc3 (TFtype a, TFtype b, TFtype c, TFtype d) { - KFtype ac, bd, ad, bc, x, y; - KCtype res; + TFtype ac, bd, ad, bc, x, y; + TCtype res; ac = a * c; bd = b * d; Index: libgcc/config/rs6000/_divkc3.c =================================================================== --- libgcc/config/rs6000/_divkc3.c (revision 256120) +++ libgcc/config/rs6000/_divkc3.c (working copy) @@ -23,12 +23,12 @@ see the files COPYING3 and COPYING.RUNTI /* This is a temporary specialization of code from libgcc/libgcc2.c. */ -typedef float KFtype __attribute__ ((mode (KF))); -typedef __complex float KCtype __attribute__ ((mode (KC))); +#include "soft-fp.h" +#include "quad-float128.h" -#define COPYSIGN(x,y) __builtin_copysignq (x, y) -#define INFINITY __builtin_infq () -#define FABS __builtin_fabsq +#define COPYSIGN(x,y) __builtin_copysignf128 (x, y) +#define INFINITY __builtin_inff128 () +#define FABS __builtin_fabsf128 #define isnan __builtin_isnan #define isinf __builtin_isinf #define isfinite __builtin_isfinite @@ -37,13 +37,11 @@ typedef __complex float KCtype __attribu #define __divkc3 __divkc3_sw #endif -extern KCtype __divkc3 (KFtype, KFtype, KFtype, KFtype); - -KCtype -__divkc3 (KFtype a, KFtype b, KFtype c, KFtype d) +TCtype +__divkc3 (TFtype a, TFtype b, TFtype c, TFtype d) { - KFtype denom, ratio, x, y; - KCtype res; + TFtype denom, ratio, x, y; + TCtype res; /* ??? We can get better behavior from logarithmic scaling instead of the division. But that would mean starting to link libgcc against Index: libgcc/config/rs6000/extendkftf2-sw.c =================================================================== --- libgcc/config/rs6000/extendkftf2-sw.c (revision 256120) +++ libgcc/config/rs6000/extendkftf2-sw.c (working copy) @@ -44,7 +44,7 @@ #endif IBM128_TYPE -__extendkftf2_sw (__float128 value) +__extendkftf2_sw (TFtype value) { IBM128_TYPE ret; Index: libgcc/config/rs6000/trunctfkf2-sw.c =================================================================== --- libgcc/config/rs6000/trunctfkf2-sw.c (revision 256120) +++ libgcc/config/rs6000/trunctfkf2-sw.c (working copy) @@ -43,10 +43,10 @@ #define __trunctfkf2_sw __trunctfkf2 #endif -__float128 +TFtype __trunctfkf2_sw (IBM128_TYPE value) { - __float128 ret; + TFtype ret; CVT_IBM128_TO_FLOAT128 (ret, value); return ret;