From patchwork Fri Nov 4 20:07:07 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Glisse X-Patchwork-Id: 80918 Delivered-To: patch@linaro.org Received: by 10.140.97.165 with SMTP id m34csp155121qge; Fri, 4 Nov 2016 13:07:42 -0700 (PDT) X-Received: by 10.99.112.65 with SMTP id a1mr24590735pgn.31.1478290062253; Fri, 04 Nov 2016 13:07:42 -0700 (PDT) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id n5si18399955pgh.23.2016.11.04.13.07.41 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 04 Nov 2016 13:07:42 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-440496-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org; spf=pass (google.com: domain of gcc-patches-return-440496-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-440496-patch=linaro.org@gcc.gnu.org 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:message-id:mime-version:content-type; q=dns; s= default; b=kOM+jEmbMrH38WE/g3P6Z3AYI1yybqZhS7566GQ1o4Ji7KjenNxcX vPV2igyREbTdDI2vt7gLYv0ViNKKJeRoQQ4v5ooCoEUjGKRLfwRGb46NYY3hptu1 88Ty008J5wE1AveyqICx4FLvK822L7q3c13bIvBzBsbg6rCVSVDwlM= 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:message-id:mime-version:content-type; s= default; bh=oreOHrWe26aao2kuscHbrjExPFo=; b=Dlnsw2jaAMB+XUqX9+/G JxSxVxgIrz1Zi7iGWEDixU+4qdPA2Qwk7qlZoreVJ5xtpwdK5Dy90/tjXOWRWD+U e4Uig1Rginhq4SBTq3lsPFPBM138vIGUQ5PyYgh2MJgcJysG8LHH7aPr4vl49uPZ oGyqKZFEHx9pzO+Kc/TkcGU= Received: (qmail 76153 invoked by alias); 4 Nov 2016 20:07:27 -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 76141 invoked by uid 89); 4 Nov 2016 20:07:26 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=AWL, BAYES_00, KAM_ASCII_DIVIDERS, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=sk:TYPE_OV, sk:type_ov, non_lvalue, sk:any_int X-HELO: mail2-relais-roc.national.inria.fr Received: from mail2-relais-roc.national.inria.fr (HELO mail2-relais-roc.national.inria.fr) (192.134.164.83) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 04 Nov 2016 20:07:16 +0000 Received: from ip-118.net-89-2-234.rev.numericable.fr (HELO laptop-mg.local) ([89.2.234.118]) by mail2-relais-roc.national.inria.fr with ESMTP/TLS/DHE-RSA-AES256-SHA; 04 Nov 2016 21:07:14 +0100 Date: Fri, 4 Nov 2016 21:07:07 +0100 (CET) From: Marc Glisse To: gcc-patches@gcc.gnu.org Subject: Simplify X / X, 0 / X and X % X Message-ID: User-Agent: Alpine 2.02 (DEB 1266 2009-07-14) MIME-Version: 1.0 Hello, since we were discussing this recently... The condition is copied from the existing 0 % X case, visible in the context of the diff. As far as I understand, the main case where we do not want to optimize is during constexpr evaluation in the C++ front-end (it wants to detect the undefined behavior), and with late folding I think this means we only need to care about an explicit 0/0, not about X/X where X would become 0 after the simplification. And later, if we do have something like X/0, we could handle it the same way as we currently handle *(char*)0, insert a trap after that instruction and clear the following code, which likely gives better code than replacing 0/0 with 1. Bootstrap+regtest on powerpc64le-unknown-linux-gnu. 2016-11-07 Marc Glisse gcc/ * match.pd (0 / X, X / X, X % X): New simplifications. gcc/testsuite/ * gcc.dg/tree-ssa/divide-5.c: New file. -- Marc Glisse Index: gcc/match.pd =================================================================== --- gcc/match.pd (revision 241856) +++ gcc/match.pd (working copy) @@ -133,33 +133,47 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (non_lvalue @0))) /* Transform x * -1.0 into -x. */ (simplify (mult @0 real_minus_onep) (if (!HONOR_SNANS (type) && (!HONOR_SIGNED_ZEROS (type) || !COMPLEX_FLOAT_TYPE_P (type))) (negate @0))) -/* Make sure to preserve divisions by zero. This is the reason why - we don't simplify x / x to 1 or 0 / x to 0. */ +/* X * 1, X / 1 -> X. */ (for op (mult trunc_div ceil_div floor_div round_div exact_div) (simplify (op @0 integer_onep) (non_lvalue @0))) +/* Preserve explicit divisions by 0: the C++ front-end wants to detect + undefined behavior in constexpr evaluation, and assuming that the division + traps enables better optimizations than these anyway. */ (for div (trunc_div ceil_div floor_div round_div exact_div) + /* 0 / X is always zero. */ + (simplify + (div integer_zerop@0 @1) + /* But not for 0 / 0 so that we can get the proper warnings and errors. */ + (if (!integer_zerop (@1)) + @0)) /* X / -1 is -X. */ (simplify (div @0 integer_minus_onep@1) (if (!TYPE_UNSIGNED (type)) (negate @0))) + /* X / X is one. */ + (simplify + (div @0 @0) + /* But not for 0 / 0 so that we can get the proper warnings and errors. */ + (if (!integer_zerop (@0)) + { build_one_cst (type); })) /* X / abs (X) is X < 0 ? -1 : 1. */ (simplify (div:C @0 (abs @0)) (if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type)) (cond (lt @0 { build_zero_cst (type); }) { build_minus_one_cst (type); } { build_one_cst (type); }))) /* X / -X is -1. */ (simplify (div:C @0 (negate @0)) @@ -269,38 +283,42 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && !real_zerop (@1)) (with { tree tem = const_binop (RDIV_EXPR, type, build_one_cst (type), @1); } (if (tem) (mult @0 { tem; } ))) (if (cst != COMPLEX_CST) (with { tree inverse = exact_inverse (type, @1); } (if (inverse) (mult @0 { inverse; } )))))))) -/* Same applies to modulo operations, but fold is inconsistent here - and simplifies 0 % x to 0, only preserving literal 0 % 0. */ (for mod (ceil_mod floor_mod round_mod trunc_mod) /* 0 % X is always zero. */ (simplify (mod integer_zerop@0 @1) /* But not for 0 % 0 so that we can get the proper warnings and errors. */ (if (!integer_zerop (@1)) @0)) /* X % 1 is always zero. */ (simplify (mod @0 integer_onep) { build_zero_cst (type); }) /* X % -1 is zero. */ (simplify (mod @0 integer_minus_onep@1) (if (!TYPE_UNSIGNED (type)) { build_zero_cst (type); })) + /* X % X is zero. */ + (simplify + (mod @0 @0) + /* But not for 0 % 0 so that we can get the proper warnings and errors. */ + (if (!integer_zerop (@0)) + { build_zero_cst (type); })) /* (X % Y) % Y is just X % Y. */ (simplify (mod (mod@2 @0 @1) @1) @2) /* From extract_muldiv_1: (X * C1) % C2 is zero if C1 is a multiple of C2. */ (simplify (mod (mult @0 INTEGER_CST@1) INTEGER_CST@2) (if (ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_UNDEFINED (type) && wi::multiple_of_p (@1, @2, TYPE_SIGN (type))) Index: gcc/testsuite/gcc.dg/tree-ssa/divide-5.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/divide-5.c (revision 0) +++ gcc/testsuite/gcc.dg/tree-ssa/divide-5.c (working copy) @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +int f(int x){ + int y = x; + int z = 0; + return x / y - x % y + z / y; +} + +/* { dg-final { scan-tree-dump "return 1;" "optimized"} } */