From patchwork Fri Feb 9 23:37:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 871597 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-472994-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="bZV23TBc"; 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 3zdWy94FcTz9s4q for ; Sat, 10 Feb 2018 10:49:51 +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:cc:subject:message-id:reply-to:mime-version :content-type; q=dns; s=default; b=YVqlWOvNTF+K2njqWHX2ztuuk98/k t8zNSYhMh5bmogs63OKz23W0e5uxK0Zpv6nwGmnTM1dbe55k2Zwe4zoEQ5oRiPG1 F4BsPrBCfnE7677vDsU7ddYXtnlx0LNmhulqFVMc8CYp2IEN+D9yD4KeH9uuwVGq cyAjY041vFWqs4= 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:reply-to:mime-version :content-type; s=default; bh=k+LKny5mwLTiA2/sQ6cb99F7LJw=; b=bZV 23TBcLHPSy7b6w3DH1kyzWhNq0cLvo1jPJVEF9wy0t5Fq+X5989e8XcDopqZlVmC BHWSBPzgLsvWs6bfEKVda8Lhwj3o1tpYDEEk6zQSbfktJ1qLk1h+sOYfaoxTdSuH yImLi1Sdv3ne3YMfGo2nxHFGgoj4GTyNcTMx4es8= Received: (qmail 33375 invoked by alias); 9 Feb 2018 23:49:44 -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 33353 invoked by uid 89); 9 Feb 2018 23:49:43 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-12.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_LOW, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=LOG X-HELO: mx1.redhat.com Received: from mx3-rdu2.redhat.com (HELO mx1.redhat.com) (66.187.233.73) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 09 Feb 2018 23:49:41 +0000 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 696788182D37 for ; Fri, 9 Feb 2018 23:49:30 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-204-85.brq.redhat.com [10.40.204.85]) by smtp.corp.redhat.com (Postfix) with ESMTPS id B21381010058 for ; Fri, 9 Feb 2018 23:49:29 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id w19NbeDH021952; Sat, 10 Feb 2018 00:37:41 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id w19Nbce7021951; Sat, 10 Feb 2018 00:37:38 +0100 Date: Sat, 10 Feb 2018 00:37:38 +0100 From: Jakub Jelinek To: Richard Biener , Jeff Law , Wilco Dijkstra Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] Improve pow (C, x) -> exp (log (C) * x) optimization (PR middle-end/84309) Message-ID: <20180209233738.GQ5867@tucnak> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.9.1 (2017-09-22) X-IsSubscribed: yes Hi! Apparently the new pow(C,x) -> exp(log(C)*x) if C > 0 optimization breaks some package (Marek should know which), as it has 7ulp error. Generally one should be prepared for some errors with -ffast-math. Though, in this case, if the target has c99 runtime and C is a positive 0x1pNN it seems much better to use exp2 over exp, for C being 2 pow (2, x) is optimized into exp2 (x) and even for other values log2(C) will still be some positive or negative integer, so in many cases there won't be any rounding errors in the multiplication. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? Perhaps we should do something similar if C is a power of 10 (use exp10 and log10). 2018-02-10 Jakub Jelinek PR middle-end/84309 * match.pd (pow(C,x) -> exp(log(C)*x)): Optimize instead into exp2(log2(C)*x) if C is a power of 2 and c99 runtime is available. * gcc.dg/pr84309.c: New test. Jakub --- gcc/match.pd.jj 2018-01-26 12:43:23.208922420 +0100 +++ gcc/match.pd 2018-02-09 18:48:26.412021408 +0100 @@ -3992,15 +3992,33 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (logs (pows @0 @1)) (mult @1 (logs @0)))) - /* pow(C,x) -> exp(log(C)*x) if C > 0. */ + /* pow(C,x) -> exp(log(C)*x) if C > 0, + or if C is a positive power of 2, + pow(C,x) -> exp2(log2(C)*x). */ (for pows (POW) exps (EXP) logs (LOG) + exp2s (EXP2) + log2s (LOG2) (simplify (pows REAL_CST@0 @1) - (if (real_compare (GT_EXPR, TREE_REAL_CST_PTR (@0), &dconst0) - && real_isfinite (TREE_REAL_CST_PTR (@0))) - (exps (mult (logs @0) @1))))) + (if (real_compare (GT_EXPR, TREE_REAL_CST_PTR (@0), &dconst0) + && real_isfinite (TREE_REAL_CST_PTR (@0))) + (with { + const REAL_VALUE_TYPE *const value = TREE_REAL_CST_PTR (@0); + bool use_exp2 = false; + if (targetm.libc_has_function (function_c99_misc) + && value->cl == rvc_normal) + { + REAL_VALUE_TYPE frac_rvt = *value; + SET_REAL_EXP (&frac_rvt, 1); + if (real_equal (&frac_rvt, &dconst1)) + use_exp2 = true; + } + } + (if (use_exp2) + (exp2s (mult (log2s @0) @1)) + (exps (mult (logs @0) @1))))))) (for sqrts (SQRT) cbrts (CBRT) --- gcc/testsuite/gcc.dg/pr84309.c.jj 2018-02-09 18:54:52.254787678 +0100 +++ gcc/testsuite/gcc.dg/pr84309.c 2018-02-09 18:59:02.343636178 +0100 @@ -0,0 +1,14 @@ +/* PR middle-end/84309 */ +/* { dg-do run { target c99_runtime } } */ +/* { dg-options "-O2 -ffast-math" } */ + +int +main () +{ + unsigned long a = 1024; + unsigned long b = 16 * 1024; + unsigned long c = __builtin_pow (2, (__builtin_log2 (a) + __builtin_log2 (b)) / 2); + if (c != 4096) + __builtin_abort (); + return 0; +}