From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2140) id 1722E39AE80F; Mon, 28 Jun 2021 15:42:23 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1722E39AE80F Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Alexandre Oliva To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/users/aoliva/heads/testme)] ipa-modref: merge flags when adding escape X-Act-Checkin: gcc X-Git-Author: Alexandre Oliva X-Git-Refname: refs/users/aoliva/heads/testme X-Git-Oldrev: 084635aa80daa45403aebd86712b2c61779c4173 X-Git-Newrev: b54230f5409463ba380a83a7569ec1de7b88cb35 Message-Id: <20210628154223.1722E39AE80F@sourceware.org> Date: Mon, 28 Jun 2021 15:42:23 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Jun 2021 15:42:23 -0000 https://gcc.gnu.org/g:b54230f5409463ba380a83a7569ec1de7b88cb35 commit b54230f5409463ba380a83a7569ec1de7b88cb35 Author: Alexandre Oliva Date: Mon Jun 28 12:40:30 2021 -0300 ipa-modref: merge flags when adding escape While working on some function splitting changes, I've got a miscompilation in stagefeedback that I've tracked down to a complicated scenario: - ipa-modref miscomputes a function parameter as having EAF_DIRECT, because it's dereferenced and passed on to another function, but add_escape_point does not update the flags for the dereferenced SSA_NAME passed as a parameter, and the EAF_UNUSED in the value that first initializes it, that remains unchanged throughout, causes deref_flags to set EAF_DIRECT, among other flags. - structalias, seeing the EAF_DIRECT in the parameter for that function, refrains from mak[ing]_transitive_closure_constraints for a pointer passed in that parameter. - tree dse2 concludes the initializer of the pointed-to variable is a dead store and removes it. The test depends on gimple passes's processing of functions in a certain order to expose parm flag miscomputed by ipa-modref. A different order may enable the non-ipa modref2 pass to compute flags differently and avoid the problem. I've arranged for add_escape_point to merge flags, as the non-ipa path does. I've also caught and fixed an error in the dumping of escaping flags. for gcc/ChangeLog * ipa-modref.c (modref_lattice::add_escape_point): Merge min_flags into flags. (modref_lattice::dump): Fix escape_point's min_flags dumping. for gcc/testsuite/ChangeLog * c-c++-common/modref-dse.c: New. Diff: --- gcc/ipa-modref.c | 4 ++-- gcc/testsuite/c-c++-common/modref-dse.c | 38 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c index d5a8332fb55..3b0830cb875 100644 --- a/gcc/ipa-modref.c +++ b/gcc/ipa-modref.c @@ -1392,7 +1392,7 @@ modref_lattice::dump (FILE *out, int indent) const fprintf (out, "%*s Arg %i (%s) min flags", indent, "", escape_points[i].arg, escape_points[i].direct ? "direct" : "indirect"); - dump_eaf_flags (out, flags, false); + dump_eaf_flags (out, escape_points[i].min_flags, false); fprintf (out, " in call "); print_gimple_stmt (out, escape_points[i].call, 0); } @@ -1411,7 +1411,7 @@ modref_lattice::add_escape_point (gcall *call, int arg, int min_flags, /* If we already determined flags to be bad enough, * we do not need to record. */ - if ((flags & min_flags) == flags) + if (!merge (min_flags)) return false; FOR_EACH_VEC_ELT (escape_points, i, ep) diff --git a/gcc/testsuite/c-c++-common/modref-dse.c b/gcc/testsuite/c-c++-common/modref-dse.c new file mode 100644 index 00000000000..5f64e8f4b59 --- /dev/null +++ b/gcc/testsuite/c-c++-common/modref-dse.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dse2-details" } */ +/* { dg-final { scan-tree-dump-not "Deleted dead store" "dse2" } } */ + +struct foo { unsigned long bar; }; + +unsigned y; + +static int __attribute__ ((__noinline__, __noclone__)) +wrapped (struct foo *p, int i); + +static int wrapper (struct foo *p); + +static int __attribute__ ((__noclone__)) +wrapper (struct foo *p) { + return wrapped (p, 1); +} + +static int __attribute__ ((__noinline__, __noclone__)) +dind (struct foo **pp); + +int __attribute__ ((__noclone__, __no_reorder__)) +xfn () { + struct foo x = { 0xBADC0FFE }; + struct foo *p = &x; + return dind (&p); +} + +static int __attribute__ ((__noinline__, __no_reorder__)) +wrapped (struct foo *p, int i) { + return p->bar + i == y++; +} + +static int __attribute__ ((__noinline__, __noclone__, __no_reorder__)) +dind (struct foo **pp) { + wrapper (*pp); + return 0; +}