From patchwork Fri Nov 1 19:25:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew MacLeod X-Patchwork-Id: 2005284 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=KawtJgTG; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.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 ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Xg9np467dz1xwc for ; Sat, 2 Nov 2024 06:26:06 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C559E3857B9F for ; Fri, 1 Nov 2024 19:26:04 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id C5A35385840C for ; Fri, 1 Nov 2024 19:25:18 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C5A35385840C Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org C5A35385840C Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730489124; cv=none; b=xDrzy1klTQ93p5lo+XXFMWpfvMU1goG2UpeoY3gQJGKH9aC1Gr0IYvXyHAMZjktwJ0whSXO+fP3KJOe5mrj6m5ZodP/+NX2I32EOToNYaHmhqq1WpfJ74gO66yzWmPvBWl7T/FwbtRh3JlBIPU07O8uERiXidsJ9bBZiouoEpsA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730489124; c=relaxed/simple; bh=yubYcxPYWx7WFIVOq7vVkYSBDYcm1SrSvtGP3p3HbjY=; h=DKIM-Signature:Message-ID:Date:MIME-Version:To:From:Subject; b=WGnEaJHFH30vdvEOFGJqMDdZrOTL0RUKlaXwVXw83JnYDkji09npHJV5mK16FX9IyTP0bPzF8AXtiZNbZloaYwMVwxjd9OxgO3Nv1gWkGbKgcTQAd2/ayvUOfJeqphqS2awBBMeJjfuXHXXwBqs7oKrlsk5K1xiGEC3hXDCqaGI= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1730489118; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type; bh=ueIVIwhHm7gmGdzsnN53/ThLo7DMdU8FizzhSct090s=; b=KawtJgTGXb80bCyO4vQtz1dRobpDB75Aj4zHqiCiToZsR74mKI6ha79ezg8ddq1t4EZam8 tkggbYaeuOL7uDdDsPS6ErLKUnBpT/EWsSn74IAHAMhkK5uoDj4srzCGt5fL+QyEO8k/ia rsnSzFC6idey5KzK9skj/W9GCj3wHlo= Received: from mail-qv1-f70.google.com (mail-qv1-f70.google.com [209.85.219.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-148-sW_SrykoN7yJdJcT3oNy1w-1; Fri, 01 Nov 2024 15:25:16 -0400 X-MC-Unique: sW_SrykoN7yJdJcT3oNy1w-1 Received: by mail-qv1-f70.google.com with SMTP id 6a1803df08f44-6ce23cf761bso35997376d6.3 for ; Fri, 01 Nov 2024 12:25:16 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730489115; x=1731093915; h=subject:from:to:content-language:user-agent:mime-version:date :message-id:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=Am5PQCL30Y00hU0yBRj8Oh+jD/rQ3+cJaZqL6bJclvw=; b=hayDT6Vfo9PhbZl+6hyCzGpu3Odep9BAHod+55G0ZBn+o4sZxK6kZFQOoNeIOI2q8d qH9+E9VrDgkU4TAm5UZq+Gws3ZYnsppQC1TUTlq2MboT9tFEmy2uFBTBYrGq6eUhMXut cCeVIkf2Sw3Muu58p7w0CiJfyeF7kjDN+cn5chDnLJc989+v6mUXjqiWsuWFCtuuMdOO g5bKQaakLVbbx7ptJsSe3nlLUM5igkpas0/XltWk4G5fKnJRSS3/nZD4DLhSaCrqYQKf uHUqFIgdBjQ8NKBohyEjlIt6FnFB3N8rlazj6yMZt6JLV99sYl9Bo8aQW7NYPJLQRL1v dDjw== X-Gm-Message-State: AOJu0YwtdW9TYFglXS/zPDVRxislxaafxGbUJgtLjiOYOSdR68H1V00t WnoxnVNgQVjBZypu0+plkjeklXEFZsLx70nMRWiVEwT9bCdSnw6xrIO8U4NxTThLHKCmGQkAZlL s+Ga1abB03jDvq1ea2C1kFvhRZjpWAwr1jJZLKjteCce1fdaBa+s0pRmHI/0uj7GPAWAujA2hqm 1jlw2oTHmFHSQJ0yu9UnvuHvRj1f6wmX9eN44baScgbA== X-Received: by 2002:a05:6214:319f:b0:6d3:535e:70ab with SMTP id 6a1803df08f44-6d3535e7250mr111016946d6.17.1730489115247; Fri, 01 Nov 2024 12:25:15 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFubNytcbO+In6yZdi8Nlh3FNPNKX6p1Kv/yhv+unn3lYfjqXuVRTYhkgIkwgWLzcJbDZg1UA== X-Received: by 2002:a05:6214:319f:b0:6d3:535e:70ab with SMTP id 6a1803df08f44-6d3535e7250mr111016606d6.17.1730489114704; Fri, 01 Nov 2024 12:25:14 -0700 (PDT) Received: from ?IPV6:2607:fea8:51de:a700::c2e1? ([2607:fea8:51de:a700::c2e1]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-6d35417a3c5sm22211646d6.130.2024.11.01.12.25.13 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 01 Nov 2024 12:25:13 -0700 (PDT) Message-ID: Date: Fri, 1 Nov 2024 15:25:12 -0400 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird To: gcc-patches From: Andrew MacLeod Subject: [COMMITTED 1/3] Make fur_edge accessible. X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org The next patch requires a fur_edge class.  It needs to calculate ranges on both edges and statements, and this provides a way to do both without having different routines. This patch simply moves it out of the source file and into gimple-range-fold.h where it is generally accessible. Bootstrapped on x86_64-pc-linux-gnu with no regressions.  Pushed. Andrew From 548a78d0e4c02f1e5d07c8812d4324fef581d14b Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Thu, 31 Oct 2024 15:44:15 -0400 Subject: [PATCH 1/3] Make fur_edge accessible. Move the decl of fur_edge out of the source file into the header file. * gimple-range-fold.cc (class fur_edge): Relocate from here. (fur_edge::fur_edge): Also move to: * gimple-range-fold.h (class fur_edge): Relocate to here. (fur_edge::fur_edge): Likewise. --- gcc/gimple-range-fold.cc | 20 -------------------- gcc/gimple-range-fold.h | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index 82dd363f2ec..a4063b718f6 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -109,26 +109,6 @@ fur_source::register_relation (edge e ATTRIBUTE_UNUSED, { } -// This version of fur_source will pick a range up off an edge. - -class fur_edge : public fur_source -{ -public: - fur_edge (edge e, range_query *q = NULL); - virtual bool get_operand (vrange &r, tree expr) override; - virtual bool get_phi_operand (vrange &r, tree expr, edge e) override; -private: - edge m_edge; -}; - -// Instantiate an edge based fur_source. - -inline -fur_edge::fur_edge (edge e, range_query *q) : fur_source (q) -{ - m_edge = e; -} - // Get the value of EXPR on edge m_edge. bool diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h index 37c49596c33..109510853a2 100644 --- a/gcc/gimple-range-fold.h +++ b/gcc/gimple-range-fold.h @@ -150,6 +150,20 @@ public: tree op2) override; }; + +// This version of fur_source will pick a range up off an edge. + +class fur_edge : public fur_source +{ +public: + fur_edge (edge e, range_query *q = NULL) : fur_source (q) + { m_edge = e; } + virtual bool get_operand (vrange &r, tree expr) override; + virtual bool get_phi_operand (vrange &r, tree expr, edge e) override; +private: + edge m_edge; +}; + // This class uses ranges to fold a gimple statement producing a range for // the LHS. The source of all operands is supplied via the fur_source class // which provides a range_query as well as a source location and any other -- 2.45.0 From patchwork Fri Nov 1 19:25:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew MacLeod X-Patchwork-Id: 2005289 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=gF/uPBdm; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.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 ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Xg9qP3H8Hz1xwc for ; Sat, 2 Nov 2024 06:27:29 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 87E8B3858283 for ; Fri, 1 Nov 2024 19:27:27 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id 5876D3857BA7 for ; Fri, 1 Nov 2024 19:25:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5876D3857BA7 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 5876D3857BA7 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730489147; cv=none; b=f3n1iOdrACYzpW6/gHuSZq52Z/71sCyEuyNZI5IAXYWvzo8QmeonDhS6pVDMBUCltwp6bnmojCJHNEIwBAKMN3Ifqw+2jCGq/dxi36oZFcLOCCLdQ8wyMkhl9cFs0mNxVfRjUsSeWuG8nUU0P/rH/ZziC6zdMtvD28o0mG1Y8Mc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730489147; c=relaxed/simple; bh=7wDuX8Hexh/QpLePVW4PoNxEwkdLYmpvkTtcVNlvaiE=; h=DKIM-Signature:Message-ID:Date:MIME-Version:To:From:Subject; b=NhA98qIW/5gXq9osxwv/s4M5jMTMuoftiBm3Iqf20kX7BI/5ZI9eGVwcGaC3JJUPoko14b2+6+7g5BtNymO3TzUObLsYYPKbxOcsfRzy+njTE5jnUDUXZPW8RZ3ZBwivCzoM65hRYmFzzLEk3SRDC9DniyJl9d2wreTxx6iFJ3Y= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1730489132; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type; bh=jTSKQSlM8VSJ2v99JwIQ0fkyAy6Xb9/rbi8zWwkjMLM=; b=gF/uPBdmNLPtQKrQ9p5g/ElKvIiY7/gmR4jnVKFEwVHd1t/hVoLDugjZAk/EXRJjd9gdaK 8mdltNVM1IQcjPP0tVvQmkLqCD4a/D8PdE2OpwN4Ul9385uSLOCfjEtD2EARLx63Sw8DaC zSpgJ8Sjwr1ZHVtmwXJJi1Xqau9sb5I= Received: from mail-qk1-f198.google.com (mail-qk1-f198.google.com [209.85.222.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-75-jq0Ve4suMA-cI-n0oIqV8w-1; Fri, 01 Nov 2024 15:25:30 -0400 X-MC-Unique: jq0Ve4suMA-cI-n0oIqV8w-1 Received: by mail-qk1-f198.google.com with SMTP id af79cd13be357-7b13ff957cbso394765185a.0 for ; Fri, 01 Nov 2024 12:25:29 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730489127; x=1731093927; h=cc:subject:from:to:content-language:user-agent:mime-version:date :message-id:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=p8JFU1BbYHzrPc1VuWj9VJ+USQujDozpR8qshcmj3gY=; b=KId2FoCL4LgN3Ztzg8Y4AMUpuxJsAvRQ51TT3/p3gzWsJMi7dY+qUkV99KqLqUPog/ jSKPX4TKhd755WVMc/HJiLxG5vAAfZ3w/CNiXe5+aG5LV4PtNalmX0M7sUFTpl1XtXkI XdtKUQYG8ubthWMvpRtL9QZsUXxayEHzeN7kaexJ4SwGScJLvIM0Cw5x5orhp3CRxNcO ONzp7fzEIf4O2YAscuMJhcHA2e3snwHxduRNvUoI3tNBaUSmA5D7TlL+WQ37AaT1vBVe Xj4ExDlxfjjYe9hY3yDHkEF+f2ihacuzG+LJtA7pChtpenCJeaJMt/dgnWUmZx7/rABd 1N1g== X-Gm-Message-State: AOJu0YzypxivE1sGlYI4Gb/Ug+noA0QDgZjG9nB57xDsfrukBs1SjiYT kSVr/4o+7yW3prLNhSBcX9B1Gm4qH1/tfO4Ab6Z70RMzIDS2aMW5CbvEM/VcZJWt7UpXu/NoC9n 0b12zZkYCJkyo4pr8A7cy3ZIawvZ6U20cUXkeFs3xKIzxDvR9VSZuVL2D1+BtJISAI5LLqU3vDT rI2Vi6sa4MUReEhhAEp4AKaIdZgbn/YaVegDlzdBYR1A== X-Received: by 2002:a05:620a:49e:b0:7b1:ae79:be2b with SMTP id af79cd13be357-7b1ae79bf6cmr1245649685a.6.1730489127177; Fri, 01 Nov 2024 12:25:27 -0700 (PDT) X-Google-Smtp-Source: AGHT+IE8D4Hrz8GBukWZjWlrHI7++7o+ZI0yZIO02NZnYT5Z88GD/RW4r1iQGtNTMkWQ0khWrWeKHA== X-Received: by 2002:a05:620a:49e:b0:7b1:ae79:be2b with SMTP id af79cd13be357-7b1ae79bf6cmr1245646285a.6.1730489126719; Fri, 01 Nov 2024 12:25:26 -0700 (PDT) Received: from ?IPV6:2607:fea8:51de:a700::c2e1? ([2607:fea8:51de:a700::c2e1]) by smtp.gmail.com with ESMTPSA id af79cd13be357-7b2f39fae58sm197116585a.49.2024.11.01.12.25.24 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 01 Nov 2024 12:25:25 -0700 (PDT) Message-ID: <0b2c27d9-bd13-4c6b-98a1-0f4b22952fb9@redhat.com> Date: Fri, 1 Nov 2024 15:25:24 -0400 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird To: gcc-patches From: Andrew MacLeod Subject: [COMMITTED 2/3] PR tree-optimization/117287 - Reimplement 'assume' processing pass. Cc: Jakub Jelinek X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org The PR exposed latent issues with the assume pass.  Upon deeper investigation, the original approach was a bit naive, and I found other flaws. There are numerous changes. The original mechanism made a single pass working back from the return statement. This fails when flow starts to get a bit complicated.  It now looks at what the values of the parameters are on EACH path to the return statement that results ina TRUE value and combines those. It also no longer intergrates tightly with ranger components, and instead is simply a client pass using the generic range_query API.  AS such, I moved all the related code out of tree-vrp.cc and gimple-range.cc  and into its own self contained pass file, tree-assume.cc I put a lot of comments at the top of that file to indicate how assume works, and this new algorithm seems to be much more robust the previous version. I wanted to get it in sooner than later so Jakub can work with it to see if anything else shows up.   Meanwhile, I will addmore diagnostic/debugging abilities as right now its pretty much does its job silently, and there is no indication of HOW it determined values  (not that there was much before :-) The new approach uses GORI to determine any ranges in any basic block immediately preceeding the return block (including the return block itelf), and then invokes ranger for any other ranges feeding that.   Any time it cant be sure if an edge is executes or it cant determine specific values for any reason, it'll default to a conservative answer based on what ranger says. With more complex flow, I can imagine situations where we are not quite as precise as we could be (as in the following patch), but I haven't been able to produce one yet that is dependent on more changes to this alogithm.  This is certainly better than it was before anyway, and I think it should always be correct. Bootstrapped on x86_64-pc-linux-gnu with no regressions.  Pushed. Andrew From 74710442f291902c19b84cebf7642b74ecec8965 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Mon, 28 Oct 2024 10:19:27 -0400 Subject: [PATCH 2/3] Reimplement 'assume' processing pass. Rework the assume pass to work properly and fail conservatively when it does. Also move it to its own file. PR tree-optimization/117287 gcc/ * Makefile.in (IBJS): Add tree-assume.o * gimple-range.cc (assume_query::assume_range_p): Remove. (assume_query::range_of_expr): Remove. (assume_query::assume_query): Move to tree-assume.cc. (assume_query::~assume_query): Remove. (assume_query::calculate_op): Move to tree-assume.cc. (assume_query::calculate_phi): Likewise. (assume_query::check_taken_edge): Remove. (assume_query::calculate_stmt): Move to tree-assume.cc. (assume_query::dump): Remove. * gimple-range.h (class assume_query): Move to tree-assume.cc * tree-assume.cc: New * tree-vrp.cc (struct pass_data_assumptions): Move to tree-assume.cc. (class pass_assumptions): Likewise. (make_pass_assumptions): Likewise. gcc/testsuite/ * g++.dg/cpp23/pr117287-attr.C: New. --- gcc/Makefile.in | 1 + gcc/gimple-range.cc | 194 ----------- gcc/gimple-range.h | 17 - gcc/testsuite/g++.dg/cpp23/pr117287-attr.C | 38 +++ gcc/tree-assume.cc | 369 +++++++++++++++++++++ gcc/tree-vrp.cc | 60 ---- 6 files changed, 408 insertions(+), 271 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp23/pr117287-attr.C create mode 100644 gcc/tree-assume.cc diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 1be4ea02992..a1ffc173b97 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1699,6 +1699,7 @@ OBJS = \ sanopt.o \ sancov.o \ simple-diagnostic-path.o \ + tree-assume.o \ tree-call-cdce.o \ tree-cfg.o \ tree-cfgcleanup.o \ diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index f6aa27399a2..00e1a3c4ad5 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -700,200 +700,6 @@ disable_ranger (struct function *fun) fun->x_range_query = NULL; } -// ------------------------------------------------------------------------ - -// If there is a non-varying value associated with NAME, return true and the -// range in R. - -bool -assume_query::assume_range_p (vrange &r, tree name) -{ - if (global.get_range (r, name)) - return !r.varying_p (); - return false; -} - -// Query used by GORI to pick up any known value on entry to a block. - -bool -assume_query::range_of_expr (vrange &r, tree expr, gimple *stmt) -{ - if (!gimple_range_ssa_p (expr)) - return get_tree_range (r, expr, stmt); - - if (!global.get_range (r, expr)) - r.set_varying (TREE_TYPE (expr)); - return true; -} - -// If the current function returns an integral value, and has a single return -// statement, it will calculate any SSA_NAMES it can determine ranges for -// assuming the function returns 1. - -assume_query::assume_query () -{ - create_gori (0, param_vrp_switch_limit); - basic_block exit_bb = EXIT_BLOCK_PTR_FOR_FN (cfun); - if (single_pred_p (exit_bb)) - { - basic_block bb = single_pred (exit_bb); - gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb); - if (gsi_end_p (gsi)) - return; - gimple *s = gsi_stmt (gsi); - if (!is_a (s)) - return; - greturn *gret = as_a (s); - tree op = gimple_return_retval (gret); - if (!gimple_range_ssa_p (op)) - return; - tree lhs_type = TREE_TYPE (op); - if (!irange::supports_p (lhs_type)) - return; - - unsigned prec = TYPE_PRECISION (lhs_type); - int_range<2> lhs_range (lhs_type, wi::one (prec), wi::one (prec)); - global.set_range (op, lhs_range); - - gimple *def = SSA_NAME_DEF_STMT (op); - if (!def || gimple_get_lhs (def) != op) - return; - fur_stmt src (gret, this); - calculate_stmt (def, lhs_range, src); - } -} - -assume_query::~assume_query () -{ - destroy_gori (); -} - -// Evaluate operand OP on statement S, using the provided LHS range. -// If successful, set the range in the global table, then visit OP's def stmt. - -void -assume_query::calculate_op (tree op, gimple *s, vrange &lhs, fur_source &src) -{ - value_range op_range (TREE_TYPE (op)); - if (gori ().compute_operand_range (op_range, s, lhs, op, src) - && !op_range.varying_p ()) - { - // Set the global range, merging if there is already a range. - global.merge_range (op, op_range); - gimple *def_stmt = SSA_NAME_DEF_STMT (op); - if (def_stmt && gimple_get_lhs (def_stmt) == op) - calculate_stmt (def_stmt, op_range, src); - } -} - -// Evaluate PHI statement, using the provided LHS range. -// Check each constant argument predecessor if it can be taken -// provide LHS to any symbolic arguments, and process their def statements. - -void -assume_query::calculate_phi (gphi *phi, vrange &lhs_range, fur_source &src) -{ - for (unsigned x= 0; x < gimple_phi_num_args (phi); x++) - { - tree arg = gimple_phi_arg_def (phi, x); - value_range arg_range (TREE_TYPE (arg)); - if (gimple_range_ssa_p (arg)) - { - // A symbol arg will be the LHS value. - arg_range = lhs_range; - range_cast (arg_range, TREE_TYPE (arg)); - if (!global.get_range (arg_range, arg)) - { - global.set_range (arg, arg_range); - gimple *def_stmt = SSA_NAME_DEF_STMT (arg); - if (def_stmt && gimple_get_lhs (def_stmt) == arg) - calculate_stmt (def_stmt, arg_range, src); - } - } - else if (get_tree_range (arg_range, arg, NULL)) - { - // If this is a constant value that differs from LHS, this - // edge cannot be taken. - arg_range.intersect (lhs_range); - if (arg_range.undefined_p ()) - continue; - // Otherwise check the condition feeding this edge. - edge e = gimple_phi_arg_edge (phi, x); - check_taken_edge (e, src); - } - } -} - -// If an edge is known to be taken, examine the outgoing edge to see -// if it carries any range information that can also be evaluated. - -void -assume_query::check_taken_edge (edge e, fur_source &src) -{ - gimple *stmt = gimple_outgoing_range_stmt_p (e->src); - if (stmt && is_a (stmt)) - { - int_range<2> cond; - gcond_edge_range (cond, e); - calculate_stmt (stmt, cond, src); - } -} - -// Evaluate statement S which produces range LHS_RANGE. - -void -assume_query::calculate_stmt (gimple *s, vrange &lhs_range, fur_source &src) -{ - gimple_range_op_handler handler (s); - if (handler) - { - tree op = gimple_range_ssa_p (handler.operand1 ()); - if (op) - calculate_op (op, s, lhs_range, src); - op = gimple_range_ssa_p (handler.operand2 ()); - if (op) - calculate_op (op, s, lhs_range, src); - } - else if (is_a (s)) - { - calculate_phi (as_a (s), lhs_range, src); - // Don't further check predecessors of blocks with PHIs. - return; - } - - // Even if the walk back terminates before the top, if this is a single - // predecessor block, see if the predecessor provided any ranges to get here. - if (single_pred_p (gimple_bb (s))) - check_taken_edge (single_pred_edge (gimple_bb (s)), src); -} - -// Show everything that was calculated. - -void -assume_query::dump (FILE *f) -{ - fprintf (f, "Assumption details calculated:\n"); - for (unsigned i = 0; i < num_ssa_names; i++) - { - tree name = ssa_name (i); - if (!name || !gimple_range_ssa_p (name)) - continue; - tree type = TREE_TYPE (name); - if (!value_range::supports_type_p (type)) - continue; - - value_range assume_range (type); - if (assume_range_p (assume_range, name)) - { - print_generic_expr (f, name, TDF_SLIM); - fprintf (f, " -> "); - assume_range.dump (f); - fputc ('\n', f); - } - } - fprintf (f, "------------------------------\n"); -} - // --------------------------------------------------------------------------- // // The DOM based ranger assumes a single DOM walk through the IL, and is diff --git a/gcc/gimple-range.h b/gcc/gimple-range.h index 62bd8a87112..252c2d79d65 100644 --- a/gcc/gimple-range.h +++ b/gcc/gimple-range.h @@ -82,23 +82,6 @@ extern gimple_ranger *enable_ranger (struct function *m, bool use_imm_uses = true); extern void disable_ranger (struct function *); -class assume_query : public range_query -{ -public: - assume_query (); - ~assume_query (); - bool assume_range_p (vrange &r, tree name); - virtual bool range_of_expr (vrange &r, tree expr, gimple * = NULL); - void dump (FILE *f); -protected: - void calculate_stmt (gimple *s, vrange &lhs_range, fur_source &src); - void calculate_op (tree op, gimple *s, vrange &lhs, fur_source &src); - void calculate_phi (gphi *phi, vrange &lhs_range, fur_source &src); - void check_taken_edge (edge e, fur_source &src); - - ssa_lazy_cache global; -}; - // DOM based ranger for fast VRP. // This must be processed in DOM order, and does only basic range operations. diff --git a/gcc/testsuite/g++.dg/cpp23/pr117287-attr.C b/gcc/testsuite/g++.dg/cpp23/pr117287-attr.C new file mode 100644 index 00000000000..759c21dc283 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/pr117287-attr.C @@ -0,0 +1,38 @@ +// P1774R8 - Portable assumptions +// { dg-do run { target c++23 } } +// { dg-options "-O2 --param=logical-op-non-short-circuit=0" } +// Test the we can optimize based on conditions in assume. + +static inline bool +foo (unsigned x) +{ + return x == 4 || x == 5 || x == 9 || x == 10; +} + +int v; + +[[gnu::noipa]] void +bar (const char *p) +{ + if (p[0] != (v ? 'a' : 'b') || p[1]) + __builtin_abort (); +} + +[[gnu::noipa]] void +baz (unsigned x) +{ + bool a = x == 5; + [[assume (foo (x))]]; + bar (a ? "a" : "b"); +} + +int +main () +{ + baz (4); + v = 1; + baz (5); + v = 0; + baz (9); + baz (10); +} diff --git a/gcc/tree-assume.cc b/gcc/tree-assume.cc new file mode 100644 index 00000000000..dd279f58179 --- /dev/null +++ b/gcc/tree-assume.cc @@ -0,0 +1,369 @@ +/* Support for C++23 ASSUME keyword functionailty. + Copyright (C) 2023-2024 Free Software Foundation, Inc. + Contributed by Andrew MacLeod . + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "basic-block.h" +#include "bitmap.h" +#include "options.h" +#include "function.h" +#include "cfg.h" +#include "tree.h" +#include "gimple.h" +#include "tree-pass.h" +#include "ssa.h" +#include "gimple-iterator.h" +#include "gimple-range.h" +#include "tree-dfa.h" + +// An assume query utilizes the current range query to implelemtn the assume +// keyword. +// For any return value of 1 from the function, it attempts to determine +// which paths leads to a 1 value being returned. On those paths, what +// the ranges of any ssa_names listed in bitmap P (usually the parm list for +// the function) are, and combined them all. +// These ranges are then set as the global ranges for those parms in this +// function. +// Other functions which then refer to this function in an assume builtin +// will then pick up these ranges for the paramters via the inferred range +// mechanism. +// See gimple-range-infer.cc::gimple_infer_range::check_assume_func () +// +// my_func (int x) +// { +// <...> +// assume [[(x == 1 || x ==4))]] +// if (x ==3) +// +// a small temporary assume function consisting of +// assume_f1 (int x) { return x == 1 || x == 4; } +// is constructed by the front end, and optimzed, at the very end of +// optimization, instead of generating code, we instead invoke the assume pass +// which uses this query to set the the global value of parm x to [1,1][4,4] +// +// Meanwhile., my_Fund has been rewritten to be: +// +// my_func (int x_2) +// { +// <...> +// assume_builtin_call assume_f1 (x_2); +// if (x_2 == 3) +// +// When ranger is processing the assume_builtin_call, it looks up the global +// value of the paramter in assume_f1, which is [1,1][4,4]. It then registers +// and inferred range at this statement setting the value x_2 to [1,1][4,4] +// +// Any uses of x_2 after this statement will now utilzie this inferred range. +// +// When VRP precoesses if (x_2 == 3), it picks up the inferred range, and +// determines that x_2 can never be 3, and will rewrite the branch to +// if (0 != 0) + +class assume_query +{ +public: + assume_query (function *f, bitmap p); +protected: + inline void process_stmts (gimple *s, vrange &lhs_range) + { + fur_depend src (s, get_range_query (m_func)); + calculate_stmt (s, lhs_range, src); + update_parms (src); + } + void update_parms (fur_source &src); + void calculate_stmt (gimple *s, vrange &lhs_range, fur_source &src); + void calculate_op (tree op, gimple *s, vrange &lhs, fur_source &src); + void calculate_phi (gphi *phi, vrange &lhs_range); + + ssa_lazy_cache m_path; // Values found on path + ssa_lazy_cache m_parms; // Cumulative parameter value calculated + bitmap &m_parm_list; // Parameter ssa-names list. + function *m_func; +}; + +// If function F returns a integral value, and has a single return +// statement, try to calculate the range of each value in P that leads +// to the return statement returning TRUE. + +assume_query::assume_query (function *f, bitmap p) : m_parm_list (p), + m_func (f) +{ + basic_block exit_bb = EXIT_BLOCK_PTR_FOR_FN (f); + // If there is more than one precessor to the exit block, bail. + if (!single_pred_p (exit_bb)) + return; + + basic_block bb = single_pred (exit_bb); + gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb); + if (gsi_end_p (gsi)) + return; + gimple *s = gsi_stmt (gsi); + if (!is_a (s)) + return; + + // Check if the single return value is a symbolic and supported type. + greturn *gret = as_a (s); + tree op = gimple_return_retval (gret); + if (!gimple_range_ssa_p (op)) + return; + tree lhs_type = TREE_TYPE (op); + if (!irange::supports_p (lhs_type)) + return; + + // Only values of interest are when the return value is 1. The defintion + // of the return value must be in the same block, or we have + // complicated flow control we don't understand, and just return. + unsigned prec = TYPE_PRECISION (lhs_type); + int_range<2> lhs_range (lhs_type, wi::one (prec), wi::one (prec)); + + gimple *def = SSA_NAME_DEF_STMT (op); + if (!def || gimple_get_lhs (def) != op || gimple_bb (def) != bb) + return; + + // Determine if this is a PHI or a linear sequence to deal with. + if (is_a (def)) + calculate_phi (as_a (def), lhs_range); + else + process_stmts (def, lhs_range); + + if (dump_file) + fprintf (dump_file, "Assumptions :\n--------------\n"); + + // Now export any interesting values that were found. + bitmap_iterator bi; + unsigned x; + EXECUTE_IF_SET_IN_BITMAP (m_parm_list, 0, x, bi) + { + tree name = ssa_name (x); + tree type = TREE_TYPE (name); + value_range assume_range (type); + // Set the global range of NAME to anything calculated. + if (m_parms.get_range (assume_range, name) && !assume_range.varying_p ()) + set_range_info (name, assume_range); + } +} + +// This function Will update all the current value of interesting parameters. +// It tries, in order: +// a) a range found via path calculations. +// b) range of the parm at SRC point in the IL. (either edge or stmt) +// c) VARYING if those options fail. +// The value is then unioned with any existing value, allowing for the +// cumulation of all ranges leading to the return that return 1. + +void +assume_query::update_parms (fur_source &src) +{ + // Merge any parameter values. + bitmap_iterator bi; + unsigned x; + EXECUTE_IF_SET_IN_BITMAP (m_parm_list, 0, x, bi) + { + tree name = ssa_name (x); + tree type = TREE_TYPE (name); + + // Find a valu efrom calculations. + value_range glob_range (type); + if (!m_path.get_range (glob_range, name) + && !src.get_operand (glob_range, name)) + glob_range.set_varying (type); + + // Find any current value of parm, and combine them. + value_range parm_range (type); + if (m_parms.get_range (parm_range, name)) + glob_range.union_ (parm_range); + + // Set this new value. + m_parms.set_range (name, glob_range); + } + // Now reset the path values for the next path. + m_path.clear (); +} + + +// Evaluate PHI statement, using the provided LHS range. +// Only process edge that are both taken and returns the LHS of the PHI. + +void +assume_query::calculate_phi (gphi *phi, vrange &lhs_range) +{ + for (unsigned x= 0; x < gimple_phi_num_args (phi); x++) + { + tree arg = gimple_phi_arg_def (phi, x); + value_range arg_range (TREE_TYPE (arg)); + edge e = gimple_phi_arg_edge (phi, x); + value_range edge_range (TREE_TYPE (arg)); + // If we can't get an edge range, be conservative and assume the + // edge can be taken. + // NOte this can be either an ssa_name or a constant. + if (get_range_query (m_func)->range_on_edge (edge_range, e, arg)) + { + if (gimple_range_ssa_p (arg)) + { + arg_range = lhs_range; + range_cast (arg_range, TREE_TYPE (arg)); + + // An SSA_NAME arg will start with the LHS value. + // Check the range of ARG on the edge leading here. If that range + // cannot be any value from the LHS of the PHI, then this branch + // will not be taken to return the LHS value and can be ignored. + arg_range.intersect (edge_range); + if (arg_range.undefined_p ()) + continue; + + // If the def is in the immediate preceeding block, process it + // with GORI to determine what values can produce this + // argument value. Otherwise there is more flow, so just query + // the edge for parm ranges and be conservative. + gimple *def_stmt = SSA_NAME_DEF_STMT (arg); + if (def_stmt && gimple_get_lhs (def_stmt) == arg + && gimple_bb (def_stmt) == e->src) + { + process_stmts (def_stmt, arg_range); + continue; + } + // Fall through to process the edge. + } + else + { + // If this is a constant value that differs from LHS, this + // edge cannot be taken and we can ignore it. Otherwise fall + // thorugh and process the edge. + edge_range.intersect (lhs_range); + if (edge_range.undefined_p ()) + continue; + } + } + // If this point is reached the edge needs processing. + fur_edge src (e, get_range_query (m_func)); + update_parms (src); + } +} + +// Evaluate operand OP on statement S, using the provided LHS range. +// If successful, set the range in path table, then visit OP's def stmt +// if it is in the same BB. + +void +assume_query::calculate_op (tree op, gimple *s, vrange &lhs, fur_source &src) +{ + basic_block bb = gimple_bb (s); + value_range op_range (TREE_TYPE (op)); + if (src.gori () && + src.gori ()->compute_operand_range (op_range, s, lhs, op, src) + && !op_range.varying_p ()) + { + // Set the global range, merging if there is already a range. + m_path.merge_range (op, op_range); + gimple *def_stmt = SSA_NAME_DEF_STMT (op); + // Terminate if the patway leads to a different block as we + // are not analyzing flow. + if (def_stmt && gimple_get_lhs (def_stmt) == op + && gimple_bb (def_stmt) == bb) + calculate_stmt (def_stmt, op_range, src); + } +} + + +// Evaluate statement S which produces range LHS_RANGE. Use GORI to +// determine what values the operands can have to produce the LHS, +// and set these in the M_PATH table. + +void +assume_query::calculate_stmt (gimple *s, vrange &lhs_range, fur_source &src) +{ + gimple_range_op_handler handler (s); + if (handler) + { + tree op = gimple_range_ssa_p (handler.operand1 ()); + if (op) + calculate_op (op, s, lhs_range, src); + op = gimple_range_ssa_p (handler.operand2 ()); + if (op) + calculate_op (op, s, lhs_range, src); + } +} + +namespace { + +const pass_data pass_data_assumptions = +{ + GIMPLE_PASS, /* type */ + "assumptions", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_TREE_ASSUMPTIONS, /* tv_id */ + PROP_ssa, /* properties_required */ + PROP_assumptions_done, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_end */ +}; + + +class pass_assumptions : public gimple_opt_pass +{ +public: + pass_assumptions (gcc::context *ctxt) + : gimple_opt_pass (pass_data_assumptions, ctxt) + {} + + /* opt_pass methods: */ + bool gate (function *fun) final override { return fun->assume_function; } + unsigned int execute (function *fun) final override + { + // Create a bitmap of all the paramters in this function. + // Invoke the assume_query to detemine what values these parameters + // have when the function returns TRUE, and set the globals value of + // those parameters in this function based on that. This will later be + // utilized by ranger when prcessing the builtin_assumer function. + auto_bitmap decls; + for (tree arg = DECL_ARGUMENTS (fun->decl); arg; arg = DECL_CHAIN (arg)) + { + tree name = ssa_default_def (fun, arg); + if (!name || !gimple_range_ssa_p (name)) + continue; + tree type = TREE_TYPE (name); + if (!value_range::supports_type_p (type)) + continue; + bitmap_set_bit (decls, SSA_NAME_VERSION (name)); + } + // If there are no parameters to map, simply return; + if (bitmap_empty_p (decls)) + return TODO_discard_function; + + enable_ranger (fun); + + // This assume query will set any global values required. + assume_query query (fun, decls); + + disable_ranger (fun); + return TODO_discard_function; + } + +}; // class pass_assumptions + +} // anon namespace + +gimple_opt_pass * +make_pass_assumptions (gcc::context *ctx) +{ + return new pass_assumptions (ctx); +} diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc index c265672bf99..f40bd6cdf5a 100644 --- a/gcc/tree-vrp.cc +++ b/gcc/tree-vrp.cc @@ -1353,60 +1353,6 @@ public: const pass_data &data; bool final_p; }; // class pass_vrp - -const pass_data pass_data_assumptions = -{ - GIMPLE_PASS, /* type */ - "assumptions", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ - TV_TREE_ASSUMPTIONS, /* tv_id */ - PROP_ssa, /* properties_required */ - PROP_assumptions_done, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0, /* todo_flags_end */ -}; - -class pass_assumptions : public gimple_opt_pass -{ -public: - pass_assumptions (gcc::context *ctxt) - : gimple_opt_pass (pass_data_assumptions, ctxt) - {} - - /* opt_pass methods: */ - bool gate (function *fun) final override { return fun->assume_function; } - unsigned int execute (function *) final override - { - assume_query query; - if (dump_file) - fprintf (dump_file, "Assumptions :\n--------------\n"); - - for (tree arg = DECL_ARGUMENTS (cfun->decl); arg; arg = DECL_CHAIN (arg)) - { - tree name = ssa_default_def (cfun, arg); - if (!name || !gimple_range_ssa_p (name)) - continue; - tree type = TREE_TYPE (name); - if (!value_range::supports_type_p (type)) - continue; - value_range assume_range (type); - // Set the global range of NAME to anything calculated. - if (query.assume_range_p (assume_range, name)) - set_range_info (name, assume_range); - } - if (dump_file) - { - fputc ('\n', dump_file); - gimple_dump_cfg (dump_file, dump_flags & ~TDF_DETAILS); - if (dump_flags & TDF_DETAILS) - query.dump (dump_file); - } - return TODO_discard_function; - } - -}; // class pass_assumptions - } // anon namespace gimple_opt_pass * @@ -1426,9 +1372,3 @@ make_pass_fast_vrp (gcc::context *ctxt) { return new pass_vrp (ctxt, pass_data_fast_vrp); } - -gimple_opt_pass * -make_pass_assumptions (gcc::context *ctx) -{ - return new pass_assumptions (ctx); -} -- 2.45.0 From patchwork Fri Nov 1 19:25:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew MacLeod X-Patchwork-Id: 2005285 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=bLAK+gpo; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Xg9p21S1qz1xwc for ; Sat, 2 Nov 2024 06:26:18 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 656F93857B9B for ; Fri, 1 Nov 2024 19:26:16 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id F1E7E3858290 for ; Fri, 1 Nov 2024 19:25:44 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org F1E7E3858290 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org F1E7E3858290 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730489147; cv=none; b=KmrlAFQhd5di/yr6ry4Q5DM253JFwhXVe8eOypXS9LMWRzJyJp6fYT8sqL2RO47Z5Ry7/mXskYjbPpaCPFH4OuEHeFZW1NoAwDPiygdwxwtB0SjJNnuFX2QZLCC14cBku6LNYmNjmvwpKhh/gHdXQZHbj4U49HNSV115Eq8NN7E= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730489147; c=relaxed/simple; bh=jL3lRrbfwu4hwXPEmbeKStvz1/YF4Ma4/dMFjrx5nkE=; h=DKIM-Signature:Message-ID:Date:MIME-Version:To:From:Subject; b=XWdaqPvUO7XsmfwZAhuqTSNRsYEEnGqv4bV3V7xd9b/QkXHmO7JgXTSf7VIvJ0au7KecYy5r19Y8Yw3Sp5Yys3BULWnxdWIJXPFonTUJTcEC0Rs70f6STApi0LMst+50a+Jp8Ipjhc/VXtvWSrOGNzBv2wb9yCc+DhRkaZPuGSc= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1730489144; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type; bh=FlT8Je65qPSlfj5DlsNHcAahta3oGDYEqzc1QKAMiOg=; b=bLAK+gpoz3QSpSBbk+e5+5hxLE7PWbIHu9qAmwzm0O/9HdgCVCwKM+cORYbQWDZPsmm5yQ ZHhSOkfXmyJBEGfPtzweQwtHGmdv+0ObmkWKr1EvMHzvoJs8o9BfDTnLIq79RS/ZkJUjsY rNSODYdEKiKysrKU8mctazt6iJZrdWM= Received: from mail-oi1-f198.google.com (mail-oi1-f198.google.com [209.85.167.198]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-226-FiVEoI3XOyO32tnt0Nj0SA-1; Fri, 01 Nov 2024 15:25:43 -0400 X-MC-Unique: FiVEoI3XOyO32tnt0Nj0SA-1 Received: by mail-oi1-f198.google.com with SMTP id 5614622812f47-3e5f78786cbso2895422b6e.1 for ; Fri, 01 Nov 2024 12:25:43 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730489141; x=1731093941; h=subject:from:cc:to:content-language:user-agent:mime-version:date :message-id:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=nU2M0xj9GaJvtZAkOiUoxwUUlKGfy/KuChN/ESnKv2c=; b=Twef2RH6uJxxns8J5sN0f5o18ebvZ2tpKb3BcC3NnID2wrGg/lR/1/QoVMsLj7vSUy tOFfxAVRZo3f68wfejq1iurkSG9aMNkV+MsMf62BcKQcHiTC4geHcx4D4+TrHhlf6hLA pM37xc4zJk3sFNEf1nUKb5kjtDnSsz5VYfhpwvkEwWXAj/cPIl0mziXt+72a3X2y796b q52snm1o9t5OHNVartK5wypAC7TAHL1HEP9/KI0WG5VlwCvggPSWTp7rzSFNDlGbXm5W Htoc9lhtNi0pjYxX96PQ61h8jqGHp/D0r9I9el+se1zidpRA3x7FV/o+Dw3Ux50MgLre RkiQ== X-Gm-Message-State: AOJu0YyBnt4LbtOe1r15/X483VlT9vdM2rz2tEw8hb9cmQKFDRbK5scx GEv1Eew7i9r/84DOvmX3AyGIS+nNIfVHxceR2QouwmtvCS2eEhZ1eE8d85MMGP3PjhYFcvLU1b7 PhVK4nxkkiK8OGJ1jJneHpj7r1wJXc+Ef3vxRpo1YmKDM9pClIxXFVpCqMI7+m+WUxT3ZdqmxDu +Uw3T6w1wLrjC4fc9R74ZgDH2M8q34QYmk9muqxeS5ig== X-Received: by 2002:a05:6808:308e:b0:3e5:f7d8:b560 with SMTP id 5614622812f47-3e6608dfc0cmr7351995b6e.18.1730489141611; Fri, 01 Nov 2024 12:25:41 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGRAp+tvi0PGHtAOfdYineefY/72GMozVPZzzmEasKDfdDxGmFFx6Gh3sUAJJjmilKVg3lExw== X-Received: by 2002:a05:6808:308e:b0:3e5:f7d8:b560 with SMTP id 5614622812f47-3e6608dfc0cmr7351981b6e.18.1730489141211; Fri, 01 Nov 2024 12:25:41 -0700 (PDT) Received: from ?IPV6:2607:fea8:51de:a700::c2e1? ([2607:fea8:51de:a700::c2e1]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-6d353fc5f13sm22329096d6.37.2024.11.01.12.25.38 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 01 Nov 2024 12:25:39 -0700 (PDT) Message-ID: <1e175b59-7c54-4646-b291-e753431d9c59@redhat.com> Date: Fri, 1 Nov 2024 15:25:37 -0400 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird To: gcc-patches Cc: Jakub Jelinek From: Andrew MacLeod Subject: [COMMITTED 3/3] Update bitwise_or op_range. X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org When experimenting with more complex flow for the assume pass, I found a case where we were not as precise as we should be, but it was because range-ops hadn't been taught that if the LHS of a bitwise OR was positive, that the 2 RHS operands must also be positive. The testcase is simple a tweaked version of an existing testcase which turned if (a_1 < 0 && b_2 < 0) goto bb3; else goto bb4; into _4 = a_1 | b_2 if (_4 < 0) goto bb3; else goto bb4; on the branch to bb4, the condition is _4 >= 0 and we were not getting positive values for a_1 and b_2 on that edge resulting in ranges that included [-INF, -1] that shouldn't have been there. This patch fixes that by implementing this functionality in op1_range in operator_bitwise_or, and adds the testcase. Bootstrapped on x86_64-pc-linux-gnu with no regressions.  Pushed. Andrew From 9283b1b3593f708a4fc11fb6dfcf208ab218a5d9 Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Thu, 31 Oct 2024 14:07:00 -0400 Subject: [PATCH 3/3] Update bitwise_or op_range. If the LHS of a bitwise OR is positive, then so are both operands when using op1_range or op2_range. gcc/ * range-op.cc (operator_bitwise_or::op1_range): If LHS is signed positive, so are both operands. gcc/testsuite * g++.dg/cpp23/attr-assume-opt.C (f2b): Alternate flow test. --- gcc/range-op.cc | 13 +++++++ gcc/testsuite/g++.dg/cpp23/attr-assume-opt.C | 37 +++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 58734cddd2f..5a1eb59f3cd 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -3822,6 +3822,19 @@ operator_bitwise_or::op1_range (irange &r, tree type, r.set_zero (type); return true; } + + // if (A < 0 && B < 0) + // Sometimes gets translated to + // _1 = A | B + // if (_1 < 0)) + // It is useful for ranger to recognize a positive LHS means the RHS + // operands are also positive when dealing with the ELSE range.. + if (TYPE_SIGN (type) == SIGNED && wi::ge_p (lhs.lower_bound (), 0, SIGNED)) + { + unsigned prec = TYPE_PRECISION (type); + r.set (type, wi::zero (prec), wi::max_value (prec, SIGNED)); + return true; + } r.set_varying (type); return true; } diff --git a/gcc/testsuite/g++.dg/cpp23/attr-assume-opt.C b/gcc/testsuite/g++.dg/cpp23/attr-assume-opt.C index 88d5e78dbba..e61ba7a27e0 100644 --- a/gcc/testsuite/g++.dg/cpp23/attr-assume-opt.C +++ b/gcc/testsuite/g++.dg/cpp23/attr-assume-opt.C @@ -38,5 +38,40 @@ f3 (int x, int y, int z) return 1; } +// This is the same as f2, except there is more complicated flow and +// required a range-op update to bitwise or. + +void barn(int x); +// assume (x+12 == 14 && y >= 0 && y + 10 < 13 && z + 4 >= 4 && z - 2 < 18) +// in different order and form with function calls to cause branches. +bool assume_func (int x, int y, int z) +{ + if (z - 2 >= 18) + return false; + if (x+12 != 14) + return false; + barn (x); + if (y < 0) + return false; + if (z + 4 < 4) + return false; + barn (y); + if (y + 10 >= 13) + return false; + barn (z); + return true; +} + +int +f2b (int x, int y, int z) +{ + [[assume (assume_func (x, y, z))]]; + unsigned q = x + y + z; + if (q*2 > 46) + return 0; + return 1; +} + + /* { dg-final { scan-tree-dump-times "return 0" 0 "vrp2" } } */ -/* { dg-final { scan-tree-dump-times "return 1" 3 "vrp2" } } */ +/* { dg-final { scan-tree-dump-times "return 1" 4 "vrp2" } } */ -- 2.45.0