Index: ipa-inline-transform.c
===================================================================
--- ipa-inline-transform.c	(revision 230924)
+++ 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 230924)
+++ 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: alias.c
===================================================================
--- alias.c	(revision 230924)
+++ alias.c	(working copy)
@@ -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 230924)
+++ 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: cp/rtti.c
===================================================================
--- cp/rtti.c	(revision 230924)
+++ 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: fold-const.c
===================================================================
--- fold-const.c	(revision 230924)
+++ 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: lto/lto-symtab.c
===================================================================
--- lto/lto-symtab.c	(revision 230924)
+++ 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: tree-streamer-out.c
===================================================================
--- tree-streamer-out.c	(revision 230924)
+++ tree-streamer-out.c	(working copy)
@@ -317,13 +319,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: c-family/c-common.c
===================================================================
--- c-family/c-common.c	(revision 230924)
+++ c-family/c-common.c	(working copy)
@@ -9987,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;
@@ -10080,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,
@@ -10092,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;
 }
Index: tree-streamer-in.c
===================================================================
--- tree-streamer-in.c	(revision 230924)
+++ 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: 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,19 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { { -O2 -flto } } } */
+int val;
+
+int *ptr = &val;
+float *ptr2 = &val;
+
+extern void typefun(void);
+
+
+main()
+{ 
+  *ptr=1;
+  typefun ();
+  if (*ptr)
+    link_error ();
+  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,7 @@
+/* { dg-options "-fno-strict-aliasing" } */
+extern float *ptr2;
+__attribute__((optimize ("-fno-strict-aliasing")))
+typefun ()
+{ 
+  *ptr2=0;
+}
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: tree.c
===================================================================
--- tree.c	(revision 230924)
+++ 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.  */
