From patchwork Thu Jan 21 21:25:26 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Meissner X-Patchwork-Id: 571356 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 549861402D8 for ; Fri, 22 Jan 2016 08:25:44 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=aGCHsLLN; 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:message-id:references:mime-version :content-type:in-reply-to; q=dns; s=default; b=XHJ/CvaJuVK3xiILN MgnAUE5YYJJyaeEdZEL+agCeF/4cJ9XvCObigNNEKrApKblsYawTz6h8D3J86Y8r cMghvUgAZGuRJFZ5D+WT3doXS9FbZ59GiaJSHHP/Uf9Pm8n8FU6E1OlX4bSx8NUR lezkBPWj4dT63BphRk3HUNVn64= 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:message-id:references:mime-version :content-type:in-reply-to; s=default; bh=KN4hB3qFJaDOPfeNLMe9Uph 6sfU=; b=aGCHsLLNKmQ51xPWHO5vSfIj7R3wi0OlHoNh5x8cdiSQLys2os9fHmI mnvZxccbCYms2SiZ5kuyYSSZrEzVYx/wlfMXn2Hw0aHRfTX/8ozsGGd/YOu/BZPB ySriY4bHDV8kJhmsUJqGMjn4ePBz3cvImnGBK+hjDA1BqT7maATk= Received: (qmail 52958 invoked by alias); 21 Jan 2016 21:25:35 -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 52947 invoked by uid 89); 21 Jan 2016 21:25:35 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=2.2 required=5.0 tests=AWL, BAYES_50, KAM_ASCII_DIVIDERS, KAM_LAZY_DOMAIN_SECURITY autolearn=no version=3.3.2 spammy=Input, IEEE, *prefix, meissnerlinuxvnetibmcom X-HELO: e17.ny.us.ibm.com Received: from e17.ny.us.ibm.com (HELO e17.ny.us.ibm.com) (129.33.205.207) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Thu, 21 Jan 2016 21:25:33 +0000 Received: from localhost by e17.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 21 Jan 2016 16:25:31 -0500 Received: from d01dlp01.pok.ibm.com (9.56.250.166) by e17.ny.us.ibm.com (146.89.104.204) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 21 Jan 2016 16:25:29 -0500 X-IBM-Helo: d01dlp01.pok.ibm.com X-IBM-MailFrom: meissner@ibm-tiger.the-meissners.org X-IBM-RcptTo: gcc-patches@gcc.gnu.org Received: from b01cxnp22034.gho.pok.ibm.com (b01cxnp22034.gho.pok.ibm.com [9.57.198.24]) by d01dlp01.pok.ibm.com (Postfix) with ESMTP id 075FE38C8039 for ; Thu, 21 Jan 2016 16:25:28 -0500 (EST) Received: from d01av02.pok.ibm.com (d01av02.pok.ibm.com [9.56.224.216]) by b01cxnp22034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u0LLPReW28115098 for ; Thu, 21 Jan 2016 21:25:28 GMT Received: from d01av02.pok.ibm.com (localhost [127.0.0.1]) by d01av02.pok.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u0LLPRrI000954 for ; Thu, 21 Jan 2016 16:25:27 -0500 Received: from ibm-tiger.the-meissners.org (dhcp-9-32-77-111.usma.ibm.com [9.32.77.111]) by d01av02.pok.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id u0LLPQYI000882; Thu, 21 Jan 2016 16:25:26 -0500 Received: by ibm-tiger.the-meissners.org (Postfix, from userid 500) id 5D65945F3E; Thu, 21 Jan 2016 16:25:26 -0500 (EST) Date: Thu, 21 Jan 2016 16:25:26 -0500 From: Michael Meissner To: David Edelsohn Cc: Michael Meissner , Joseph Myers , GCC Patches , Steven Munroe , Tulio Magno Quites Machado Filho Subject: Re: [PATCH], PowerPC IEEE 128-bit fp, #12 (default -mfloat128 on PowerPC-Linux) Message-ID: <20160121212525.GA18118@ibm-tiger.the-meissners.org> Mail-Followup-To: Michael Meissner , David Edelsohn , Joseph Myers , GCC Patches , Steven Munroe , Tulio Magno Quites Machado Filho References: <20160106224754.GA1627@ibm-tiger.the-meissners.org> <20160111185547.GA27662@ibm-tiger.the-meissners.org> <20160112183143.GA17279@ibm-tiger.the-meissners.org> <20160114220316.GA23218@ibm-tiger.the-meissners.org> <20160121010020.GA25262@ibm-tiger.the-meissners.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.20 (2009-12-10) X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16012121-0041-0000-0000-000003158B59 X-IsSubscribed: yes This is the final patch (at least so far) that turns on -mfloat128 by default for PowerPC Linux systems where the VSX instruction set is enabled. As I mentioned in the last email, because we don't build the __float128 emulator on other systems, I didn't think it would be useful to make it the default. I did a boostrap build/check with no regressions on a little endian power8 system. Are the patches ok to check in? [gcc] 2016-01-21 Michael Meissner * config/rs6000/rs6000.c (rs6000_option_override_internal): Enable -mfloat128 by default on PowerPC Linux systems with the VSX instruction enabled. [gcc/testsuite] 2016-01-21 Michael Meissner * gcc.target/powerpc/float128-1.c: New test for IEEE 128-bit floating point support. * gcc.target/powerpc/float128-2.c: Likewise. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 232690) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -4236,6 +4236,15 @@ rs6000_option_override_internal (bool gl } } + /* At present, we only build the __float128 emulator on PowerPC Linux. + Enable default __float128 support for PowerPC Linux systems, but not for + others. */ +#ifdef POWERPC_LINUX + if (TARGET_VSX && !TARGET_FLOAT128 + && (rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128) == 0) + rs6000_isa_flags |= OPTION_MASK_FLOAT128; +#endif + /* __float128 requires VSX support. */ if (TARGET_FLOAT128 && !TARGET_VSX) { Index: gcc/testsuite/gcc.target/powerpc/float128-1.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-1.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/float128-1.c (revision 0) @@ -0,0 +1,147 @@ +/* { dg-do run { target { powerpc*-*-linux* } } } */ +/* { dg-require-effective-target ppc_float128_sw } */ +/* { dg-options "-mcpu=power7 -O2 -mfloat128 -static-libgcc" } */ + +#ifdef DEBUG +#include +#include +#include +#include +#endif + +#if !defined(__FLOAT128__) || !defined(_ARCH_PPC) +static __float128 +pass_through (__float128 x) +{ + return x; +} + +__float128 (*no_optimize) (__float128) = pass_through; +#endif + +#ifdef DEBUG +__attribute__((__noinline__)) +static void +print_f128 (__float128 x) +{ + unsigned sign; + unsigned exponent; + uint64_t mantissa1; + uint64_t mantissa2; + uint64_t upper; + uint64_t lower; + +#if defined(_ARCH_PPC) && defined(__BIG_ENDIAN__) + struct ieee128 { + uint64_t upper; + uint64_t lower; + }; + +#elif (defined(_ARCH_PPC) && defined(__LITTLE_ENDIAN__)) || defined(__x86_64__) + struct ieee128 { + uint64_t lower; + uint64_t upper; + }; + +#else +#error "Unknown system" +#endif + + union { + __float128 f128; + struct ieee128 s128; + } u; + + u.f128 = x; + upper = u.s128.upper; + lower = u.s128.lower; + + sign = (unsigned)((upper >> 63) & 1); + exponent = (unsigned)((upper >> 48) & ((((uint64_t)1) << 16) - 1)); + mantissa1 = (upper & ((((uint64_t)1) << 48) - 1)); + mantissa2 = lower; + + printf ("%c 0x%.4x 0x%.12" PRIx64 " 0x%.16" PRIx64, + sign ? '-' : '+', + exponent, + mantissa1, + mantissa2); +} +#endif + +__attribute__((__noinline__)) +static void +do_test (__float128 expected, __float128 got, const char *name) +{ + int equal_p = (expected == got); + +#ifdef DEBUG + printf ("Test %s, expected: ", name); + print_f128 (expected); + printf (" %5g, got: ", (double) expected); + print_f128 (got); + printf (" %5g, result %s\n", + (double) got, + (equal_p) ? "equal" : "not equal"); +#endif + + if (!equal_p) + __builtin_abort (); +} + + +int +main (void) +{ + __float128 one = 1.0q; + __float128 two = 2.0q; + __float128 three = 3.0q; + __float128 four = 4.0q; + __float128 five = 5.0q; + __float128 add_result = (1.0q + 2.0q); + __float128 mul_result = ((1.0q + 2.0q) * 3.0q); + __float128 div_result = (((1.0q + 2.0q) * 3.0q) / 4.0q); + __float128 sub_result = ((((1.0q + 2.0q) * 3.0q) / 4.0q) - 5.0q); + __float128 neg_result = - sub_result; + __float128 add_xresult; + __float128 mul_xresult; + __float128 div_xresult; + __float128 sub_xresult; + __float128 neg_xresult; + +#if defined(__FLOAT128__) && defined(_ARCH_PPC) + __asm__ (" #prevent constant folding, %x0" : "+wa" (one)); + __asm__ (" #prevent constant folding, %x0" : "+wa" (two)); + __asm__ (" #prevent constant folding, %x0" : "+wa" (three)); + __asm__ (" #prevent constant folding, %x0" : "+wa" (four)); + __asm__ (" #prevent constant folding, %x0" : "+wa" (five)); + +#else + one = no_optimize (one); + two = no_optimize (two); + three = no_optimize (three); + four = no_optimize (four); + five = no_optimize (five); +#endif + + add_xresult = (one + two); + do_test (add_result, add_xresult, "add"); + + mul_xresult = add_xresult * three; + do_test (mul_result, mul_xresult, "mul"); + + div_xresult = mul_xresult / four; + do_test (div_result, div_xresult, "div"); + + sub_xresult = div_xresult - five; + do_test (sub_result, sub_xresult, "sub"); + + neg_xresult = - sub_xresult; + do_test (neg_result, neg_xresult, "neg"); + +#ifdef DEBUG + printf ("Passed\n"); +#endif + + return 0; +} Index: gcc/testsuite/gcc.target/powerpc/float128-2.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-2.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/float128-2.c (revision 0) @@ -0,0 +1,226 @@ +/* { dg-do run { target { powerpc*-*-linux* } } } */ +/* { dg-require-effective-target ppc_float128_sw } */ +/* { dg-options "-mcpu=power7 -O2 -mfloat128 -static-libgcc" } */ + +/* + * Test program to make sure we are getting more precision than the 53 bits we + * get with IEEE double. + */ + +#include +#include +#include +#include + +#ifndef TYPE +#define TYPE __float128 +#endif + +#ifndef NO_INLINE +#define NO_INLINE __attribute__((__noinline__)) +#endif + +static TYPE power_of_two (ssize_t) NO_INLINE; +static TYPE calc1 (TYPE) NO_INLINE; +static TYPE calc2 (TYPE) NO_INLINE; +static TYPE calc3 (TYPE) NO_INLINE; + +#ifndef POWER2 +#define POWER2 60 +#endif + + +/* + * Print TYPE in hex. + */ + + +#if defined(DEBUG) || defined(DEBUG2) +static void print_hex (const char *prefix, TYPE, const char *suffix) NO_INLINE; + +#if defined (__i386__) || defined (__x86_64__) || defined (__LITTLE_ENDIAN__) +#define ENDIAN_REVERSE(N, MAX) ((MAX) - 1 - (N)) + +#else +#define ENDIAN_REVERSE(N, MAX) (N) +#endif + +static void +print_hex (const char *prefix, TYPE value, const char *suffix) +{ + union { + TYPE f128; + unsigned char uc[sizeof (TYPE)]; + } u; + + size_t i; + + u.f128 = value; + printf ("%s0x", prefix); + for (i = 0; i < sizeof (TYPE); i++) + printf ("%.2x", u.uc[ ENDIAN_REVERSE (i, sizeof (TYPE)) ]); + + printf (", %24.2Lf%s", (long double)value, suffix); +} +#endif + + +/* + * Return a power of two. + */ + +static TYPE +power_of_two (ssize_t num) +{ + TYPE ret = (TYPE) 1.0; + ssize_t i; + + if (num >= 0) + { + for (i = 0; i < num; i++) + ret *= (TYPE) 2.0; + } + else + { + ssize_t num2 = -num; + for (i = 0; i < num2; i++) + ret /= (TYPE) 2.0; + } + +#ifdef DEBUG + printf ("power_of_two (%2ld) = ", (long) num); + print_hex ("", ret, "\n"); +#endif + + return ret; +} + + +#ifdef ADDSUB +static TYPE add (TYPE a, TYPE b) NO_INLINE; +static TYPE sub (TYPE a, TYPE b) NO_INLINE; + +static TYPE +add (TYPE a, TYPE b) +{ + TYPE c; +#ifdef DEBUG + print_hex ("add, arg1 = ", a, "\n"); + print_hex ("add, arg2 = ", b, "\n"); +#endif + c = a + b; +#ifdef DEBUG + print_hex ("add, result = ", c, "\n"); +#endif + return c; +} + +static TYPE +sub (TYPE a, TYPE b) +{ + TYPE c; +#ifdef DEBUG + print_hex ("sub, arg1 = ", a, "\n"); + print_hex ("sub, arg2 = ", b, "\n"); +#endif + c = a - b; +#ifdef DEBUG + print_hex ("sub, result = ", c, "\n"); +#endif + return c; +} + +#else +#define add(x, y) ((x) + (y)) +#define sub(x, y) ((x) - (y)) +#endif + +/* + * Various calculations. Add in 2**POWER2, and subtract 2**(POWER2-1) twice, and we should + * get the original value. + */ + +static TYPE +calc1 (TYPE num) +{ + TYPE num2 = add (power_of_two (POWER2), num); + TYPE ret; + +#ifdef DEBUG + print_hex ("calc1 (before call) = ", num2, "\n"); +#endif + + ret = calc2 (num2); + +#ifdef DEBUG + print_hex ("calc1 (after call) = ", ret, "\n"); +#endif + + return ret; +} + +static TYPE +calc2 (TYPE num) +{ + TYPE num2 = sub (num, power_of_two (POWER2-1)); + TYPE ret; + +#ifdef DEBUG + print_hex ("calc2 (before call) = ", num2, "\n"); +#endif + + ret = calc3 (num2); + +#ifdef DEBUG + print_hex ("calc2 (after call) = ", ret, "\n"); +#endif + + return ret; +} + +static TYPE +calc3 (TYPE num) +{ + TYPE ret = sub (num, (((TYPE) 2.0) * power_of_two (POWER2-2))); + +#ifdef DEBUG + print_hex ("calc3 = ", ret, "\n"); +#endif + + return ret; +} + + +int +main (void) +{ + TYPE input, output; + +#ifdef DEBUG + printf ("Testing, %ld bytes\n", (long) sizeof (TYPE)); +#endif + + input = power_of_two (-1); + if ((double)input != 0.5) + { +#if defined(DEBUG) || defined(DEBUG2) + print_hex ("Input should be 0.5: ", output, "\n"); + return 1; +#else + __builtin_abort (); +#endif + } + + output = calc1 (input); + if ((double)output != 0.5) + { +#if defined(DEBUG) || defined(DEBUG2) + print_hex ("Output should be 0.5: ", output, "\n"); + return 1; +#else + __builtin_abort (); +#endif + } + + return 0; +}