From patchwork Mon Apr 28 21:39:53 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adhemerval Zanella Netto X-Patchwork-Id: 741 Return-Path: X-Original-To: siddhesh@wilcox.dreamhost.com Delivered-To: siddhesh@wilcox.dreamhost.com Received: from homiemail-mx20.g.dreamhost.com (mx2.sub5.homie.mail.dreamhost.com [208.113.200.128]) by wilcox.dreamhost.com (Postfix) with ESMTP id 6BDBE360072 for ; Mon, 28 Apr 2014 14:40:06 -0700 (PDT) Received: by homiemail-mx20.g.dreamhost.com (Postfix, from userid 14307373) id 1E38E41681523; Mon, 28 Apr 2014 14:40:06 -0700 (PDT) X-Original-To: glibc@patchwork.siddhesh.in Delivered-To: x14307373@homiemail-mx20.g.dreamhost.com 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 homiemail-mx20.g.dreamhost.com (Postfix) with ESMTPS id F3D4D41681517 for ; Mon, 28 Apr 2014 14:40:05 -0700 (PDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:message-id:date:from:mime-version:to:subject :content-type:content-transfer-encoding; q=dns; s=default; b=Uq3 LaENKt68tp5bz8NcdLdAWhj/V5DSTKcygDtFPdRqjzZuYd1orI3ymBHqmANMAcQ1 wGdiuPDMLSAJI1qJ1ip7fTPsuIbf/XkRDvdn2Bt2rMp3Nl/pTrgN0T/WdXepLR78 Wd73MvtEW0G6NgfdQQE+gk6Z53/STIUqwMpQNVPI= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:message-id:date:from:mime-version:to:subject :content-type:content-transfer-encoding; s=default; bh=ItUiA1kih ovfk9agrrN0eg2xpRc=; b=hWTgwSppEvrWcZXbSGl9GVzsAP4dk+75G5aLNdgVR YH93IfSP5kkyHZ0/iAo3nhSfe+a49GLSGy1Fk4wq9H1h2V+/cJhx77uc01hBwmMn W25GxL533KBls5wXlFE8Pgve8Z9ULyUD9431hlKGJLIiywKB10/7i+daOOIr0JVn Ng= Received: (qmail 23552 invoked by alias); 28 Apr 2014 21:40:04 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 23540 invoked by uid 89); 28 Apr 2014 21:40:03 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: e24smtp03.br.ibm.com Message-ID: <535ECAA9.4080800@linux.vnet.ibm.com> Date: Mon, 28 Apr 2014 18:39:53 -0300 From: Adhemerval Zanella User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.4.0 MIME-Version: 1.0 To: "GNU C. Library" Subject: [PATCH] PowerPC: Suppress unnecessary FPSCR write X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 14042821-9564-0000-0000-000000AF9E65 X-DH-Original-To: glibc@patchwork.siddhesh.in This patch optimizes the FPSCR update on exception and rounding change functions by just updating its value if new value if different from current one. It also optimizes fedisableexcept and feenableexcept by removing an unecessary FPSCR read. Tested on powerpc32, powerpc64, and powerpc64le. --- 2014-04-28 Adhemerval Zanella * sysdeps/powerpc/fpu/fclrexcpt.c (__feclearexcept): Do not update FPSCR if value do not change. * sysdeps/powerpc/fpu/fedisblxcpt.c (fedisableexcept): Likewise. * sysdeps/powerpc/fpu/feenablxcpt.c (feenableexcept): Likewise. * sysdeps/powerpc/fpu/feholdexcpt.c (feholdexcept): Likewise. * sysdeps/powerpc/fpu/fesetenv.c (__fesetenv): Likewise. * sysdeps/powerpc/fpu/fsetexcptflg.c (__fesetexceptflag): Likewise. * sysdeps/powerpc/fpu/fenv_libc.h (fenv_reg_to_exceptions): New helper function. diff --git a/sysdeps/powerpc/fpu/fclrexcpt.c b/sysdeps/powerpc/fpu/fclrexcpt.c index cda2810..4607f62 100644 --- a/sysdeps/powerpc/fpu/fclrexcpt.c +++ b/sysdeps/powerpc/fpu/fclrexcpt.c @@ -22,17 +22,18 @@ int __feclearexcept (int excepts) { - fenv_union_t u; + fenv_union_t u, n; /* Get the current state. */ u.fenv = fegetenv_register (); /* Clear the relevant bits. */ - u.l = u.l & ~((-(excepts >> (31 - FPSCR_VX) & 1) & FE_ALL_INVALID) + n.l = u.l & ~((-(excepts >> (31 - FPSCR_VX) & 1) & FE_ALL_INVALID) | (excepts & FPSCR_STICKY_BITS)); /* Put the new state in effect. */ - fesetenv_register (u.fenv); + if (u.l != n.l) + fesetenv_register (n.fenv); /* Success. */ return 0; diff --git a/sysdeps/powerpc/fpu/fedisblxcpt.c b/sysdeps/powerpc/fpu/fedisblxcpt.c index 5883e09..94c01ab 100644 --- a/sysdeps/powerpc/fpu/fedisblxcpt.c +++ b/sysdeps/powerpc/fpu/fedisblxcpt.c @@ -22,15 +22,17 @@ int fedisableexcept (int excepts) { - fenv_union_t fe; - int result, new; + fenv_union_t fe, curr; + int result = 0, new; - result = __fegetexcept (); + /* Get current exception mask to return. */ + fe.fenv = curr.fenv = fegetenv_register (); + result = fenv_reg_to_exceptions (fe.l); if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID) excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID; - fe.fenv = fegetenv_register (); + /* Sets the new exception mask. */ if (excepts & FE_INEXACT) fe.l &= ~(1 << (31 - FPSCR_XE)); if (excepts & FE_DIVBYZERO) @@ -41,7 +43,9 @@ fedisableexcept (int excepts) fe.l &= ~(1 << (31 - FPSCR_OE)); if (excepts & FE_INVALID) fe.l &= ~(1 << (31 - FPSCR_VE)); - fesetenv_register (fe.fenv); + + if (fe.l != curr.l) + fesetenv_register (fe.fenv); new = __fegetexcept (); if (new == 0 && result != 0) diff --git a/sysdeps/powerpc/fpu/feenablxcpt.c b/sysdeps/powerpc/fpu/feenablxcpt.c index 8ad0f97..01a68cf 100644 --- a/sysdeps/powerpc/fpu/feenablxcpt.c +++ b/sysdeps/powerpc/fpu/feenablxcpt.c @@ -22,15 +22,17 @@ int feenableexcept (int excepts) { - fenv_union_t fe; - int result, new; + fenv_union_t fe, curr; + int result = 0, new; - result = __fegetexcept (); + /* Get current exception mask to return. */ + fe.fenv = curr.fenv = fegetenv_register (); + result = fenv_reg_to_exceptions (fe.l); if ((excepts & FE_ALL_INVALID) == FE_ALL_INVALID) excepts = (excepts | FE_INVALID) & ~ FE_ALL_INVALID; - fe.fenv = fegetenv_register (); + /* Sets the new exception mask. */ if (excepts & FE_INEXACT) fe.l |= (1 << (31 - FPSCR_XE)); if (excepts & FE_DIVBYZERO) @@ -41,7 +43,9 @@ feenableexcept (int excepts) fe.l |= (1 << (31 - FPSCR_OE)); if (excepts & FE_INVALID) fe.l |= (1 << (31 - FPSCR_VE)); - fesetenv_register (fe.fenv); + + if (fe.l != curr.l) + fesetenv_register (fe.fenv); new = __fegetexcept (); if (new != 0 && result == 0) diff --git a/sysdeps/powerpc/fpu/feholdexcpt.c b/sysdeps/powerpc/fpu/feholdexcpt.c index 1375a2f..764dd38 100644 --- a/sysdeps/powerpc/fpu/feholdexcpt.c +++ b/sysdeps/powerpc/fpu/feholdexcpt.c @@ -32,6 +32,9 @@ feholdexcept (fenv_t *envp) flag. */ new.l = old.l & 0xffffffff00000007LL; + if (new.l == old.l) + return 0; + /* If the old env had any enabled exceptions, then mask SIGFPE in the MSR FE0/FE1 bits. This may allow the FPU to run faster because it always takes the default action and can not generate SIGFPE. */ diff --git a/sysdeps/powerpc/fpu/fenv_libc.h b/sysdeps/powerpc/fpu/fenv_libc.h index 28e4d1f..c1df5ce 100644 --- a/sysdeps/powerpc/fpu/fenv_libc.h +++ b/sysdeps/powerpc/fpu/fenv_libc.h @@ -146,6 +146,23 @@ enum { /* the remaining two least-significant bits keep the rounding mode */ }; +static inline int +fenv_reg_to_exceptions (unsigned long long l) +{ + int result = 0; + if (l & (1 << (31 - FPSCR_XE))) + result |= FE_INEXACT; + if (l & (1 << (31 - FPSCR_ZE))) + result |= FE_DIVBYZERO; + if (l & (1 << (31 - FPSCR_UE))) + result |= FE_UNDERFLOW; + if (l & (1 << (31 - FPSCR_OE))) + result |= FE_OVERFLOW; + if (l & (1 << (31 - FPSCR_VE))) + result |= FE_INVALID; + return result; +} + #ifdef _ARCH_PWR6 /* Not supported in ISA 2.05. Provided for source compat only. */ # define FPSCR_NI 29 diff --git a/sysdeps/powerpc/fpu/fesetenv.c b/sysdeps/powerpc/fpu/fesetenv.c index fa99ddb..138bde0 100644 --- a/sysdeps/powerpc/fpu/fesetenv.c +++ b/sysdeps/powerpc/fpu/fesetenv.c @@ -29,6 +29,8 @@ __fesetenv (const fenv_t *envp) /* get the currently set exceptions. */ new.fenv = *envp; old.fenv = fegetenv_register (); + if (old.l == new.l) + return 0; /* If the old env has no enabled exceptions and the new env has any enabled exceptions, then unmask SIGFPE in the MSR FE0/FE1 bits. This will put the diff --git a/sysdeps/powerpc/fpu/fsetexcptflg.c b/sysdeps/powerpc/fpu/fsetexcptflg.c index 95193c1..cee6682 100644 --- a/sysdeps/powerpc/fpu/fsetexcptflg.c +++ b/sysdeps/powerpc/fpu/fsetexcptflg.c @@ -21,7 +21,7 @@ int __fesetexceptflag (const fexcept_t *flagp, int excepts) { - fenv_union_t u; + fenv_union_t u, n; fexcept_t flag; /* Get the current state. */ @@ -31,7 +31,7 @@ __fesetexceptflag (const fexcept_t *flagp, int excepts) flag = *flagp & excepts; /* Replace the exception status */ - u.l = ((u.l & ~(FPSCR_STICKY_BITS & excepts)) + n.l = ((u.l & ~(FPSCR_STICKY_BITS & excepts)) | (flag & FPSCR_STICKY_BITS) | (flag >> ((31 - FPSCR_VX) - (31 - FPSCR_VXSOFT)) & FE_INVALID_SOFTWARE)); @@ -39,7 +39,8 @@ __fesetexceptflag (const fexcept_t *flagp, int excepts) /* Store the new status word (along with the rest of the environment). This may cause floating-point exceptions if the restored state requests it. */ - fesetenv_register (u.fenv); + if (n.l != u.l) + fesetenv_register (u.fenv); /* Deal with FE_INVALID_SOFTWARE not being implemented on some chips. */ if (flag & FE_INVALID)