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: [PATCH] Don't optimize builtins declared always_inline until after inlining (PR middle-end/38454, take 2)


On Tue, Dec 9, 2008 at 11:13 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> Here is an updated patch that hopefully addresses the things you've raised
> here and on IRC.  Honza said on IRC unless always_inline functions
> are recursive and similar weirdnesses that after early inlining (when -O1+)
> always_inline functions should be inlined.
>
> Bootstrapped/regtested on x86_64-linux, ok for trunk?

Ok.

Thanks,
Richard.

> 2008-12-09  Jakub Jelinek  <jakub@redhat.com>
>
>        PR middle-end/38454
>        * function.h (struct function): Add always_inline_functions_inlined.
>        * ipa-inline.c (cgraph_early_inlining): Set it to true.
>        * tree-optimize.c (execute_fixup_cfg): Likewise.
>        * builtins.c (avoid_folding_inline_builtin): New function.
>        (fold_call_expr): Don't optimize always_inline builtins before
>        inlining.
>        (fold_call_stmt): Likewise.
>        (fold_builtin_call_array): Likewise.  Don't call
>        fold_builtin_varargs for BUILT_IN_MD builtins.
>
>        * gcc.dg/memset-1.c: New test.
>        * gcc.dg/memcpy-2.c: New test.
>
> --- gcc/ipa-inline.c.jj 2008-09-30 16:57:11.000000000 +0200
> +++ gcc/ipa-inline.c    2008-12-09 21:41:43.000000000 +0100
> @@ -1528,6 +1528,7 @@ cgraph_early_inlining (void)
>       todo = optimize_inline_calls (current_function_decl);
>       timevar_pop (TV_INTEGRATION);
>     }
> +  cfun->always_inline_functions_inlined = true;
>   return todo;
>  }
>
> --- gcc/function.h.jj   2008-09-30 16:57:11.000000000 +0200
> +++ gcc/function.h      2008-12-09 21:39:14.000000000 +0100
> @@ -578,6 +578,7 @@ struct function GTY(())
>   unsigned int dont_save_pending_sizes_p : 1;
>
>   unsigned int after_inlining : 1;
> +  unsigned int always_inline_functions_inlined : 1;
>
>   /* Fields below this point are not set for abstract functions; see
>      allocate_struct_function.  */
> --- gcc/tree-optimize.c.jj      2008-09-30 16:57:11.000000000 +0200
> +++ gcc/tree-optimize.c 2008-12-09 21:42:06.000000000 +0100
> @@ -293,6 +293,7 @@ execute_fixup_cfg (void)
>   int todo = gimple_in_ssa_p (cfun) ? TODO_verify_ssa : 0;
>
>   cfun->after_inlining = true;
> +  cfun->always_inline_functions_inlined = true;
>
>   if (cfun->eh)
>     FOR_EACH_BB (bb)
> --- gcc/builtins.c.jj   2008-12-09 16:48:24.000000000 +0100
> +++ gcc/builtins.c      2008-12-09 21:48:57.000000000 +0100
> @@ -10797,6 +10797,22 @@ fold_builtin_varargs (tree fndecl, tree
>   return NULL_TREE;
>  }
>
> +/* Return true if FNDECL shouldn't be folded right now.
> +   If a built-in function has an inline attribute always_inline
> +   wrapper, defer folding it after always_inline functions have
> +   been inlined, otherwise e.g. -D_FORTIFY_SOURCE checking
> +   might not be performed.  */
> +
> +static bool
> +avoid_folding_inline_builtin (tree fndecl)
> +{
> +  return (DECL_DECLARED_INLINE_P (fndecl)
> +         && DECL_DISREGARD_INLINE_LIMITS (fndecl)
> +         && cfun
> +         && !cfun->always_inline_functions_inlined
> +         && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fndecl)));
> +}
> +
>  /* A wrapper function for builtin folding that prevents warnings for
>    "statement without effect" and the like, caused by removing the
>    call node earlier than the warning is generated.  */
> @@ -10829,6 +10845,9 @@ fold_call_expr (tree exp, bool ignore)
>            return NULL_TREE;
>        }
>
> +      if (avoid_folding_inline_builtin (fndecl))
> +       return NULL_TREE;
> +
>       /* FIXME: Don't use a list in this interface.  */
>       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
>          return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore);
> @@ -10931,6 +10950,8 @@ fold_builtin_call_array (tree type,
>                && DECL_FUNCTION_CODE (fndecl2) == BUILT_IN_VA_ARG_PACK)
>              return build_call_array (type, fn, n, argarray);
>          }
> +       if (avoid_folding_inline_builtin (fndecl))
> +         return build_call_array (type, fn, n, argarray);
>         if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
>           {
>             tree arglist = NULL_TREE;
> @@ -10939,6 +10960,7 @@ fold_builtin_call_array (tree type,
>             ret = targetm.fold_builtin (fndecl, arglist, false);
>             if (ret)
>               return ret;
> +           return build_call_array (type, fn, n, argarray);
>           }
>         else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
>           {
> @@ -13647,6 +13669,8 @@ fold_call_stmt (gimple stmt, bool ignore
>     {
>       int nargs = gimple_call_num_args (stmt);
>
> +      if (avoid_folding_inline_builtin (fndecl))
> +       return NULL_TREE;
>       /* FIXME: Don't use a list in this interface.  */
>       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
>         {
> --- gcc/testsuite/gcc.dg/memcpy-2.c.jj  2008-12-09 16:50:28.000000000 +0100
> +++ gcc/testsuite/gcc.dg/memcpy-2.c     2008-12-09 16:50:28.000000000 +0100
> @@ -0,0 +1,25 @@
> +/* PR middle-end/38454 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +typedef __SIZE_TYPE__ size_t;
> +
> +extern inline __attribute__((gnu_inline, always_inline, artificial)) void *
> +memcpy (void *__restrict dest, const void *__restrict src, size_t len)
> +{
> +  return __builtin___memcpy_chk (dest, /* { dg-warning "will always overflow destination buffer" } */
> +                                src, len, __builtin_object_size (dest, 0));
> +}
> +
> +struct S { char buf[10]; } s;
> +
> +void
> +foo (void)
> +{
> +  char buf[12];
> +  char *p = buf + 4;
> +  struct S *q = (struct S *) p;
> +  memcpy (q, &s, sizeof (s));
> +}
> +
> +/* { dg-final { scan-assembler "__memcpy_chk" } } */
> --- gcc/testsuite/gcc.dg/memset-1.c.jj  2008-12-09 16:50:28.000000000 +0100
> +++ gcc/testsuite/gcc.dg/memset-1.c     2008-12-09 16:50:28.000000000 +0100
> @@ -0,0 +1,28 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +typedef __SIZE_TYPE__ size_t;
> +
> +extern void warn_memset_zero_len (void)
> +__attribute__((__warning__ ("memset used with constant zero length parameter;"
> +                           " this could be due to transposed parameters")));
> +
> +extern inline __attribute__((gnu_inline, always_inline, artificial)) void *
> +memset (void *dest, int ch, size_t len)
> +{
> +  if (__builtin_constant_p (len) && len == 0)
> +    {
> +      warn_memset_zero_len (); /* { dg-warning "memset used with constant zero" } */
> +      return dest;
> +    }
> +  return __builtin_memset (dest, ch, len);
> +}
> +
> +char buf[10];
> +
> +int
> +main (void)
> +{
> +  memset (buf, sizeof (buf), 0);
> +  return 0;
> +}
>
>        Jakub
>


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