| Message ID | orfr9n82r7.fsf_-_@lxoliva.fsfla.org |
|---|---|
| State | New |
| Headers |
Return-Path: <gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org> 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 369AE48F1777 for <patchwork@sourceware.org>; Sun, 7 Dec 2025 02:07:09 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 369AE48F1777 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, secure) header.d=adacore.com header.i=@adacore.com header.a=rsa-sha256 header.s=google header.b=XMb2KoOd X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pg1-f182.google.com (mail-pg1-f182.google.com [209.85.215.182]) by sourceware.org (Postfix) with ESMTPS id C742948F3402 for <gcc-patches@gcc.gnu.org>; Sun, 7 Dec 2025 02:06:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C742948F3402 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=adacore.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=adacore.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org C742948F3402 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=209.85.215.182 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1765073187; cv=none; b=bv5I9DGLmrqsnF3KVIsUZKAtv72ivzReAgNZF/+4q2aJqQyiNuKRkLEZ+ldB4j/kMlznKjxW6eU5fmzsPS6XlQf9uVJCbUNeH9Mss9moqQF02kXeogkIB3HH3JWebq3Vpw+azfen/MMdlNRvjB1YZd317ARgIiuzWQRiiFGT7Jc= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1765073187; c=relaxed/simple; bh=iVP8Fd/C/A3oHoG7J7j5LXbrRpeXcr4mEkeBptnw6kw=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=hGRBXUh2fae4Q1iY4By/EbWiTmzBVDQfHY+vN5oySgPnW6kQKYjZx6Uaiucqc9wF4d6Pb2zgvO2W0neVvm7gNAwvgxhnb9Hn5iHT0Kwh7aP9RnpWJY8dhVvRuQbje8VzSK0cdPwnNbHeh4vr7Y6Wf2NojBo/g3SidiSTYy3PMt4= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C742948F3402 Received: by mail-pg1-f182.google.com with SMTP id 41be03b00d2f7-bf5ac50827dso2284650a12.2 for <gcc-patches@gcc.gnu.org>; Sat, 06 Dec 2025 18:06:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=adacore.com; s=google; t=1765073185; x=1765677985; darn=gcc.gnu.org; h=mime-version:user-agent:message-id:in-reply-to:date:references :organization:subject:cc:to:from:from:to:cc:subject:date:message-id :reply-to; bh=Mch/8g0Eg6wc7B1SkU0BWyyjpVZjHysUoFrc9PLH7CE=; b=XMb2KoOdpaUivhVNvfuyyQPGUu2WyQP9vnXmy0D4Av0MqKQNwz+kE9vHIYOASdWNNu Xc3olD46iv59tcA0fOGQdkyIyF8HxCGAvnhBLMIMO643agQXGX70t5rvIRxkclwSwbZ1 PIEIU8VySKX4oJUWsUxgswYjmTI+Vih/sehNom/fC56f3OGlkqkEO6FxedcJX6mQtmPu bCmmkTQg86ZtUn2joaRWtbBXanl0EtkKuXvHcXZEfYK6jN9GvofWgEsLvt0YTXMynCrI 9MCD27Heek4mSSNurLdzGS3fEqxd2+0Cr3y7cec2daz9BkrGLYkWFaEjbkGEMAf4QajG t/EQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1765073185; x=1765677985; h=mime-version:user-agent:message-id:in-reply-to:date:references :organization:subject:cc:to:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=Mch/8g0Eg6wc7B1SkU0BWyyjpVZjHysUoFrc9PLH7CE=; b=JlgzlIFRK6WuYHN6HKC5FQoUaAlfrdRSLt80r/+KxwJ7NldnGZ/+kcDE8VUlYjL3Sn gk04uWwtfs2VQoyT2iI/0qbLTLao2to56M0izP5/SYg50Rt6dLLAr6UBLObY49sqfB9B GNgmY83BeSOt9blJaHFp/SGjXzmDcoLt18xASh1xHEj35ifwlwBY9m5pX+gGdEr5Fnss jaYnyoyQ6owlYd4h8vGEBZkmzdy10m+LJUEt/bpI9arwPoH6JXYy3CdQea5/KUamKu17 JYAJyfRWn+j90xGxGyNZ9Gx413S6Z1uHDhEo59lZ5nhNVxac3qZnnjl4vl9pmcr4JSKz iuow== X-Gm-Message-State: AOJu0YyXj+U9Maf9+RHv7ib6qh1wdARJjF66ujdurNobwaC97vszcdwL Yfxx0TzWEEr4XhOBkMi98YGWtZQdJnVU/VtZpFy8xWnCAZS0xObx+ZeO462dD0fiHfqMo71ipmn pGT0= X-Gm-Gg: ASbGncvt44DLrqriB63AHGphymBZdHME1NgeWvYiBf6toluwiRFIsYFGgJZ9oCYYy8L 2POW/Ng78cWrp/cBMjsK+0lZ6b3UIN0SZCWpTmPSpyqM4Q8RS60QcKSC44UBS3Btt6WqQSKBMnl 0ZOgOHJeCXmRVvzqTgLNV1RBr9MfIabch9mVYBBH7tRDm+7QnG2figpdAUzk0QUwWIgVdC0IBI5 LowTPM//su2aB7iQpxIHrpfm70LWXUPbuyPjY3SqQngcCHRiF1wDDwO0nDBXzZoayIX0oDDHw8f ohw8kgQ3bmaEPSR2FTRlcXBqh6gQ9K4ex/RMe5RpYzavv4YK6vhMtFJUQCO6pxyq0saAsloHfIf K3T48JrTuW6APIhI6WQqbl7GOiJ7rj7X0x+vrx4rueYdJ3ImeW5/0b5A4+L5omkM= X-Google-Smtp-Source: AGHT+IHkDhZgUYYmYYR4Qnklob3UECtcGFc7bgr7dTg5EUdIb8b0w9USMvYP1HpqEe5dscCF2pTGLg== X-Received: by 2002:a05:693c:2291:b0:2ab:c279:9dce with SMTP id 5a478bee46e88-2abc70e7c0bmr2266852eec.7.1765073185207; Sat, 06 Dec 2025 18:06:25 -0800 (PST) Received: from free.home ([2804:14c:4d1:41a6::1455]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2aba8816ae9sm26701411eec.5.2025.12.06.18.06.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 06 Dec 2025 18:06:24 -0800 (PST) Received: from livre (livre.home [172.31.160.2]) by free.home (8.15.2/8.15.2) with ESMTPS id 5B7264OW639297 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Sat, 6 Dec 2025 23:06:05 -0300 From: Alexandre Oliva <oliva@adacore.com> To: Eric Botcazou <botcazou@adacore.com> Cc: gcc-patches@gcc.gnu.org, Steven Bosscher <steven@gcc.gnu.org> Subject: [PATCH v2] cselib: lookup mem addr during invalidation Organization: Free thinker, does not speak for AdaCore References: <or4iqeep59.fsf@lxoliva.fsfla.org> <2196418.9o76ZdvQCi@fomalhaut> Date: Sat, 06 Dec 2025 23:06:04 -0300 In-Reply-To: <2196418.9o76ZdvQCi@fomalhaut> (Eric Botcazou's message of "Fri, 05 Dec 2025 10:40:50 +0100") Message-ID: <orfr9n82r7.fsf_-_@lxoliva.fsfla.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Scanned-By: MIMEDefang 2.84 X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_BLOCKED, WEIRD_QUOTING 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 <gcc-patches.gcc.gnu.org> List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe> List-Archive: <https://gcc.gnu.org/pipermail/gcc-patches/> List-Post: <mailto:gcc-patches@gcc.gnu.org> List-Help: <mailto:gcc-patches-request@gcc.gnu.org?subject=help> List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe> Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org |
| Series |
[v2] cselib: lookup mem addr during invalidation
|
|
Commit Message
Alexandre Oliva
Dec. 7, 2025, 2:06 a.m. UTC
On Dec 5, 2025, Eric Botcazou <botcazou@adacore.com> wrote: >> * cselib.cc (cselib_invalidate_mem): Lookup the address as >> part of canonicalizing it. > The cselib_invalidate_mem change looks a bit risky at this stage ... and here's that part split out for the next stage1. Ok then? When processing stores for e.g. parameters passed on the stack, as in gcc.dg/pr117239.c, each store invalidates other stores pertaining to the same argument, because we can tell they refer to the same object, but not that the offsets don't overlap. The reason for that is that the mem_rtx being invalidated is canonicalized to an SP offset, while those in the cselib table have canonical values as addresses, and alias.cc can't resolve SP to values to compare the offsets. With this change, pr117239.c doesn't require -fschedule-insns to fail, with the PR117239 fixes reverted. for gcc/ChangeLog * cselib.cc (cselib_invalidate_mem): Lookup the address as part of canonicalizing it. --- gcc/cselib.cc | 8 ++++++++ 1 file changed, 8 insertions(+)
Comments
> ... and here's that part split out for the next stage1. Ok then?
Sure.
On Dec 6, 2025, Alexandre Oliva <oliva@adacore.com> wrote: > When processing stores for e.g. parameters passed on the stack, as in > gcc.dg/pr117239.c, each store invalidates other stores pertaining to > the same argument, because we can tell they refer to the same object, > but not that the offsets don't overlap. The reason for that is that > the mem_rtx being invalidated is canonicalized to an SP offset, while > those in the cselib table have canonical values as addresses, and > alias.cc can't resolve SP to values to compare the offsets. I withdraw the patch: > * cselib.cc (cselib_invalidate_mem): Lookup the address as > part of canonicalizing it. because base terms aren't preserved in cselib, and even with WIP code to preserve them, when stack and frame pointer differ by a constant, they end up in the same cluster of VALUEs, but alias.cc wants them to have different base terms. I suppose one way to improve on this is for the frame pointer after reload to share the base term with the stack pointer. This would also prevent the sp restore from bp to cause sp's reg_value to be reset, and avoid the need for special-casing of the bp set up from sp. Would such a change be desirable/acceptable? Is there interest in code to preserve base terms in cselib tables?
On Dec 12, 2025, Alexandre Oliva <oliva@adacore.com> wrote: > because base terms aren't preserved in cselib, and even with WIP code to > preserve them, when stack and frame pointer differ by a constant, they > end up in the same cluster of VALUEs, but alias.cc wants them to have > different base terms. > I suppose one way to improve on this is for the frame pointer after > reload to share the base term with the stack pointer. This would also > prevent the sp restore from bp to cause sp's reg_value to be reset, and > avoid the need for special-casing of the bp set up from sp. Would such > a change be desirable/acceptable? > Is there interest in code to preserve base terms in cselib tables? I'm posting this WIP patch FTR as reference for https://gcc.gnu.org/pipermail/gcc-patches/2025-December/703846.html and to figure out whether there's interest in such an approach to retain ADDRESSes in cselib tables. This regstraps on x86_64-linux-gnu, but it would require some further polishing to replace local declarations of external functions with global ones, drop #if0 and whatnot. diff --git a/gcc/alias.cc b/gcc/alias.cc index a23396eaa35e0..f6f59c8e13119 100644 --- a/gcc/alias.cc +++ b/gcc/alias.cc @@ -1659,6 +1659,16 @@ get_reg_base_value (unsigned int regno) return (*reg_base_value)[regno]; } +rtx +get_reg_base_value_checked (unsigned int regno) +{ + if (!reg_base_value) + return NULL_RTX; + if (regno >= reg_base_value->length ()) + return NULL_RTX; + return get_reg_base_value (regno); +} + /* If a value is known for REGNO, return it. */ rtx @@ -1964,6 +1974,12 @@ find_base_term (rtx x, vec<std::pair<cselib_val *, return temp; } + case VALUE_ADDRESS: + x = XEXP (x, 0); + if (GET_CODE (x) != VALUE) + return x; + /* Fall through. */ + case VALUE: val = CSELIB_VAL_PTR (x); ret = NULL_RTX; @@ -2070,6 +2086,13 @@ find_base_term (rtx x) return res; } +rtx +find_value_base_term (rtx x) +{ + gcc_checking_assert (GET_CODE (x) == VALUE); + return find_base_term (x); +} + /* Return true if accesses to address X may alias accesses based on the stack pointer. */ @@ -2315,8 +2338,16 @@ get_addr (rtx x) for (l = v->locs; l; l = l->next) if (CONSTANT_P (l->loc)) return l->loc; +#if 0 + else if (GET_CODE (l->loc) == VALUE_ADDRESS) + return x; +#endif for (l = v->locs; l; l = l->next) if (!REG_P (l->loc) && !MEM_P (l->loc) + /* ENTRY_VALUEs are not useful addresses, we can't get aliasing + information from them. */ + && GET_CODE (l->loc) != ENTRY_VALUE + && GET_CODE (l->loc) != VALUE_ADDRESS /* Avoid infinite recursion when potentially dealing with var-tracking artificial equivalences, by skipping the equivalences themselves, and not choosing expressions @@ -2330,6 +2361,8 @@ get_addr (rtx x) for (l = v->locs; l; l = l->next) if (REG_P (l->loc) || (GET_CODE (l->loc) != VALUE + && GET_CODE (l->loc) != ENTRY_VALUE + && GET_CODE (l->loc) != VALUE_ADDRESS && !refs_newer_value_p (l->loc, x))) return l->loc; /* Return the canonical value. */ @@ -3080,6 +3113,38 @@ canon_true_dependence (const_rtx mem, machine_mode mem_mode, rtx mem_addr, x, x_addr, /*mem_canonicalized=*/true); } +/* Return true iff x and m are addresses with the same base term, and that are + equivalent memrefs. Both are presumed canonicalized. */ +bool +same_base_term_known_overlap_p (rtx x, rtx m, poly_int64 size) +{ + rtx tx = get_addr (x); + rtx tm = get_addr (m); + + rtx bx = find_base_term (tx); + rtx bm = find_base_term (tm); + + if (bx != bm && bx && bm + && !(GET_CODE (bx) == ADDRESS + && GET_CODE (bm) == ADDRESS + && bx->u.fld[0].rt_int <= 0 + && bm->u.fld[0].rt_int <= 0) + /* libgo runtime may different decls for the same symbol used within the + same function, because they come from different units compiled + together. */ + && !(GET_CODE (bx) == SYMBOL_REF + && GET_CODE (bm) == SYMBOL_REF + && XSTR (bx, 0) == XSTR (bm, 0))) + return false; + +#if 0 + x = canon_rtx (tx); + m = canon_rtx (tm); +#endif + + return memrefs_conflict_p (size, x, size, m, 0) != 0; +} + /* Returns true if a write to X might alias a previous read from (or, if WRITEP is true, a write to) MEM. If X_CANONCALIZED is true, then X_ADDR is the canonicalized address of X, @@ -3290,16 +3355,25 @@ init_alias_target (void) && targetm.hard_regno_mode_ok (i, Pmode)) static_reg_base_value[i] = arg_base_value; - /* RTL code is required to be consistent about whether it uses the - stack pointer, the frame pointer or the argument pointer to - access a given area of the frame. We can therefore use the - base address to distinguish between the different areas. */ + /* RTL code is required to be consistent about whether it uses the stack + pointer, the frame pointer or the argument pointer to access a given area + of the frame. We can therefore use the base address to distinguish + between the different areas. However, after register allocation and + especially prologue generation, cselib makes all these areas part of the + same cluster of VALUEs, making it hard to distinguish the areas, so make + them all share the same base term then. */ static_reg_base_value[STACK_POINTER_REGNUM] - = unique_base_value (UNIQUE_BASE_VALUE_SP); + = (reload_completed + ? arg_base_value + : unique_base_value (UNIQUE_BASE_VALUE_SP)); static_reg_base_value[ARG_POINTER_REGNUM] - = unique_base_value (UNIQUE_BASE_VALUE_ARGP); + = (reload_completed + ? arg_base_value + : unique_base_value (UNIQUE_BASE_VALUE_ARGP)); static_reg_base_value[FRAME_POINTER_REGNUM] - = unique_base_value (UNIQUE_BASE_VALUE_FP); + = (reload_completed + ? arg_base_value + : unique_base_value (UNIQUE_BASE_VALUE_FP)); /* The above rules extend post-reload, with eliminations applying consistently to each of the three pointers. Cope with cases in @@ -3307,7 +3381,9 @@ init_alias_target (void) rather than the stack pointer. */ if (!HARD_FRAME_POINTER_IS_FRAME_POINTER) static_reg_base_value[HARD_FRAME_POINTER_REGNUM] - = unique_base_value (UNIQUE_BASE_VALUE_HFP); + = (reload_completed + ? arg_base_value + : unique_base_value (UNIQUE_BASE_VALUE_HFP)); } /* Set MEMORY_MODIFIED when X modifies DATA (that is assumed diff --git a/gcc/cselib.cc b/gcc/cselib.cc index c6628abf2a989..a6cae62bb2fee 100644 --- a/gcc/cselib.cc +++ b/gcc/cselib.cc @@ -2505,6 +2505,8 @@ cselib_lookup (rtx x, machine_mode mode, static void cselib_invalidate_regno_val (unsigned int regno, struct elt_list **l) { + extern rtx get_reg_base_value_checked (unsigned); + rtx value_address = get_reg_base_value_checked (regno); cselib_val *v = (*l)->elt; if (*l == REG_VALUES (regno)) { @@ -2517,7 +2519,12 @@ cselib_invalidate_regno_val (unsigned int regno, struct elt_list **l) l = &(*l)->next; } else - unchain_one_elt_list (l); + { + if (value_address + && GET_MODE (value_address) != GET_MODE (v->val_rtx)) + value_address = NULL_RTX; + unchain_one_elt_list (l); + } v = canonical_cselib_val (v); @@ -2533,6 +2540,56 @@ cselib_invalidate_regno_val (unsigned int regno, struct elt_list **l) if (REG_P (x) && REGNO (x) == regno) { unchain_one_elt_loc_list (p); + + extern rtx find_value_base_term (rtx); + /* Preserve the VALUE_ADDRESS associated with the regno previously + held in v, if we can't identify it any longer. */ + rtx found_value_address = find_value_base_term (v->val_rtx); + cselib_val *add_address_to = NULL; + if (value_address && found_value_address != value_address) + add_address_to = v; + + rtx wanted_value_address + = value_address ? value_address : found_value_address; + + if (wanted_value_address) + { + cselib_val *addrv = v; + for (;;) + { + rtx addr = canon_rtx (get_addr (addrv->val_rtx)); + if (addr == addrv->val_rtx + || GET_CODE (addr) != PLUS + || GET_CODE (XEXP (addr, 0)) != VALUE + || !CONSTANT_P (XEXP (addr, 1))) + break; + + rtx addr_value_address + = find_value_base_term (XEXP (addr, 0)); + if (addr_value_address) + break; + else + { + gcc_checking_assert (addr_value_address + != wanted_value_address); + addrv = add_address_to + = canonical_cselib_val (CSELIB_VAL_PTR (XEXP (addr, 0))); + } + } + } + + if (add_address_to) + { + if (add_address_to != v) + p = &add_address_to->locs; + + elt_loc_list *n = *p; + *p = elt_loc_list_pool.allocate (); + (*p)->loc = gen_rtx_VALUE_ADDRESS (GET_MODE (v->val_rtx), + wanted_value_address); + (*p)->setting_insn = setting_insn; + (*p)->next = n; + } break; } } @@ -2628,6 +2685,10 @@ cselib_invalidate_mem (rtx mem_rtx) if ((v = cselib_lookup (mem_addr, GET_MODE (mem_addr), 0, GET_MODE (mem_rtx)))) { + extern bool same_base_term_known_overlap_p (rtx, rtx, poly_int64); + gcc_checking_assert (same_base_term_known_overlap_p + (mem_addr, v->val_rtx, + GET_MODE_SIZE (GET_MODE (mem_rtx)))); mem_addr = v->val_rtx; mem_rtx = replace_equiv_address_nv (mem_rtx, mem_addr); } diff --git a/gcc/rtl.def b/gcc/rtl.def index 15ae7d10fcc10..b1f68fb00d25a 100644 --- a/gcc/rtl.def +++ b/gcc/rtl.def @@ -128,6 +128,9 @@ DEF_RTL_EXPR(SEQUENCE, "sequence", "E", RTX_EXTRA) /* Represents a non-global base address. This is only used in alias.cc. */ DEF_RTL_EXPR(ADDRESS, "address", "i", RTX_EXTRA) +/* Represents a base address within a cselib table. */ +DEF_RTL_EXPR(VALUE_ADDRESS, "value_address", "e", RTX_OBJ) + /* ---------------------------------------------------------------------- Expression types used for things in the instruction chain. diff --git a/gcc/var-tracking.cc b/gcc/var-tracking.cc index 8732c3ba62aa5..21cde6b0a7b6c 100644 --- a/gcc/var-tracking.cc +++ b/gcc/var-tracking.cc @@ -2442,6 +2442,7 @@ unsuitable_loc (rtx loc) case SCRATCH: case ASM_INPUT: case ASM_OPERANDS: + case VALUE_ADDRESS: return true; default:
On Wed, Dec 17, 2025 at 3:06 AM Alexandre Oliva <oliva@adacore.com> wrote: > > On Dec 12, 2025, Alexandre Oliva <oliva@adacore.com> wrote: > > > because base terms aren't preserved in cselib, and even with WIP code to > > preserve them, when stack and frame pointer differ by a constant, they > > end up in the same cluster of VALUEs, but alias.cc wants them to have > > different base terms. > > > I suppose one way to improve on this is for the frame pointer after > > reload to share the base term with the stack pointer. This would also > > prevent the sp restore from bp to cause sp's reg_value to be reset, and > > avoid the need for special-casing of the bp set up from sp. Would such > > a change be desirable/acceptable? > > > Is there interest in code to preserve base terms in cselib tables? IMO "base terms" (aka RTLs "points-to analysis") needs to be re-architected. > I'm posting this WIP patch FTR as reference for > https://gcc.gnu.org/pipermail/gcc-patches/2025-December/703846.html and > to figure out whether there's interest in such an approach to retain > ADDRESSes in cselib tables. This regstraps on x86_64-linux-gnu, but it > would require some further polishing to replace local declarations of > external functions with global ones, drop #if0 and whatnot. > > diff --git a/gcc/alias.cc b/gcc/alias.cc > index a23396eaa35e0..f6f59c8e13119 100644 > --- a/gcc/alias.cc > +++ b/gcc/alias.cc > @@ -1659,6 +1659,16 @@ get_reg_base_value (unsigned int regno) > return (*reg_base_value)[regno]; > } > > +rtx > +get_reg_base_value_checked (unsigned int regno) > +{ > + if (!reg_base_value) > + return NULL_RTX; > + if (regno >= reg_base_value->length ()) > + return NULL_RTX; > + return get_reg_base_value (regno); > +} > + > /* If a value is known for REGNO, return it. */ > > rtx > @@ -1964,6 +1974,12 @@ find_base_term (rtx x, vec<std::pair<cselib_val *, > return temp; > } > > + case VALUE_ADDRESS: > + x = XEXP (x, 0); > + if (GET_CODE (x) != VALUE) > + return x; > + /* Fall through. */ > + > case VALUE: > val = CSELIB_VAL_PTR (x); > ret = NULL_RTX; > @@ -2070,6 +2086,13 @@ find_base_term (rtx x) > return res; > } > > +rtx > +find_value_base_term (rtx x) > +{ > + gcc_checking_assert (GET_CODE (x) == VALUE); > + return find_base_term (x); > +} > + > /* Return true if accesses to address X may alias accesses based > on the stack pointer. */ > > @@ -2315,8 +2338,16 @@ get_addr (rtx x) > for (l = v->locs; l; l = l->next) > if (CONSTANT_P (l->loc)) > return l->loc; > +#if 0 > + else if (GET_CODE (l->loc) == VALUE_ADDRESS) > + return x; > +#endif > for (l = v->locs; l; l = l->next) > if (!REG_P (l->loc) && !MEM_P (l->loc) > + /* ENTRY_VALUEs are not useful addresses, we can't get aliasing > + information from them. */ > + && GET_CODE (l->loc) != ENTRY_VALUE > + && GET_CODE (l->loc) != VALUE_ADDRESS > /* Avoid infinite recursion when potentially dealing with > var-tracking artificial equivalences, by skipping the > equivalences themselves, and not choosing expressions > @@ -2330,6 +2361,8 @@ get_addr (rtx x) > for (l = v->locs; l; l = l->next) > if (REG_P (l->loc) > || (GET_CODE (l->loc) != VALUE > + && GET_CODE (l->loc) != ENTRY_VALUE > + && GET_CODE (l->loc) != VALUE_ADDRESS > && !refs_newer_value_p (l->loc, x))) > return l->loc; > /* Return the canonical value. */ > @@ -3080,6 +3113,38 @@ canon_true_dependence (const_rtx mem, machine_mode mem_mode, rtx mem_addr, > x, x_addr, /*mem_canonicalized=*/true); > } > > +/* Return true iff x and m are addresses with the same base term, and that are > + equivalent memrefs. Both are presumed canonicalized. */ > +bool > +same_base_term_known_overlap_p (rtx x, rtx m, poly_int64 size) > +{ > + rtx tx = get_addr (x); > + rtx tm = get_addr (m); > + > + rtx bx = find_base_term (tx); > + rtx bm = find_base_term (tm); > + > + if (bx != bm && bx && bm > + && !(GET_CODE (bx) == ADDRESS > + && GET_CODE (bm) == ADDRESS > + && bx->u.fld[0].rt_int <= 0 > + && bm->u.fld[0].rt_int <= 0) > + /* libgo runtime may different decls for the same symbol used within the > + same function, because they come from different units compiled > + together. */ > + && !(GET_CODE (bx) == SYMBOL_REF > + && GET_CODE (bm) == SYMBOL_REF > + && XSTR (bx, 0) == XSTR (bm, 0))) > + return false; > + > +#if 0 > + x = canon_rtx (tx); > + m = canon_rtx (tm); > +#endif > + > + return memrefs_conflict_p (size, x, size, m, 0) != 0; > +} > + > /* Returns true if a write to X might alias a previous read from > (or, if WRITEP is true, a write to) MEM. > If X_CANONCALIZED is true, then X_ADDR is the canonicalized address of X, > @@ -3290,16 +3355,25 @@ init_alias_target (void) > && targetm.hard_regno_mode_ok (i, Pmode)) > static_reg_base_value[i] = arg_base_value; > > - /* RTL code is required to be consistent about whether it uses the > - stack pointer, the frame pointer or the argument pointer to > - access a given area of the frame. We can therefore use the > - base address to distinguish between the different areas. */ > + /* RTL code is required to be consistent about whether it uses the stack > + pointer, the frame pointer or the argument pointer to access a given area > + of the frame. We can therefore use the base address to distinguish > + between the different areas. However, after register allocation and > + especially prologue generation, cselib makes all these areas part of the > + same cluster of VALUEs, making it hard to distinguish the areas, so make > + them all share the same base term then. */ > static_reg_base_value[STACK_POINTER_REGNUM] > - = unique_base_value (UNIQUE_BASE_VALUE_SP); > + = (reload_completed > + ? arg_base_value > + : unique_base_value (UNIQUE_BASE_VALUE_SP)); > static_reg_base_value[ARG_POINTER_REGNUM] > - = unique_base_value (UNIQUE_BASE_VALUE_ARGP); > + = (reload_completed > + ? arg_base_value > + : unique_base_value (UNIQUE_BASE_VALUE_ARGP)); > static_reg_base_value[FRAME_POINTER_REGNUM] > - = unique_base_value (UNIQUE_BASE_VALUE_FP); > + = (reload_completed > + ? arg_base_value > + : unique_base_value (UNIQUE_BASE_VALUE_FP)); > > /* The above rules extend post-reload, with eliminations applying > consistently to each of the three pointers. Cope with cases in > @@ -3307,7 +3381,9 @@ init_alias_target (void) > rather than the stack pointer. */ > if (!HARD_FRAME_POINTER_IS_FRAME_POINTER) > static_reg_base_value[HARD_FRAME_POINTER_REGNUM] > - = unique_base_value (UNIQUE_BASE_VALUE_HFP); > + = (reload_completed > + ? arg_base_value > + : unique_base_value (UNIQUE_BASE_VALUE_HFP)); > } > > /* Set MEMORY_MODIFIED when X modifies DATA (that is assumed > diff --git a/gcc/cselib.cc b/gcc/cselib.cc > index c6628abf2a989..a6cae62bb2fee 100644 > --- a/gcc/cselib.cc > +++ b/gcc/cselib.cc > @@ -2505,6 +2505,8 @@ cselib_lookup (rtx x, machine_mode mode, > static void > cselib_invalidate_regno_val (unsigned int regno, struct elt_list **l) > { > + extern rtx get_reg_base_value_checked (unsigned); > + rtx value_address = get_reg_base_value_checked (regno); > cselib_val *v = (*l)->elt; > if (*l == REG_VALUES (regno)) > { > @@ -2517,7 +2519,12 @@ cselib_invalidate_regno_val (unsigned int regno, struct elt_list **l) > l = &(*l)->next; > } > else > - unchain_one_elt_list (l); > + { > + if (value_address > + && GET_MODE (value_address) != GET_MODE (v->val_rtx)) > + value_address = NULL_RTX; > + unchain_one_elt_list (l); > + } > > v = canonical_cselib_val (v); > > @@ -2533,6 +2540,56 @@ cselib_invalidate_regno_val (unsigned int regno, struct elt_list **l) > if (REG_P (x) && REGNO (x) == regno) > { > unchain_one_elt_loc_list (p); > + > + extern rtx find_value_base_term (rtx); > + /* Preserve the VALUE_ADDRESS associated with the regno previously > + held in v, if we can't identify it any longer. */ > + rtx found_value_address = find_value_base_term (v->val_rtx); > + cselib_val *add_address_to = NULL; > + if (value_address && found_value_address != value_address) > + add_address_to = v; > + > + rtx wanted_value_address > + = value_address ? value_address : found_value_address; > + > + if (wanted_value_address) > + { > + cselib_val *addrv = v; > + for (;;) > + { > + rtx addr = canon_rtx (get_addr (addrv->val_rtx)); > + if (addr == addrv->val_rtx > + || GET_CODE (addr) != PLUS > + || GET_CODE (XEXP (addr, 0)) != VALUE > + || !CONSTANT_P (XEXP (addr, 1))) > + break; > + > + rtx addr_value_address > + = find_value_base_term (XEXP (addr, 0)); > + if (addr_value_address) > + break; > + else > + { > + gcc_checking_assert (addr_value_address > + != wanted_value_address); > + addrv = add_address_to > + = canonical_cselib_val (CSELIB_VAL_PTR (XEXP (addr, 0))); > + } > + } > + } > + > + if (add_address_to) > + { > + if (add_address_to != v) > + p = &add_address_to->locs; > + > + elt_loc_list *n = *p; > + *p = elt_loc_list_pool.allocate (); > + (*p)->loc = gen_rtx_VALUE_ADDRESS (GET_MODE (v->val_rtx), > + wanted_value_address); > + (*p)->setting_insn = setting_insn; > + (*p)->next = n; > + } > break; > } > } > @@ -2628,6 +2685,10 @@ cselib_invalidate_mem (rtx mem_rtx) > if ((v = cselib_lookup (mem_addr, GET_MODE (mem_addr), > 0, GET_MODE (mem_rtx)))) > { > + extern bool same_base_term_known_overlap_p (rtx, rtx, poly_int64); > + gcc_checking_assert (same_base_term_known_overlap_p > + (mem_addr, v->val_rtx, > + GET_MODE_SIZE (GET_MODE (mem_rtx)))); > mem_addr = v->val_rtx; > mem_rtx = replace_equiv_address_nv (mem_rtx, mem_addr); > } > diff --git a/gcc/rtl.def b/gcc/rtl.def > index 15ae7d10fcc10..b1f68fb00d25a 100644 > --- a/gcc/rtl.def > +++ b/gcc/rtl.def > @@ -128,6 +128,9 @@ DEF_RTL_EXPR(SEQUENCE, "sequence", "E", RTX_EXTRA) > /* Represents a non-global base address. This is only used in alias.cc. */ > DEF_RTL_EXPR(ADDRESS, "address", "i", RTX_EXTRA) > > +/* Represents a base address within a cselib table. */ > +DEF_RTL_EXPR(VALUE_ADDRESS, "value_address", "e", RTX_OBJ) > + > /* ---------------------------------------------------------------------- > Expression types used for things in the instruction chain. > > diff --git a/gcc/var-tracking.cc b/gcc/var-tracking.cc > index 8732c3ba62aa5..21cde6b0a7b6c 100644 > --- a/gcc/var-tracking.cc > +++ b/gcc/var-tracking.cc > @@ -2442,6 +2442,7 @@ unsuitable_loc (rtx loc) > case SCRATCH: > case ASM_INPUT: > case ASM_OPERANDS: > + case VALUE_ADDRESS: > return true; > > default: > > > -- > Alexandre Oliva, happy hacker https://blog.lx.oliva.nom.br/ > Free Software Activist FSFLA co-founder GNU Toolchain Engineer > More tolerance and less prejudice are key for inclusion and diversity. > Excluding neuro-others for not behaving ""normal"" is *not* inclusive!
diff --git a/gcc/cselib.cc b/gcc/cselib.cc index 930357409bc54..c6628abf2a989 100644 --- a/gcc/cselib.cc +++ b/gcc/cselib.cc @@ -2623,6 +2623,14 @@ cselib_invalidate_mem (rtx mem_rtx) rtx mem_addr; mem_addr = canon_rtx (get_addr (XEXP (mem_rtx, 0))); + /* Resolve MEM_ADDR to a VALUE_RTX, so that canon_anti_dependence can compare + offsets from the same base, even for SP-based addresses. */ + if ((v = cselib_lookup (mem_addr, GET_MODE (mem_addr), + 0, GET_MODE (mem_rtx)))) + { + mem_addr = v->val_rtx; + mem_rtx = replace_equiv_address_nv (mem_rtx, mem_addr); + } mem_rtx = canon_rtx (mem_rtx); vp = &first_containing_mem;