This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Optimize callers using nonnull attribute


On Mon, Oct 7, 2013 at 12:33 AM, Marc Glisse <marc.glisse@inria.fr> wrote:
> Hello,
>
> this patch asserts that when we call a function with the nonnull attribute,
> the corresponding argument is not zero, just like when we dereference a
> pointer. Everything is under a check for flag_delete_null_pointer_checks.
>
> Note that this function currently gives up if the statement may throw
> (because in some languages indirections may throw?), but this could probably
> be relaxed a bit so my example would still work when compiled with g++,
> without having to mark f1 and f2 as throw().
>
> Bootstrap (default languages) + testsuite on x86_64-unknown-linux-gnu.

Can you please restructure it in a way to not require a goto?  That is,
move searching for a non-null opportunity into a helper function?

Ok with that change.  (I wonder how many bogus nonnull attributes
this catches ...)

Thanks,
Richard.

> 2013-10-08  Marc Glisse  <marc.glisse@inria.fr>
>
>         PR tree-optimization/58480
> gcc/
>         * tree-vrp.c (infer_value_range): Look for a nonnull attribute.
>
> gcc/testsuite/
>         * gcc.dg/tree-ssa/pr58480.c: New file.
>
> --
> Marc Glisse
> Index: testsuite/gcc.dg/tree-ssa/pr58480.c
> ===================================================================
> --- testsuite/gcc.dg/tree-ssa/pr58480.c (revision 0)
> +++ testsuite/gcc.dg/tree-ssa/pr58480.c (working copy)
> @@ -0,0 +1,19 @@
> +/* { dg-do compile { target { ! keeps_null_pointer_checks } } } */
> +/* { dg-options "-O2 -fdump-tree-vrp1" } */
> +
> +extern void eliminate (void);
> +extern void* f1 (void *a, void *b) __attribute__((nonnull));
> +extern void* f2 (void *a, void *b) __attribute__((nonnull(2)));
> +void g1 (void*p, void*q){
> +  f1 (q, p);
> +  if (p == 0)
> +    eliminate ();
> +}
> +void g2 (void*p, void*q){
> +  f2 (q, p);
> +  if (p == 0)
> +    eliminate ();
> +}
> +
> +/* { dg-final { scan-tree-dump-times "Folding predicate\[^\\n\]*to 0" 2
> "vrp1" } } */
> +/* { dg-final { cleanup-tree-dump "vrp1" } } */
>
> Property changes on: testsuite/gcc.dg/tree-ssa/pr58480.c
> ___________________________________________________________________
> Added: svn:keywords
> ## -0,0 +1 ##
> +Author Date Id Revision URL
> \ No newline at end of property
> Added: svn:eol-style
> ## -0,0 +1 ##
> +native
> \ No newline at end of property
> Index: tree-vrp.c
> ===================================================================
> --- tree-vrp.c  (revision 203229)
> +++ tree-vrp.c  (working copy)
> @@ -4493,28 +4493,58 @@ infer_value_range (gimple stmt, tree op,
>    /* We can only assume that a pointer dereference will yield
>       non-NULL if -fdelete-null-pointer-checks is enabled.  */
>    if (flag_delete_null_pointer_checks
>        && POINTER_TYPE_P (TREE_TYPE (op))
>        && gimple_code (stmt) != GIMPLE_ASM)
>      {
>        unsigned num_uses, num_loads, num_stores;
>
>        count_uses_and_derefs (op, stmt, &num_uses, &num_loads, &num_stores);
>        if (num_loads + num_stores > 0)
> +       goto nonnull;
> +
> +      if (gimple_code (stmt) == GIMPLE_CALL)
>         {
> -         *val_p = build_int_cst (TREE_TYPE (op), 0);
> -         *comp_code_p = NE_EXPR;
> -         return true;
> +         tree fntype = gimple_call_fntype (stmt);
> +         tree attrs = TYPE_ATTRIBUTES (fntype);
> +         for (; attrs; attrs = TREE_CHAIN (attrs))
> +           {
> +             attrs = lookup_attribute ("nonnull", attrs);
> +
> +             /* If "nonnull" wasn't specified, we know nothing about
> +                the argument.  */
> +             if (attrs == NULL_TREE)
> +               return false;
> +
> +             /* If "nonnull" applies to all the arguments, then ARG
> +                is non-null.  */
> +             if (TREE_VALUE (attrs) == NULL_TREE)
> +               goto nonnull;
> +
> +             /* Now see if op appears in the nonnull list.  */
> +             for (tree t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
> +               {
> +                 int idx = TREE_INT_CST_LOW (TREE_VALUE (t)) - 1;
> +                 tree arg = gimple_call_arg (stmt, idx);
> +                 if (op == arg)
> +                   goto nonnull;
> +               }
> +           }
>         }
>      }
>
>    return false;
> +
> +nonnull:
> +  *val_p = build_int_cst (TREE_TYPE (op), 0);
> +  *comp_code_p = NE_EXPR;
> +  return true;
>  }
>
>
>  void dump_asserts_for (FILE *, tree);
>  void debug_asserts_for (tree);
>  void dump_all_asserts (FILE *);
>  void debug_all_asserts (void);
>
>  /* Dump all the registered assertions for NAME to FILE.  */
>
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]