On Fri, 4 Apr 2014, Jan Hubicka wrote:

> Hi,
> here is an updated version of my earlier ipa.c change.  It turns out that the
> problem was that I did not drop always_inline.
> In this version I just drop always_inline attribute on all functions whose 
> body
> is removed.  The patch will affect non-LTO compilation, too, but IMO only by
> making us to not inline&diagnose the cases where indirect call to always 
> inline
> is turned direct in between early opts and inline. Does that seem acceptable?
> (I personally would preffer this over inventing yet another way to special 
> case
> always_inline for LTO only; we never made any strong promises on always_inline
> and indirect calls)

I think it's fine if indirect calls to always-inline fns go to an
offline copy (or cause a link-time error if there is no offline copy).
I've always thought that taking the address of an always_inline fn
should get you the address of an "external" symbol (an inline "clone"
isn't addressable).

So the patch is fine with me.

Thanks,
Richard.

> Honza
> 
>       * lto-cgraph.c (input_overwrite_node): Check that partitioning
>       flags are set only during streaming.
>       * ipa.c (process_references, walk_polymorphic_call_targets,
>       symtab_remove_unreachable_nodes): Drop bodies of always inline
>       after early inlining.
>       (symtab_remove_unreachable_nodes): Remove always_inline attribute.
> 
>       * gcc.dg/lto/pr59626_0.c: New testcase.
>       * gcc.dg/lto/pr59626_1.c: New testcase.
> Index: lto-cgraph.c
> ===================================================================
> --- lto-cgraph.c      (revision 209062)
> +++ lto-cgraph.c      (working copy)
> @@ -1001,6 +1001,9 @@ input_overwrite_node (struct lto_file_de
>    node->thunk.thunk_p = bp_unpack_value (bp, 1);
>    node->resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution,
>                                    LDPR_NUM_KNOWN);
> +  gcc_assert (flag_ltrans
> +           || (!node->in_other_partition
> +               && !node->used_from_other_partition));
>  }
>  
>  /* Return string alias is alias of.  */
> @@ -1169,6 +1172,9 @@ input_varpool_node (struct lto_file_decl
>    node->same_comdat_group = (symtab_node *) (intptr_t) ref;
>    node->resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution,
>                                               LDPR_NUM_KNOWN);
> +  gcc_assert (flag_ltrans
> +           || (!node->in_other_partition
> +               && !node->used_from_other_partition));
>  
>    return node;
>  }
> Index: ipa.c
> ===================================================================
> --- ipa.c     (revision 209062)
> +++ ipa.c     (working copy)
> @@ -139,7 +139,10 @@ process_references (struct ipa_ref_list
>  
>        if (node->definition && !node->in_other_partition
>         && ((!DECL_EXTERNAL (node->decl) || node->alias)
> -           || (before_inlining_p
> +           || (((before_inlining_p
> +                 && (cgraph_state < CGRAPH_STATE_IPA_SSA
> +                     || !lookup_attribute ("always_inline",
> +                                           DECL_ATTRIBUTES (node->decl)))))
>                 /* We use variable constructors during late complation for
>                    constant folding.  Keep references alive so partitioning
>                    knows about potential references.  */
> @@ -191,7 +194,10 @@ walk_polymorphic_call_targets (pointer_s
>         /* Prior inlining, keep alive bodies of possible targets for
>            devirtualization.  */
>          if (n->definition
> -            && before_inlining_p)
> +            && (before_inlining_p
> +                && (cgraph_state < CGRAPH_STATE_IPA_SSA
> +                    || !lookup_attribute ("always_inline",
> +                                          DECL_ATTRIBUTES (n->decl)))))
>            pointer_set_insert (reachable, n);
>  
>         /* Even after inlining we want to keep the possible targets in the
> @@ -491,6 +497,12 @@ symtab_remove_unreachable_nodes (bool be
>             node->alias = false;
>             node->thunk.thunk_p = false;
>             node->weakref = false;
> +           /* After early inlining we drop always_inline attributes on
> +              bodies of functions that are still referenced (have their
> +              address taken).  */
> +           DECL_ATTRIBUTES (node->decl)
> +             = remove_attribute ("always_inline",
> +                                 DECL_ATTRIBUTES (node->decl));
>             if (!node->in_other_partition)
>               node->local.local = false;
>             cgraph_node_remove_callees (node);
> Index: testsuite/gcc.dg/lto/pr59626_1.c
> ===================================================================
> --- testsuite/gcc.dg/lto/pr59626_1.c  (revision 0)
> +++ testsuite/gcc.dg/lto/pr59626_1.c  (revision 0)
> @@ -0,0 +1,4 @@
> +int bar (int (*fn)(const char *))
> +{
> +  return fn ("0");
> +}
> Index: testsuite/gcc.dg/lto/pr59626_0.c
> ===================================================================
> --- testsuite/gcc.dg/lto/pr59626_0.c  (revision 0)
> +++ testsuite/gcc.dg/lto/pr59626_0.c  (revision 0)
> @@ -0,0 +1,15 @@
> +/* { dg-lto-do run } */
> +
> +int __atoi  (const char *) __asm__("atoi");
> +extern inline __attribute__((always_inline,gnu_inline))
> +int atoi (const char *x)
> +{
> +  return __atoi (x);
> +}
> +
> +int bar (int (*)(const char *));
> +
> +int main()
> +{
> +  return bar (atoi);
> +}
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imend"orffer

Reply via email to