From patchwork Tue Aug 13 08:33:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robin Dapp X-Patchwork-Id: 1146127 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-506778-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="gAHPp4tF"; 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 4675fL25fZz9sNy for ; Tue, 13 Aug 2019 18:36:26 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:in-reply-to:references:message-id; q=dns; s= default; b=dkwoNMD4P9G99I9jvvRik2pz3jXvw6dy3Po8G8J8JUEWItj6MkxL7 3o4HYbLQ1ObGUJ+hU4hVjcY6lNWcmLB8XwZvpNhiHdPeUaiS+q10zTnytobjbYIB PPT+xL1+vPg+PmM10rnIC8cfV6jTv4G5VdAfWJ5hSVllAqX/hphNCE= 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:from :to:subject:date:in-reply-to:references:message-id; s=default; bh=K8SVKaJpR3suMmugDmDTVkUx/jk=; b=gAHPp4tFSo+01Q5uzkouPeR0v49x yQffpZHeX/rVqqJKO35BPzIsuBQftSaaiFXBO40sZbv1oNZWTugsnCsCrcUnhMJy c/VqOfwOm/vGi8Mm4PZrTXJ02OaW4uCljF3JKFtS1dL0ApY2rjZrGV4YNDBDzf6F xb1YJCBvmdPuEPk= Received: (qmail 121759 invoked by alias); 13 Aug 2019 08:33:36 -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 121656 invoked by uid 89); 13 Aug 2019 08:33:36 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.1 spammy= X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0b-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.158.5) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 13 Aug 2019 08:33:34 +0000 Received: from pps.filterd (m0098419.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x7D8X8Gq055132 for ; Tue, 13 Aug 2019 04:33:32 -0400 Received: from e06smtp05.uk.ibm.com (e06smtp05.uk.ibm.com [195.75.94.101]) by mx0b-001b2d01.pphosted.com with ESMTP id 2ubrcrup46-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Tue, 13 Aug 2019 04:33:32 -0400 Received: from localhost by e06smtp05.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 13 Aug 2019 09:33:30 +0100 Received: from b06cxnps4075.portsmouth.uk.ibm.com (9.149.109.197) by e06smtp05.uk.ibm.com (192.168.101.135) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Tue, 13 Aug 2019 09:33:28 +0100 Received: from b06wcsmtp001.portsmouth.uk.ibm.com (b06wcsmtp001.portsmouth.uk.ibm.com [9.149.105.160]) by b06cxnps4075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id x7D8XR5l8519840 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Tue, 13 Aug 2019 08:33:27 GMT Received: from b06wcsmtp001.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 94490A405B for ; Tue, 13 Aug 2019 08:33:27 +0000 (GMT) Received: from b06wcsmtp001.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 77412A4064 for ; Tue, 13 Aug 2019 08:33:27 +0000 (GMT) Received: from oc6142347168.ibm.com (unknown [9.152.222.26]) by b06wcsmtp001.portsmouth.uk.ibm.com (Postfix) with ESMTP for ; Tue, 13 Aug 2019 08:33:27 +0000 (GMT) From: Robin Dapp To: gcc-patches@gcc.gnu.org Subject: [PATCH 2/3] Add simplify rules for wrapped binary operations. Date: Tue, 13 Aug 2019 10:33:25 +0200 In-Reply-To: <20190813083326.10833-1-rdapp@linux.ibm.com> References: <20190813083326.10833-1-rdapp@linux.ibm.com> x-cbid: 19081308-0020-0000-0000-0000035F14C8 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 19081308-0021-0000-0000-000021B427EF Message-Id: <20190813083326.10833-3-rdapp@linux.ibm.com> X-IsSubscribed: yes We would like to simplify code like (larger_type)(var + const1) + const2 to (larger_type)(var + combined_const1_const2) when we know that no overflow happens. --- gcc/match.pd | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/gcc/match.pd b/gcc/match.pd index 0317bc704f7..94400529ad8 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -2020,6 +2020,107 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (cst && !TREE_OVERFLOW (cst)) (plus { cst; } @0)))) +/* ((T)(A + CST1)) + CST2 -> (T)(A) + CST */ +#if GIMPLE + (simplify + (plus (convert (plus @0 INTEGER_CST@1)) INTEGER_CST@2) + (if (INTEGRAL_TYPE_P (type) + && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@0))) + /* We actually want to perform two simplifications here: + (1) (T)(A + CST1) + CST2 --> (T)(A) + (T)(CST1) + If for (A + CST1) we either do not care about overflow (e.g. + for a signed inner type) or the overflow is ok for an unsigned + inner type. + (2) (T)(A) + (T)(CST1) + CST2 --> (T)(A) + (T)(CST1 + CST2) + If (CST1 + CST2) does not overflow and we do care about overflow + (for a signed outer type) or we do not care about overflow in an + unsigned outer type. */ + (with + { + tree inner_type = TREE_TYPE (@0); + wide_int wmin0, wmax0; + wide_int cst1 = wi::to_wide (@1); + + wi::overflow_type min_ovf = wi::OVF_OVERFLOW, + max_ovf = wi::OVF_OVERFLOW; + + /* Get overflow behavior. */ + bool ovf_undef_inner = TYPE_OVERFLOW_UNDEFINED (inner_type); + bool ovf_undef_outer = TYPE_OVERFLOW_UNDEFINED (type); + + /* Get value range of A. */ + enum value_range_kind vr0 = get_range_info (@0, &wmin0, &wmax0); + + /* If we have a proper range, determine min and max overflow + of (A + CST1). + ??? We might also want to handle anti ranges. */ + if (vr0 == VR_RANGE) + { + wi::add (wmin0, cst1, TYPE_SIGN (inner_type), &min_ovf); + wi::add (wmax0, cst1, TYPE_SIGN (inner_type), &max_ovf); + } + + /* Inner overflow does not matter in this case. */ + if (ovf_undef_inner) + { + min_ovf = wi::OVF_NONE; + max_ovf = wi::OVF_NONE; + } + + /* Extend CST from INNER_TYPE to TYPE. */ + cst1 = cst1.from (cst1, TYPE_PRECISION (type), TYPE_SIGN (inner_type)); + + /* Check for overflow of (TYPE)(CST1 + CST2). */ + wi::overflow_type outer_ovf = wi::OVF_OVERFLOW; + wide_int cst = wi::add (cst1, wi::to_wide (@2), TYPE_SIGN (type), + &outer_ovf); + + /* We *do* care about an overflow here as we do not want to introduce + new undefined behavior that was not there before. */ + if (ovf_undef_outer && outer_ovf) + { + /* Set these here to prevent the final conversion below + to take place instead of introducing a new guard variable. */ + min_ovf = wi::OVF_OVERFLOW; + max_ovf = wi::OVF_OVERFLOW; + } + } + (if (min_ovf == wi::OVF_NONE && max_ovf == wi::OVF_NONE) + (plus (convert @0) { wide_int_to_tree (type, cst); } + ))))) +#endif + +/* ((T)(A)) + CST -> (T)(A + CST) */ +#if GIMPLE + (simplify + (plus (convert SSA_NAME@0) INTEGER_CST@1) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && INTEGRAL_TYPE_P (type) + && TYPE_PRECISION (type) > TYPE_PRECISION (TREE_TYPE (@0)) + && int_fits_type_p (@1, TREE_TYPE (@0))) + /* Perform binary operation inside the cast if the constant fits + and (A + CST)'s range does not overflow. */ + (with + { + wi::overflow_type min_ovf = wi::OVF_OVERFLOW, + max_ovf = wi::OVF_OVERFLOW; + tree inner_type = TREE_TYPE (@0); + + wide_int w1 = w1.from (wi::to_wide (@1), TYPE_PRECISION (inner_type), + TYPE_SIGN (inner_type)); + + wide_int wmin0, wmax0; + if (get_range_info (@0, &wmin0, &wmax0) == VR_RANGE) + { + wi::add (wmin0, w1, TYPE_SIGN (inner_type), &min_ovf); + wi::add (wmax0, w1, TYPE_SIGN (inner_type), &max_ovf); + } + } + (if (min_ovf == wi::OVF_NONE && max_ovf == wi::OVF_NONE) + (convert (plus @0 { {wide_int_to_tree (TREE_TYPE (@0), w1)}; }))) + ))) +#endif + /* ~A + A -> -1 */ (simplify (plus:c (bit_not @0) @0)