public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Fix PR82060
@ 2017-09-04 10:40 Richard Biener
  0 siblings, 0 replies; only message in thread
From: Richard Biener @ 2017-09-04 10:40 UTC (permalink / raw)
  To: gcc-patches


The following fixes PR82060 but canonicalizing mems before dispatching
to the devrit machinery.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2017-09-04  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/82060
	* tree-ssa-pre.c (eliminate_dom_walker::before_dom_children):
	Move devirtualization after stmt folding and before EH/AB/noreturn
	cleanup to get the stmt refs canonicalized.  Use a bool instead
	of gimple_modified_p since that doesn't work for NOPs.  Schedule
	NOPs generated by folding for removal.

	* g++.dg/torture/pr82060.C: New testcase.

Index: gcc/tree-ssa-pre.c
===================================================================
--- gcc/tree-ssa-pre.c	(revision 251559)
+++ gcc/tree-ssa-pre.c	(working copy)
@@ -4592,6 +4592,7 @@ eliminate_dom_walker::before_dom_childre
       /* If we didn't replace the whole stmt (or propagate the result
          into all uses), replace all uses on this stmt with their
 	 leaders.  */
+      bool modified = false;
       use_operand_p use_p;
       ssa_op_iter iter;
       FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
@@ -4613,7 +4614,7 @@ eliminate_dom_walker::before_dom_childre
 		  || !bitmap_bit_p (inserted_exprs, SSA_NAME_VERSION (sprime))))
 	    {
 	      propagate_value (use_p, sprime);
-	      gimple_set_modified (stmt, true);
+	      modified = true;
 	      if (TREE_CODE (sprime) == SSA_NAME
 		  && !is_gimple_debug (stmt))
 		gimple_set_plf (SSA_NAME_DEF_STMT (sprime),
@@ -4621,8 +4622,56 @@ eliminate_dom_walker::before_dom_childre
 	    }
 	}
 
+      /* Fold the stmt if modified, this canonicalizes MEM_REFs we propagated
+         into which is a requirement for the IPA devirt machinery.  */
+      gimple *old_stmt = stmt;
+      if (modified)
+	{
+	  /* If a formerly non-invariant ADDR_EXPR is turned into an
+	     invariant one it was on a separate stmt.  */
+	  if (gimple_assign_single_p (stmt)
+	      && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR)
+	    recompute_tree_invariant_for_addr_expr (gimple_assign_rhs1 (stmt));
+	  gimple_stmt_iterator prev = gsi;
+	  gsi_prev (&prev);
+	  if (fold_stmt (&gsi))
+	    {
+	      /* fold_stmt may have created new stmts inbetween
+		 the previous stmt and the folded stmt.  Mark
+		 all defs created there as varying to not confuse
+		 the SCCVN machinery as we're using that even during
+		 elimination.  */
+	      if (gsi_end_p (prev))
+		prev = gsi_start_bb (b);
+	      else
+		gsi_next (&prev);
+	      if (gsi_stmt (prev) != gsi_stmt (gsi))
+		do
+		  {
+		    tree def;
+		    ssa_op_iter dit;
+		    FOR_EACH_SSA_TREE_OPERAND (def, gsi_stmt (prev),
+					       dit, SSA_OP_ALL_DEFS)
+		      /* As existing DEFs may move between stmts
+			 we have to guard VN_INFO_GET.  */
+		      if (! has_VN_INFO (def))
+			VN_INFO_GET (def)->valnum = def;
+		    if (gsi_stmt (prev) == gsi_stmt (gsi))
+		      break;
+		    gsi_next (&prev);
+		  }
+		while (1);
+	    }
+	  stmt = gsi_stmt (gsi);
+	  /* In case we folded the stmt away schedule the NOP for removal.  */
+	  if (gimple_nop_p (stmt))
+	    el_to_remove.safe_push (stmt);
+	}
+
       /* Visit indirect calls and turn them into direct calls if
-	 possible using the devirtualization machinery.  */
+	 possible using the devirtualization machinery.  Do this before
+	 checking for required EH/abnormal/noreturn cleanup as devird
+	 may expose more of those.  */
       if (gcall *call_stmt = dyn_cast <gcall *> (stmt))
 	{
 	  tree fn = gimple_call_fn (call_stmt);
@@ -4631,24 +4680,21 @@ eliminate_dom_walker::before_dom_childre
 	      && virtual_method_call_p (fn))
 	    {
 	      tree otr_type = obj_type_ref_class (fn);
+	      unsigned HOST_WIDE_INT otr_tok
+		= tree_to_uhwi (OBJ_TYPE_REF_TOKEN (fn));
 	      tree instance;
-	      ipa_polymorphic_call_context context (current_function_decl, fn, stmt, &instance);
+	      ipa_polymorphic_call_context context (current_function_decl,
+						    fn, stmt, &instance);
+	      context.get_dynamic_type (instance, OBJ_TYPE_REF_OBJECT (fn),
+					otr_type, stmt);
 	      bool final;
-
-	      context.get_dynamic_type (instance, OBJ_TYPE_REF_OBJECT (fn), otr_type, stmt);
-
-	      vec <cgraph_node *>targets
+	      vec <cgraph_node *> targets
 		= possible_polymorphic_call_targets (obj_type_ref_class (fn),
-						     tree_to_uhwi
-						       (OBJ_TYPE_REF_TOKEN (fn)),
-						     context,
-						     &final);
+						     otr_tok, context, &final);
 	      if (dump_file)
 		dump_possible_polymorphic_call_targets (dump_file, 
 							obj_type_ref_class (fn),
-							tree_to_uhwi
-							  (OBJ_TYPE_REF_TOKEN (fn)),
-							context);
+							otr_tok, context);
 	      if (final && targets.length () <= 1 && dbg_cnt (devirt))
 		{
 		  tree fn;
@@ -4658,7 +4704,7 @@ eliminate_dom_walker::before_dom_childre
 		    fn = builtin_decl_implicit (BUILT_IN_UNREACHABLE);
 		  if (dump_enabled_p ())
 		    {
-		      location_t loc = gimple_location_safe (stmt);
+		      location_t loc = gimple_location (stmt);
 		      dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
 				       "converting indirect call to "
 				       "function %s\n",
@@ -4675,50 +4721,13 @@ eliminate_dom_walker::before_dom_childre
 			  == void_type_node))
 		    gimple_call_set_fntype (call_stmt, TREE_TYPE (fn));
 		  maybe_remove_unused_call_args (cfun, call_stmt);
-		  gimple_set_modified (stmt, true);
+		  modified = true;
 		}
 	    }
 	}
 
-      if (gimple_modified_p (stmt))
+      if (modified)
 	{
-	  /* If a formerly non-invariant ADDR_EXPR is turned into an
-	     invariant one it was on a separate stmt.  */
-	  if (gimple_assign_single_p (stmt)
-	      && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR)
-	    recompute_tree_invariant_for_addr_expr (gimple_assign_rhs1 (stmt));
-	  gimple *old_stmt = stmt;
-	  gimple_stmt_iterator prev = gsi;
-	  gsi_prev (&prev);
-	  if (fold_stmt (&gsi))
-	    {
-	      /* fold_stmt may have created new stmts inbetween
-		 the previous stmt and the folded stmt.  Mark
-		 all defs created there as varying to not confuse
-		 the SCCVN machinery as we're using that even during
-		 elimination.  */
-	      if (gsi_end_p (prev))
-		prev = gsi_start_bb (b);
-	      else
-		gsi_next (&prev);
-	      if (gsi_stmt (prev) != gsi_stmt (gsi))
-		do
-		  {
-		    tree def;
-		    ssa_op_iter dit;
-		    FOR_EACH_SSA_TREE_OPERAND (def, gsi_stmt (prev),
-					       dit, SSA_OP_ALL_DEFS)
-		      /* As existing DEFs may move between stmts
-			 we have to guard VN_INFO_GET.  */
-		      if (! has_VN_INFO (def))
-			VN_INFO_GET (def)->valnum = def;
-		    if (gsi_stmt (prev) == gsi_stmt (gsi))
-		      break;
-		    gsi_next (&prev);
-		  }
-		while (1);
-	    }
-	  stmt = gsi_stmt (gsi);
 	  /* When changing a call into a noreturn call, cfg cleanup
 	     is needed to fix up the noreturn call.  */
 	  if (!was_noreturn
Index: gcc/testsuite/g++.dg/torture/pr82060.C
===================================================================
--- gcc/testsuite/g++.dg/torture/pr82060.C	(nonexistent)
+++ gcc/testsuite/g++.dg/torture/pr82060.C	(working copy)
@@ -0,0 +1,32 @@
+// { dg-do compile }
+
+struct A
+{
+  char a[1]; // must be char array
+};
+
+struct B
+{
+  A& a() { return ma; } // must be accessed through a getter
+  A ma;
+};
+
+struct C
+{
+  B& b() { return mb; } // must be accessed through a getter
+  B mb;
+};
+
+struct D
+{
+  virtual A getA() = 0; // must be virtual
+};
+
+void
+foo(D& d) // The D object must not be created locally
+          // (so that getA implementation is not known at compile time?)
+{
+  C c;
+  for (;;) // must be in a loop
+    c.b().a() = d.getA();
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2017-09-04 10:40 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-04 10:40 [PATCH] Fix PR82060 Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).