https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87627
--- Comment #6 from Alexander Monakov <amonakov at gcc dot gnu.org> ---
FWIW the following CSE enhancement cleans this up, but I'm unhappy with this
patch because it's too narrowly targeted; in particular, won't clean up
void g(int a, int *b, int c);
void f(int a, int *b, int c)
{
if (a) *b = c;
g(a, b, c);
}
Had to special-case for PARM_DECL because, in general, automatic variables that
are not address-taken on GIMPLE can become addressable on RTL when ABI requires
passing a large argument by reference.
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -2232,6 +2232,15 @@ hash_rtx_string (const char *ps)
return hash;
}
+static bool
+mem_escapes_p (const_rtx x)
+{
+ tree decl = MEM_EXPR (x);
+ if (!decl || TREE_CODE (decl) != PARM_DECL)
+ return true;
+ return may_be_aliased (decl);
+}
+
/* Same as hash_rtx, but call CB on each rtx if it is not NULL.
When the callback returns true, we continue with the new rtx. */
@@ -2421,7 +2430,8 @@ hash_rtx_cb (const_rtx x, machine_mode mode,
return 0;
}
if (hash_arg_in_memory_p && !MEM_READONLY_P (x))
- *hash_arg_in_memory_p = 1;
+ if (*hash_arg_in_memory_p != 1)
+ *hash_arg_in_memory_p = mem_escapes_p (x) ? 1 : 2;
/* Now that we have already found this special case,
might as well speed it up as much as possible. */
@@ -6127,7 +6137,7 @@ invalidate_memory (void)
for (p = table[i]; p; p = next)
{
next = p->next_same_hash;
- if (p->in_memory)
+ if (p->in_memory == 1)
remove_from_table (p, i);
}
}