https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127647
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |jamborm at gcc dot gnu.org
--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> ---
Hmm, no. Sinking isn't really set up to cross other (non-aliasing) stores.
C++ testcase showing the STLF issue; the best thing would be to eliminate
'tem' alltogether, but the late memcpy inlining makes this difficult. SRA
says
Candidate (5305): tem
Allowed ADDR_EXPR of tem because of __builtin_memcpy (x_18(D), &tem, 12);
! Disqualifying tem - No scalar replacements to be created.
Martin? We seem to have a single outer access from the memcpy and
children for the stores.
Naiively doing
diff --git a/gcc/tree-sra.cc b/gcc/tree-sra.cc
index f951a38442a..33f0a6235a7 100644
--- a/gcc/tree-sra.cc
+++ b/gcc/tree-sra.cc
@@ -1422,7 +1422,10 @@ build_access_from_call_arg (tree expr, gimple *stmt,
bool can_be_returned,
return false;
}
- bool read = build_access_from_expr (base, stmt, false);
+ auto raccess = build_access_from_expr_1 (base, stmt, false);
+ bool read = raccess != NULL;
+ if (raccess)
+ raccess->grp_total_scalarization = 1;
bool write = build_access_from_expr (base, stmt, true);
if (read || write)
{
to trigger total scalarization of course "fails" in the sense that SRA
cannot rewrite a __builtin_memcpy. But with this I see
MEM <int> [(void *)&tem] = tem$a_24;
MEM <int> [(void *)&tem + 4B] = tem$b_25;
MEM <int> [(void *)&tem + 8B] = tem$c_26;
__builtin_memcpy (x_18(D), &tem, 12);
and thus at least the desired "sinking" done ... but still RTL cannot
recover
movl %eax, -12(%rsp)
movl %r8d, -8(%rsp)
movl %ecx, 8(%rdi)
movq -12(%rsp), %rax
movq %rax, (%rdi)
That said, I'm still a believer in SRA guiding "larger" memcpy expansion
(as opposed to unleashing fold_stmt).
struct X { int a; int b; int c; };
void foo (int *x, int *p, int stride)
{
struct X tem;
int p0, p1, p2;
tem.a = p0 = p[0];
tem.b = p1 = p[1];
tem.c = p2 = p[2];
if (stride != 1)
{
x[0] = p0;
x[stride] = p1;
x[stride*2] = p2;
}
else
__builtin_memcpy (x, &tem, sizeof (X));
}