Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2226271/?format=api
{ "id": 2226271, "url": "http://patchwork.ozlabs.org/api/patches/2226271/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhubeob5uw.gcc.gcc-TEST.pinskia.21.1.3@forge-stage.sourceware.org/", "project": { "id": 17, "url": "http://patchwork.ozlabs.org/api/projects/17/?format=api", "name": "GNU Compiler Collection", "link_name": "gcc", "list_id": "gcc-patches.gcc.gnu.org", "list_email": "gcc-patches@gcc.gnu.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<bmm.hhubeob5uw.gcc.gcc-TEST.pinskia.21.1.3@forge-stage.sourceware.org>", "list_archive_url": null, "date": "2026-04-22T10:31:26", "name": "[v1,3/4] cfgexpand: Rewrite add_scope_conflicts_2 to use cache and look back further [PR111422]", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "de55e0bafa374e410bb6a2a005c66a6e6362e2a8", "submitter": { "id": 93219, "url": "http://patchwork.ozlabs.org/api/people/93219/?format=api", "name": "Andrew Pinski via Sourceware Forge", "email": "forge-bot+pinskia@forge-stage.sourceware.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhubeob5uw.gcc.gcc-TEST.pinskia.21.1.3@forge-stage.sourceware.org/mbox/", "series": [ { "id": 500980, "url": "http://patchwork.ozlabs.org/api/series/500980/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=500980", "date": "2026-04-22T10:31:24", "name": "scoped_conflicts", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/500980/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2226271/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2226271/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)", "sourceware.org; dmarc=none (p=none dis=none)\n header.from=forge-stage.sourceware.org", "sourceware.org;\n spf=pass smtp.mailfrom=forge-stage.sourceware.org", "server2.sourceware.org;\n arc=none smtp.remote-ip=38.145.34.39" ], "Received": [ "from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g0x4g3BhNz1yHB\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 20:57:07 +1000 (AEST)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id D06434BC8979\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 10:57:01 +0000 (GMT)", "from forge-stage.sourceware.org (vm08.sourceware.org [38.145.34.39])\n by sourceware.org (Postfix) with ESMTPS id CF44E4BBC092\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 10:32:22 +0000 (GMT)", "from forge-stage.sourceware.org (localhost [IPv6:::1])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256)\n (No client certificate requested)\n by forge-stage.sourceware.org (Postfix) with ESMTPS id A990442B26\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 10:32:22 +0000 (UTC)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org D06434BC8979", "OpenDKIM Filter v2.11.0 sourceware.org CF44E4BBC092" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org CF44E4BBC092", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org CF44E4BBC092", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776853942; cv=none;\n b=hgObbN+0RuQ2UgzYMPnPk0AlsIGt7fZy3Fyf03gJ4vYe1fMssRM7RJMwkylS7uS1QPae7BRHq2OJTEiKHH6VYjYHSdXPkdFwRloQLF/2YaiAKHKMn3kHRWp3QYub1tirD+rcmWChwLWxY7w6lsI+LvOk5GxoXXnmlLN1or1aKCk=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776853942; c=relaxed/simple;\n bh=XUutRcHN2eRKejS7Xn04tY5SzfiuE2i5gRYjvT1SXtA=;\n h=From:Date:Subject:To:Message-ID;\n b=gDXYCzrE9W/iuoB2FHYFmwVE1D627WtfeoG2/mF9boEH6yZDnhV5JOPOSp9ybsAWnLI20x+Pej7BdkInjLqecb4XtF0TkeAzGRxHJIQSh7Ou5q/BDR4rVDeiof5GZ9XNWjBmEAJmhIaGarJT96US/AwquMfrC0s08bqjNvzYFqw=", "ARC-Authentication-Results": "i=1; server2.sourceware.org", "From": "Andrew Pinski via Sourceware Forge\n <forge-bot+pinskia@forge-stage.sourceware.org>", "Date": "Wed, 22 Apr 2026 10:31:26 +0000", "Subject": "[PATCH v1 3/4] cfgexpand: Rewrite add_scope_conflicts_2 to use cache\n and look back further [PR111422]", "To": "gcc-patches mailing list <gcc-patches@gcc.gnu.org>", "Message-ID": "\n <bmm.hhubeob5uw.gcc.gcc-TEST.pinskia.21.1.3@forge-stage.sourceware.org>", "X-Mailer": "batrachomyomachia", "X-Pull-Request-Organization": "gcc", "X-Pull-Request-Repository": "gcc-TEST", "X-Pull-Request": "https://forge.sourceware.org/gcc/gcc-TEST/pulls/21", "References": "\n <bmm.hhubeob5uw.gcc.gcc-TEST.pinskia.21.1.0@forge-stage.sourceware.org>", "In-Reply-To": "\n <bmm.hhubeob5uw.gcc.gcc-TEST.pinskia.21.1.0@forge-stage.sourceware.org>", "X-Patch-URL": "\n https://forge.sourceware.org/pinskia/gcc-TEST/commit/312604406c1c1ef460e2e51d4d7d4ae5cec0c97e", "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>,\n <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>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>", "Reply-To": "gcc-patches mailing list <gcc-patches@gcc.gnu.org>,\n pinskia@gcc.gnu.org", "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org" }, "content": "From: Andrew Pinski <quic_apinski@quicinc.com>\n\nAfter fixing loop-im to do the correct overflow rewriting\nfor pointer types too. We end up with code like:\n```\n_9 = (unsigned long) &g;\n_84 = _9 + 18446744073709551615;\n_11 = _42 + _84;\n_44 = (signed char *) _11;\n...\n*_44 = 10;\ng ={v} {CLOBBER(eos)};\n...\nn[0] = &f;\n*_44 = 8;\ng ={v} {CLOBBER(eos)};\n```\n\nWhich was not being recongized by the scope conflicts code.\nThis was because it only handled one level walk backs rather than multiple ones.\nThis fixes the issue by having a cache which records all references to addresses\nof stack variables.\n\nUnlike the previous patch, this only records and looks at addresses of stack variables.\nThe cache uses a bitmap and uses the index as the bit to look at.\n\n\tPR middle-end/117426\n\tPR middle-end/111422\ngcc/ChangeLog:\n\n\t* cfgexpand.cc (struct vars_ssa_cache): New class.\n\t(vars_ssa_cache::vars_ssa_cache): New constructor.\n\t(vars_ssa_cache::~vars_ssa_cache): New deconstructor.\n\t(vars_ssa_cache::create): New method.\n\t(vars_ssa_cache::exists): New method.\n\t(vars_ssa_cache::add_one): New method.\n\t(vars_ssa_cache::update): New method.\n\t(vars_ssa_cache::dump): New method.\n\t(add_scope_conflicts_2): Factor mostly out to\n\tvars_ssa_cache::operator(). New cache argument.\n\tWalk the bitmap cache for the stack variables addresses.\n\t(vars_ssa_cache::operator()): New method factored out from\n\tadd_scope_conflicts_2. Rewrite to be a full walk of all operands\n\tand use a worklist.\n\t(add_scope_conflicts_1): Add cache new argument for the addr cache.\n\tJust call add_scope_conflicts_2 for the phi result instead of calling\n\tfor the uses and don't call walk_stmt_load_store_addr_ops for phis.\n\tUpdate call to add_scope_conflicts_2 to add cache argument.\n\t(add_scope_conflicts): Add cache argument and update calls to\n\tadd_scope_conflicts_1.\n\ngcc/testsuite/ChangeLog:\n\n\t* gcc.dg/torture/pr117426-1.c: New test.\n\nSigned-off-by: Andrew Pinski <quic_apinski@quicinc.com>\n---\n gcc/cfgexpand.cc | 292 +++++++++++++++++++---\n gcc/testsuite/gcc.dg/torture/pr117426-1.c | 53 ++++\n 2 files changed, 308 insertions(+), 37 deletions(-)\n create mode 100644 gcc/testsuite/gcc.dg/torture/pr117426-1.c", "diff": "diff --git a/gcc/cfgexpand.cc b/gcc/cfgexpand.cc\nindex b88e8827667b..841d3c1254e9 100644\n--- a/gcc/cfgexpand.cc\n+++ b/gcc/cfgexpand.cc\n@@ -585,35 +585,243 @@ visit_conflict (gimple *, tree op, tree, void *data)\n return false;\n }\n \n-/* Helper function for add_scope_conflicts_1. For USE on\n- a stmt, if it is a SSA_NAME and in its SSA_NAME_DEF_STMT is known to be\n- based on some ADDR_EXPR, invoke VISIT on that ADDR_EXPR. */\n+/* A cache for ssa name to address of stack variables.\n+ When taking into account if a ssa name refers to an\n+ address of a stack variable, we need to walk the\n+ expressions backwards to find the addresses. This\n+ cache is there so we don't need to walk the expressions\n+ all the time. */\n+struct vars_ssa_cache\n+{\n+private:\n+ /* Currently an entry is a bitmap of all of the known stack variables\n+ addresses that are referenced by the ssa name.\n+ When the bitmap is the nullptr, then there is no cache.\n+ Currently only empty bitmaps are shared.\n+ The reason for why empty cache is not just a null is so we know the\n+ cache for an entry is filled in. */\n+ struct entry\n+ {\n+ bitmap bmap = nullptr;\n+ };\n+ entry *vars_ssa_caches;\n+public:\n \n-static inline void\n-add_scope_conflicts_2 (tree use, bitmap work,\n-\t\t walk_stmt_load_store_addr_fn visit)\n+ vars_ssa_cache();\n+ ~vars_ssa_cache();\n+ const_bitmap operator() (tree name);\n+ void dump (FILE *file);\n+\n+private:\n+ /* Can't copy. */\n+ vars_ssa_cache(const vars_ssa_cache&) = delete;\n+ vars_ssa_cache(vars_ssa_cache&&) = delete;\n+\n+ /* The shared empty bitmap. */\n+ bitmap empty;\n+\n+ /* Unshare the index, currently only need\n+ to unshare if the entry was empty. */\n+ void unshare(int indx)\n+ {\n+ if (vars_ssa_caches[indx].bmap == empty)\n+\tvars_ssa_caches[indx].bmap = BITMAP_ALLOC (&stack_var_bitmap_obstack);\n+ }\n+ void create (tree);\n+ bool exists (tree use);\n+ void add_one (tree old_name, unsigned);\n+ bool update (tree old_name, tree use);\n+};\n+\n+/* Constructor of the cache, create the cache array. */\n+vars_ssa_cache::vars_ssa_cache ()\n+{\n+ vars_ssa_caches = new entry[num_ssa_names]{};\n+\n+ /* Create the shared empty bitmap too. */\n+ empty = BITMAP_ALLOC (&stack_var_bitmap_obstack);\n+}\n+\n+/* Delete the array. The bitmaps will be freed\n+ when stack_var_bitmap_obstack is freed. */\n+vars_ssa_cache::~vars_ssa_cache ()\n+{\n+ delete []vars_ssa_caches;\n+}\n+\n+/* Create an empty entry for the USE ssa name. */\n+void\n+vars_ssa_cache::create (tree use)\n {\n- if (TREE_CODE (use) == SSA_NAME\n- && (POINTER_TYPE_P (TREE_TYPE (use))\n-\t || INTEGRAL_TYPE_P (TREE_TYPE (use))))\n+ int num = SSA_NAME_VERSION (use);\n+ if (vars_ssa_caches[num].bmap)\n+ return;\n+ vars_ssa_caches[num].bmap = empty;\n+}\n+\n+/* Returns true if the cache for USE exists. */\n+bool\n+vars_ssa_cache::exists (tree use)\n+{\n+ int num = SSA_NAME_VERSION (use);\n+ return vars_ssa_caches[num].bmap != nullptr;\n+}\n+\n+/* Add to USE's bitmap for stack variable IDX. */\n+void\n+vars_ssa_cache::add_one (tree use, unsigned idx)\n+{\n+ gcc_assert (idx != INVALID_STACK_INDEX);\n+ int num = SSA_NAME_VERSION (use);\n+ gcc_assert (vars_ssa_caches[num].bmap);\n+ unshare (num);\n+ bitmap_set_bit (vars_ssa_caches[num].bmap, idx);\n+}\n+\n+/* Update cache of OLD_NAME from the USE's cache. */\n+bool\n+vars_ssa_cache::update (tree old_name, tree use)\n+{\n+ if (old_name == use)\n+ return false;\n+ int num = SSA_NAME_VERSION (use);\n+ int old_num = SSA_NAME_VERSION (old_name);\n+\n+ /* If the old name was empty, then there is nothing to be updated. */\n+ if (vars_ssa_caches[num].bmap == empty)\n+ return false;\n+ unshare (old_num);\n+ return bitmap_ior_into (vars_ssa_caches[old_num].bmap, vars_ssa_caches[num].bmap);\n+}\n+\n+/* Dump out the cache. Note empty and non-filled\n+ in ssa names are not printed out. */\n+void\n+vars_ssa_cache::dump (FILE *file)\n+{\n+ fprintf (file, \"var ssa address cache\\n\");\n+ for (unsigned num = 0; num < num_ssa_names; num++)\n {\n+ if (!vars_ssa_caches[num].bmap\n+\t || vars_ssa_caches[num].bmap == empty)\n+\tcontinue;\n+ fprintf (file, \"_%d refers to:\\n\", num);\n+ bitmap_iterator bi;\n+ unsigned i;\n+ EXECUTE_IF_SET_IN_BITMAP (vars_ssa_caches[num].bmap, 0, i, bi)\n+\t{\n+\t fputc ('\\t', file);\n+\t print_generic_expr (file, stack_vars[i].decl, dump_flags);\n+\t}\n+ fputc ('\\n', file);\n+ }\n+ fputc ('\\n', file);\n+}\n+\n+/* Returns the filled in cache for NAME.\n+ This will fill in the cache if it does not exist already.\n+ Returns an empty for ssa names that can't contain pointers\n+ (only intergal types and pointer types will contain pointers). */\n+\n+const_bitmap\n+vars_ssa_cache::operator() (tree name)\n+{\n+ gcc_assert (TREE_CODE (name) == SSA_NAME);\n+\n+ if (!POINTER_TYPE_P (TREE_TYPE (name))\n+ && !INTEGRAL_TYPE_P (TREE_TYPE (name)))\n+ return empty;\n+\n+ if (exists (name))\n+ return vars_ssa_caches[SSA_NAME_VERSION (name)].bmap;\n+\n+ auto_vec<std::pair<tree,tree>, 4> work_list;\n+ auto_vec<std::pair<tree,tree>, 4> update_cache_list;\n+\n+ work_list.safe_push (std::make_pair (name, name));\n+\n+ while (!work_list.is_empty ())\n+ {\n+ auto item = work_list.pop();\n+ tree use = item.first;\n+ tree old_name = item.second;\n+ if (TREE_CODE (use) == ADDR_EXPR)\n+\t{\n+\t tree op = TREE_OPERAND (use, 0);\n+\t op = get_base_address (op);\n+\t unsigned idx = decl_stack_index (op);\n+\t if (idx != INVALID_STACK_INDEX)\n+\t add_one (old_name, idx);\n+\t continue;\n+\t}\n+\n+ if (TREE_CODE (use) != SSA_NAME)\n+\tcontinue;\n+\n+ if (!POINTER_TYPE_P (TREE_TYPE (use))\n+\t && !INTEGRAL_TYPE_P (TREE_TYPE (use)))\n+\tcontinue;\n+\n+ /* Mark the old ssa name needs to be update from the use. */\n+ update_cache_list.safe_push (item);\n+\n+ /* If the cache exists for the use, don't try to recreate it. */\n+ if (exists (use))\n+\tcontinue;\n+\n+ /* Create the cache bitmap for the use and also\n+\t so we don't go into an infinite loop for some phi nodes with loops. */\n+ create (use);\n+\n+ /* For assignments, walk each operand for possible addresses.\n+\t For PHI nodes, walk each argument. */\n gimple *g = SSA_NAME_DEF_STMT (use);\n if (gassign *a = dyn_cast <gassign *> (g))\n \t{\n-\t if (tree op = gimple_assign_rhs1 (a))\n-\t if (TREE_CODE (op) == ADDR_EXPR)\n-\t visit (a, TREE_OPERAND (op, 0), op, work);\n+\t /* operand 0 is the lhs. */\n+\t for (unsigned i = 1; i < gimple_num_ops (g); i++)\n+\t work_list.safe_push (std::make_pair (gimple_op (a, i), use));\n \t}\n else if (gphi *p = dyn_cast <gphi *> (g))\n \tfor (unsigned i = 0; i < gimple_phi_num_args (p); ++i)\n-\t if (TREE_CODE (use = gimple_phi_arg_def (p, i)) == SSA_NAME)\n-\t if (gassign *a = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (use)))\n-\t {\n-\t\tif (tree op = gimple_assign_rhs1 (a))\n-\t\t if (TREE_CODE (op) == ADDR_EXPR)\n-\t\t visit (a, TREE_OPERAND (op, 0), op, work);\n-\t }\n+\t work_list.safe_push (std::make_pair (gimple_phi_arg_def (p, i), use));\n }\n+\n+ /* Update the cache. Note a loop is needed as phi nodes could\n+ cause a loop to form. The number of times through this loop\n+ will be small though. */\n+ bool changed;\n+ do {\n+ changed = false;\n+ for (auto &e : update_cache_list)\n+ {\n+\tif (update (e.second, e.first))\n+\t changed = true;\n+ }\n+ } while (changed);\n+\n+ return vars_ssa_caches[SSA_NAME_VERSION (name)].bmap;\n+}\n+\n+/* Helper function for add_scope_conflicts_1. For USE on\n+ a stmt, if it is a SSA_NAME and in its defining statement\n+ is known to be based on some ADDR_EXPR, invoke VISIT\n+ on that ADDR_EXPR. */\n+\n+static inline void\n+add_scope_conflicts_2 (vars_ssa_cache &cache, tree name,\n+\t\t bitmap work, walk_stmt_load_store_addr_fn visit)\n+{\n+ gcc_assert (TREE_CODE (name) == SSA_NAME);\n+\n+ /* Querry the cache for the mapping of addresses that are referendd by\n+ ssa name NAME. Querrying it will fill in it. */\n+ bitmap_iterator bi;\n+ unsigned i;\n+ const_bitmap bmap = cache (name);\n+ /* Visit each stack variable that is referenced. */\n+ EXECUTE_IF_SET_IN_BITMAP (bmap, 0, i, bi)\n+ visit (nullptr, stack_vars[i].decl, nullptr, work);\n }\n \n /* Helper routine for add_scope_conflicts, calculating the active partitions\n@@ -622,7 +830,7 @@ add_scope_conflicts_2 (tree use, bitmap work,\n liveness. */\n \n static void\n-add_scope_conflicts_1 (basic_block bb, bitmap work, bool for_conflict)\n+add_scope_conflicts_1 (vars_ssa_cache &cache, basic_block bb, bitmap work, bool for_conflict)\n {\n edge e;\n edge_iterator ei;\n@@ -630,40 +838,45 @@ add_scope_conflicts_1 (basic_block bb, bitmap work, bool for_conflict)\n walk_stmt_load_store_addr_fn visit;\n use_operand_p use_p;\n ssa_op_iter iter;\n+ bool had_non_clobbers = false;\n \n bitmap_clear (work);\n+ /* The copy what was alive out going from the edges. */\n FOR_EACH_EDGE (e, ei, bb->preds)\n bitmap_ior_into (work, (bitmap)e->src->aux);\n \n- visit = visit_op;\n+ visit = for_conflict ? visit_conflict : visit_op;\n \n+ /* Addresses coming into the bb via phis are alive at the entry point. */\n for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))\n- {\n- gimple *stmt = gsi_stmt (gsi);\n- gphi *phi = as_a <gphi *> (stmt);\n- walk_stmt_load_store_addr_ops (stmt, work, NULL, NULL, visit);\n- FOR_EACH_PHI_ARG (use_p, phi, iter, SSA_OP_USE)\n-\tadd_scope_conflicts_2 (USE_FROM_PTR (use_p), work, visit);\n- }\n+ add_scope_conflicts_2 (cache, gimple_phi_result (gsi_stmt (gsi)), work, visit_op);\n+\n for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); gsi_next (&gsi))\n {\n gimple *stmt = gsi_stmt (gsi);\n \n+ /* Debug statements are not considered for liveness. */\n+ if (is_gimple_debug (stmt))\n+\tcontinue;\n+\n+ /* If we had `var = {CLOBBER}`, then var is no longer\n+\t considered alive after this point but might become\n+\t alive later on. */\n if (gimple_clobber_p (stmt))\n \t{\n \t tree lhs = gimple_assign_lhs (stmt);\n-\t /* Handle only plain var clobbers.\n+\t /* Handle only plain var clobbers, not partial ones.\n \t Nested functions lowering and C++ front-end inserts clobbers\n-\t which are not just plain variables. */\n+\t which are partial clobbers. */\n \t if (!VAR_P (lhs))\n \t continue;\n \t unsigned indx = decl_stack_index (lhs);\n \t if (indx != INVALID_STACK_INDEX)\n \t bitmap_clear_bit (work, indx);\n \t}\n- else if (!is_gimple_debug (stmt))\n+ else\n \t{\n-\t if (for_conflict && visit == visit_op)\n+\t if (for_conflict && !had_non_clobbers)\n \t {\n \t /* When we are inheriting live variables from our predecessors\n \t\t through a CFG merge we might not see an actual mention of\n@@ -685,17 +898,17 @@ add_scope_conflicts_1 (basic_block bb, bitmap work, bool for_conflict)\n \t\t a->conflicts = BITMAP_ALLOC (&stack_var_bitmap_obstack);\n \t\t bitmap_ior_into (a->conflicts, work);\n \t\t }\n-\t visit = visit_conflict;\n+\t had_non_clobbers = true;\n \t }\n \t walk_stmt_load_store_addr_ops (stmt, work, visit, visit, visit);\n \t FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)\n-\t add_scope_conflicts_2 (USE_FROM_PTR (use_p), work, visit);\n+\t add_scope_conflicts_2 (cache, USE_FROM_PTR (use_p), work, visit);\n \t}\n }\n \n /* When there was no real instruction but there's a CFG merge we need\n to add the conflicts now. */\n- if (for_conflict && visit == visit_op && EDGE_COUNT (bb->preds) > 1)\n+ if (for_conflict && !had_non_clobbers && EDGE_COUNT (bb->preds) > 1)\n {\n bitmap_iterator bi;\n unsigned i;\n@@ -726,6 +939,8 @@ add_scope_conflicts (void)\n int *rpo;\n int n_bbs;\n \n+ vars_ssa_cache cache;\n+\n /* We approximate the live range of a stack variable by taking the first\n mention of its name as starting point(s), and by the end-of-scope\n death clobber added by gimplify as ending point(s) of the range.\n@@ -752,14 +967,17 @@ add_scope_conflicts (void)\n \t bitmap active;\n \t bb = BASIC_BLOCK_FOR_FN (cfun, rpo[i]);\n \t active = (bitmap)bb->aux;\n-\t add_scope_conflicts_1 (bb, work, false);\n+\t add_scope_conflicts_1 (cache, bb, work, false);\n \t if (bitmap_ior_into (active, work))\n \t changed = true;\n \t}\n }\n \n FOR_EACH_BB_FN (bb, cfun)\n- add_scope_conflicts_1 (bb, work, true);\n+ add_scope_conflicts_1 (cache, bb, work, true);\n+\n+ if (dump_file && (dump_flags & TDF_DETAILS))\n+ cache.dump (dump_file);\n \n free (rpo);\n BITMAP_FREE (work);\ndiff --git a/gcc/testsuite/gcc.dg/torture/pr117426-1.c b/gcc/testsuite/gcc.dg/torture/pr117426-1.c\nnew file mode 100644\nindex 000000000000..e32dd5358930\n--- /dev/null\n+++ b/gcc/testsuite/gcc.dg/torture/pr117426-1.c\n@@ -0,0 +1,53 @@\n+/* { dg-do run } */\n+\n+/* PR middle-end/117426 */\n+\n+\n+/* o and q stack variables should not be allocated at the same parition.\n+ At -O3 with unrolling, the stack conflicts code was missing both variables\n+ were alive at the same time. */\n+__attribute__((noipa)) void func1() {}\n+int a[6];\n+int b, d, i, j, l, m, n;\n+char *c;\n+int f[8][8][4];\n+int *g = &d;\n+char p[11];\n+int main() {\n+ short q[6];\n+ int k = 0;\n+ for (; k < 2; k++) {\n+ {\n+ char o[3];\n+ int e = 53;\n+ char *h = o;\n+ c = p;\n+ while (e)\n+ *c++ = e /= 10;\n+ while (c != p)\n+ *h++ = *--c;\n+ *h++ = '\\0';\n+ n = h - o;\n+ }\n+ q[n - 2] = 1;\n+ }\n+ *g = q[1];\n+ if (d != 1)\n+ __builtin_abort ();\n+ l = 0;\n+ for (; l < 10; l++)\n+ if (m)\n+ func1();\n+ i = 0;\n+ for (; i < 7; i++) {\n+ j = 0;\n+ for (; j < 7; j++)\n+ b = a[b];\n+ }\n+ j = 0;\n+ for (; j < 8; j++) {\n+ l = 0;\n+ for (; l < 4; l++)\n+ b = a[b ^ f[i][j][l]];\n+ }\n+}\n", "prefixes": [ "v1", "3/4" ] }