On 5 May 2017 at 12:46, Richard Biener <rguent...@suse.de> wrote:
> On Thu, 4 May 2017, Jeff Law wrote:
>
>> On 05/04/2017 10:00 AM, Prathamesh Kulkarni wrote:
>> > Hi,
>> > As mentioned in PR, the issue is that cddce1 marks the call to
>> > __builtin_strdup as necessary:
>> > marking necessary through .MEM_6 stmt p_7 = __builtin_strdup (&d);
>> >
>> > and since p_7 doesn't get added to worklist in propagate_necessity()
>> > because it's used only within free(), it's treated as "dead"
>> > and wrongly gets released.
>> > The patch fixes that by adding strdup/strndup in corresponding condition
>> > in eliminate_unnecessary_stmts().
>> >
>> > Another issue, was that my previous patch failed to remove multiple
>> > calls to strdup:
>> > char *f(char **tt)
>> > {
>> >    char *t = *tt;
>> >    char *p;
>> >
>> >    p = __builtin_strdup (t);
>> >    p = __builtin_strdup (t);
>> >    return p;
>> > }
>> >
>> > That's fixed in patch by adding strdup/strndup to another
>> > corresponding condition in propagate_necessity() so that only one
>> > instance of strdup would be kept.
>> >
>> > Bootstrapped+tested on x86_64-unknown-linux-gnu.
>> > Cross-testing on arm*-*-* and aarch64*-*-* in progress.
>> > OK to commit if testing passes ?
>> >
>> > Thanks
>> > Prathamesh
>> >
>> >
>> > pr80613-1.txt
>> >
>> >
>> > 2017-05-04  Prathamesh Kulkarni<prathamesh.kulka...@linaro.org>
>> >
>> >     PR tree-optimization/80613
>> >     * tree-ssa-dce.c (propagate_necessity): Add cases for BUILT_IN_STRDUP
>> >     and BUILT_IN_STRNDUP.
>> >     * (eliminate_unnecessary_stmts): Likewise.
>> >
>> > testsuite/
>> >     * gcc.dg/tree-ssa/pr80613-1.c: New test-case.
>> >     * gcc.dg/tree-ssa/pr80613-2.c: New test-case.
>> So I'm comfortable with the change to eliminate_unnecessary_stmts as well as
>> the associated testcase pr80613-1.c.  GIven that addresses the core of the
>> bug, I'd go ahead and install that part immediately.
>>
>> I'm still trying to understand the code in propagate_necessity.
>
> That part of the patch is clearly wrong unless compensation code is
> added elsehwere.
>
> I think adding str[n]dup within the existing mechanism to remove
> allocate/free pairs was wrong given str[n]dup have a use and there's
> no code in DCE that can compensate for str[n]dup only becoming
> necessary late.
>
> I don't see how such compenstation code would work reliably without
> becoming too gross (re-start iteration).
>
> So I think the best is to revert the initial patch and look for a
> pattern-matching approach instead.
Hi Richard,
The attached patch removes str[n]dup in propagate_necessity() for
allocation/free pair
removal.
I assume it'd be OK to leave str[n]dup in
mark_stmt_if_obviously_necessary(), so dce
removes calls to strn[n]dup if lhs is dead (or not present) ?

Thanks,
Prathamesh
>
> Thanks,
> Richard.
>
>
>
>>
>>
>> >
>> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr80613-1.c
>> > b/gcc/testsuite/gcc.dg/tree-ssa/pr80613-1.c
>> > new file mode 100644
>> > index 00000000000..56176427922
>> > --- /dev/null
>> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr80613-1.c
>> > @@ -0,0 +1,13 @@
>> > +/* { dg-do compile } */
>> > +/* { dg-options "-O2" } */
>> > +
>> > +char *a(int);
>> > +int b;
>> > +
>> > +void c() {
>> > +  for (;;) {
>> > +    char d = *a(b);
>> > +    char *e = __builtin_strdup (&d);
>> > +    __builtin_free(e);
>> > +  }
>> > +}
>> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr80613-2.c
>> > b/gcc/testsuite/gcc.dg/tree-ssa/pr80613-2.c
>> > new file mode 100644
>> > index 00000000000..c58cc08d6c5
>> > --- /dev/null
>> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr80613-2.c
>> > @@ -0,0 +1,16 @@
>> > +/* { dg-do compile } */
>> > +/* { dg-options "-O2 -fdump-tree-cddce1" } */
>> > +
>> > +/* There should only be one instance of __builtin_strdup after cddce1.  */
>> > +
>> > +char *f(char **tt)
>> > +{
>> > +  char *t = *tt;
>> > +  char *p;
>> > +
>> > +  p = __builtin_strdup (t);
>> > +  p = __builtin_strdup (t);
>> > +  return p;
>> > +}
>> > +
>> > +/* { dg-final { scan-tree-dump-times "__builtin_strdup" 1 "cddce1" } } */
>> > diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
>> > index e17659df91f..7c05f981307 100644
>> > --- a/gcc/tree-ssa-dce.c
>> > +++ b/gcc/tree-ssa-dce.c
>> > @@ -852,7 +852,9 @@ propagate_necessity (bool aggressive)
>> >                       == BUILT_IN_ALLOCA_WITH_ALIGN)
>> >                   || DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_SAVE
>> >                   || DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE
>> > -                 || DECL_FUNCTION_CODE (callee) ==
>> > BUILT_IN_ASSUME_ALIGNED))
>> > +                 || DECL_FUNCTION_CODE (callee) ==
>> > BUILT_IN_ASSUME_ALIGNED
>> > +                 || DECL_FUNCTION_CODE (callee) == BUILT_IN_STRDUP
>> > +                 || DECL_FUNCTION_CODE (callee) == BUILT_IN_STRNDUP))
>> >             continue;
>> What I'm struggling with is that str[n]dup read from the memory pointed to by
>> their incoming argument, so ISTM they are not "merely acting are barriers or
>> that only store to memory" and thus shouldn't be treated like memset, malloc 
>> &
>> friends.  Otherwise couldn't we end up incorrectly removing a store to memory
>> that is only read by a live strdup?
>>
>> So while I agree you ought to be able to remove the first call to strdup in
>> the second testcase, I'm not sure the approach you've used works correctly.
>>
>> jeff
>>
>>
>>
>
> --
> Richard Biener <rguent...@suse.de>
> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
> 21284 (AG Nuernberg)
2017-05-05  Prathamesh Kulkarni  <prathamesh.kulka...@linaro.org>

        PR tree-optimization/80613
        * tree-ssa-dce.c (propagate_necessity): Remove cases for
        BUILT_IN_STRDUP and BUILT_IN_STRNDUP.

testsuite/
        * gcc.dg/tree-ssa/pr79697.c (k): Remove.

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr79697.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr79697.c
index d4f64739787..fc3580e3ce3 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr79697.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr79697.c
@@ -16,18 +16,6 @@ void h(void)
   __builtin_realloc (0, 10);
 }
 
-void k(void)
-{
-  char *p = __builtin_strdup ("abc");
-  __builtin_free (p);
-
-  char *q = __builtin_strndup ("abc", 3);
-  __builtin_free (q);
-}
-
 /* { dg-final { scan-tree-dump "Deleting : __builtin_strdup" "cddce1" } } */
 /* { dg-final { scan-tree-dump "Deleting : __builtin_strndup" "cddce1" } } */
 /* { dg-final { scan-tree-dump "__builtin_malloc" "gimple" } } */
-/* { dg-final { scan-tree-dump-not "__builtin_strdup" "optimized" } } */
-/* { dg-final { scan-tree-dump-not "__builtin_strndup" "optimized" } } */
-/* { dg-final { scan-tree-dump-not "__builtin_free" "optimized" } } */
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index e17659df91f..4225c3cc1a1 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -782,9 +782,7 @@ propagate_necessity (bool aggressive)
                  && DECL_BUILT_IN_CLASS (def_callee) == BUILT_IN_NORMAL
                  && (DECL_FUNCTION_CODE (def_callee) == BUILT_IN_ALIGNED_ALLOC
                      || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_MALLOC
-                     || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_CALLOC
-                     || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_STRDUP
-                     || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_STRNDUP))
+                     || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_CALLOC))
                {
                  gimple *bounds_def_stmt;
                  tree bounds;

Reply via email to