{"id":2226271,"url":"http://patchwork.ozlabs.org/api/1.2/patches/2226271/?format=json","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/1.2/projects/17/?format=json","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/1.2/people/93219/?format=json","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/1.2/series/500980/?format=json","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"]}