]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
cgraphbuild.c (record_reference): Update.
authorJan Hubicka <jh@suse.cz>
Sat, 19 May 2012 09:49:47 +0000 (11:49 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sat, 19 May 2012 09:49:47 +0000 (09:49 +0000)
* cgraphbuild.c (record_reference): Update.
* lto-cgraph.c (lto_output_varpool_node): External vars
are not in other partition even if they are not output
in current partition.
* gimple-fold.c (can_refer_decl_in_current_unit_p): Take FROM_DECL
argument; fix.
(canonicalize_constructor_val): Take FROM_DECL argument.
(fold_ctor_reference, fold_string_cst_ctor_reference,
fold_array_ctor_reference, fold_nonarray_ctor_reference,
fold_ctor_reference): Likewise.
(fold_const_aggregate_ref_1, gimple_get_virt_method_for_binfo): Update.
* gimple.h (gimple_fold_builtin): Likewise.

From-SVN: r187678

gcc/ChangeLog
gcc/cgraphbuild.c
gcc/gimple-fold.c
gcc/gimple.h

index 85b47acd4213a019cc1853aac29f7152486cfa32..b648c7032b5b39dfaae0b96520fe5a507b584f14 100644 (file)
@@ -1,3 +1,18 @@
+2012-05-18  Jan Hubicka  <jh@suse.cz>
+
+       * cgraphbuild.c (record_reference): Update.
+       * lto-cgraph.c (lto_output_varpool_node): External vars
+       are not in other partition even if they are not output
+       in current partition.
+       * gimple-fold.c (can_refer_decl_in_current_unit_p): Take FROM_DECL
+       argument; fix.
+       (canonicalize_constructor_val): Take FROM_DECL argument.
+       (fold_ctor_reference, fold_string_cst_ctor_reference,
+       fold_array_ctor_reference, fold_nonarray_ctor_reference,
+       fold_ctor_reference): Likewise.
+       (fold_const_aggregate_ref_1, gimple_get_virt_method_for_binfo): Update.
+       * gimple.h (gimple_fold_builtin): Likewise.
+
 2012-05-18  Olivier Hainque  <hainque@adacore.com>
 
        * Makefile.in (FLAGS_TO_PASS): Pass $(libexecsubdir) instead of
index ea5351342c076c1c04ca35af6ffd0719cbafa418..ce8f2ee080a798f8fe1a1efab09aa4e8dedbeef0 100644 (file)
@@ -54,7 +54,7 @@ record_reference (tree *tp, int *walk_subtrees, void *data)
   tree decl;
   struct record_reference_ctx *ctx = (struct record_reference_ctx *)data;
 
-  t = canonicalize_constructor_val (t);
+  t = canonicalize_constructor_val (t, NULL);
   if (!t)
     t = *tp;
   else if (t != *tp)
index dbe1b838c5baf64423c9cfee2f3090ab41cde331..6b4d987e025715e9c4d462921253b3061df385d2 100644 (file)
@@ -33,8 +33,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-fold.h"
 
 /* Return true when DECL can be referenced from current unit.
-   We can get declarations that are not possible to reference for
-   various reasons:
+   FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
+   We can get declarations that are not possible to reference for various
+   reasons:
 
      1) When analyzing C++ virtual tables.
        C++ virtual tables do have known constructors even
@@ -54,19 +55,35 @@ along with GCC; see the file COPYING3.  If not see
         directly.  */
 
 static bool
-can_refer_decl_in_current_unit_p (tree decl)
+can_refer_decl_in_current_unit_p (tree decl, tree from_decl)
 {
   struct varpool_node *vnode;
   struct cgraph_node *node;
-
-  if (!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
+  symtab_node snode;
+
+  /* We will later output the initializer, so we can reffer to it.
+     So we are concerned only when DECL comes from initializer of
+     external var.  */
+  if (!from_decl
+      || TREE_CODE (from_decl) != VAR_DECL
+      || !DECL_EXTERNAL (from_decl)
+      || (symtab_get_node (from_decl)->symbol.in_other_partition))
+    return true;
+  /* We are concerned ony about static/external vars and functions.  */
+  if ((!TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
+      || (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL))
     return true;
-  /* External flag is set, so we deal with C++ reference
-     to static object from other file.
-     We also may see weakref that is always safe.  */
-  if (DECL_EXTERNAL (decl) && TREE_STATIC (decl)
-      && TREE_CODE (decl) == VAR_DECL)
-    return lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)) != NULL;
+  /* Weakrefs have somewhat confusing DECL_EXTERNAL flag set; they are always safe.  */
+  if (DECL_EXTERNAL (decl)
+      && lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
+    return true;
+  /* We are folding reference from external vtable.  The vtable may reffer
+     to a symbol keyed to other compilation unit.  The other compilation
+     unit may be in separate DSO and the symbol may be hidden.  */
+  if (DECL_VISIBILITY_SPECIFIED (decl)
+      && DECL_EXTERNAL (decl)
+      && (!(snode = symtab_get_node (decl)) || !snode->symbol.in_other_partition))
+    return false;
   /* When function is public, we always can introduce new reference.
      Exception are the COMDAT functions where introducing a direct
      reference imply need to include function body in the curren tunit.  */
@@ -75,14 +92,19 @@ can_refer_decl_in_current_unit_p (tree decl)
   /* We are not at ltrans stage; so don't worry about WHOPR.
      Also when still gimplifying all referred comdat functions will be
      produced.
-     ??? as observed in PR20991 for already optimized out comdat virtual functions
-     we may not neccesarily give up because the copy will be output elsewhere when
-     corresponding vtable is output.  */
+
+     As observed in PR20991 for already optimized out comdat virtual functions
+     it may be tempting to not neccesarily give up because the copy will be
+     output elsewhere when corresponding vtable is output.  
+     This is however not possible - ABI specify that COMDATs are output in
+     units where they are used and when the other unit was compiled with LTO
+     it is possible that vtable was kept public while the function itself
+     was privatized. */
   if (!flag_ltrans && (!DECL_COMDAT (decl) || !cgraph_function_flags_ready))
     return true;
-  /* If we already output the function body, we are safe.  */
-  if (TREE_ASM_WRITTEN (decl))
-    return true;
+
+  /* OK we are seeing either COMDAT or static variable.  In this case we must
+     check that the definition is still around so we can refer it.  */
   if (TREE_CODE (decl) == FUNCTION_DECL)
     {
       node = cgraph_get_node (decl);
@@ -92,22 +114,29 @@ can_refer_decl_in_current_unit_p (tree decl)
          compilation stage when making a new reference no longer makes callee
          to be compiled.  */
       if (!node || !node->analyzed || node->global.inlined_to)
-       return false;
+       {
+         gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
+         return false;
+       }
     }
   else if (TREE_CODE (decl) == VAR_DECL)
     {
       vnode = varpool_get_node (decl);
-      if (!vnode || !vnode->finalized)
-       return false;
+      if (!vnode || !vnode->analyzed)
+       {
+         gcc_checking_assert (!TREE_ASM_WRITTEN (decl));
+         return false;
+       }
     }
   return true;
 }
 
 /* CVAL is value taken from DECL_INITIAL of variable.  Try to transform it into
-   acceptable form for is_gimple_min_invariant.   */
+   acceptable form for is_gimple_min_invariant.
+   FROM_DECL (if non-NULL) specify variable whose constructor contains CVAL.  */
 
 tree
-canonicalize_constructor_val (tree cval)
+canonicalize_constructor_val (tree cval, tree from_decl)
 {
   STRIP_NOPS (cval);
   if (TREE_CODE (cval) == POINTER_PLUS_EXPR
@@ -130,7 +159,7 @@ canonicalize_constructor_val (tree cval)
 
       if ((TREE_CODE (base) == VAR_DECL
           || TREE_CODE (base) == FUNCTION_DECL)
-         && !can_refer_decl_in_current_unit_p (base))
+         && !can_refer_decl_in_current_unit_p (base, from_decl))
        return NULL_TREE;
       if (TREE_CODE (base) == VAR_DECL)
        {
@@ -163,7 +192,7 @@ get_symbol_constant_value (tree sym)
       tree val = DECL_INITIAL (sym);
       if (val)
        {
-         val = canonicalize_constructor_val (val);
+         val = canonicalize_constructor_val (val, sym);
          if (val && is_gimple_min_invariant (val))
            return val;
          else
@@ -2627,7 +2656,7 @@ gimple_fold_stmt_to_constant (gimple stmt, tree (*valueize) (tree))
 
 static tree fold_ctor_reference (tree type, tree ctor,
                                 unsigned HOST_WIDE_INT offset,
-                                unsigned HOST_WIDE_INT size);
+                                unsigned HOST_WIDE_INT size, tree);
 
 /* See if we can find constructor defining value of BASE.
    When we know the consructor with constant offset (such as
@@ -2735,7 +2764,8 @@ fold_string_cst_ctor_reference (tree type, tree ctor,
 static tree
 fold_array_ctor_reference (tree type, tree ctor,
                           unsigned HOST_WIDE_INT offset,
-                          unsigned HOST_WIDE_INT size)
+                          unsigned HOST_WIDE_INT size,
+                          tree from_decl)
 {
   unsigned HOST_WIDE_INT cnt;
   tree cfield, cval;
@@ -2824,7 +2854,8 @@ fold_array_ctor_reference (tree type, tree ctor,
       /* Do we have match?  */
       if (double_int_cmp (access_index, index, 1) >= 0
          && double_int_cmp (access_index, max_index, 1) <= 0)
-       return fold_ctor_reference (type, cval, inner_offset, size);
+       return fold_ctor_reference (type, cval, inner_offset, size,
+                                   from_decl);
     }
   /* When memory is not explicitely mentioned in constructor,
      it is 0 (or out of range).  */
@@ -2837,7 +2868,8 @@ fold_array_ctor_reference (tree type, tree ctor,
 static tree
 fold_nonarray_ctor_reference (tree type, tree ctor,
                              unsigned HOST_WIDE_INT offset,
-                             unsigned HOST_WIDE_INT size)
+                             unsigned HOST_WIDE_INT size,
+                             tree from_decl)
 {
   unsigned HOST_WIDE_INT cnt;
   tree cfield, cval;
@@ -2892,7 +2924,8 @@ fold_nonarray_ctor_reference (tree type, tree ctor,
          if (double_int_cmp (uhwi_to_double_int (offset), bitoffset, 0) < 0)
            return NULL_TREE;
          return fold_ctor_reference (type, cval,
-                                     double_int_to_uhwi (inner_offset), size);
+                                     double_int_to_uhwi (inner_offset), size,
+                                     from_decl);
        }
     }
   /* When memory is not explicitely mentioned in constructor, it is 0.  */
@@ -2904,14 +2937,14 @@ fold_nonarray_ctor_reference (tree type, tree ctor,
 
 static tree
 fold_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT offset,
-                    unsigned HOST_WIDE_INT size)
+                    unsigned HOST_WIDE_INT size, tree from_decl)
 {
   tree ret;
 
   /* We found the field with exact match.  */
   if (useless_type_conversion_p (type, TREE_TYPE (ctor))
       && !offset)
-    return canonicalize_constructor_val (ctor);
+    return canonicalize_constructor_val (ctor, from_decl);
 
   /* We are at the end of walk, see if we can view convert the
      result.  */
@@ -2920,7 +2953,7 @@ fold_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT offset,
       && operand_equal_p (TYPE_SIZE (type),
                          TYPE_SIZE (TREE_TYPE (ctor)), 0))
     {
-      ret = canonicalize_constructor_val (ctor);
+      ret = canonicalize_constructor_val (ctor, from_decl);
       ret = fold_unary (VIEW_CONVERT_EXPR, type, ret);
       if (ret)
        STRIP_NOPS (ret);
@@ -2933,9 +2966,11 @@ fold_ctor_reference (tree type, tree ctor, unsigned HOST_WIDE_INT offset,
 
       if (TREE_CODE (TREE_TYPE (ctor)) == ARRAY_TYPE
          || TREE_CODE (TREE_TYPE (ctor)) == VECTOR_TYPE)
-       return fold_array_ctor_reference (type, ctor, offset, size);
+       return fold_array_ctor_reference (type, ctor, offset, size,
+                                         from_decl);
       else
-       return fold_nonarray_ctor_reference (type, ctor, offset, size);
+       return fold_nonarray_ctor_reference (type, ctor, offset, size,
+                                            from_decl);
     }
 
   return NULL_TREE;
@@ -3008,7 +3043,8 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
                return NULL_TREE;
              return fold_ctor_reference (TREE_TYPE (t), ctor, offset,
                                          TREE_INT_CST_LOW (unit_size)
-                                         * BITS_PER_UNIT);
+                                         * BITS_PER_UNIT,
+                                         base);
            }
        }
       /* Fallthru.  */
@@ -3034,7 +3070,8 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
       if (offset < 0)
        return NULL_TREE;
 
-      return fold_ctor_reference (TREE_TYPE (t), ctor, offset, size);
+      return fold_ctor_reference (TREE_TYPE (t), ctor, offset, size,
+                                 base);
 
     case REALPART_EXPR:
     case IMAGPART_EXPR:
@@ -3068,9 +3105,9 @@ tree
 gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo)
 {
   unsigned HOST_WIDE_INT offset, size;
-  tree v, fn;
+  tree v, fn, vtable;
 
-  v = BINFO_VTABLE (known_binfo);
+  vtable = v = BINFO_VTABLE (known_binfo);
   /* If there is no virtual methods table, leave the OBJ_TYPE_REF alone.  */
   if (!v)
     return NULL_TREE;
@@ -3096,7 +3133,7 @@ gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo)
   size = tree_low_cst (TYPE_SIZE (TREE_TYPE (TREE_TYPE (v))), 1);
   offset += token * size;
   fn = fold_ctor_reference (TREE_TYPE (TREE_TYPE (v)), DECL_INITIAL (v),
-                           offset, size);
+                           offset, size, vtable);
   if (!fn || integer_zerop (fn))
     return NULL_TREE;
   gcc_assert (TREE_CODE (fn) == ADDR_EXPR
@@ -3108,7 +3145,7 @@ gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo)
      devirtualize.  This can happen in WHOPR when the actual method
      ends up in other partition, because we found devirtualization
      possibility too late.  */
-  if (!can_refer_decl_in_current_unit_p (fn))
+  if (!can_refer_decl_in_current_unit_p (fn, vtable))
     return NULL_TREE;
 
   /* Make sure we create a cgraph node for functions we'll reference.
index 2b10f1a9b1477e4a1a09bfdab5b8afeeee3ed51c..aefccaaeab7c301560a8863ba0e2799130a5f3bb 100644 (file)
@@ -5315,7 +5315,7 @@ tree gimple_fold_builtin (gimple);
 bool fold_stmt (gimple_stmt_iterator *);
 bool fold_stmt_inplace (gimple_stmt_iterator *);
 tree get_symbol_constant_value (tree);
-tree canonicalize_constructor_val (tree);
+tree canonicalize_constructor_val (tree, tree);
 extern tree maybe_fold_and_comparisons (enum tree_code, tree, tree, 
                                        enum tree_code, tree, tree);
 extern tree maybe_fold_or_comparisons (enum tree_code, tree, tree,