diff mbox

Fix verify_type ICE during Ada bootstrap

Message ID 20151130065855.GA22602@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka Nov. 30, 2015, 6:58 a.m. UTC
Hi,
here is updated patch which bootstraps&regtestes, lto-bootstraps x86_64-linux and
also works for Firefox. The basic pain is to identify which calls to get_alias_set
are used to build alias sets themselves and thus must be made -fstrict-aliasing
independent and which are used to drive queries to oracle and thus should follow
-fstrict-aliasing.  Fortunately the sanity checking I added seems pretty effective
to check bugs in this area: either we get ice in tree-streamer-out.c because alias
set is 0 when it is not expected to be or we get an ice in record_component_aliases
because alias set of component gets 0.

OK?
Honza

	* tree.c (free_lang_data): Pass true to get_alias_set.
	* tree-streamer-in.c (unpack_ts_type_common_value_fields): Do not stream
	alias set.
	* tree-ssa-alias.c (ao_ref_base_alias_set, ao_ref_alias_set): Pass true
	to get_alias_set; comment.
	(same_type_for_tbaa): Likewise.
	* alias.c (alias_set_subset_of, alias_sets_conflict_p): When strict
	aliasing is disabled, return true.
	(get_alias_set): New parameter strict.
	(new_alias_set): Always produce new alias set.
	(record_component_aliases): Pass true to get_alias_set.
	* alias.h (get_alias_set): New optional parameter STRICT.
	* lto-streamer-out.c (hash_tree): Do not hash alias set.
	* ipa-inline-transform.c (inline_call): Drop strict aliasing of
	caller if needed.
	* ipa-icf-gimple.c (func_checker::compatible_types_p): Pass true
	to get_alias_set.
	* tree-streamer-out.c (pack_ts_type_common_value_fields): Do not
	stream TYPE_ALIAS_SET; sanity check that alias set 0 at LTO time will
	match what frontneds does.
	* fold-const.c (operand_equal_p): Be cureful about TBAA info before
	inlining even with -fno-strict-aliasing.
	* gimple.c (gimple_get_alias_set): Pass true to get_alias_set.

	* misc.c (gnat_get_alias_set): Pass true to get_alias_set.
	* utils.c (relate_alias_sets): Likewise.
	* trans.c (validate_unchecked_conversion): Likewise.

	* lto-symtab.c (warn_type_compatibility_p): Pass true to get_alias_set.
	* lto.c (compare_tree_sccs_1): Do not ocmpare TYPE_ALIAS_SET.

	* gcc.c-torture/execute/alias-1.c: New testcase.
	* gcc.dg/lto/alias-1_0.c: New testcase.
	* gcc.dg/lto/alias-1_1.c: New testcase.

	* c-common.c (parse_optimize_options): Remove hack about
	flag_strict_aliasing.
	(convert_vector_to_pointer_for_subscript): Pass true to get_alias_set.

	* cp-objcp-common.c (cxx_get_alias_set): Pass true to get_alias_set.
	
	* rtti.c (typeid_ok_p): Pass true to get_alias_set.

Comments

Eric Botcazou Nov. 30, 2015, 7:21 a.m. UTC | #1
> 	* misc.c (gnat_get_alias_set): Pass true to get_alias_set.
> 	* utils.c (relate_alias_sets): Likewise.
> 	* trans.c (validate_unchecked_conversion): Likewise.

Missing gcc-interface/ prefix here.

But can't we use a default value (of true I suppose) for the new parameter?
Jan Hubicka Nov. 30, 2015, 7:55 a.m. UTC | #2
> > 	* misc.c (gnat_get_alias_set): Pass true to get_alias_set.
> > 	* utils.c (relate_alias_sets): Likewise.
> > 	* trans.c (validate_unchecked_conversion): Likewise.
> 
> Missing gcc-interface/ prefix here.
Updated.
> 
> But can't we use a default value (of true I suppose) for the new parameter?

I originally went for default value of false with an assumption that most of
uses of get_alias_set are from the optimizers and in this context it is better
to keep the original beaviour (returning 0 for -fno-strict-aliasing)

The code used to build types I updated should be less actively developed.
Since I ended up modifying quite few calls I have no problem with flipping the
default or perhaps going for two entry points.

Honza
> 
> -- 
> Eric Botcazou
Richard Biener Nov. 30, 2015, 1:46 p.m. UTC | #3
On Mon, 30 Nov 2015, Jan Hubicka wrote:

> Hi,
> here is updated patch which bootstraps&regtestes, lto-bootstraps x86_64-linux and
> also works for Firefox. The basic pain is to identify which calls to get_alias_set
> are used to build alias sets themselves and thus must be made -fstrict-aliasing
> independent and which are used to drive queries to oracle and thus should follow
> -fstrict-aliasing.  Fortunately the sanity checking I added seems pretty effective
> to check bugs in this area: either we get ice in tree-streamer-out.c because alias
> set is 0 when it is not expected to be or we get an ice in record_component_aliases
> because alias set of component gets 0.
> 
> OK?

I think you are doing too many things in one patch.  I'm fine with
dropping the zero-alias-set streaming (but I'd rather not assert
as FE get_alias_set langhook may assign zero to random tree nodes).

I'm also fine with handling flag_strict_aliasing conservatively
during inlining - but the condition you placed on this handling
needs a comment.  I couldn't decipher it ;)

> +      if (dump_file)
> +     fprintf (dump_file, "Dropping flag_strict_aliasing on %s:%i\n",
> +              to->name (), to->order);

So I wonder if it makes sense to pessimize such inlining as well.

The two above should be enough to fix the correctness issue.

The parse_optimize_options hack looks indeed interesting, but we solved
the issue differently by

2014-11-27  Richard Biener  <rguenther@suse.de>

        PR middle-end/63704
        * alias.c (mems_in_disjoint_alias_sets_p): Remove assert
        and instead return false when !fstrict-aliasing.

So the hack can be removed as a separate commit after the first one
above.  This should make optimize("fno-strict-aliasing") work.


I don't really see why we need all the other changes and IMHO the
get_alias_set interface change is ugly and fragile.  And this doesn't
look like sth for stage3.

Thus please split the patch up.

Thanks,
Richard.

> Honza
> 
> 	* tree.c (free_lang_data): Pass true to get_alias_set.
> 	* tree-streamer-in.c (unpack_ts_type_common_value_fields): Do not stream
> 	alias set.
> 	* tree-ssa-alias.c (ao_ref_base_alias_set, ao_ref_alias_set): Pass true
> 	to get_alias_set; comment.
> 	(same_type_for_tbaa): Likewise.
> 	* alias.c (alias_set_subset_of, alias_sets_conflict_p): When strict
> 	aliasing is disabled, return true.
> 	(get_alias_set): New parameter strict.
> 	(new_alias_set): Always produce new alias set.
> 	(record_component_aliases): Pass true to get_alias_set.
> 	* alias.h (get_alias_set): New optional parameter STRICT.
> 	* lto-streamer-out.c (hash_tree): Do not hash alias set.
> 	* ipa-inline-transform.c (inline_call): Drop strict aliasing of
> 	caller if needed.
> 	* ipa-icf-gimple.c (func_checker::compatible_types_p): Pass true
> 	to get_alias_set.
> 	* tree-streamer-out.c (pack_ts_type_common_value_fields): Do not
> 	stream TYPE_ALIAS_SET; sanity check that alias set 0 at LTO time will
> 	match what frontneds does.
> 	* fold-const.c (operand_equal_p): Be cureful about TBAA info before
> 	inlining even with -fno-strict-aliasing.
> 	* gimple.c (gimple_get_alias_set): Pass true to get_alias_set.
> 
> 	* misc.c (gnat_get_alias_set): Pass true to get_alias_set.
> 	* utils.c (relate_alias_sets): Likewise.
> 	* trans.c (validate_unchecked_conversion): Likewise.
> 
> 	* lto-symtab.c (warn_type_compatibility_p): Pass true to get_alias_set.
> 	* lto.c (compare_tree_sccs_1): Do not ocmpare TYPE_ALIAS_SET.
> 
> 	* gcc.c-torture/execute/alias-1.c: New testcase.
> 	* gcc.dg/lto/alias-1_0.c: New testcase.
> 	* gcc.dg/lto/alias-1_1.c: New testcase.
> 
> 	* c-common.c (parse_optimize_options): Remove hack about
> 	flag_strict_aliasing.
> 	(convert_vector_to_pointer_for_subscript): Pass true to get_alias_set.
> 
> 	* cp-objcp-common.c (cxx_get_alias_set): Pass true to get_alias_set.
> 	
> 	* rtti.c (typeid_ok_p): Pass true to get_alias_set.
> Index: tree.c
> ===================================================================
> --- tree.c	(revision 231020)
> +++ tree.c	(working copy)
> @@ -5971,7 +5971,8 @@ free_lang_data (void)
>       while the slots are still in the way the frontends generated them.  */
>    for (i = 0; i < itk_none; ++i)
>      if (integer_types[i])
> -      TYPE_ALIAS_SET (integer_types[i]) = get_alias_set (integer_types[i]);
> +      TYPE_ALIAS_SET (integer_types[i]) = get_alias_set (integer_types[i],
> +							 true);
>  
>    /* Traverse the IL resetting language specific information for
>       operands, expressions, etc.  */
> Index: cp/rtti.c
> ===================================================================
> --- cp/rtti.c	(revision 231020)
> +++ cp/rtti.c	(working copy)
> @@ -300,10 +300,10 @@ typeid_ok_p (void)
>    /* Make sure abi::__type_info_pseudo has the same alias set
>       as std::type_info.  */
>    if (! TYPE_ALIAS_SET_KNOWN_P (pseudo_type_info))
> -    TYPE_ALIAS_SET (pseudo_type_info) = get_alias_set (type_info_type);
> +    TYPE_ALIAS_SET (pseudo_type_info) = get_alias_set (type_info_type, true);
>    else
>      gcc_assert (TYPE_ALIAS_SET (pseudo_type_info)
> -		== get_alias_set (type_info_type));
> +		== get_alias_set (type_info_type, true));
>  
>    return true;
>  }
> Index: cp/cp-objcp-common.c
> ===================================================================
> --- cp/cp-objcp-common.c	(revision 231020)
> +++ cp/cp-objcp-common.c	(working copy)
> @@ -32,7 +32,7 @@ cxx_get_alias_set (tree t)
>    if (IS_FAKE_BASE_TYPE (t))
>      /* The base variant of a type must be in the same alias set as the
>         complete type.  */
> -    return get_alias_set (TYPE_CONTEXT (t));
> +    return get_alias_set (TYPE_CONTEXT (t), true);
>  
>    /* Punt on PMFs until we canonicalize functions properly.  */
>    if (TYPE_PTRMEMFUNC_P (t)
> Index: tree-streamer-in.c
> ===================================================================
> --- tree-streamer-in.c	(revision 231020)
> +++ tree-streamer-in.c	(working copy)
> @@ -366,7 +366,6 @@ unpack_ts_type_common_value_fields (stru
>    TYPE_RESTRICT (expr) = (unsigned) bp_unpack_value (bp, 1);
>    TYPE_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1);
>    TYPE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1);
> -  TYPE_ALIAS_SET (expr) = bp_unpack_value (bp, 1) ? 0 : -1;
>    if (RECORD_OR_UNION_TYPE_P (expr))
>      {
>        TYPE_TRANSPARENT_AGGR (expr) = (unsigned) bp_unpack_value (bp, 1);
> Index: tree-ssa-alias.c
> ===================================================================
> --- tree-ssa-alias.c	(revision 231020)
> +++ tree-ssa-alias.c	(working copy)
> @@ -563,7 +563,10 @@ ao_ref_base_alias_set (ao_ref *ref)
>    base_ref = ref->ref;
>    while (handled_component_p (base_ref))
>      base_ref = TREE_OPERAND (base_ref, 0);
> -  ref->base_alias_set = get_alias_set (base_ref);
> +  /* Do not return 0 in case of strict aliasing; this function is used at
> +     IPA level by ipa-icf-gimple.c.  It is job of caller to give up on
> +     using TBAA oracle when asked to not do so.  */
> +  ref->base_alias_set = get_alias_set (base_ref, true);
>    return ref->base_alias_set;
>  }
>  
> @@ -574,7 +577,10 @@ ao_ref_alias_set (ao_ref *ref)
>  {
>    if (ref->ref_alias_set != -1)
>      return ref->ref_alias_set;
> -  ref->ref_alias_set = get_alias_set (ref->ref);
> +  /* Do not return 0 in case of strict aliasing; this function is used at
> +     IPA level by ipa-icf-gimple.c.  It is job of caller to give up on
> +     using TBAA oracle when asked to not do so.  */
> +  ref->ref_alias_set = get_alias_set (ref->ref, true);
>    return ref->ref_alias_set;
>  }
>  
> @@ -668,7 +674,7 @@ same_type_for_tbaa (tree type1, tree typ
>       would mean that conversions between them are useless, whereas they are
>       not (e.g. type and subtypes can have different modes).  So, in the end,
>       they are only guaranteed to have the same alias set.  */
> -  if (get_alias_set (type1) == get_alias_set (type2))
> +  if (get_alias_set (type1, true) == get_alias_set (type2, true))
>      return -1;
>  
>    /* The types are known to be not equal.  */
> Index: alias.c
> ===================================================================
> --- alias.c	(revision 231020)
> +++ alias.c	(working copy)
> @@ -406,7 +406,7 @@ alias_set_subset_of (alias_set_type set1
>    alias_set_entry *ase2;
>  
>    /* Everything is a subset of the "aliases everything" set.  */
> -  if (set2 == 0)
> +  if (set2 == 0 || !flag_strict_aliasing)
>      return true;
>  
>    /* Check if set1 is a subset of set2.  */
> @@ -467,7 +467,7 @@ alias_sets_conflict_p (alias_set_type se
>    alias_set_entry *ase2;
>  
>    /* The easy case.  */
> -  if (alias_sets_must_conflict_p (set1, set2))
> +  if (!flag_strict_aliasing || alias_sets_must_conflict_p (set1, set2))
>      return 1;
>  
>    /* See if the first alias set is a subset of the second.  */
> @@ -809,17 +809,21 @@ init_alias_set_entry (alias_set_type set
>  }
>  
>  /* Return the alias set for T, which may be either a type or an
> -   expression.  Call language-specific routine for help, if needed.  */
> +   expression.  Call language-specific routine for help, if needed.
> +   If STRICT is true, ignore value of flag_strict_aliasing.  This is needed
> +   in cases we are in -fno-strict-aliasing region but still need to compute
> +   alias sets for some reason (this is used, for example, by rtti code to copy
> +   alias set from type to type).  */
>  
>  alias_set_type
> -get_alias_set (tree t)
> +get_alias_set (tree t, bool strict)
>  {
>    alias_set_type set;
>  
>    /* If we're not doing any alias analysis, just assume everything
>       aliases everything else.  Also return 0 if this or its type is
>       an error.  */
> -  if (! flag_strict_aliasing || t == error_mark_node
> +  if ((! flag_strict_aliasing && !strict)|| t == error_mark_node
>        || (! TYPE_P (t)
>  	  && (TREE_TYPE (t) == 0 || TREE_TYPE (t) == error_mark_node)))
>      return 0;
> @@ -898,7 +902,7 @@ get_alias_set (tree t)
>        /* For arrays with unknown size the conservative answer is the
>  	 alias set of the element type.  */
>        if (TREE_CODE (t) == ARRAY_TYPE)
> -	return get_alias_set (TREE_TYPE (t));
> +	return get_alias_set (TREE_TYPE (t), true);
>  
>        /* But return zero as a conservative answer for incomplete types.  */
>        return 0;
> @@ -920,7 +924,7 @@ get_alias_set (tree t)
>       normal usage.  And indeed lets vectors be treated more like an
>       array slice.  */
>    else if (TREE_CODE (t) == VECTOR_TYPE)
> -    set = get_alias_set (TREE_TYPE (t));
> +    set = get_alias_set (TREE_TYPE (t), true);
>  
>    /* Unless the language specifies otherwise, treat array types the
>       same as their components.  This avoids the asymmetry we get
> @@ -933,7 +937,7 @@ get_alias_set (tree t)
>    else if (TREE_CODE (t) == ARRAY_TYPE
>  	   && (!TYPE_NONALIASED_COMPONENT (t)
>  	       || TYPE_STRUCTURAL_EQUALITY_P (t)))
> -    set = get_alias_set (TREE_TYPE (t));
> +    set = get_alias_set (TREE_TYPE (t), true);
>  
>    /* From the former common C and C++ langhook implementation:
>  
> @@ -997,7 +1001,7 @@ get_alias_set (tree t)
>  	 (see record_component_aliases) and thus it is safe it to use it for
>  	 pointers to types with TYPE_STRUCTURAL_EQUALITY_P.  */
>        if (TREE_CODE (p) == VOID_TYPE || TYPE_STRUCTURAL_EQUALITY_P (p))
> -	set = get_alias_set (ptr_type_node);
> +	set = get_alias_set (ptr_type_node, true);
>        else
>  	{
>  	  /* Rebuild pointer type starting from canonical types using
> @@ -1085,15 +1089,10 @@ get_alias_set (tree t)
>  alias_set_type
>  new_alias_set (void)
>  {
> -  if (flag_strict_aliasing)
> -    {
> -      if (alias_sets == 0)
> -	vec_safe_push (alias_sets, (alias_set_entry *) NULL);
> -      vec_safe_push (alias_sets, (alias_set_entry *) NULL);
> -      return alias_sets->length () - 1;
> -    }
> -  else
> -    return 0;
> +  if (alias_sets == 0)
> +    vec_safe_push (alias_sets, (alias_set_entry *) NULL);
> +  vec_safe_push (alias_sets, (alias_set_entry *) NULL);
> +  return alias_sets->length () - 1;
>  }
>  
>  /* Indicate that things in SUBSET can alias things in SUPERSET, but that
> @@ -1169,7 +1168,7 @@ record_alias_subset (alias_set_type supe
>  void
>  record_component_aliases (tree type)
>  {
> -  alias_set_type superset = get_alias_set (type);
> +  alias_set_type superset = get_alias_set (type, true);
>    tree field;
>  
>    if (superset == 0)
> @@ -1215,16 +1214,17 @@ record_component_aliases (tree type)
>  		if (POINTER_TYPE_P (t))
>  		  t = ptr_type_node;
>  		else if (flag_checking)
> -		  gcc_checking_assert (get_alias_set (t)
> -				       == get_alias_set (TREE_TYPE (field)));
> +		  gcc_checking_assert (get_alias_set (t, true)
> +				       == get_alias_set (TREE_TYPE (field),
> +							 true));
>  	      }
>  
> -	    record_alias_subset (superset, get_alias_set (t));
> +	    record_alias_subset (superset, get_alias_set (t, true));
>  	  }
>        break;
>  
>      case COMPLEX_TYPE:
> -      record_alias_subset (superset, get_alias_set (TREE_TYPE (type)));
> +      record_alias_subset (superset, get_alias_set (TREE_TYPE (type), true));
>        break;
>  
>      /* VECTOR_TYPE and ARRAY_TYPE share the alias set with their
> Index: alias.h
> ===================================================================
> --- alias.h	(revision 231020)
> +++ alias.h	(working copy)
> @@ -21,7 +21,7 @@ along with GCC; see the file COPYING3.
>  #define GCC_ALIAS_H
>  
>  extern alias_set_type new_alias_set (void);
> -extern alias_set_type get_alias_set (tree);
> +extern alias_set_type get_alias_set (tree, bool strict = false);
>  extern alias_set_type get_deref_alias_set (tree);
>  extern alias_set_type get_varargs_alias_set (void);
>  extern alias_set_type get_frame_alias_set (void);
> Index: lto/lto-symtab.c
> ===================================================================
> --- lto/lto-symtab.c	(revision 231020)
> +++ lto/lto-symtab.c	(working copy)
> @@ -276,8 +276,8 @@ warn_type_compatibility_p (tree prevaili
>       we make ptr_type_node to TBAA compatible with every other type.  */
>    if (type_with_alias_set_p (type) && type_with_alias_set_p (prevailing_type))
>      {
> -      alias_set_type set1 = get_alias_set (type);
> -      alias_set_type set2 = get_alias_set (prevailing_type);
> +      alias_set_type set1 = get_alias_set (type, true);
> +      alias_set_type set2 = get_alias_set (prevailing_type, true);
>  
>        if (set1 && set2 && set1 != set2 
>            && (!POINTER_TYPE_P (type) || !POINTER_TYPE_P (prevailing_type)
> Index: lto/lto.c
> ===================================================================
> --- lto/lto.c	(revision 231020)
> +++ lto/lto.c	(working copy)
> @@ -1166,7 +1166,9 @@ compare_tree_sccs_1 (tree t1, tree t2, t
>        compare_values (TYPE_READONLY);
>        compare_values (TYPE_PRECISION);
>        compare_values (TYPE_ALIGN);
> -      compare_values (TYPE_ALIAS_SET);
> +      /* Do not compare TYPE_ALIAS_SET.  Doing so introduce ordering issues
> +         with calls to get_alias_set which may initialize it for streamed
> + 	 in types.  */
>      }
>  
>    /* We don't want to compare locations, so there is nothing do compare
> Index: testsuite/gcc.c-torture/execute/alias-1.c
> ===================================================================
> --- testsuite/gcc.c-torture/execute/alias-1.c	(revision 0)
> +++ testsuite/gcc.c-torture/execute/alias-1.c	(revision 0)
> @@ -0,0 +1,19 @@
> +int val;
> +
> +int *ptr = &val;
> +float *ptr2 = &val;
> +
> +__attribute__((optimize ("-fno-strict-aliasing")))
> +typepun ()
> +{
> +  *ptr2=0;
> +}
> +
> +main()
> +{
> +  *ptr=1;
> +  typepun ();
> +  if (*ptr)
> +    __builtin_abort ();
> +}
> +
> Index: testsuite/gcc.dg/lto/alias-1_0.c
> ===================================================================
> --- testsuite/gcc.dg/lto/alias-1_0.c	(revision 0)
> +++ testsuite/gcc.dg/lto/alias-1_0.c	(revision 0)
> @@ -0,0 +1,22 @@
> +/* { dg-lto-do run } */
> +/* { dg-lto-options { { -O2 -flto } } } */
> +int val;
> +
> +int *ptr = &val;
> +float *ptr2 = &val;
> +
> +extern void typefun(void);
> +
> +void link_error (void);
> +
> +int
> +main()
> +{ 
> +  *ptr=1;
> +  typefun ();
> +  if (*ptr)
> +    /*link_error ();*/
> +    __builtin_abort ();
> +  return 0;
> +}
> +
> Index: testsuite/gcc.dg/lto/alias-1_1.c
> ===================================================================
> --- testsuite/gcc.dg/lto/alias-1_1.c	(revision 0)
> +++ testsuite/gcc.dg/lto/alias-1_1.c	(revision 0)
> @@ -0,0 +1,8 @@
> +/* { dg-options "-fno-strict-aliasing" } */
> +extern float *ptr2;
> +void
> +__attribute__((optimize ("-fno-strict-aliasing")))
> +typefun ()
> +{ 
> +  *ptr2=0;
> +}
> Index: c-family/c-common.c
> ===================================================================
> --- c-family/c-common.c	(revision 231048)
> +++ c-family/c-common.c	(working copy)
> @@ -9988,7 +9988,6 @@ parse_optimize_options (tree args, bool
>    bool ret = true;
>    unsigned opt_argc;
>    unsigned i;
> -  int saved_flag_strict_aliasing;
>    const char **opt_argv;
>    struct cl_decoded_option *decoded_options;
>    unsigned int decoded_options_count;
> @@ -10081,8 +10080,6 @@ parse_optimize_options (tree args, bool
>    for (i = 1; i < opt_argc; i++)
>      opt_argv[i] = (*optimize_args)[i];
>  
> -  saved_flag_strict_aliasing = flag_strict_aliasing;
> -
>    /* Now parse the options.  */
>    decode_cmdline_options_to_array_default_mask (opt_argc, opt_argv,
>  						&decoded_options,
> @@ -10093,9 +10090,6 @@ parse_optimize_options (tree args, bool
>  
>    targetm.override_options_after_change();
>  
> -  /* Don't allow changing -fstrict-aliasing.  */
> -  flag_strict_aliasing = saved_flag_strict_aliasing;
> -
>    optimize_args->truncate (0);
>    return ret;
>  }
> @@ -12930,8 +12924,8 @@ convert_vector_to_pointer_for_subscript
>  	  /* If the original vector isn't declared may_alias and it
>  	     isn't a bare vector look if the subscripting would
>  	     alias the vector we subscript, and if not, force ref-all.  */
> -	  alias_set_type vecset = get_alias_set (*vecp);
> -	  alias_set_type sset = get_alias_set (type);
> +	  alias_set_type vecset = get_alias_set (*vecp, true);
> +	  alias_set_type sset = get_alias_set (type, true);
>  	  if (!alias_sets_must_conflict_p (sset, vecset)
>  	      && !alias_set_subset_of (sset, vecset))
>  	    ref_all = true;
> Index: lto-streamer-out.c
> ===================================================================
> --- lto-streamer-out.c	(revision 231020)
> +++ lto-streamer-out.c	(working copy)
> @@ -1109,10 +1109,6 @@ hash_tree (struct streamer_tree_cache_d
>        hstate.commit_flag ();
>        hstate.add_int (TYPE_PRECISION (t));
>        hstate.add_int (TYPE_ALIGN (t));
> -      hstate.add_int ((TYPE_ALIAS_SET (t) == 0
> -					 || (!in_lto_p
> -					     && get_alias_set (t) == 0))
> -					? 0 : -1);
>      }
>  
>    if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
> Index: ipa-inline-transform.c
> ===================================================================
> --- ipa-inline-transform.c	(revision 231020)
> +++ ipa-inline-transform.c	(working copy)
> @@ -322,6 +322,23 @@ inline_call (struct cgraph_edge *e, bool
>    if (DECL_FUNCTION_PERSONALITY (callee->decl))
>      DECL_FUNCTION_PERSONALITY (to->decl)
>        = DECL_FUNCTION_PERSONALITY (callee->decl);
> +  if (!opt_for_fn (callee->decl, flag_strict_aliasing)
> +      && opt_for_fn (to->decl, flag_strict_aliasing)
> +      && (!callee->merged
> +	  || lookup_attribute ("optimization", DECL_ATTRIBUTES (e->caller->decl))
> +	  || lookup_attribute ("optimization", DECL_ATTRIBUTES (callee->decl))))
> +    {
> +      struct gcc_options opts = global_options;
> +      cl_optimization_restore (&opts,
> +	 TREE_OPTIMIZATION (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (to->decl)));
> +      opts.x_flag_strict_aliasing = false;
> +      if (dump_file)
> +	fprintf (dump_file, "Dropping flag_strict_aliasing on %s:%i\n",
> +		 to->name (), to->order);
> +      build_optimization_node (&opts);
> +      DECL_FUNCTION_SPECIFIC_OPTIMIZATION (to->decl)
> +	 = build_optimization_node (&opts);
> +    }
>  
>    /* If aliases are involved, redirect edge to the actual destination and
>       possibly remove the aliases.  */
> Index: ipa-icf-gimple.c
> ===================================================================
> --- ipa-icf-gimple.c	(revision 231020)
> +++ ipa-icf-gimple.c	(working copy)
> @@ -241,7 +241,7 @@ func_checker::compatible_types_p (tree t
>       For time being just avoid calling get_alias_set on types that are not
>       having alias sets defined at all.  */
>    if (type_with_alias_set_p (t1) && type_with_alias_set_p (t2)
> -      && get_alias_set (t1) != get_alias_set (t2))
> +      && get_alias_set (t1, true) != get_alias_set (t2, true))
>      return return_false_with_msg ("alias sets are different");
>  
>    return true;
> Index: tree-streamer-out.c
> ===================================================================
> --- tree-streamer-out.c	(revision 231020)
> +++ tree-streamer-out.c	(working copy)
> @@ -317,13 +321,18 @@ pack_ts_type_common_value_fields (struct
>    bp_pack_value (bp, TYPE_RESTRICT (expr), 1);
>    bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1);
>    bp_pack_value (bp, TYPE_READONLY (expr), 1);
> -  /* Make sure to preserve the fact whether the frontend would assign
> -     alias-set zero to this type.  Do that only for main variants, because
> -     type variants alias sets are never computed.
> -     FIXME:  This does not work for pre-streamed builtin types.  */
> -  bp_pack_value (bp, (TYPE_ALIAS_SET (expr) == 0
> -		      || (!in_lto_p && TYPE_MAIN_VARIANT (expr) == expr
> -			  && get_alias_set (expr) == 0)), 1);
> +  /* We used to stream TYPE_ALIAS_SET == 0 information to let frontends mark
> +     types that are opaque for TBAA.  This however did not work as intended,
> +     becuase TYPE_ALIAS_SET == 0 was regularly lost in type merging.
> +
> +     Instead now double check that all aliaset set 0 types will be alias set
> +     0 in LTO world, too.  */
> +  gcc_checking_assert (!type_with_alias_set_p (expr)
> +		       || !canonical_type_used_p (expr)
> +		       || TYPE_ALIAS_SET (expr) != 0
> +		       || expr == char_type_node
> +		       || expr == signed_char_type_node
> +		       || expr == unsigned_char_type_node);
>    if (RECORD_OR_UNION_TYPE_P (expr))
>      {
>        bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1);
> Index: fold-const.c
> ===================================================================
> --- fold-const.c	(revision 231020)
> +++ fold-const.c	(working copy)
> @@ -2987,7 +2987,7 @@ operand_equal_p (const_tree arg0, const_
>  					   flags)))
>  		return 0;
>  	      /* Verify that accesses are TBAA compatible.  */
> -	      if (flag_strict_aliasing
> +	      if ((flag_strict_aliasing || !cfun->after_inlining)
>  		  && (!alias_ptr_types_compatible_p
>  		        (TREE_TYPE (TREE_OPERAND (arg0, 1)),
>  		         TREE_TYPE (TREE_OPERAND (arg1, 1)))
> Index: ada/gcc-interface/misc.c
> ===================================================================
> --- ada/gcc-interface/misc.c	(revision 231020)
> +++ ada/gcc-interface/misc.c	(working copy)
> @@ -592,13 +592,14 @@ gnat_get_alias_set (tree type)
>  {
>    /* If this is a padding type, use the type of the first field.  */
>    if (TYPE_IS_PADDING_P (type))
> -    return get_alias_set (TREE_TYPE (TYPE_FIELDS (type)));
> +    return get_alias_set (TREE_TYPE (TYPE_FIELDS (type)), true);
>  
>    /* If the type is an unconstrained array, use the type of the
>       self-referential array we make.  */
>    else if (TREE_CODE (type) == UNCONSTRAINED_ARRAY_TYPE)
>      return
> -      get_alias_set (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (type)))));
> +      get_alias_set (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (type)))),
> +		     true);
>  
>    /* If the type can alias any other types, return the alias set 0.  */
>    else if (TYPE_P (type) && TYPE_UNIVERSAL_ALIASING_P (type))
> Index: ada/gcc-interface/utils.c
> ===================================================================
> --- ada/gcc-interface/utils.c	(revision 231020)
> +++ ada/gcc-interface/utils.c	(working copy)
> @@ -1520,14 +1520,14 @@ relate_alias_sets (tree gnu_new_type, tr
>  		      && TYPE_NONALIASED_COMPONENT (gnu_new_type)
>  			 != TYPE_NONALIASED_COMPONENT (gnu_old_type)));
>  
> -      TYPE_ALIAS_SET (gnu_new_type) = get_alias_set (gnu_old_type);
> +      TYPE_ALIAS_SET (gnu_new_type) = get_alias_set (gnu_old_type, true);
>        break;
>  
>      case ALIAS_SET_SUBSET:
>      case ALIAS_SET_SUPERSET:
>        {
> -	alias_set_type old_set = get_alias_set (gnu_old_type);
> -	alias_set_type new_set = get_alias_set (gnu_new_type);
> +	alias_set_type old_set = get_alias_set (gnu_old_type, true);
> +	alias_set_type new_set = get_alias_set (gnu_new_type, true);
>  
>  	/* Do nothing if the alias sets conflict.  This ensures that we
>  	   never call record_alias_subset several times for the same pair
> Index: ada/gcc-interface/trans.c
> ===================================================================
> --- ada/gcc-interface/trans.c	(revision 231020)
> +++ ada/gcc-interface/trans.c	(working copy)
> @@ -9702,11 +9702,13 @@ validate_unchecked_conversion (Node_Id g
>  				   ? TREE_TYPE (gnu_source_type)
>  				   : NULL_TREE;
>        tree gnu_target_desig_type = TREE_TYPE (gnu_target_type);
> -      alias_set_type target_alias_set = get_alias_set (gnu_target_desig_type);
> +      alias_set_type target_alias_set = get_alias_set (gnu_target_desig_type,
> +						       true);
>  
>        if (target_alias_set != 0
>  	  && (!POINTER_TYPE_P (gnu_source_type)
> -	      || !alias_sets_conflict_p (get_alias_set (gnu_source_desig_type),
> +	      || !alias_sets_conflict_p (get_alias_set (gnu_source_desig_type,
> +							true),
>  					 target_alias_set)))
>  	{
>  	  post_error_ne ("?possible aliasing problem for type&",
> @@ -9728,11 +9730,13 @@ validate_unchecked_conversion (Node_Id g
>  	  : NULL_TREE;
>        tree gnu_target_desig_type
>  	= TREE_TYPE (TREE_TYPE (TYPE_FIELDS (gnu_target_type)));
> -      alias_set_type target_alias_set = get_alias_set (gnu_target_desig_type);
> +      alias_set_type target_alias_set = get_alias_set (gnu_target_desig_type,
> +						       true);
>  
>        if (target_alias_set != 0
>  	  && (!TYPE_IS_FAT_POINTER_P (gnu_source_type)
> -	      || !alias_sets_conflict_p (get_alias_set (gnu_source_desig_type),
> +	      || !alias_sets_conflict_p (get_alias_set (gnu_source_desig_type,
> +							true),
>  					 target_alias_set)))
>  	{
>  	  post_error_ne ("?possible aliasing problem for type&",
> Index: gimple.c
> ===================================================================
> --- gimple.c	(revision 231020)
> +++ gimple.c	(working copy)
> @@ -2408,7 +2408,7 @@ gimple_get_alias_set (tree t)
>  
>        /* t1 == t can happen for boolean nodes which are always unsigned.  */
>        if (t1 != t)
> -	return get_alias_set (t1);
> +	return get_alias_set (t1, true);
>      }
>  
>    return -1;
> 
>
Jan Hubicka Nov. 30, 2015, 5:09 p.m. UTC | #4
> 
> I think you are doing too many things in one patch.  I'm fine with
> dropping the zero-alias-set streaming (but I'd rather not assert
> as FE get_alias_set langhook may assign zero to random tree nodes).

Ok, the assert was there mostly to double check that all zero alias
sets rematerialize correctly in LTO which I tested so it can go.
> 
> I'm also fine with handling flag_strict_aliasing conservatively
> during inlining - but the condition you placed on this handling
> needs a comment.  I couldn't decipher it ;)

OK, there is symmetric condition in ipa-inline-analysis, will comment on it.
It indeed can go in separately.
> 
> > +      if (dump_file)
> > +     fprintf (dump_file, "Dropping flag_strict_aliasing on %s:%i\n",
> > +              to->name (), to->order);
> 
> So I wonder if it makes sense to pessimize such inlining as well.

I don't know - even for Firefox that heavily mix -fstrict-aliasing
and -fno-strict-aliasing units this seems quite rare occasion and it
is hard to judge when dopping the flag_strict_aliasing.
> 
> The two above should be enough to fix the correctness issue.

We also need to prevent ipa-icf and fold_const from optimizing functions
early in a way that is not compatible with inlining -fno-strict-aliasing comdat
to -fstrict-aliasing function.

Honza
> 
> The parse_optimize_options hack looks indeed interesting, but we solved
> the issue differently by
> 
> 2014-11-27  Richard Biener  <rguenther@suse.de>
> 
>         PR middle-end/63704
>         * alias.c (mems_in_disjoint_alias_sets_p): Remove assert
>         and instead return false when !fstrict-aliasing.
> 
> So the hack can be removed as a separate commit after the first one
> above.  This should make optimize("fno-strict-aliasing") work.
> 
> 
> I don't really see why we need all the other changes and IMHO the
> get_alias_set interface change is ugly and fragile.  And this doesn't
> look like sth for stage3.
> 
> Thus please split the patch up.
> 
> Thanks,
> Richard.
> 
> > Honza
> > 
> > 	* tree.c (free_lang_data): Pass true to get_alias_set.
> > 	* tree-streamer-in.c (unpack_ts_type_common_value_fields): Do not stream
> > 	alias set.
> > 	* tree-ssa-alias.c (ao_ref_base_alias_set, ao_ref_alias_set): Pass true
> > 	to get_alias_set; comment.
> > 	(same_type_for_tbaa): Likewise.
> > 	* alias.c (alias_set_subset_of, alias_sets_conflict_p): When strict
> > 	aliasing is disabled, return true.
> > 	(get_alias_set): New parameter strict.
> > 	(new_alias_set): Always produce new alias set.
> > 	(record_component_aliases): Pass true to get_alias_set.
> > 	* alias.h (get_alias_set): New optional parameter STRICT.
> > 	* lto-streamer-out.c (hash_tree): Do not hash alias set.
> > 	* ipa-inline-transform.c (inline_call): Drop strict aliasing of
> > 	caller if needed.
> > 	* ipa-icf-gimple.c (func_checker::compatible_types_p): Pass true
> > 	to get_alias_set.
> > 	* tree-streamer-out.c (pack_ts_type_common_value_fields): Do not
> > 	stream TYPE_ALIAS_SET; sanity check that alias set 0 at LTO time will
> > 	match what frontneds does.
> > 	* fold-const.c (operand_equal_p): Be cureful about TBAA info before
> > 	inlining even with -fno-strict-aliasing.
> > 	* gimple.c (gimple_get_alias_set): Pass true to get_alias_set.
> > 
> > 	* misc.c (gnat_get_alias_set): Pass true to get_alias_set.
> > 	* utils.c (relate_alias_sets): Likewise.
> > 	* trans.c (validate_unchecked_conversion): Likewise.
> > 
> > 	* lto-symtab.c (warn_type_compatibility_p): Pass true to get_alias_set.
> > 	* lto.c (compare_tree_sccs_1): Do not ocmpare TYPE_ALIAS_SET.
> > 
> > 	* gcc.c-torture/execute/alias-1.c: New testcase.
> > 	* gcc.dg/lto/alias-1_0.c: New testcase.
> > 	* gcc.dg/lto/alias-1_1.c: New testcase.
> > 
> > 	* c-common.c (parse_optimize_options): Remove hack about
> > 	flag_strict_aliasing.
> > 	(convert_vector_to_pointer_for_subscript): Pass true to get_alias_set.
> > 
> > 	* cp-objcp-common.c (cxx_get_alias_set): Pass true to get_alias_set.
> > 	
> > 	* rtti.c (typeid_ok_p): Pass true to get_alias_set.
> > Index: tree.c
> > ===================================================================
> > --- tree.c	(revision 231020)
> > +++ tree.c	(working copy)
> > @@ -5971,7 +5971,8 @@ free_lang_data (void)
> >       while the slots are still in the way the frontends generated them.  */
> >    for (i = 0; i < itk_none; ++i)
> >      if (integer_types[i])
> > -      TYPE_ALIAS_SET (integer_types[i]) = get_alias_set (integer_types[i]);
> > +      TYPE_ALIAS_SET (integer_types[i]) = get_alias_set (integer_types[i],
> > +							 true);
> >  
> >    /* Traverse the IL resetting language specific information for
> >       operands, expressions, etc.  */
> > Index: cp/rtti.c
> > ===================================================================
> > --- cp/rtti.c	(revision 231020)
> > +++ cp/rtti.c	(working copy)
> > @@ -300,10 +300,10 @@ typeid_ok_p (void)
> >    /* Make sure abi::__type_info_pseudo has the same alias set
> >       as std::type_info.  */
> >    if (! TYPE_ALIAS_SET_KNOWN_P (pseudo_type_info))
> > -    TYPE_ALIAS_SET (pseudo_type_info) = get_alias_set (type_info_type);
> > +    TYPE_ALIAS_SET (pseudo_type_info) = get_alias_set (type_info_type, true);
> >    else
> >      gcc_assert (TYPE_ALIAS_SET (pseudo_type_info)
> > -		== get_alias_set (type_info_type));
> > +		== get_alias_set (type_info_type, true));
> >  
> >    return true;
> >  }
> > Index: cp/cp-objcp-common.c
> > ===================================================================
> > --- cp/cp-objcp-common.c	(revision 231020)
> > +++ cp/cp-objcp-common.c	(working copy)
> > @@ -32,7 +32,7 @@ cxx_get_alias_set (tree t)
> >    if (IS_FAKE_BASE_TYPE (t))
> >      /* The base variant of a type must be in the same alias set as the
> >         complete type.  */
> > -    return get_alias_set (TYPE_CONTEXT (t));
> > +    return get_alias_set (TYPE_CONTEXT (t), true);
> >  
> >    /* Punt on PMFs until we canonicalize functions properly.  */
> >    if (TYPE_PTRMEMFUNC_P (t)
> > Index: tree-streamer-in.c
> > ===================================================================
> > --- tree-streamer-in.c	(revision 231020)
> > +++ tree-streamer-in.c	(working copy)
> > @@ -366,7 +366,6 @@ unpack_ts_type_common_value_fields (stru
> >    TYPE_RESTRICT (expr) = (unsigned) bp_unpack_value (bp, 1);
> >    TYPE_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1);
> >    TYPE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1);
> > -  TYPE_ALIAS_SET (expr) = bp_unpack_value (bp, 1) ? 0 : -1;
> >    if (RECORD_OR_UNION_TYPE_P (expr))
> >      {
> >        TYPE_TRANSPARENT_AGGR (expr) = (unsigned) bp_unpack_value (bp, 1);
> > Index: tree-ssa-alias.c
> > ===================================================================
> > --- tree-ssa-alias.c	(revision 231020)
> > +++ tree-ssa-alias.c	(working copy)
> > @@ -563,7 +563,10 @@ ao_ref_base_alias_set (ao_ref *ref)
> >    base_ref = ref->ref;
> >    while (handled_component_p (base_ref))
> >      base_ref = TREE_OPERAND (base_ref, 0);
> > -  ref->base_alias_set = get_alias_set (base_ref);
> > +  /* Do not return 0 in case of strict aliasing; this function is used at
> > +     IPA level by ipa-icf-gimple.c.  It is job of caller to give up on
> > +     using TBAA oracle when asked to not do so.  */
> > +  ref->base_alias_set = get_alias_set (base_ref, true);
> >    return ref->base_alias_set;
> >  }
> >  
> > @@ -574,7 +577,10 @@ ao_ref_alias_set (ao_ref *ref)
> >  {
> >    if (ref->ref_alias_set != -1)
> >      return ref->ref_alias_set;
> > -  ref->ref_alias_set = get_alias_set (ref->ref);
> > +  /* Do not return 0 in case of strict aliasing; this function is used at
> > +     IPA level by ipa-icf-gimple.c.  It is job of caller to give up on
> > +     using TBAA oracle when asked to not do so.  */
> > +  ref->ref_alias_set = get_alias_set (ref->ref, true);
> >    return ref->ref_alias_set;
> >  }
> >  
> > @@ -668,7 +674,7 @@ same_type_for_tbaa (tree type1, tree typ
> >       would mean that conversions between them are useless, whereas they are
> >       not (e.g. type and subtypes can have different modes).  So, in the end,
> >       they are only guaranteed to have the same alias set.  */
> > -  if (get_alias_set (type1) == get_alias_set (type2))
> > +  if (get_alias_set (type1, true) == get_alias_set (type2, true))
> >      return -1;
> >  
> >    /* The types are known to be not equal.  */
> > Index: alias.c
> > ===================================================================
> > --- alias.c	(revision 231020)
> > +++ alias.c	(working copy)
> > @@ -406,7 +406,7 @@ alias_set_subset_of (alias_set_type set1
> >    alias_set_entry *ase2;
> >  
> >    /* Everything is a subset of the "aliases everything" set.  */
> > -  if (set2 == 0)
> > +  if (set2 == 0 || !flag_strict_aliasing)
> >      return true;
> >  
> >    /* Check if set1 is a subset of set2.  */
> > @@ -467,7 +467,7 @@ alias_sets_conflict_p (alias_set_type se
> >    alias_set_entry *ase2;
> >  
> >    /* The easy case.  */
> > -  if (alias_sets_must_conflict_p (set1, set2))
> > +  if (!flag_strict_aliasing || alias_sets_must_conflict_p (set1, set2))
> >      return 1;
> >  
> >    /* See if the first alias set is a subset of the second.  */
> > @@ -809,17 +809,21 @@ init_alias_set_entry (alias_set_type set
> >  }
> >  
> >  /* Return the alias set for T, which may be either a type or an
> > -   expression.  Call language-specific routine for help, if needed.  */
> > +   expression.  Call language-specific routine for help, if needed.
> > +   If STRICT is true, ignore value of flag_strict_aliasing.  This is needed
> > +   in cases we are in -fno-strict-aliasing region but still need to compute
> > +   alias sets for some reason (this is used, for example, by rtti code to copy
> > +   alias set from type to type).  */
> >  
> >  alias_set_type
> > -get_alias_set (tree t)
> > +get_alias_set (tree t, bool strict)
> >  {
> >    alias_set_type set;
> >  
> >    /* If we're not doing any alias analysis, just assume everything
> >       aliases everything else.  Also return 0 if this or its type is
> >       an error.  */
> > -  if (! flag_strict_aliasing || t == error_mark_node
> > +  if ((! flag_strict_aliasing && !strict)|| t == error_mark_node
> >        || (! TYPE_P (t)
> >  	  && (TREE_TYPE (t) == 0 || TREE_TYPE (t) == error_mark_node)))
> >      return 0;
> > @@ -898,7 +902,7 @@ get_alias_set (tree t)
> >        /* For arrays with unknown size the conservative answer is the
> >  	 alias set of the element type.  */
> >        if (TREE_CODE (t) == ARRAY_TYPE)
> > -	return get_alias_set (TREE_TYPE (t));
> > +	return get_alias_set (TREE_TYPE (t), true);
> >  
> >        /* But return zero as a conservative answer for incomplete types.  */
> >        return 0;
> > @@ -920,7 +924,7 @@ get_alias_set (tree t)
> >       normal usage.  And indeed lets vectors be treated more like an
> >       array slice.  */
> >    else if (TREE_CODE (t) == VECTOR_TYPE)
> > -    set = get_alias_set (TREE_TYPE (t));
> > +    set = get_alias_set (TREE_TYPE (t), true);
> >  
> >    /* Unless the language specifies otherwise, treat array types the
> >       same as their components.  This avoids the asymmetry we get
> > @@ -933,7 +937,7 @@ get_alias_set (tree t)
> >    else if (TREE_CODE (t) == ARRAY_TYPE
> >  	   && (!TYPE_NONALIASED_COMPONENT (t)
> >  	       || TYPE_STRUCTURAL_EQUALITY_P (t)))
> > -    set = get_alias_set (TREE_TYPE (t));
> > +    set = get_alias_set (TREE_TYPE (t), true);
> >  
> >    /* From the former common C and C++ langhook implementation:
> >  
> > @@ -997,7 +1001,7 @@ get_alias_set (tree t)
> >  	 (see record_component_aliases) and thus it is safe it to use it for
> >  	 pointers to types with TYPE_STRUCTURAL_EQUALITY_P.  */
> >        if (TREE_CODE (p) == VOID_TYPE || TYPE_STRUCTURAL_EQUALITY_P (p))
> > -	set = get_alias_set (ptr_type_node);
> > +	set = get_alias_set (ptr_type_node, true);
> >        else
> >  	{
> >  	  /* Rebuild pointer type starting from canonical types using
> > @@ -1085,15 +1089,10 @@ get_alias_set (tree t)
> >  alias_set_type
> >  new_alias_set (void)
> >  {
> > -  if (flag_strict_aliasing)
> > -    {
> > -      if (alias_sets == 0)
> > -	vec_safe_push (alias_sets, (alias_set_entry *) NULL);
> > -      vec_safe_push (alias_sets, (alias_set_entry *) NULL);
> > -      return alias_sets->length () - 1;
> > -    }
> > -  else
> > -    return 0;
> > +  if (alias_sets == 0)
> > +    vec_safe_push (alias_sets, (alias_set_entry *) NULL);
> > +  vec_safe_push (alias_sets, (alias_set_entry *) NULL);
> > +  return alias_sets->length () - 1;
> >  }
> >  
> >  /* Indicate that things in SUBSET can alias things in SUPERSET, but that
> > @@ -1169,7 +1168,7 @@ record_alias_subset (alias_set_type supe
> >  void
> >  record_component_aliases (tree type)
> >  {
> > -  alias_set_type superset = get_alias_set (type);
> > +  alias_set_type superset = get_alias_set (type, true);
> >    tree field;
> >  
> >    if (superset == 0)
> > @@ -1215,16 +1214,17 @@ record_component_aliases (tree type)
> >  		if (POINTER_TYPE_P (t))
> >  		  t = ptr_type_node;
> >  		else if (flag_checking)
> > -		  gcc_checking_assert (get_alias_set (t)
> > -				       == get_alias_set (TREE_TYPE (field)));
> > +		  gcc_checking_assert (get_alias_set (t, true)
> > +				       == get_alias_set (TREE_TYPE (field),
> > +							 true));
> >  	      }
> >  
> > -	    record_alias_subset (superset, get_alias_set (t));
> > +	    record_alias_subset (superset, get_alias_set (t, true));
> >  	  }
> >        break;
> >  
> >      case COMPLEX_TYPE:
> > -      record_alias_subset (superset, get_alias_set (TREE_TYPE (type)));
> > +      record_alias_subset (superset, get_alias_set (TREE_TYPE (type), true));
> >        break;
> >  
> >      /* VECTOR_TYPE and ARRAY_TYPE share the alias set with their
> > Index: alias.h
> > ===================================================================
> > --- alias.h	(revision 231020)
> > +++ alias.h	(working copy)
> > @@ -21,7 +21,7 @@ along with GCC; see the file COPYING3.
> >  #define GCC_ALIAS_H
> >  
> >  extern alias_set_type new_alias_set (void);
> > -extern alias_set_type get_alias_set (tree);
> > +extern alias_set_type get_alias_set (tree, bool strict = false);
> >  extern alias_set_type get_deref_alias_set (tree);
> >  extern alias_set_type get_varargs_alias_set (void);
> >  extern alias_set_type get_frame_alias_set (void);
> > Index: lto/lto-symtab.c
> > ===================================================================
> > --- lto/lto-symtab.c	(revision 231020)
> > +++ lto/lto-symtab.c	(working copy)
> > @@ -276,8 +276,8 @@ warn_type_compatibility_p (tree prevaili
> >       we make ptr_type_node to TBAA compatible with every other type.  */
> >    if (type_with_alias_set_p (type) && type_with_alias_set_p (prevailing_type))
> >      {
> > -      alias_set_type set1 = get_alias_set (type);
> > -      alias_set_type set2 = get_alias_set (prevailing_type);
> > +      alias_set_type set1 = get_alias_set (type, true);
> > +      alias_set_type set2 = get_alias_set (prevailing_type, true);
> >  
> >        if (set1 && set2 && set1 != set2 
> >            && (!POINTER_TYPE_P (type) || !POINTER_TYPE_P (prevailing_type)
> > Index: lto/lto.c
> > ===================================================================
> > --- lto/lto.c	(revision 231020)
> > +++ lto/lto.c	(working copy)
> > @@ -1166,7 +1166,9 @@ compare_tree_sccs_1 (tree t1, tree t2, t
> >        compare_values (TYPE_READONLY);
> >        compare_values (TYPE_PRECISION);
> >        compare_values (TYPE_ALIGN);
> > -      compare_values (TYPE_ALIAS_SET);
> > +      /* Do not compare TYPE_ALIAS_SET.  Doing so introduce ordering issues
> > +         with calls to get_alias_set which may initialize it for streamed
> > + 	 in types.  */
> >      }
> >  
> >    /* We don't want to compare locations, so there is nothing do compare
> > Index: testsuite/gcc.c-torture/execute/alias-1.c
> > ===================================================================
> > --- testsuite/gcc.c-torture/execute/alias-1.c	(revision 0)
> > +++ testsuite/gcc.c-torture/execute/alias-1.c	(revision 0)
> > @@ -0,0 +1,19 @@
> > +int val;
> > +
> > +int *ptr = &val;
> > +float *ptr2 = &val;
> > +
> > +__attribute__((optimize ("-fno-strict-aliasing")))
> > +typepun ()
> > +{
> > +  *ptr2=0;
> > +}
> > +
> > +main()
> > +{
> > +  *ptr=1;
> > +  typepun ();
> > +  if (*ptr)
> > +    __builtin_abort ();
> > +}
> > +
> > Index: testsuite/gcc.dg/lto/alias-1_0.c
> > ===================================================================
> > --- testsuite/gcc.dg/lto/alias-1_0.c	(revision 0)
> > +++ testsuite/gcc.dg/lto/alias-1_0.c	(revision 0)
> > @@ -0,0 +1,22 @@
> > +/* { dg-lto-do run } */
> > +/* { dg-lto-options { { -O2 -flto } } } */
> > +int val;
> > +
> > +int *ptr = &val;
> > +float *ptr2 = &val;
> > +
> > +extern void typefun(void);
> > +
> > +void link_error (void);
> > +
> > +int
> > +main()
> > +{ 
> > +  *ptr=1;
> > +  typefun ();
> > +  if (*ptr)
> > +    /*link_error ();*/
> > +    __builtin_abort ();
> > +  return 0;
> > +}
> > +
> > Index: testsuite/gcc.dg/lto/alias-1_1.c
> > ===================================================================
> > --- testsuite/gcc.dg/lto/alias-1_1.c	(revision 0)
> > +++ testsuite/gcc.dg/lto/alias-1_1.c	(revision 0)
> > @@ -0,0 +1,8 @@
> > +/* { dg-options "-fno-strict-aliasing" } */
> > +extern float *ptr2;
> > +void
> > +__attribute__((optimize ("-fno-strict-aliasing")))
> > +typefun ()
> > +{ 
> > +  *ptr2=0;
> > +}
> > Index: c-family/c-common.c
> > ===================================================================
> > --- c-family/c-common.c	(revision 231048)
> > +++ c-family/c-common.c	(working copy)
> > @@ -9988,7 +9988,6 @@ parse_optimize_options (tree args, bool
> >    bool ret = true;
> >    unsigned opt_argc;
> >    unsigned i;
> > -  int saved_flag_strict_aliasing;
> >    const char **opt_argv;
> >    struct cl_decoded_option *decoded_options;
> >    unsigned int decoded_options_count;
> > @@ -10081,8 +10080,6 @@ parse_optimize_options (tree args, bool
> >    for (i = 1; i < opt_argc; i++)
> >      opt_argv[i] = (*optimize_args)[i];
> >  
> > -  saved_flag_strict_aliasing = flag_strict_aliasing;
> > -
> >    /* Now parse the options.  */
> >    decode_cmdline_options_to_array_default_mask (opt_argc, opt_argv,
> >  						&decoded_options,
> > @@ -10093,9 +10090,6 @@ parse_optimize_options (tree args, bool
> >  
> >    targetm.override_options_after_change();
> >  
> > -  /* Don't allow changing -fstrict-aliasing.  */
> > -  flag_strict_aliasing = saved_flag_strict_aliasing;
> > -
> >    optimize_args->truncate (0);
> >    return ret;
> >  }
> > @@ -12930,8 +12924,8 @@ convert_vector_to_pointer_for_subscript
> >  	  /* If the original vector isn't declared may_alias and it
> >  	     isn't a bare vector look if the subscripting would
> >  	     alias the vector we subscript, and if not, force ref-all.  */
> > -	  alias_set_type vecset = get_alias_set (*vecp);
> > -	  alias_set_type sset = get_alias_set (type);
> > +	  alias_set_type vecset = get_alias_set (*vecp, true);
> > +	  alias_set_type sset = get_alias_set (type, true);
> >  	  if (!alias_sets_must_conflict_p (sset, vecset)
> >  	      && !alias_set_subset_of (sset, vecset))
> >  	    ref_all = true;
> > Index: lto-streamer-out.c
> > ===================================================================
> > --- lto-streamer-out.c	(revision 231020)
> > +++ lto-streamer-out.c	(working copy)
> > @@ -1109,10 +1109,6 @@ hash_tree (struct streamer_tree_cache_d
> >        hstate.commit_flag ();
> >        hstate.add_int (TYPE_PRECISION (t));
> >        hstate.add_int (TYPE_ALIGN (t));
> > -      hstate.add_int ((TYPE_ALIAS_SET (t) == 0
> > -					 || (!in_lto_p
> > -					     && get_alias_set (t) == 0))
> > -					? 0 : -1);
> >      }
> >  
> >    if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
> > Index: ipa-inline-transform.c
> > ===================================================================
> > --- ipa-inline-transform.c	(revision 231020)
> > +++ ipa-inline-transform.c	(working copy)
> > @@ -322,6 +322,23 @@ inline_call (struct cgraph_edge *e, bool
> >    if (DECL_FUNCTION_PERSONALITY (callee->decl))
> >      DECL_FUNCTION_PERSONALITY (to->decl)
> >        = DECL_FUNCTION_PERSONALITY (callee->decl);
> > +  if (!opt_for_fn (callee->decl, flag_strict_aliasing)
> > +      && opt_for_fn (to->decl, flag_strict_aliasing)
> > +      && (!callee->merged
> > +	  || lookup_attribute ("optimization", DECL_ATTRIBUTES (e->caller->decl))
> > +	  || lookup_attribute ("optimization", DECL_ATTRIBUTES (callee->decl))))
> > +    {
> > +      struct gcc_options opts = global_options;
> > +      cl_optimization_restore (&opts,
> > +	 TREE_OPTIMIZATION (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (to->decl)));
> > +      opts.x_flag_strict_aliasing = false;
> > +      if (dump_file)
> > +	fprintf (dump_file, "Dropping flag_strict_aliasing on %s:%i\n",
> > +		 to->name (), to->order);
> > +      build_optimization_node (&opts);
> > +      DECL_FUNCTION_SPECIFIC_OPTIMIZATION (to->decl)
> > +	 = build_optimization_node (&opts);
> > +    }
> >  
> >    /* If aliases are involved, redirect edge to the actual destination and
> >       possibly remove the aliases.  */
> > Index: ipa-icf-gimple.c
> > ===================================================================
> > --- ipa-icf-gimple.c	(revision 231020)
> > +++ ipa-icf-gimple.c	(working copy)
> > @@ -241,7 +241,7 @@ func_checker::compatible_types_p (tree t
> >       For time being just avoid calling get_alias_set on types that are not
> >       having alias sets defined at all.  */
> >    if (type_with_alias_set_p (t1) && type_with_alias_set_p (t2)
> > -      && get_alias_set (t1) != get_alias_set (t2))
> > +      && get_alias_set (t1, true) != get_alias_set (t2, true))
> >      return return_false_with_msg ("alias sets are different");
> >  
> >    return true;
> > Index: tree-streamer-out.c
> > ===================================================================
> > --- tree-streamer-out.c	(revision 231020)
> > +++ tree-streamer-out.c	(working copy)
> > @@ -317,13 +321,18 @@ pack_ts_type_common_value_fields (struct
> >    bp_pack_value (bp, TYPE_RESTRICT (expr), 1);
> >    bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1);
> >    bp_pack_value (bp, TYPE_READONLY (expr), 1);
> > -  /* Make sure to preserve the fact whether the frontend would assign
> > -     alias-set zero to this type.  Do that only for main variants, because
> > -     type variants alias sets are never computed.
> > -     FIXME:  This does not work for pre-streamed builtin types.  */
> > -  bp_pack_value (bp, (TYPE_ALIAS_SET (expr) == 0
> > -		      || (!in_lto_p && TYPE_MAIN_VARIANT (expr) == expr
> > -			  && get_alias_set (expr) == 0)), 1);
> > +  /* We used to stream TYPE_ALIAS_SET == 0 information to let frontends mark
> > +     types that are opaque for TBAA.  This however did not work as intended,
> > +     becuase TYPE_ALIAS_SET == 0 was regularly lost in type merging.
> > +
> > +     Instead now double check that all aliaset set 0 types will be alias set
> > +     0 in LTO world, too.  */
> > +  gcc_checking_assert (!type_with_alias_set_p (expr)
> > +		       || !canonical_type_used_p (expr)
> > +		       || TYPE_ALIAS_SET (expr) != 0
> > +		       || expr == char_type_node
> > +		       || expr == signed_char_type_node
> > +		       || expr == unsigned_char_type_node);
> >    if (RECORD_OR_UNION_TYPE_P (expr))
> >      {
> >        bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1);
> > Index: fold-const.c
> > ===================================================================
> > --- fold-const.c	(revision 231020)
> > +++ fold-const.c	(working copy)
> > @@ -2987,7 +2987,7 @@ operand_equal_p (const_tree arg0, const_
> >  					   flags)))
> >  		return 0;
> >  	      /* Verify that accesses are TBAA compatible.  */
> > -	      if (flag_strict_aliasing
> > +	      if ((flag_strict_aliasing || !cfun->after_inlining)
> >  		  && (!alias_ptr_types_compatible_p
> >  		        (TREE_TYPE (TREE_OPERAND (arg0, 1)),
> >  		         TREE_TYPE (TREE_OPERAND (arg1, 1)))
> > Index: ada/gcc-interface/misc.c
> > ===================================================================
> > --- ada/gcc-interface/misc.c	(revision 231020)
> > +++ ada/gcc-interface/misc.c	(working copy)
> > @@ -592,13 +592,14 @@ gnat_get_alias_set (tree type)
> >  {
> >    /* If this is a padding type, use the type of the first field.  */
> >    if (TYPE_IS_PADDING_P (type))
> > -    return get_alias_set (TREE_TYPE (TYPE_FIELDS (type)));
> > +    return get_alias_set (TREE_TYPE (TYPE_FIELDS (type)), true);
> >  
> >    /* If the type is an unconstrained array, use the type of the
> >       self-referential array we make.  */
> >    else if (TREE_CODE (type) == UNCONSTRAINED_ARRAY_TYPE)
> >      return
> > -      get_alias_set (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (type)))));
> > +      get_alias_set (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (type)))),
> > +		     true);
> >  
> >    /* If the type can alias any other types, return the alias set 0.  */
> >    else if (TYPE_P (type) && TYPE_UNIVERSAL_ALIASING_P (type))
> > Index: ada/gcc-interface/utils.c
> > ===================================================================
> > --- ada/gcc-interface/utils.c	(revision 231020)
> > +++ ada/gcc-interface/utils.c	(working copy)
> > @@ -1520,14 +1520,14 @@ relate_alias_sets (tree gnu_new_type, tr
> >  		      && TYPE_NONALIASED_COMPONENT (gnu_new_type)
> >  			 != TYPE_NONALIASED_COMPONENT (gnu_old_type)));
> >  
> > -      TYPE_ALIAS_SET (gnu_new_type) = get_alias_set (gnu_old_type);
> > +      TYPE_ALIAS_SET (gnu_new_type) = get_alias_set (gnu_old_type, true);
> >        break;
> >  
> >      case ALIAS_SET_SUBSET:
> >      case ALIAS_SET_SUPERSET:
> >        {
> > -	alias_set_type old_set = get_alias_set (gnu_old_type);
> > -	alias_set_type new_set = get_alias_set (gnu_new_type);
> > +	alias_set_type old_set = get_alias_set (gnu_old_type, true);
> > +	alias_set_type new_set = get_alias_set (gnu_new_type, true);
> >  
> >  	/* Do nothing if the alias sets conflict.  This ensures that we
> >  	   never call record_alias_subset several times for the same pair
> > Index: ada/gcc-interface/trans.c
> > ===================================================================
> > --- ada/gcc-interface/trans.c	(revision 231020)
> > +++ ada/gcc-interface/trans.c	(working copy)
> > @@ -9702,11 +9702,13 @@ validate_unchecked_conversion (Node_Id g
> >  				   ? TREE_TYPE (gnu_source_type)
> >  				   : NULL_TREE;
> >        tree gnu_target_desig_type = TREE_TYPE (gnu_target_type);
> > -      alias_set_type target_alias_set = get_alias_set (gnu_target_desig_type);
> > +      alias_set_type target_alias_set = get_alias_set (gnu_target_desig_type,
> > +						       true);
> >  
> >        if (target_alias_set != 0
> >  	  && (!POINTER_TYPE_P (gnu_source_type)
> > -	      || !alias_sets_conflict_p (get_alias_set (gnu_source_desig_type),
> > +	      || !alias_sets_conflict_p (get_alias_set (gnu_source_desig_type,
> > +							true),
> >  					 target_alias_set)))
> >  	{
> >  	  post_error_ne ("?possible aliasing problem for type&",
> > @@ -9728,11 +9730,13 @@ validate_unchecked_conversion (Node_Id g
> >  	  : NULL_TREE;
> >        tree gnu_target_desig_type
> >  	= TREE_TYPE (TREE_TYPE (TYPE_FIELDS (gnu_target_type)));
> > -      alias_set_type target_alias_set = get_alias_set (gnu_target_desig_type);
> > +      alias_set_type target_alias_set = get_alias_set (gnu_target_desig_type,
> > +						       true);
> >  
> >        if (target_alias_set != 0
> >  	  && (!TYPE_IS_FAT_POINTER_P (gnu_source_type)
> > -	      || !alias_sets_conflict_p (get_alias_set (gnu_source_desig_type),
> > +	      || !alias_sets_conflict_p (get_alias_set (gnu_source_desig_type,
> > +							true),
> >  					 target_alias_set)))
> >  	{
> >  	  post_error_ne ("?possible aliasing problem for type&",
> > Index: gimple.c
> > ===================================================================
> > --- gimple.c	(revision 231020)
> > +++ gimple.c	(working copy)
> > @@ -2408,7 +2408,7 @@ gimple_get_alias_set (tree t)
> >  
> >        /* t1 == t can happen for boolean nodes which are always unsigned.  */
> >        if (t1 != t)
> > -	return get_alias_set (t1);
> > +	return get_alias_set (t1, true);
> >      }
> >  
> >    return -1;
> > 
> > 
> 
> -- 
> Richard Biener <rguenther@suse.de>
> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)
diff mbox

Patch

Index: tree.c
===================================================================
--- tree.c	(revision 231020)
+++ tree.c	(working copy)
@@ -5971,7 +5971,8 @@  free_lang_data (void)
      while the slots are still in the way the frontends generated them.  */
   for (i = 0; i < itk_none; ++i)
     if (integer_types[i])
-      TYPE_ALIAS_SET (integer_types[i]) = get_alias_set (integer_types[i]);
+      TYPE_ALIAS_SET (integer_types[i]) = get_alias_set (integer_types[i],
+							 true);
 
   /* Traverse the IL resetting language specific information for
      operands, expressions, etc.  */
Index: cp/rtti.c
===================================================================
--- cp/rtti.c	(revision 231020)
+++ cp/rtti.c	(working copy)
@@ -300,10 +300,10 @@  typeid_ok_p (void)
   /* Make sure abi::__type_info_pseudo has the same alias set
      as std::type_info.  */
   if (! TYPE_ALIAS_SET_KNOWN_P (pseudo_type_info))
-    TYPE_ALIAS_SET (pseudo_type_info) = get_alias_set (type_info_type);
+    TYPE_ALIAS_SET (pseudo_type_info) = get_alias_set (type_info_type, true);
   else
     gcc_assert (TYPE_ALIAS_SET (pseudo_type_info)
-		== get_alias_set (type_info_type));
+		== get_alias_set (type_info_type, true));
 
   return true;
 }
Index: cp/cp-objcp-common.c
===================================================================
--- cp/cp-objcp-common.c	(revision 231020)
+++ cp/cp-objcp-common.c	(working copy)
@@ -32,7 +32,7 @@  cxx_get_alias_set (tree t)
   if (IS_FAKE_BASE_TYPE (t))
     /* The base variant of a type must be in the same alias set as the
        complete type.  */
-    return get_alias_set (TYPE_CONTEXT (t));
+    return get_alias_set (TYPE_CONTEXT (t), true);
 
   /* Punt on PMFs until we canonicalize functions properly.  */
   if (TYPE_PTRMEMFUNC_P (t)
Index: tree-streamer-in.c
===================================================================
--- tree-streamer-in.c	(revision 231020)
+++ tree-streamer-in.c	(working copy)
@@ -366,7 +366,6 @@  unpack_ts_type_common_value_fields (stru
   TYPE_RESTRICT (expr) = (unsigned) bp_unpack_value (bp, 1);
   TYPE_USER_ALIGN (expr) = (unsigned) bp_unpack_value (bp, 1);
   TYPE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1);
-  TYPE_ALIAS_SET (expr) = bp_unpack_value (bp, 1) ? 0 : -1;
   if (RECORD_OR_UNION_TYPE_P (expr))
     {
       TYPE_TRANSPARENT_AGGR (expr) = (unsigned) bp_unpack_value (bp, 1);
Index: tree-ssa-alias.c
===================================================================
--- tree-ssa-alias.c	(revision 231020)
+++ tree-ssa-alias.c	(working copy)
@@ -563,7 +563,10 @@  ao_ref_base_alias_set (ao_ref *ref)
   base_ref = ref->ref;
   while (handled_component_p (base_ref))
     base_ref = TREE_OPERAND (base_ref, 0);
-  ref->base_alias_set = get_alias_set (base_ref);
+  /* Do not return 0 in case of strict aliasing; this function is used at
+     IPA level by ipa-icf-gimple.c.  It is job of caller to give up on
+     using TBAA oracle when asked to not do so.  */
+  ref->base_alias_set = get_alias_set (base_ref, true);
   return ref->base_alias_set;
 }
 
@@ -574,7 +577,10 @@  ao_ref_alias_set (ao_ref *ref)
 {
   if (ref->ref_alias_set != -1)
     return ref->ref_alias_set;
-  ref->ref_alias_set = get_alias_set (ref->ref);
+  /* Do not return 0 in case of strict aliasing; this function is used at
+     IPA level by ipa-icf-gimple.c.  It is job of caller to give up on
+     using TBAA oracle when asked to not do so.  */
+  ref->ref_alias_set = get_alias_set (ref->ref, true);
   return ref->ref_alias_set;
 }
 
@@ -668,7 +674,7 @@  same_type_for_tbaa (tree type1, tree typ
      would mean that conversions between them are useless, whereas they are
      not (e.g. type and subtypes can have different modes).  So, in the end,
      they are only guaranteed to have the same alias set.  */
-  if (get_alias_set (type1) == get_alias_set (type2))
+  if (get_alias_set (type1, true) == get_alias_set (type2, true))
     return -1;
 
   /* The types are known to be not equal.  */
Index: alias.c
===================================================================
--- alias.c	(revision 231020)
+++ alias.c	(working copy)
@@ -406,7 +406,7 @@  alias_set_subset_of (alias_set_type set1
   alias_set_entry *ase2;
 
   /* Everything is a subset of the "aliases everything" set.  */
-  if (set2 == 0)
+  if (set2 == 0 || !flag_strict_aliasing)
     return true;
 
   /* Check if set1 is a subset of set2.  */
@@ -467,7 +467,7 @@  alias_sets_conflict_p (alias_set_type se
   alias_set_entry *ase2;
 
   /* The easy case.  */
-  if (alias_sets_must_conflict_p (set1, set2))
+  if (!flag_strict_aliasing || alias_sets_must_conflict_p (set1, set2))
     return 1;
 
   /* See if the first alias set is a subset of the second.  */
@@ -809,17 +809,21 @@  init_alias_set_entry (alias_set_type set
 }
 
 /* Return the alias set for T, which may be either a type or an
-   expression.  Call language-specific routine for help, if needed.  */
+   expression.  Call language-specific routine for help, if needed.
+   If STRICT is true, ignore value of flag_strict_aliasing.  This is needed
+   in cases we are in -fno-strict-aliasing region but still need to compute
+   alias sets for some reason (this is used, for example, by rtti code to copy
+   alias set from type to type).  */
 
 alias_set_type
-get_alias_set (tree t)
+get_alias_set (tree t, bool strict)
 {
   alias_set_type set;
 
   /* If we're not doing any alias analysis, just assume everything
      aliases everything else.  Also return 0 if this or its type is
      an error.  */
-  if (! flag_strict_aliasing || t == error_mark_node
+  if ((! flag_strict_aliasing && !strict)|| t == error_mark_node
       || (! TYPE_P (t)
 	  && (TREE_TYPE (t) == 0 || TREE_TYPE (t) == error_mark_node)))
     return 0;
@@ -898,7 +902,7 @@  get_alias_set (tree t)
       /* For arrays with unknown size the conservative answer is the
 	 alias set of the element type.  */
       if (TREE_CODE (t) == ARRAY_TYPE)
-	return get_alias_set (TREE_TYPE (t));
+	return get_alias_set (TREE_TYPE (t), true);
 
       /* But return zero as a conservative answer for incomplete types.  */
       return 0;
@@ -920,7 +924,7 @@  get_alias_set (tree t)
      normal usage.  And indeed lets vectors be treated more like an
      array slice.  */
   else if (TREE_CODE (t) == VECTOR_TYPE)
-    set = get_alias_set (TREE_TYPE (t));
+    set = get_alias_set (TREE_TYPE (t), true);
 
   /* Unless the language specifies otherwise, treat array types the
      same as their components.  This avoids the asymmetry we get
@@ -933,7 +937,7 @@  get_alias_set (tree t)
   else if (TREE_CODE (t) == ARRAY_TYPE
 	   && (!TYPE_NONALIASED_COMPONENT (t)
 	       || TYPE_STRUCTURAL_EQUALITY_P (t)))
-    set = get_alias_set (TREE_TYPE (t));
+    set = get_alias_set (TREE_TYPE (t), true);
 
   /* From the former common C and C++ langhook implementation:
 
@@ -997,7 +1001,7 @@  get_alias_set (tree t)
 	 (see record_component_aliases) and thus it is safe it to use it for
 	 pointers to types with TYPE_STRUCTURAL_EQUALITY_P.  */
       if (TREE_CODE (p) == VOID_TYPE || TYPE_STRUCTURAL_EQUALITY_P (p))
-	set = get_alias_set (ptr_type_node);
+	set = get_alias_set (ptr_type_node, true);
       else
 	{
 	  /* Rebuild pointer type starting from canonical types using
@@ -1085,15 +1089,10 @@  get_alias_set (tree t)
 alias_set_type
 new_alias_set (void)
 {
-  if (flag_strict_aliasing)
-    {
-      if (alias_sets == 0)
-	vec_safe_push (alias_sets, (alias_set_entry *) NULL);
-      vec_safe_push (alias_sets, (alias_set_entry *) NULL);
-      return alias_sets->length () - 1;
-    }
-  else
-    return 0;
+  if (alias_sets == 0)
+    vec_safe_push (alias_sets, (alias_set_entry *) NULL);
+  vec_safe_push (alias_sets, (alias_set_entry *) NULL);
+  return alias_sets->length () - 1;
 }
 
 /* Indicate that things in SUBSET can alias things in SUPERSET, but that
@@ -1169,7 +1168,7 @@  record_alias_subset (alias_set_type supe
 void
 record_component_aliases (tree type)
 {
-  alias_set_type superset = get_alias_set (type);
+  alias_set_type superset = get_alias_set (type, true);
   tree field;
 
   if (superset == 0)
@@ -1215,16 +1214,17 @@  record_component_aliases (tree type)
 		if (POINTER_TYPE_P (t))
 		  t = ptr_type_node;
 		else if (flag_checking)
-		  gcc_checking_assert (get_alias_set (t)
-				       == get_alias_set (TREE_TYPE (field)));
+		  gcc_checking_assert (get_alias_set (t, true)
+				       == get_alias_set (TREE_TYPE (field),
+							 true));
 	      }
 
-	    record_alias_subset (superset, get_alias_set (t));
+	    record_alias_subset (superset, get_alias_set (t, true));
 	  }
       break;
 
     case COMPLEX_TYPE:
-      record_alias_subset (superset, get_alias_set (TREE_TYPE (type)));
+      record_alias_subset (superset, get_alias_set (TREE_TYPE (type), true));
       break;
 
     /* VECTOR_TYPE and ARRAY_TYPE share the alias set with their
Index: alias.h
===================================================================
--- alias.h	(revision 231020)
+++ alias.h	(working copy)
@@ -21,7 +21,7 @@  along with GCC; see the file COPYING3.
 #define GCC_ALIAS_H
 
 extern alias_set_type new_alias_set (void);
-extern alias_set_type get_alias_set (tree);
+extern alias_set_type get_alias_set (tree, bool strict = false);
 extern alias_set_type get_deref_alias_set (tree);
 extern alias_set_type get_varargs_alias_set (void);
 extern alias_set_type get_frame_alias_set (void);
Index: lto/lto-symtab.c
===================================================================
--- lto/lto-symtab.c	(revision 231020)
+++ lto/lto-symtab.c	(working copy)
@@ -276,8 +276,8 @@  warn_type_compatibility_p (tree prevaili
      we make ptr_type_node to TBAA compatible with every other type.  */
   if (type_with_alias_set_p (type) && type_with_alias_set_p (prevailing_type))
     {
-      alias_set_type set1 = get_alias_set (type);
-      alias_set_type set2 = get_alias_set (prevailing_type);
+      alias_set_type set1 = get_alias_set (type, true);
+      alias_set_type set2 = get_alias_set (prevailing_type, true);
 
       if (set1 && set2 && set1 != set2 
           && (!POINTER_TYPE_P (type) || !POINTER_TYPE_P (prevailing_type)
Index: lto/lto.c
===================================================================
--- lto/lto.c	(revision 231020)
+++ lto/lto.c	(working copy)
@@ -1166,7 +1166,9 @@  compare_tree_sccs_1 (tree t1, tree t2, t
       compare_values (TYPE_READONLY);
       compare_values (TYPE_PRECISION);
       compare_values (TYPE_ALIGN);
-      compare_values (TYPE_ALIAS_SET);
+      /* Do not compare TYPE_ALIAS_SET.  Doing so introduce ordering issues
+         with calls to get_alias_set which may initialize it for streamed
+ 	 in types.  */
     }
 
   /* We don't want to compare locations, so there is nothing do compare
Index: testsuite/gcc.c-torture/execute/alias-1.c
===================================================================
--- testsuite/gcc.c-torture/execute/alias-1.c	(revision 0)
+++ testsuite/gcc.c-torture/execute/alias-1.c	(revision 0)
@@ -0,0 +1,19 @@ 
+int val;
+
+int *ptr = &val;
+float *ptr2 = &val;
+
+__attribute__((optimize ("-fno-strict-aliasing")))
+typepun ()
+{
+  *ptr2=0;
+}
+
+main()
+{
+  *ptr=1;
+  typepun ();
+  if (*ptr)
+    __builtin_abort ();
+}
+
Index: testsuite/gcc.dg/lto/alias-1_0.c
===================================================================
--- testsuite/gcc.dg/lto/alias-1_0.c	(revision 0)
+++ testsuite/gcc.dg/lto/alias-1_0.c	(revision 0)
@@ -0,0 +1,22 @@ 
+/* { dg-lto-do run } */
+/* { dg-lto-options { { -O2 -flto } } } */
+int val;
+
+int *ptr = &val;
+float *ptr2 = &val;
+
+extern void typefun(void);
+
+void link_error (void);
+
+int
+main()
+{ 
+  *ptr=1;
+  typefun ();
+  if (*ptr)
+    /*link_error ();*/
+    __builtin_abort ();
+  return 0;
+}
+
Index: testsuite/gcc.dg/lto/alias-1_1.c
===================================================================
--- testsuite/gcc.dg/lto/alias-1_1.c	(revision 0)
+++ testsuite/gcc.dg/lto/alias-1_1.c	(revision 0)
@@ -0,0 +1,8 @@ 
+/* { dg-options "-fno-strict-aliasing" } */
+extern float *ptr2;
+void
+__attribute__((optimize ("-fno-strict-aliasing")))
+typefun ()
+{ 
+  *ptr2=0;
+}
Index: c-family/c-common.c
===================================================================
--- c-family/c-common.c	(revision 231048)
+++ c-family/c-common.c	(working copy)
@@ -9988,7 +9988,6 @@  parse_optimize_options (tree args, bool
   bool ret = true;
   unsigned opt_argc;
   unsigned i;
-  int saved_flag_strict_aliasing;
   const char **opt_argv;
   struct cl_decoded_option *decoded_options;
   unsigned int decoded_options_count;
@@ -10081,8 +10080,6 @@  parse_optimize_options (tree args, bool
   for (i = 1; i < opt_argc; i++)
     opt_argv[i] = (*optimize_args)[i];
 
-  saved_flag_strict_aliasing = flag_strict_aliasing;
-
   /* Now parse the options.  */
   decode_cmdline_options_to_array_default_mask (opt_argc, opt_argv,
 						&decoded_options,
@@ -10093,9 +10090,6 @@  parse_optimize_options (tree args, bool
 
   targetm.override_options_after_change();
 
-  /* Don't allow changing -fstrict-aliasing.  */
-  flag_strict_aliasing = saved_flag_strict_aliasing;
-
   optimize_args->truncate (0);
   return ret;
 }
@@ -12930,8 +12924,8 @@  convert_vector_to_pointer_for_subscript
 	  /* If the original vector isn't declared may_alias and it
 	     isn't a bare vector look if the subscripting would
 	     alias the vector we subscript, and if not, force ref-all.  */
-	  alias_set_type vecset = get_alias_set (*vecp);
-	  alias_set_type sset = get_alias_set (type);
+	  alias_set_type vecset = get_alias_set (*vecp, true);
+	  alias_set_type sset = get_alias_set (type, true);
 	  if (!alias_sets_must_conflict_p (sset, vecset)
 	      && !alias_set_subset_of (sset, vecset))
 	    ref_all = true;
Index: lto-streamer-out.c
===================================================================
--- lto-streamer-out.c	(revision 231020)
+++ lto-streamer-out.c	(working copy)
@@ -1109,10 +1109,6 @@  hash_tree (struct streamer_tree_cache_d
       hstate.commit_flag ();
       hstate.add_int (TYPE_PRECISION (t));
       hstate.add_int (TYPE_ALIGN (t));
-      hstate.add_int ((TYPE_ALIAS_SET (t) == 0
-					 || (!in_lto_p
-					     && get_alias_set (t) == 0))
-					? 0 : -1);
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL))
Index: ipa-inline-transform.c
===================================================================
--- ipa-inline-transform.c	(revision 231020)
+++ ipa-inline-transform.c	(working copy)
@@ -322,6 +322,23 @@  inline_call (struct cgraph_edge *e, bool
   if (DECL_FUNCTION_PERSONALITY (callee->decl))
     DECL_FUNCTION_PERSONALITY (to->decl)
       = DECL_FUNCTION_PERSONALITY (callee->decl);
+  if (!opt_for_fn (callee->decl, flag_strict_aliasing)
+      && opt_for_fn (to->decl, flag_strict_aliasing)
+      && (!callee->merged
+	  || lookup_attribute ("optimization", DECL_ATTRIBUTES (e->caller->decl))
+	  || lookup_attribute ("optimization", DECL_ATTRIBUTES (callee->decl))))
+    {
+      struct gcc_options opts = global_options;
+      cl_optimization_restore (&opts,
+	 TREE_OPTIMIZATION (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (to->decl)));
+      opts.x_flag_strict_aliasing = false;
+      if (dump_file)
+	fprintf (dump_file, "Dropping flag_strict_aliasing on %s:%i\n",
+		 to->name (), to->order);
+      build_optimization_node (&opts);
+      DECL_FUNCTION_SPECIFIC_OPTIMIZATION (to->decl)
+	 = build_optimization_node (&opts);
+    }
 
   /* If aliases are involved, redirect edge to the actual destination and
      possibly remove the aliases.  */
Index: ipa-icf-gimple.c
===================================================================
--- ipa-icf-gimple.c	(revision 231020)
+++ ipa-icf-gimple.c	(working copy)
@@ -241,7 +241,7 @@  func_checker::compatible_types_p (tree t
      For time being just avoid calling get_alias_set on types that are not
      having alias sets defined at all.  */
   if (type_with_alias_set_p (t1) && type_with_alias_set_p (t2)
-      && get_alias_set (t1) != get_alias_set (t2))
+      && get_alias_set (t1, true) != get_alias_set (t2, true))
     return return_false_with_msg ("alias sets are different");
 
   return true;
Index: tree-streamer-out.c
===================================================================
--- tree-streamer-out.c	(revision 231020)
+++ tree-streamer-out.c	(working copy)
@@ -317,13 +321,18 @@  pack_ts_type_common_value_fields (struct
   bp_pack_value (bp, TYPE_RESTRICT (expr), 1);
   bp_pack_value (bp, TYPE_USER_ALIGN (expr), 1);
   bp_pack_value (bp, TYPE_READONLY (expr), 1);
-  /* Make sure to preserve the fact whether the frontend would assign
-     alias-set zero to this type.  Do that only for main variants, because
-     type variants alias sets are never computed.
-     FIXME:  This does not work for pre-streamed builtin types.  */
-  bp_pack_value (bp, (TYPE_ALIAS_SET (expr) == 0
-		      || (!in_lto_p && TYPE_MAIN_VARIANT (expr) == expr
-			  && get_alias_set (expr) == 0)), 1);
+  /* We used to stream TYPE_ALIAS_SET == 0 information to let frontends mark
+     types that are opaque for TBAA.  This however did not work as intended,
+     becuase TYPE_ALIAS_SET == 0 was regularly lost in type merging.
+
+     Instead now double check that all aliaset set 0 types will be alias set
+     0 in LTO world, too.  */
+  gcc_checking_assert (!type_with_alias_set_p (expr)
+		       || !canonical_type_used_p (expr)
+		       || TYPE_ALIAS_SET (expr) != 0
+		       || expr == char_type_node
+		       || expr == signed_char_type_node
+		       || expr == unsigned_char_type_node);
   if (RECORD_OR_UNION_TYPE_P (expr))
     {
       bp_pack_value (bp, TYPE_TRANSPARENT_AGGR (expr), 1);
Index: fold-const.c
===================================================================
--- fold-const.c	(revision 231020)
+++ fold-const.c	(working copy)
@@ -2987,7 +2987,7 @@  operand_equal_p (const_tree arg0, const_
 					   flags)))
 		return 0;
 	      /* Verify that accesses are TBAA compatible.  */
-	      if (flag_strict_aliasing
+	      if ((flag_strict_aliasing || !cfun->after_inlining)
 		  && (!alias_ptr_types_compatible_p
 		        (TREE_TYPE (TREE_OPERAND (arg0, 1)),
 		         TREE_TYPE (TREE_OPERAND (arg1, 1)))
Index: ada/gcc-interface/misc.c
===================================================================
--- ada/gcc-interface/misc.c	(revision 231020)
+++ ada/gcc-interface/misc.c	(working copy)
@@ -592,13 +592,14 @@  gnat_get_alias_set (tree type)
 {
   /* If this is a padding type, use the type of the first field.  */
   if (TYPE_IS_PADDING_P (type))
-    return get_alias_set (TREE_TYPE (TYPE_FIELDS (type)));
+    return get_alias_set (TREE_TYPE (TYPE_FIELDS (type)), true);
 
   /* If the type is an unconstrained array, use the type of the
      self-referential array we make.  */
   else if (TREE_CODE (type) == UNCONSTRAINED_ARRAY_TYPE)
     return
-      get_alias_set (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (type)))));
+      get_alias_set (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (type)))),
+		     true);
 
   /* If the type can alias any other types, return the alias set 0.  */
   else if (TYPE_P (type) && TYPE_UNIVERSAL_ALIASING_P (type))
Index: ada/gcc-interface/utils.c
===================================================================
--- ada/gcc-interface/utils.c	(revision 231020)
+++ ada/gcc-interface/utils.c	(working copy)
@@ -1520,14 +1520,14 @@  relate_alias_sets (tree gnu_new_type, tr
 		      && TYPE_NONALIASED_COMPONENT (gnu_new_type)
 			 != TYPE_NONALIASED_COMPONENT (gnu_old_type)));
 
-      TYPE_ALIAS_SET (gnu_new_type) = get_alias_set (gnu_old_type);
+      TYPE_ALIAS_SET (gnu_new_type) = get_alias_set (gnu_old_type, true);
       break;
 
     case ALIAS_SET_SUBSET:
     case ALIAS_SET_SUPERSET:
       {
-	alias_set_type old_set = get_alias_set (gnu_old_type);
-	alias_set_type new_set = get_alias_set (gnu_new_type);
+	alias_set_type old_set = get_alias_set (gnu_old_type, true);
+	alias_set_type new_set = get_alias_set (gnu_new_type, true);
 
 	/* Do nothing if the alias sets conflict.  This ensures that we
 	   never call record_alias_subset several times for the same pair
Index: ada/gcc-interface/trans.c
===================================================================
--- ada/gcc-interface/trans.c	(revision 231020)
+++ ada/gcc-interface/trans.c	(working copy)
@@ -9702,11 +9702,13 @@  validate_unchecked_conversion (Node_Id g
 				   ? TREE_TYPE (gnu_source_type)
 				   : NULL_TREE;
       tree gnu_target_desig_type = TREE_TYPE (gnu_target_type);
-      alias_set_type target_alias_set = get_alias_set (gnu_target_desig_type);
+      alias_set_type target_alias_set = get_alias_set (gnu_target_desig_type,
+						       true);
 
       if (target_alias_set != 0
 	  && (!POINTER_TYPE_P (gnu_source_type)
-	      || !alias_sets_conflict_p (get_alias_set (gnu_source_desig_type),
+	      || !alias_sets_conflict_p (get_alias_set (gnu_source_desig_type,
+							true),
 					 target_alias_set)))
 	{
 	  post_error_ne ("?possible aliasing problem for type&",
@@ -9728,11 +9730,13 @@  validate_unchecked_conversion (Node_Id g
 	  : NULL_TREE;
       tree gnu_target_desig_type
 	= TREE_TYPE (TREE_TYPE (TYPE_FIELDS (gnu_target_type)));
-      alias_set_type target_alias_set = get_alias_set (gnu_target_desig_type);
+      alias_set_type target_alias_set = get_alias_set (gnu_target_desig_type,
+						       true);
 
       if (target_alias_set != 0
 	  && (!TYPE_IS_FAT_POINTER_P (gnu_source_type)
-	      || !alias_sets_conflict_p (get_alias_set (gnu_source_desig_type),
+	      || !alias_sets_conflict_p (get_alias_set (gnu_source_desig_type,
+							true),
 					 target_alias_set)))
 	{
 	  post_error_ne ("?possible aliasing problem for type&",
Index: gimple.c
===================================================================
--- gimple.c	(revision 231020)
+++ gimple.c	(working copy)
@@ -2408,7 +2408,7 @@  gimple_get_alias_set (tree t)
 
       /* t1 == t can happen for boolean nodes which are always unsigned.  */
       if (t1 != t)
-	return get_alias_set (t1);
+	return get_alias_set (t1, true);
     }
 
   return -1;