From patchwork Wed May 6 21:03:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Uros Bizjak X-Patchwork-Id: 1284765 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=rDvDC04P; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49HTbX3YC1z9sRf for ; Thu, 7 May 2020 07:03:51 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 0BDB2386F819; Wed, 6 May 2020 21:03:48 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 0BDB2386F819 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1588799028; bh=IU4Xi9kgRXcVZUca6F+5t+AbZC9Gm7hAYv4ww7KgqEg=; h=Date:Subject:To:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=rDvDC04PBCkX9AlbmVhfzty+BLkOqX16hoSJTUDK1yczyR5I5fuAYCXm3dXYMJZBl i7zeScrRNz1uH++dQUscfrM1khFiORJx4bjoanYaoee0X8ZZkcmPM6YDCpJhcre7u7 Xc9v2bsWcZHgs1limtcmt4A3Wdb7QKK5vX4t7vQI= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-il1-x134.google.com (mail-il1-x134.google.com [IPv6:2607:f8b0:4864:20::134]) by sourceware.org (Postfix) with ESMTPS id 602AF386F819 for ; Wed, 6 May 2020 21:03:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 602AF386F819 Received: by mail-il1-x134.google.com with SMTP id c18so3181185ile.5 for ; Wed, 06 May 2020 14:03:45 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=IU4Xi9kgRXcVZUca6F+5t+AbZC9Gm7hAYv4ww7KgqEg=; b=tsGpo7dC/LZr67/v6FWbee0SEUpqMaXAARZ49al2ku+OfBm+Zl/s2qcmv91tTc9HCo PEp9J/E4b0HH458MAq82i+ajsoGqCbCPsRCKJdxnWcW7JfA5zpu36FmzOIzroP7lL7zz 5YJknwgXa4zvGKavt4zpIr89NlTDg00PoWbzrFBxdBYwl/AXm6ow11j7BLHE3JRsYL1L bTtibjrr7/RC6PiFA4MMkLnSZiexMo1RlOtnPye5iGvHRhw86Xv5qggqG1K1do25gsww mb+JaiJnJE4pMskCwMs5uWLRGfK52HtdHfpBMA/jYZkLlTRpDsmSqU8YKEtJ3uQRZCvh rdzA== X-Gm-Message-State: AGi0Pub8Cj2gjcrLYfiZHW0QkRcndu+efLcJhcoX8BjYaMA33z6+pAq+ jpUvf4wbfVIe18SpTnTnkFN5pptE3IJ5tGyngfM73yzUDZw= X-Google-Smtp-Source: APiQypKQtn5SV6rQrgNuKkzS0o6bpwRD8AS3sHY5c17cOa2qhBXnrxjG2FjuUH7R8bMaXGNFBaBt6ad7MS6CaFzYkJ0= X-Received: by 2002:a92:5a54:: with SMTP id o81mr5661046ilb.128.1588799024554; Wed, 06 May 2020 14:03:44 -0700 (PDT) MIME-Version: 1.0 Date: Wed, 6 May 2020 23:03:33 +0200 Message-ID: Subject: [committed] i386: Use generic division to generate INEXACT exception To: "gcc-patches@gcc.gnu.org" X-Spam-Status: No, score=-11.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Uros Bizjak via Gcc-patches From: Uros Bizjak Reply-To: Uros Bizjak Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" Introduce math_force_eval_div to use generic division to generate INEXACT as well as INVALID and DIVZERO exceptions. libgcc/ChangeLog: 2020-05-06 Uroš Bizjak * config/i386/sfp-exceptions.c (__math_force_eval): Remove. (__math_force_eval_div): New define. (__sfp_handle_exceptions): Use __math_force_eval_div to use generic division to generate INVALID, DIVZERO and INEXACT exceptions. libatomic/ChangeLog: 2020-05-06 Uroš Bizjak * config/x86/fenv.c (__math_force_eval): Remove. (__math_force_eval_div): New define. (__atomic_deraiseexcept): Use __math_force_eval_div to use generic division to generate INVALID, DIVZERO and INEXACT exceptions. libgfortran/ChangeLog: 2020-05-06 Uroš Bizjak * config/fpu-387.h (__math_force_eval): Remove. (__math_force_eval_div): New define. (local_feraiseexcept): Use __math_force_eval_div to use generic division to generate INVALID, DIVZERO and INEXACT exceptions. (struct fenv): Define named struct instead of typedef. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Committed to mainline. Uros. diff --git a/libatomic/config/x86/fenv.c b/libatomic/config/x86/fenv.c index d972a99f594..88622c613f3 100644 --- a/libatomic/config/x86/fenv.c +++ b/libatomic/config/x86/fenv.c @@ -48,9 +48,11 @@ struct fenv }; #ifdef __SSE_MATH__ -# define __math_force_eval(x) asm volatile ("" : : "x" (x)); +# define __math_force_eval_div(x, y) \ + do { asm ("" : "+x" (x)); asm volatile ("" : : "x" (x / y)); } while (0) #else -# define __math_force_eval(x) asm volatile ("" : : "f" (x)); +# define __math_force_eval_div(x, y) \ + do { asm ("" : "+t" (x)); asm volatile ("" : : "f" (x / y)); } while (0) #endif /* Raise the supported floating-point exceptions from EXCEPTS. Other @@ -59,14 +61,15 @@ struct fenv void __atomic_feraiseexcept (int excepts) { + struct fenv temp; + if (excepts & FE_INVALID) { float f = 0.0f; - __math_force_eval (f / f); + __math_force_eval_div (f, f); } if (excepts & FE_DENORM) { - struct fenv temp; asm volatile ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= FE_DENORM; asm volatile ("fldenv\t%0" : : "m" (temp)); @@ -75,11 +78,10 @@ __atomic_feraiseexcept (int excepts) if (excepts & FE_DIVBYZERO) { float f = 1.0f, g = 0.0f; - __math_force_eval (f / g); + __math_force_eval_div (f, g); } if (excepts & FE_OVERFLOW) { - struct fenv temp; asm volatile ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= FE_OVERFLOW; asm volatile ("fldenv\t%0" : : "m" (temp)); @@ -87,7 +89,6 @@ __atomic_feraiseexcept (int excepts) } if (excepts & FE_UNDERFLOW) { - struct fenv temp; asm volatile ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= FE_UNDERFLOW; asm volatile ("fldenv\t%0" : : "m" (temp)); @@ -96,11 +97,6 @@ __atomic_feraiseexcept (int excepts) if (excepts & FE_INEXACT) { float f = 1.0f, g = 3.0f; -#ifdef __SSE_MATH__ - asm volatile ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g)); -#else - asm volatile ("fdivs\t%1" : "+t" (f) : "m" (g)); - /* No need for fwait, exception is triggered by emitted fstp. */ -#endif + __math_force_eval_div (f, g); } } diff --git a/libgcc/config/i386/sfp-exceptions.c b/libgcc/config/i386/sfp-exceptions.c index 4b3a7a08da1..72cb0f4d3bb 100644 --- a/libgcc/config/i386/sfp-exceptions.c +++ b/libgcc/config/i386/sfp-exceptions.c @@ -42,22 +42,25 @@ struct fenv }; #ifdef __SSE_MATH__ -# define __math_force_eval(x) asm volatile ("" : : "x" (x)); +# define __math_force_eval_div(x, y) \ + do { asm ("" : "+x" (x)); asm volatile ("" : : "x" (x / y)); } while (0) #else -# define __math_force_eval(x) asm volatile ("" : : "f" (x)); +# define __math_force_eval_div(x, y) \ + do { asm ("" : "+t" (x)); asm volatile ("" : : "f" (x / y)); } while (0) #endif void __sfp_handle_exceptions (int _fex) { + struct fenv temp; + if (_fex & FP_EX_INVALID) { float f = 0.0f; - __math_force_eval (f / f); + __math_force_eval_div (f, f); } if (_fex & FP_EX_DENORM) { - struct fenv temp; asm volatile ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= FP_EX_DENORM; asm volatile ("fldenv\t%0" : : "m" (temp)); @@ -66,11 +69,10 @@ __sfp_handle_exceptions (int _fex) if (_fex & FP_EX_DIVZERO) { float f = 1.0f, g = 0.0f; - __math_force_eval (f / g); + __math_force_eval_div (f, g); } if (_fex & FP_EX_OVERFLOW) { - struct fenv temp; asm volatile ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= FP_EX_OVERFLOW; asm volatile ("fldenv\t%0" : : "m" (temp)); @@ -78,7 +80,6 @@ __sfp_handle_exceptions (int _fex) } if (_fex & FP_EX_UNDERFLOW) { - struct fenv temp; asm volatile ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= FP_EX_UNDERFLOW; asm volatile ("fldenv\t%0" : : "m" (temp)); @@ -87,12 +88,7 @@ __sfp_handle_exceptions (int _fex) if (_fex & FP_EX_INEXACT) { float f = 1.0f, g = 3.0f; -#ifdef __SSE_MATH__ - asm volatile ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g)); -#else - asm volatile ("fdivs\t%1" : "+t" (f) : "m" (g)); - /* No need for fwait, exception is triggered by emitted fstp. */ -#endif + __math_force_eval_div (f, g); } } #endif diff --git a/libgfortran/config/fpu-387.h b/libgfortran/config/fpu-387.h index 41b82bc8098..8b5e758c2ca 100644 --- a/libgfortran/config/fpu-387.h +++ b/libgfortran/config/fpu-387.h @@ -69,7 +69,7 @@ has_sse (void) /* This structure corresponds to the layout of the block written by FSTENV. */ -typedef struct +struct fenv { unsigned short int __control_word; unsigned short int __unused1; @@ -79,22 +79,28 @@ typedef struct unsigned short int __unused3; unsigned int __eip; unsigned short int __cs_selector; - unsigned short int __opcode; + unsigned int __opcode:11; + unsigned int __unused4:5; unsigned int __data_offset; unsigned short int __data_selector; unsigned short int __unused5; unsigned int __mxcsr; -} -my_fenv_t; +}; /* Check we can actually store the FPU state in the allocated size. */ -_Static_assert (sizeof(my_fenv_t) <= (size_t) GFC_FPE_STATE_BUFFER_SIZE, +_Static_assert (sizeof(struct fenv) <= (size_t) GFC_FPE_STATE_BUFFER_SIZE, "GFC_FPE_STATE_BUFFER_SIZE is too small"); #ifdef __SSE_MATH__ -# define __math_force_eval(x) __asm__ __volatile__ ("" : : "x" (x)); +# define __math_force_eval_div(x, y) \ + do { \ + __asm__ ("" : "+x" (x)); __asm__ __volatile__ ("" : : "x" (x / y)); \ + } while (0) #else -# define __math_force_eval(x) __asm__ __volatile__ ("" : : "f" (x)); +# define __math_force_eval_div(x, y) \ + do { \ + __asm__ ("" : "+t" (x)); __asm__ __volatile__ ("" : : "f" (x / y)); \ + } while (0) #endif /* Raise the supported floating-point exceptions from EXCEPTS. Other @@ -104,14 +110,15 @@ _Static_assert (sizeof(my_fenv_t) <= (size_t) GFC_FPE_STATE_BUFFER_SIZE, static void local_feraiseexcept (int excepts) { + struct fenv temp; + if (excepts & _FPU_MASK_IM) { float f = 0.0f; - __math_force_eval (f / f); + __math_force_eval_div (f, f); } if (excepts & _FPU_MASK_DM) { - my_fenv_t temp; __asm__ __volatile__ ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= _FPU_MASK_DM; __asm__ __volatile__ ("fldenv\t%0" : : "m" (temp)); @@ -120,11 +127,10 @@ local_feraiseexcept (int excepts) if (excepts & _FPU_MASK_ZM) { float f = 1.0f, g = 0.0f; - __math_force_eval (f / g); + __math_force_eval_div (f, g); } if (excepts & _FPU_MASK_OM) { - my_fenv_t temp; __asm__ __volatile__ ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= _FPU_MASK_OM; __asm__ __volatile__ ("fldenv\t%0" : : "m" (temp)); @@ -132,7 +138,6 @@ local_feraiseexcept (int excepts) } if (excepts & _FPU_MASK_UM) { - my_fenv_t temp; __asm__ __volatile__ ("fnstenv\t%0" : "=m" (temp)); temp.__status_word |= _FPU_MASK_UM; __asm__ __volatile__ ("fldenv\t%0" : : "m" (temp)); @@ -141,12 +146,7 @@ local_feraiseexcept (int excepts) if (excepts & _FPU_MASK_PM) { float f = 1.0f, g = 3.0f; -#ifdef __SSE_MATH__ - __asm__ __volatile__ ("%vdivss\t{%1, %d0|%d0, %1}" : "+x" (f) : "xm" (g)); -#else - __asm__ __volatile__ ("fdivs\t%1" : "+t" (f) : "m" (g)); - /* No need for fwait, exception is triggered by emitted fstp. */ -#endif + __math_force_eval_div (f, g); } } @@ -272,7 +272,7 @@ get_fpu_except_flags (void) void set_fpu_except_flags (int set, int clear) { - my_fenv_t temp; + struct fenv temp; int exc_set = 0, exc_clr = 0; /* Translate from GFC_PE_* values to _FPU_MASK_* values. */ @@ -426,7 +426,7 @@ support_fpu_rounding_mode (int mode __attribute__((unused))) void get_fpu_state (void *state) { - my_fenv_t *envp = state; + struct fenv *envp = state; __asm__ __volatile__ ("fnstenv\t%0" : "=m" (*envp)); @@ -441,7 +441,7 @@ get_fpu_state (void *state) void set_fpu_state (void *state) { - my_fenv_t *envp = state; + struct fenv *envp = state; /* glibc sources (sysdeps/x86_64/fpu/fesetenv.c) do something more complex than this, but I think it suffices in our case. */