From patchwork Tue Sep 1 12:53:06 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Andrew MacLeod X-Patchwork-Id: 142629 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id AB6A64BA2E1F for ; Tue, 1 Sep 2026 12:53:53 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AB6A64BA2E1F Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=ZT6XrTpU 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 A11784BA5436 for ; Tue, 1 Sep 2026 12:53:11 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A11784BA5436 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine 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 A11784BA5436 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1788267191; cv=none; b=BCW69fX7hCj0G9METhHidQsEALgES7X4cBG/WIAmojkJwUICKBSP7+nUih4ILJIGYkxLdubIMwGK/MjOFmpjzomJFdcxkXGjFBkGlWJ44PzJ3sJHxqsLF3j5X3ZZHdQgs9Zgmkx6vLVMl2ej0r8W8KlvmyQae/xU0nL7X6e8X+c= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1788267191; c=relaxed/simple; bh=yCk31kcQ8HoKTcdXHRTLX/qsFpXYYRfbIzyBQ5NaICQ=; h=DKIM-Signature:Message-ID:Date:MIME-Version:To:From:Subject; b=NTKsWCnVeEHAHL3wjVNgiZHBHuZel4sPDNsr6ARQQ+jlYiRqjDTU2IpqlPrTijel4hNPh6JQPepgeMPRRryZB2NNuet521RwKnryMSo3tnHzg1mAJIW2a1cD8QKpJs28u1M+0rnscohuLhQ9spkgg0zXRrSBJ9dav09pL/tPdXo= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=ZT6XrTpU DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A11784BA5436 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1788267191; 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=wJJdQQ3iLDY7VEnuqkin0s36qEoA8bzo34DrzhGgHyI=; b=ZT6XrTpU7aH6/vubY2VogvvCdQPYqc3T+FaP2FREa3ffpthZDTalFTTgxFVSsQYJ0NR7WI LphOJKufUuCFoltZwcOVkGIgPzSnN+8/f5h8yZ9yrEP1V2q6zavxnHib2lrCBob6iqc3kJ 6J/7gamZ2F3Ne9HvFH/GrS2Mb31W4Ew= 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-321-EyCkWLMaPAOmMk1ufj4BpQ-1; Tue, 01 Sept 2026 08:53:10 -0400 X-MC-Unique: EyCkWLMaPAOmMk1ufj4BpQ-1 X-Mimecast-MFC-AGG-ID: EyCkWLMaPAOmMk1ufj4BpQ_1788267189 Received: by mail-qv1-f70.google.com with SMTP id 6a1803df08f44-90e8135d7eeso46759276d6.1 for ; Tue, 01 Sep 2026 05:53:10 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788267189; x=1788871989; h=cc:subject:from:to:content-language:user-agent:mime-version:date :message-id:content-type:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to:content-type; bh=xMHfHlikcNsBkI0oRumf+QOCl9fRXTGH3ph2Ci5JnDM=; b=ddwtSDNgMLPrRH7F3+bcEYxt9eiy7DLwdufVbRs67WYucqEkJGpEaCon18T55ya4QQ pIX1xnaTqQ5G789GW4sIQ89ySu26ya/cOtI9Zmzwr9F19a3t7zj5ft6gKUrh03w4FgK+ jloBS/yZP7MuHjbzHR0WU+cwvB88lBDomIIzgNDbWPaxEtF2jTEVIiJ7CDprZm6784eq 6i1l1I8Z9o3sl6MaZ5S3eqlY+VN/9m8GPy4wxEILNoKpEZ/dJBIm7FAW5yMibJZFEycj G3lCA6sln2+02JIgRkJsKy+/9nFtns3pVCF3OfuZXAZ6YiIyJfh4CLHgf7THPdIsUMHY bobA== X-Gm-Message-State: AFuF++l0pFq2CiiSzlTfp7dqta/e1SESrRQolxjB5SxvJvQTLeNlaTMK lGzysvfUTlnnZ+4udq9euY44LngJ2HPf9SuqOQLLiddkjKfKygisP6BBloQRKqHJMCr6sA8dgBB V6hNr1Lv/v0hdqaqmgaOC3dzzxcLXwFsyULvg50Xsvm3Y8W9vyK1T2ELmmgdnEct24eVdIAElSS mBbp51d9yo8+XgVWzOwPVklGhyohaKPaZHg7P2f2dH3V4RqQ== X-Gm-Gg: AYBFou3xl4sCzYLi+iSeVobSInnCzgIifkU2JY1ZD30G6tabz3gYeqOZRNHgyhc+jOR KUm2Ifmwj6qKdJvUEYvZa64iiTROeu4OS7YeI14g6JudlfWBOE05OcmE5+E4FJtFbRp6CMBg0KB /dyu+MzTUnidoj0QLQuR91sRjxAt5+46wLaN/cjrcYAbW1ueuFj0x0c7rU01psQCLf2qqO2bk8j tkV3+0uibcQP8BoVOKQU2Hy0k1Akr8KpJDi52SvFYn7/fXoV3MEgoC7ja1VuoAxqNNy/B/eunZb A17voFVd+HI9Ij30XtmnBo59giXW0WmUicrpfLvIO/g8sF9yd/1+LU14f4VJkEFKtZnPSANzjbn BVM3B/kjaITNANNajRC4XjR1ajM/s5xzDamx3H6tmRIq+NqLFydruXqaQ X-Received: by 2002:a05:6214:6350:b0:90e:9a7c:e5a0 with SMTP id 6a1803df08f44-90e9a7cf038mr22343406d6.17.1788267189186; Tue, 01 Sep 2026 05:53:09 -0700 (PDT) X-Received: by 2002:a05:6214:6350:b0:90e:9a7c:e5a0 with SMTP id 6a1803df08f44-90e9a7cf038mr22342446d6.17.1788267188366; Tue, 01 Sep 2026 05:53:08 -0700 (PDT) Received: from [192.168.50.116] (pool-99-240-151-212.cpe.net.cable.rogers.com. [99.240.151.212]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-90ceb0a3a09sm92262506d6.16.2026.09.01.05.53.07 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 01 Sep 2026 05:53:07 -0700 (PDT) Message-ID: Date: Tue, 1 Sep 2026 08:53:06 -0400 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird To: gcc-patches From: Andrew MacLeod Subject: [PATCH] PR tree-optimization/126942- Disallow path ranger from current_range_query. Cc: Richard Biener X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: zDBt45tAVwL048P3mXIGA4H8YeCKGoED1JQ9WZ9UkKY_1788267189 X-Mimecast-Originator: redhat.com Content-Language: en-US X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, PROLO_LEO1, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, RCVD_IN_PBL, SPF_HELO_PASS, SPF_NONE, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org 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~patchwork=sourceware.org@gcc.gnu.org I think this PR ends the debate about whether a path_range should become the current range_query. The problem is in tree-ssa-loop-ch.cc. It uses path_range_query to evaluate a path, and during a range_of_stmt() call for a statement on that path, the path ranger becomes the current range query.   While servicing that query, a nested query involving a PHI causes SCEV analysis to be invoked. SCEV then performs loop analysis using the path ranger as the current query.  This use to be a query mismatch and we refused to invoke SCEV  because it wouldn't work right when picking up ranges from the path further down in the loop during general analysis. So.  I slightly reworked the current ad-hoc "change the current query" mechanism to allow for a small amount of organized push/pop.  The current query always starts as a global_range_query.  Enable/disable_ranger() is altered to push/pop a new ranger instance (as has fast_vrp), and gimple-range-fold() also temporarily changes to current range-query IFF the incoming query is different than the current one. I added an active_query_compatible_p () method to a range_query, and have it return false for any range_query (ie path-ranger) which is not compatible with this. I put all the "smarts"  into the push routine.  There is a series of 3 PRs:  125854, 126814 and now 126942  which combined, demonstrate that the only safe course of action is to revert to the global query if there is a mismatch which can't be replaced...  And this is now what push_range_query () does.   If the current query is the same as the requested one, it does nothing.   If the incoming query to be used does not match the current query, AND is not compatible to become the current query, it instead pushes the global range query. I submit this for approval because I added a small vector to "struct function" which managed the push/pop list, and I wanted to make sure that is OK. Its currently set to  5 pointer elements and an unsigned index counter.  It might be possible to reduce it to 3, but I figured 5 was future proof.   Im not sure how sensitive the size of struct function is, so wanted to check. If anything ever traps the vec size check, we''re doing something wonky that is unexpected and needs to be examined.    Is a vec of 5 plus a word OK to add to struct function? Bootstrapped on x86_64-pc-linux-gnu with no regressions.   OK? Andrew From c3f9e9bc841b969e18a113bf2a60d9bdba7c4ebc Mon Sep 17 00:00:00 2001 From: Andrew MacLeod Date: Mon, 31 Aug 2026 14:25:21 -0400 Subject: [PATCH 2/2] Disallow path ranger from current_range_query. Provide a generic way to push/pop new range_queries, and disable path_ranger from being pushed.. PR tree-optimization/126942.c gcc/ * function.h (X_RANGE_QUERY_LIMIT): New. (x_range_query_stack): New. (x_range_query_index): New. * gimple-range-fold.cc (fold_using_range::fold_stmt): Use new push and pop interface. * gimple-range-path.h (path_ranger::active_query_compatible_p): New. * gimple-range.cc (enable_ranger): Use new interface. (disable_ranger): Likewise. * tree-vrp.cc (execute_fast_vrp): Likewise. * value-query.cc (push_range_query): New. (pop_range_query): New. * value-query.h (range_query::active_query_compatible_p): New. (push_range_query): Declare. (pop_range_query): Declare. gcc/testsuite/ * gcc.dg/pr126942.c: New. --- gcc/function.h | 7 ++++++ gcc/gimple-range-fold.cc | 17 ++++++++------ gcc/gimple-range-path.h | 2 ++ gcc/gimple-range.cc | 12 +++++----- gcc/testsuite/gcc.dg/pr126942.c | 35 +++++++++++++++++++++++++++++ gcc/tree-vrp.cc | 13 ++++++----- gcc/value-query.cc | 40 +++++++++++++++++++++++++++++++++ gcc/value-query.h | 7 ++++++ 8 files changed, 115 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr126942.c diff --git a/gcc/function.h b/gcc/function.h index 765c71309fa..1701eae67a9 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -318,6 +318,13 @@ struct GTY(()) function { should be queried by calling get_range_query(). */ range_query * GTY ((skip)) x_range_query; + /* push_range_query and pop_range_query can temporarily change the + current query. This stack allows for simple restoration. + This stack should never be very large.*/ +#define X_RANGE_QUERY_LIMIT 5 + range_query * GTY ((skip)) x_range_query_stack[X_RANGE_QUERY_LIMIT]; + unsigned x_range_query_index; + /* Last statement uid. */ int last_stmt_uid; diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index a64529603f8..ad4180023e9 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -694,9 +694,9 @@ fold_using_range::fold_stmt (vrange &r, gimple *s, fur_source &src, tree name) // If the specified query is different, make it the current one. // PR 125854 - The fold machinery may make a query call. // PR 126814 - tree_expr_nonnegative_p may make a call. - range_query *save = cfun->x_range_query; - if (src.query () != get_range_query (cfun)) - cfun->x_range_query = src.query (); + // PR 126942 - path_ranger queries should never be the current query. + // push_range_query will revert to a global query for this. + bool tmp_query_p = push_range_query (cfun, src.query ()); gimple_range_op_handler handler (s); if (gimple_code (s) == GIMPLE_ASSIGN @@ -731,7 +731,8 @@ fold_using_range::fold_stmt (vrange &r, gimple *s, fur_source &src, tree name) if (!res) { // Restore the original query. - cfun->x_range_query = save; + if (tmp_query_p) + pop_range_query (cfun); // If no name specified or range is unsupported, bail. if (!name || !gimple_range_ssa_p (name)) return false; @@ -743,7 +744,8 @@ fold_using_range::fold_stmt (vrange &r, gimple *s, fur_source &src, tree name) if (r.undefined_p ()) { // Restore the original query. - cfun->x_range_query = save; + if (tmp_query_p) + pop_range_query (cfun); return true; } @@ -771,7 +773,7 @@ fold_using_range::fold_stmt (vrange &r, gimple *s, fur_source &src, tree name) else { // If we couldn't find anything, try fold. - x_fold_context = { s, src.query () }; + x_fold_context = { s, get_range_query (cfun) }; rhs = gimple_fold_stmt_to_constant_1 (s, pta_valueize, pta_valueize); if (rhs && TREE_CODE (rhs) == ADDR_EXPR) @@ -780,7 +782,8 @@ fold_using_range::fold_stmt (vrange &r, gimple *s, fur_source &src, tree name) } } // Restore the original query. - cfun->x_range_query = save; + if (tmp_query_p) + pop_range_query (cfun); return true; } diff --git a/gcc/gimple-range-path.h b/gcc/gimple-range-path.h index 4c162ef11f6..b6a37638a33 100644 --- a/gcc/gimple-range-path.h +++ b/gcc/gimple-range-path.h @@ -42,6 +42,8 @@ public: bool range_of_expr (vrange &r, tree name, gimple * = NULL) override; bool range_of_stmt (vrange &r, gimple *, tree name = NULL) override; bool unreachable_path_p (); + // Path ranger should not be an active query. + virtual bool active_query_compatible_p () { return false; } void dump (FILE *) override; void debug (); diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index b221cfc5616..8fca11555e9 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -748,10 +748,11 @@ enable_ranger (struct function *fun, bool use_imm_uses) { gimple_ranger *r; - gcc_checking_assert (!fun->x_range_query); r = new gimple_ranger (use_imm_uses); - fun->x_range_query = r; + gcc_assert (push_range_query (fun, r)); + // Ranger should be the first and only instance. + gcc_checking_assert (fun->x_range_query_index == 1); return r; } @@ -761,9 +762,10 @@ enable_ranger (struct function *fun, bool use_imm_uses) void disable_ranger (struct function *fun) { - gcc_checking_assert (fun->x_range_query); - delete fun->x_range_query; - fun->x_range_query = NULL; + range_query *q = pop_range_query (fun); + // There should be no other range queries active. + gcc_checking_assert (fun->x_range_query_index == 0); + delete q; } // --------------------------------------------------------------------------- diff --git a/gcc/testsuite/gcc.dg/pr126942.c b/gcc/testsuite/gcc.dg/pr126942.c new file mode 100644 index 00000000000..c2100c6a895 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr126942.c @@ -0,0 +1,35 @@ +/* { dg-do run } */ +/* { dg-options "-O1" } */ + +signed char a; +int b, c; +short d[1]; + +short +foo (short *f, short g) +{ + int i = 0, j, l; + long n = 1; + for (int m = 0; m < a; m++) + for (; i <= m; i++) + n = i; + for (unsigned k = 0; k < g; k++) + { + l = 0; + do + if (f) + j = l + a; + while (++l <= k); + } + n ^= j; + while (a) + n ^= b; + return n; +} + +int +main () +{ + if (foo (d, 2) != 0) + __builtin_abort (); +} diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc index dc8256dc33d..8ef6ae7ee13 100644 --- a/gcc/tree-vrp.cc +++ b/gcc/tree-vrp.cc @@ -1241,20 +1241,21 @@ execute_fast_vrp (struct function *fun, bool final_p) { calculate_dominance_info (CDI_DOMINATORS); dom_ranger dr; + // Create a relation oracle without transitives. It will automatically + // be destroyed when the destructor for 'dr' runs. + dr.create_relation_oracle (false); fvrp_folder folder (&dr, final_p); - gcc_checking_assert (!fun->x_range_query); set_all_edges_as_executable (fun); - fun->x_range_query = &dr; - // Create a relation oracle without transitives. - get_range_query (fun)->create_relation_oracle (false); + // Make DR the current range_query. + gcc_assert (push_range_query (fun, &dr)); folder.substitute_and_fold (); if (folder.m_unreachable) folder.m_unreachable->remove (); - get_range_query (fun)->destroy_relation_oracle (); - fun->x_range_query = NULL; + range_query *q = pop_range_query (fun); + gcc_checking_assert (q == &dr); return 0; } diff --git a/gcc/value-query.cc b/gcc/value-query.cc index 831dba9a39a..5878c3e67dd 100644 --- a/gcc/value-query.cc +++ b/gcc/value-query.cc @@ -35,6 +35,46 @@ along with GCC; see the file COPYING3. If not see #include "value-range-storage.h" #include "target.h" +// Attempt to make Q the current range query for FUN. If it is already the +// current range query, return false. +// If the specified query is not compatible with being the current query, +// instead push the global query for safety. This is most common when +// the requested query is a path ranger, and it can be unstable to make +// arbitrary queries which may be in the middle or after a path. + +bool +push_range_query (struct function *fun, range_query *q) +{ + // Set the global query if it hasn't been set. + if (!fun->x_range_query) + fun->x_range_query = get_global_range_query (); + // Ensure we have't pushed too many, otherwise this is indicitive of + // a problem, + gcc_checking_assert (fun->x_range_query_index < X_RANGE_QUERY_LIMIT); + + // If this is not a compatible range query, revert to the global query. + if (!q->active_query_compatible_p ()) + q = get_global_range_query (); + + if (q == fun->x_range_query) + return false; + fun->x_range_query_stack[(fun->x_range_query_index)++] = fun->x_range_query; + fun->x_range_query = q; + return true; +} + +// Restore the previous range query, and return the current one. + +range_query * +pop_range_query (struct function *fun) +{ + range_query *q = fun->x_range_query; + gcc_checking_assert (fun->x_range_query_index > 0); + fun->x_range_query = fun->x_range_query_stack[--(fun->x_range_query_index)]; + gcc_checking_assert (fun->x_range_query); + return q; +} + // range_query default methods. bool diff --git a/gcc/value-query.h b/gcc/value-query.h index 9932d7d493b..7e1c7e7453d 100644 --- a/gcc/value-query.h +++ b/gcc/value-query.h @@ -95,6 +95,8 @@ public: void create_gori (int not_executable_flag = 0, int sw_max_edges = INT_MAX); void destroy_gori (); + // Return TRUE if this path query can be a current_range_query. + virtual bool active_query_compatible_p () { return true; } virtual void dump (FILE *); protected: @@ -139,6 +141,11 @@ get_range_query (const struct function *fun) return (fun && fun->x_range_query) ? fun->x_range_query : &global_ranges; } +// Provide a way to set and a new current range query and then restore the +// previous range query. Return FALSE if the current query didn't change. +bool push_range_query (struct function *fun, range_query *q); +range_query *pop_range_query (struct function *fun); + // Query the global range of NAME in function F. Default to cfun. extern void gimple_range_global (vrange &v, tree name, struct function *f = cfun); -- 2.55.0