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]

Update construction tracking in ipa-prop for new code


Hi,
this patch adds basic tracking of what types may be in construction because the
call appears in a polymorphic cdtor.

Bootstrapped/regtested x86_64-linux, comitted.

Honza
	* cgraph.h (struct indirect_call_info): Add IN_POLYMORPHIC_CDTOR
	* lto-cgraph.c (lto_output_edge, input_edge): Stream
	in_polymorphic_cdtor
	* cgraph.c (symbol_table::create_edge): Compute in_polymorphic_cdtor.
	(cgraph_edge::make_speculative): Copy in_polymorphic_cdtor.
	* cgraphclones.c (cgraph_edge::clone): Likewise.
	* ipa-prop.c (update_jump_functions_after_inlining, 
	try_make_edge_direct_virtual_call): Pass in_polymorphic_cdtor
	to possible_dynamic_type_change.
	(decl_maybe_in_construction_p): Allow empty OUTER_TYPE and BASE.
	(ipa_polymorphic_call_context::possible_dynamic_type_change): Add
	IN_POLY_CDOTR argument.

Index: cgraph.h
===================================================================
--- cgraph.h	(revision 215870)
+++ cgraph.h	(working copy)
@@ -1333,7 +1333,7 @@ public:
   void offset_by (HOST_WIDE_INT);
   /* Use when we can not track dynamic type change.  This speculatively assume
      type change is not happening.  */
-  void possible_dynamic_type_change (tree otr_type = NULL);
+  void possible_dynamic_type_change (bool, tree otr_type = NULL);
   /* Assume that both THIS and a given context is valid and strenghten THIS
      if possible.  Return true if any strenghtening was made.
      If actual type the context is being used in is known, OTR_TYPE should be
@@ -1512,6 +1512,9 @@ struct GTY((chain_next ("%h.next_caller"
      Optimizers may later redirect direct call to clone, so 1) and 3)
      do not need to necesarily agree with destination.  */
   unsigned int speculative : 1;
+  /* Set to true when caller is a constructor or destructor of polymorphic
+     type.  */
+  unsigned in_polymorphic_cdtor : 1;
 
 private:
   /* Remove the edge from the list of the callers of the callee.  */
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 215870)
+++ lto-cgraph.c	(working copy)
@@ -284,6 +284,7 @@ lto_output_edge (struct lto_simple_outpu
   bp_pack_value (&bp, edge->speculative, 1);
   bp_pack_value (&bp, edge->call_stmt_cannot_inline_p, 1);
   bp_pack_value (&bp, edge->can_throw_external, 1);
+  bp_pack_value (&bp, edge->in_polymorphic_cdtor, 1);
   if (edge->indirect_unknown_callee)
     {
       int flags = edge->indirect_info->ecf_flags;
@@ -1366,6 +1367,7 @@ input_edge (struct lto_input_block *ib,
   edge->inline_failed = inline_failed;
   edge->call_stmt_cannot_inline_p = bp_unpack_value (&bp, 1);
   edge->can_throw_external = bp_unpack_value (&bp, 1);
+  edge->in_polymorphic_cdtor = bp_unpack_value (&bp, 1);
   if (indirect)
     {
       if (bp_unpack_value (&bp, 1))
Index: cgraph.c
===================================================================
--- cgraph.c	(revision 215870)
+++ cgraph.c	(working copy)
@@ -819,6 +819,12 @@ symbol_table::create_edge (cgraph_node *
   edge->indirect_inlining_edge = 0;
   edge->speculative = false;
   edge->indirect_unknown_callee = indir_unknown_callee;
+  if (flag_devirtualize && call_stmt && DECL_STRUCT_FUNCTION (caller->decl))
+    edge->in_polymorphic_cdtor
+      = decl_maybe_in_construction_p (NULL, NULL, call_stmt,
+				      caller->decl);
+  else
+    edge->in_polymorphic_cdtor = caller->thunk.thunk_p;
   if (call_stmt && caller->call_site_hash)
     cgraph_add_edge_to_call_site_hash (edge);
 
@@ -1033,6 +1039,7 @@ cgraph_edge::make_speculative (cgraph_no
   else
     e2->can_throw_external = can_throw_external;
   e2->lto_stmt_uid = lto_stmt_uid;
+  e2->in_polymorphic_cdtor = in_polymorphic_cdtor;
   count -= e2->count;
   frequency -= e2->frequency;
   symtab->call_edge_duplication_hooks (this, e2);
Index: cgraphclones.c
===================================================================
--- cgraphclones.c	(revision 215870)
+++ cgraphclones.c	(working copy)
@@ -159,6 +159,7 @@ cgraph_edge::clone (cgraph_node *n, gimp
   new_edge->can_throw_external = can_throw_external;
   new_edge->call_stmt_cannot_inline_p = call_stmt_cannot_inline_p;
   new_edge->speculative = speculative;
+  new_edge->in_polymorphic_cdtor = in_polymorphic_cdtor;
   if (update_original)
     {
       count -= new_edge->count;
Index: ipa-prop.c
===================================================================
--- ipa-prop.c	(revision 215870)
+++ ipa-prop.c	(working copy)
@@ -2652,7 +2652,7 @@ update_jump_functions_after_inlining (st
 
 	      /* TODO: Make type preserved safe WRT contexts.  */
 	      if (!dst->value.ancestor.agg_preserved)
-		ctx.possible_dynamic_type_change ();
+		ctx.possible_dynamic_type_change (e->in_polymorphic_cdtor);
 	      ctx.offset_by (dst->value.ancestor.offset);
 	      if (!ctx.useless_p ())
 		{
@@ -2722,7 +2722,7 @@ update_jump_functions_after_inlining (st
 
 		  /* TODO: Make type preserved safe WRT contexts.  */
 		  if (!dst->value.ancestor.agg_preserved)
-		    ctx.possible_dynamic_type_change ();
+		    ctx.possible_dynamic_type_change (e->in_polymorphic_cdtor);
 		  if (!ctx.useless_p ())
 		    {
 		      if (!dst_ctx)
@@ -3128,7 +3128,8 @@ try_make_edge_direct_virtual_call (struc
 
       /* TODO: We want to record if type change happens.  
 	 Old code did not do that that seems like a bug.  */
-      ctx.possible_dynamic_type_change (ie->indirect_info->otr_type);
+      ctx.possible_dynamic_type_change (ie->in_polymorphic_cdtor,
+					ie->indirect_info->otr_type);
 
       updated = ie->indirect_info->context.combine_with
 		  (ctx, ie->indirect_info->otr_type);
Index: ipa-polymorphic-call.c
===================================================================
--- ipa-polymorphic-call.c	(revision 215870)
+++ ipa-polymorphic-call.c	(working copy)
@@ -475,6 +475,11 @@ contains_type_p (tree outer_type, HOST_W
    (not dynamically allocated) and we want to disprove the fact
    that it may be in construction at invocation of CALL.
 
+   BASE represents memory location where instance is stored.
+   If BASE is NULL, it is assumed to be global memory.
+   OUTER_TYPE is known type of the instance or NULL if not
+   known.
+
    For the variable to be in construction we actually need to
    be in constructor of corresponding global variable or
    the inline stack of CALL must contain the constructor.
@@ -486,8 +491,9 @@ bool
 decl_maybe_in_construction_p (tree base, tree outer_type,
 			      gimple call, tree function)
 {
-  outer_type = TYPE_MAIN_VARIANT (outer_type);
-  gcc_assert (DECL_P (base));
+  if (outer_type)
+    outer_type = TYPE_MAIN_VARIANT (outer_type);
+  gcc_assert (!base || DECL_P (base));
 
   /* After inlining the code unification optimizations may invalidate
      inline stacks.  Also we need to give up on global variables after
@@ -498,7 +504,7 @@ decl_maybe_in_construction_p (tree base,
 
   /* Pure functions can not do any changes on the dynamic type;
      that require writting to memory.  */
-  if (!auto_var_in_fn_p (base, function)
+  if (base && !auto_var_in_fn_p (base, function)
       && flags_from_decl_or_type (function) & (ECF_PURE | ECF_CONST))
     return false;
 
@@ -517,7 +523,7 @@ decl_maybe_in_construction_p (tree base,
 	       argument (pointer to the instance).  */
 	    fn = DECL_ABSTRACT_ORIGIN (fn);
 	    if (!fn
-		|| !is_global_var (base)
+		|| (!base || !is_global_var (base))
 	        || TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
 		|| (!DECL_CXX_CONSTRUCTOR_P (fn)
 		    && !DECL_CXX_DESTRUCTOR_P (fn)))
@@ -526,17 +532,20 @@ decl_maybe_in_construction_p (tree base,
 	if (flags_from_decl_or_type (fn) & (ECF_PURE | ECF_CONST))
 	  continue;
 
-	/* FIXME: this can go away once we have ODR types equivalency on
-	   LTO level.  */
-	if (in_lto_p && !polymorphic_type_binfo_p (TYPE_BINFO (outer_type)))
-	  return true;
 	tree type = TYPE_MAIN_VARIANT (method_class_type (TREE_TYPE (fn)));
-	if (types_same_for_odr (type, outer_type))
+
+	if (!outer_type || !types_odr_comparable (type, outer_type))
+	  {
+	    if (TREE_CODE (type) == RECORD_TYPE
+		&& TYPE_BINFO (type)
+		&& polymorphic_type_binfo_p (TYPE_BINFO (type)))
+	      return true;
+	  }
+ 	else if (types_same_for_odr (type, outer_type))
 	  return true;
       }
 
-  if (TREE_CODE (base) == VAR_DECL
-      && is_global_var (base))
+  if (!base || (TREE_CODE (base) == VAR_DECL && is_global_var (base)))
     {
       if (TREE_CODE (TREE_TYPE (function)) != METHOD_TYPE
 	  || (!DECL_CXX_CONSTRUCTOR_P (function)
@@ -553,12 +562,15 @@ decl_maybe_in_construction_p (tree base,
 		  && !DECL_CXX_DESTRUCTOR_P (function)))
 	    return false;
 	}
-      /* FIXME: this can go away once we have ODR types equivalency on
-	 LTO level.  */
-      if (in_lto_p && !polymorphic_type_binfo_p (TYPE_BINFO (outer_type)))
-	return true;
       tree type = TYPE_MAIN_VARIANT (method_class_type (TREE_TYPE (function)));
-      if (types_same_for_odr (type, outer_type))
+      if (!outer_type || !types_odr_comparable (type, outer_type))
+	{
+	  if (TREE_CODE (type) == RECORD_TYPE
+	      && TYPE_BINFO (type)
+	      && polymorphic_type_binfo_p (TYPE_BINFO (type)))
+	    return true;
+	}
+      else if (types_same_for_odr (type, outer_type))
 	return true;
     }
   return false;
@@ -2009,10 +2021,11 @@ ipa_polymorphic_call_context::make_specu
    type change is not happening.  */
 
 void
-ipa_polymorphic_call_context::possible_dynamic_type_change (tree otr_type)
+ipa_polymorphic_call_context::possible_dynamic_type_change (bool in_poly_cdtor,
+							    tree otr_type)
 {
   if (dynamic)
     make_speculative (otr_type);
-  else
+  else if (in_poly_cdtor)
     maybe_in_construction = true;
 }


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