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


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

Re: [patch] Fix type merging deficiency during WPA


> So sth like
> 
> Index: gcc/lto-streamer-out.c
> ===================================================================
> --- gcc/lto-streamer-out.c      (revision 238039)
> +++ gcc/lto-streamer-out.c      (working copy)
> @@ -996,7 +996,7 @@ hash_tree (struct streamer_tree_cache_d
>    else
>      hstate.add_flag (TREE_NO_WARNING (t));
>    hstate.add_flag (TREE_NOTHROW (t));
> -  hstate.add_flag (TREE_STATIC (t));
> +  //hstate.add_flag (TREE_STATIC (t));
>    hstate.add_flag (TREE_PROTECTED (t));
>    hstate.add_flag (TREE_DEPRECATED (t));
>    if (code != TREE_BINFO)
> @@ -1050,7 +1050,7 @@ hash_tree (struct streamer_tree_cache_d
>        hstate.add_flag (DECL_ARTIFICIAL (t));
>        hstate.add_flag (DECL_USER_ALIGN (t));
>        hstate.add_flag (DECL_PRESERVE_P (t));
> -      hstate.add_flag (DECL_EXTERNAL (t));
> +      //hstate.add_flag (DECL_EXTERNAL (t));
>        hstate.add_flag (DECL_GIMPLE_REG_P (t));
>        hstate.commit_flag ();
>        hstate.add_int (DECL_ALIGN (t));
> Index: gcc/lto/lto.c
> ===================================================================
> --- gcc/lto/lto.c       (revision 238039)
> +++ gcc/lto/lto.c       (working copy)
> @@ -1263,7 +1263,8 @@ compare_tree_sccs_1 (tree t1, tree t2, t
>      tree t1_ = (E1), t2_ = (E2); \
>      if (t1_ != t2_ \
>         && (!t1_ || !t2_ \
> -           || !TREE_VISITED (t2_) \
> +           || (!TREE_VISITED (t2_) \
> +               && !same_decls (t1_, t2_)) \
> 
>             || (!TREE_ASM_WRITTEN (t2_) \
> 
>                 && !compare_tree_sccs_1 (t1_, t2_, map)))) \
>        return false; \
> 
> plus the magic new function same_decls which would check if the trees are
> var/function decls with the same assembler name. The function can't use
> the cgraph as that is not yet read in unfortunately - I still think we
> should do that so we can see the prevailing nodes early.

OK, thanks for the hint, the attached patch where the call to same_decls is 
placed differently works on the testcase (modulo the gigi change I posted 
earlier today) but not on the original code...  It looks like the hash value 
computed in lto-streamer-out.c is stricter than the hash value computed for 
canonical types, I'm trying to pinpoint the difference.


	* lto-streamer-out.c (hash_tree): Do not add the TREE_STATIC and
	DECL_EXTERNAL flags for variable or function declarations.
lto/
	* lto.c (same_global_decl_p): New predicate.
	(compare_tree_sccs_1): Use it in the comparison of pointer fields.
	(walk_simple_constant_arithmetic): New function.
        (LTO_SET_PREVAIL): Use it to fix up DECL nodes in simple expressions.

-- 
Eric Botcazou
Index: lto-streamer-out.c
===================================================================
--- lto-streamer-out.c	(revision 238156)
+++ lto-streamer-out.c	(working copy)
@@ -996,7 +996,9 @@ hash_tree (struct streamer_tree_cache_d
   else
     hstate.add_flag (TREE_NO_WARNING (t));
   hstate.add_flag (TREE_NOTHROW (t));
-  hstate.add_flag (TREE_STATIC (t));
+  /* We want to unify DECL nodes in pointer fields of global types.  */
+  if (!(VAR_OR_FUNCTION_DECL_P (t)))
+    hstate.add_flag (TREE_STATIC (t));
   hstate.add_flag (TREE_PROTECTED (t));
   hstate.add_flag (TREE_DEPRECATED (t));
   if (code != TREE_BINFO)
@@ -1050,7 +1052,9 @@ hash_tree (struct streamer_tree_cache_d
       hstate.add_flag (DECL_ARTIFICIAL (t));
       hstate.add_flag (DECL_USER_ALIGN (t));
       hstate.add_flag (DECL_PRESERVE_P (t));
-      hstate.add_flag (DECL_EXTERNAL (t));
+      /* We want to unify DECL nodes in pointer fields of global types.  */
+      if (!(VAR_OR_FUNCTION_DECL_P (t)))
+	hstate.add_flag (DECL_EXTERNAL (t));
       hstate.add_flag (DECL_GIMPLE_REG_P (t));
       hstate.commit_flag ();
       hstate.add_int (DECL_ALIGN (t));
Index: lto/lto.c
===================================================================
--- lto/lto.c	(revision 238156)
+++ lto/lto.c	(working copy)
@@ -970,6 +970,27 @@ static unsigned long num_sccs_merged;
 static unsigned long num_scc_compares;
 static unsigned long num_scc_compare_collisions;
 
+/* Return true if T1 and T2 represent the same global declaration.
+
+   We need to unify declaration nodes in pointer fields of global types
+   so as to unify the types themselves before the declarations are merged.  */
+
+static inline bool
+same_global_decl_p (tree t1, tree t2)
+{
+  if (TREE_CODE (t1) != TREE_CODE (t2) || !VAR_OR_FUNCTION_DECL_P (t1))
+    return false;
+
+  if (!(TREE_PUBLIC (t1) || DECL_EXTERNAL (t1)))
+    return false;
+
+  if (!(TREE_PUBLIC (t2) || DECL_EXTERNAL (t2)))
+    return false;
+
+  return symbol_table::assembler_names_equal_p
+			 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t1)),
+			  IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t2)));
+}
 
 /* Compare the two entries T1 and T2 of two SCCs that are possibly equal,
    recursing through in-SCC tree edges.  Returns true if the SCCs entered
@@ -1262,6 +1283,7 @@ compare_tree_sccs_1 (tree t1, tree t2, t
   do { \
     tree t1_ = (E1), t2_ = (E2); \
     if (t1_ != t2_ \
+	&& !(t1_ && t2_ && same_global_decl_p (t1_, t2_)) \
 	&& (!t1_ || !t2_ \
 	    || !TREE_VISITED (t2_) \
 	    || (!TREE_ASM_WRITTEN (t2_) \
@@ -2506,15 +2528,55 @@ lto_wpa_write_files (void)
   timevar_pop (TV_WHOPR_WPA_IO);
 }
 
+/* Look inside *EXPR into simple arithmetic operations involving constants.
+   Return the address of the outermost non-arithmetic or non-constant node.
+   This should be equivalent to tree.c:skip_simple_constant_arithmetic.  */
+
+static tree *
+walk_simple_constant_arithmetic (tree *expr)
+{
+  while (TREE_CODE (*expr) == NON_LVALUE_EXPR)
+    expr = &TREE_OPERAND (*expr, 0);
+
+  while (true)
+    {
+      if (UNARY_CLASS_P (*expr))
+	expr = &TREE_OPERAND (*expr, 0);
+      else if (BINARY_CLASS_P (*expr))
+	{
+	  if (TREE_CONSTANT (TREE_OPERAND (*expr, 1)))
+	    expr = &TREE_OPERAND (*expr, 0);
+	  else if (TREE_CONSTANT (TREE_OPERAND (*expr, 0)))
+	    expr = &TREE_OPERAND (*expr, 1);
+	  else
+	    break;
+	}
+      else
+	break;
+    }
+
+  return expr;
+}
 
-/* If TT is a variable or function decl replace it with its
-   prevailing variant.  */
+/* If TT is a variable or function decl or a simple expression containing one,
+   replace the occurrence with its prevailing variant.  This should be able to
+   deal with all the expressions attached to _DECL and _TYPE nodes which were
+   streamed into the GIMPLE IR.  */
 #define LTO_SET_PREVAIL(tt) \
   do {\
+    tree *loc; \
     if ((tt) && VAR_OR_FUNCTION_DECL_P (tt) \
 	&& (TREE_PUBLIC (tt) || DECL_EXTERNAL (tt))) \
       { \
-        tt = lto_symtab_prevailing_decl (tt); \
+	tt = lto_symtab_prevailing_decl (tt); \
+	fixed = true; \
+      } \
+    else if ((tt) && EXPR_P (tt) \
+	     && (loc = walk_simple_constant_arithmetic (&tt)) \
+	     && VAR_OR_FUNCTION_DECL_P (*loc) \
+	     && (TREE_PUBLIC (*loc) || DECL_EXTERNAL (*loc))) \
+      { \
+	*loc = lto_symtab_prevailing_decl (*loc); \
 	fixed = true; \
       } \
   } while (0)

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