On Mon, 27 Nov 2023, Martin Jambor wrote: > Hi, > > The enhancement to address PR 109849 contained an importsnt thinko, > and that any reference that is passed to a function and does not > escape, must also not happen to be aliased by the return value of the > function. This has quickly transpired as bugs PR 112711 and PR > 112721. > > Just as IPA-modref does a good enough job to allow us to rely on the > escaped set of variables, it sems to be doing well also on updating > EAF_NOT_RETURNED_DIRECTLY call argument flag which happens to address > exactly the situation we need to avoid. Of course, if a call > statement ignores any returned value, we also do not need to check the > flag.
But what about EAF_NOT_RETURNED_INDIRECTLY? Don't you need to verify the parameter doesn't escape through the return at all? > > Hopefully this does not pessimize things too much, I have verified > that the PR 109849 testcae remains quick and so should also the > benchmark it is derived from. > > The patch has passed bootstrap and testing on x86_64-linux, OK for > master? > > Thanks, > > Martin > > > gcc/ChangeLog: > > 2023-11-27 Martin Jambor <mjam...@suse.cz> > > PR tree-optimization/112711 > PR tree-optimization/112721 > * tree-sra.cc (build_access_from_call_arg): New parameter > CAN_BE_RETURNED, disqualify any candidate passed by reference if it is > true. Adjust leading comment. > (scan_function): Pass appropriate value to CAN_BE_RETURNED of > build_access_from_call_arg. > > gcc/testsuite/ChangeLog: > > 2023-11-27 Martin Jambor <mjam...@suse.cz> > > PR tree-optimization/112711 > PR tree-optimization/112721 > * g++.dg/tree-ssa/pr112711.C: New test. > * gcc.dg/tree-ssa/pr112721.c: Likewise. > --- > gcc/testsuite/g++.dg/tree-ssa/pr112711.C | 31 ++++++++++++++++++ > gcc/testsuite/gcc.dg/tree-ssa/pr112721.c | 26 +++++++++++++++ > gcc/tree-sra.cc | 40 ++++++++++++++++++------ > 3 files changed, 88 insertions(+), 9 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr112711.C > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr112721.c > > diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr112711.C > b/gcc/testsuite/g++.dg/tree-ssa/pr112711.C > new file mode 100644 > index 00000000000..c04524b04a7 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/tree-ssa/pr112711.C > @@ -0,0 +1,31 @@ > +/* { dg-do run } */ > +/* { dg-options "-O1" } */ > + > +typedef int i32; > +typedef unsigned int u32; > + > +static inline void write_i32(void *memory, i32 value) { > + // swap i32 bytes as if it was u32: > + u32 u_value = value; > + value = __builtin_bswap32(u_value); > + > + // llvm infers '1' alignment from destination type > + __builtin_memcpy(__builtin_assume_aligned(memory, 1), &value, > sizeof(value)); > +} > + > +__attribute__((noipa)) > +static void bug (void) { > + #define assert_eq(lhs, rhs) if (lhs != rhs) __builtin_trap() > + > + unsigned char data[5]; > + write_i32(data, -1362446643); > + assert_eq(data[0], 0xAE); > + assert_eq(data[1], 0xCA); > + write_i32(data + 1, -1362446643); > + assert_eq(data[1], 0xAE); > +} > + > +int main() { > + bug(); > + return 0; > +} > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr112721.c > b/gcc/testsuite/gcc.dg/tree-ssa/pr112721.c > new file mode 100644 > index 00000000000..adf62613266 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr112721.c > @@ -0,0 +1,26 @@ > +/* { dg-do run } */ > +/* { dg-options "-O1" } */ > + > +unsigned * volatile gv; > + > +struct a { > + int b; > +}; > +int c, e; > +long d; > +unsigned * __attribute__((noinline)) > +f(unsigned *g) { > + for (; c;) > + e = d; > + return gv ? gv : g; > +} > +int main() { > + int *h; > + struct a i = {8}; > + int *j = &i.b; > + h = (unsigned *) f(j); > + *h = 0; > + if (i.b != 0) > + __builtin_abort (); > + return 0; > +} > diff --git a/gcc/tree-sra.cc b/gcc/tree-sra.cc > index 3a0d52675fe..6a759783990 100644 > --- a/gcc/tree-sra.cc > +++ b/gcc/tree-sra.cc > @@ -1268,18 +1268,27 @@ abnormal_edge_after_stmt_p (gimple *stmt, enum > out_edge_check *oe_check) > } > > /* Scan expression EXPR which is an argument of a call and create access > - structures for all accesses to candidates for scalarization. Return true > if > - any access has been inserted. STMT must be the statement from which the > - expression is taken. */ > + structures for all accesses to candidates for scalarization. Return true > + if any access has been inserted. STMT must be the statement from which > the > + expression is taken. CAN_BE_RETURNED must be true if call argument flags > + do not rule out that the argument is directly returned. OE_CHECK is used > + to remember result of a test for abnormal outgoing edges after this > + statement. */ > > static bool > -build_access_from_call_arg (tree expr, gimple *stmt, > +build_access_from_call_arg (tree expr, gimple *stmt, bool can_be_returned, > enum out_edge_check *oe_check) > { > if (TREE_CODE (expr) == ADDR_EXPR) > { > tree base = get_base_address (TREE_OPERAND (expr, 0)); > > + if (can_be_returned) > + { > + disqualify_base_of_expr (base, "Address possibly returned, " > + "leading to an alis SRA may not know."); > + return false; > + } > if (abnormal_edge_after_stmt_p (stmt, oe_check)) > { > disqualify_base_of_expr (base, "May lead to need to add statements " > @@ -1508,12 +1517,25 @@ scan_function (void) > case GIMPLE_CALL: > { > enum out_edge_check oe_check = SRA_OUTGOING_EDGES_UNCHECKED; > - for (i = 0; i < gimple_call_num_args (stmt); i++) > - ret |= build_access_from_call_arg (gimple_call_arg (stmt, i), > - stmt, &oe_check); > + gcall *call = as_a <gcall *> (stmt); > + for (i = 0; i < gimple_call_num_args (call); i++) > + { > + bool can_be_returned; > + if (gimple_call_lhs (call)) > + { > + int af = gimple_call_arg_flags (call, i); > + can_be_returned = !(af & EAF_NOT_RETURNED_DIRECTLY); > + } > + else > + can_be_returned = false; > + ret |= build_access_from_call_arg (gimple_call_arg (call, > + i), > + stmt, can_be_returned, > + &oe_check); > + } > if (gimple_call_chain(stmt)) > - ret |= build_access_from_call_arg (gimple_call_chain(stmt), > - stmt, &oe_check); > + ret |= build_access_from_call_arg (gimple_call_chain(call), > + stmt, false, &oe_check); > } > > t = gimple_call_lhs (stmt); > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)