https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102285

--- Comment #13 from Richard Biener <rguenth at gcc dot gnu.org> ---
Because the variable doesn't need to be addressable.

OK, so the issue is likely that we're probing the lhs with EXPAND_WRITE but
when we expand the memset we end up with using expand_expr_addr_expr_1
with EXPAND_NORMAL.  So our probe ends up with

(mem/c:BLK (plus:DI (reg/f:DI 77 virtual-stack-vars)
        (const_int -16 [0xfffffffffffffff0])) [0  S-1 A128])

which means it created a stack slot - that's not what we intended.

We could try sth like the following which should cover this testcase and
also hopefully doesn't break anything else.

diff --git a/gcc/expr.c b/gcc/expr.c
index e0bcbccd905..ab3b5b26c20 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -5322,7 +5322,7 @@ non_mem_decl_p (tree base)
 /* Returns true if REF refers to an object that does not
    reside in memory and has non-BLKmode.  */

-static inline bool
+bool
 mem_ref_refers_to_non_mem_p (tree ref)
 {
   tree base;
diff --git a/gcc/expr.h b/gcc/expr.h
index 94a85b40dca..85650e96834 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -346,4 +346,6 @@ extern void expand_operands (tree, tree, rtx, rtx*, rtx*,
 /* Return an rtx for the size in bytes of the value of an expr.  */
 extern rtx expr_size (tree);

+extern bool mem_ref_refers_to_non_mem_p (tree ref);
+
 #endif /* GCC_EXPR_H */
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 8312d08aab2..c1d23dfd21e 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -3015,8 +3015,10 @@ expand_DEFERRED_INIT (internal_fn, gcall *stmt)
     reg_lhs = true;
   else
     {
-      rtx tem = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
-      reg_lhs = !MEM_P (tem);
+      tree lhs_base = lhs;
+      while (handled_component_p (lhs_base))
+       lhs_base = TREE_OPERAND (lhs_base, 0);
+      reg_lhs = mem_refers_to_non_mem_p (lhs_base);
     }

   if (!reg_lhs)

Reply via email to