[PATCH] Break too deep TER chains for debug stmts during expansion (PR debug/64817)

Jakub Jelinek jakub@redhat.com
Fri Jan 30 19:01:00 GMT 2015


Hi!

As the following two testcases show, while we have avoid_complex_debug_insns
that decreases debug insn complexity after expansion is done, there is a
problem during expansion if the TER chains are too deep, because
simplify-rtx.c in some cases is inherently quadratic - does not like
arbitrarily large RTL expressions.

The following patch fixes that by breaking the TER chains for debug insns
by adding DEBUG_EXPR_DECLs temporaries.  Some non-zero depth is desirable,
we want to simplify things, but must avoid creating too large expressions
that way.

The patch inserts the debug bind stmts early during expansion, but of course
can't adjust the uses of those SSA_NAMEs, because those are used by
non-debug stmts too, so keeps the SSA_NAME -> DEBUG_EXPR_DECL mapping in a
hash_map.

Bootstrapped/regtested on x86_64-linux and i686-linux, with only very
minimal effect on debug info, e.g. in x86_64-linux bootstrap only
debug info of dominance.o, ipa-polymorphic-call.o and lto-streamer-out.o
is affected, and only a few .debug_info/.debug_loc section byte differences.

Ok for trunk?

2015-01-30  Jakub Jelinek  <jakub@redhat.com>

	PR debug/64817
	* cfgexpand.c (deep_ter_debug_map): New variable.
	(avoid_deep_ter_for_debug): New function.
	(expand_debug_expr): If TERed SSA_NAME is in
	deep_ter_debug_map, use the corresponding DEBUG_EXPR_DECL
	instead of trying to expand SSA_NAME's def stmt.
	(expand_debug_locations): When expanding debug bind
	of a DEBUG_EXPR_DECL to corresponding SSA_NAME,
	temporarily remove the DEBUG_EXPR_DECL from deep_ter_debug_map's
	value.
	(pass_expand::execute): Call avoid_deep_ter_for_debug on
	all debug bind stmts.  Delete deep_ter_debug_map after
	expand_debug_location if non-NULL and clear it.

	* gcc.dg/pr64817-1.c: New test.
	* gcc.dg/pr64817-2.c: New test.

--- gcc/cfgexpand.c.jj	2015-01-28 21:24:56.000000000 +0100
+++ gcc/cfgexpand.c	2015-01-30 13:22:46.002579984 +0100
@@ -3767,6 +3767,48 @@ convert_debug_memory_address (machine_mo
   return x;
 }
 
+/* Map from SSA_NAMEs to corresponding DEBUG_EXPR_DECLs created
+   by avoid_deep_ter_for_debug.  */
+
+hash_map<tree, tree> *deep_ter_debug_map;
+
+/* Split too deep TER chains for debug stmts using debug temporaries.  */
+
+static void
+avoid_deep_ter_for_debug (gimple stmt, int depth)
+{
+  use_operand_p use_p;
+  ssa_op_iter iter;
+  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+    {
+      tree use = USE_FROM_PTR (use_p);
+      if (TREE_CODE (use) != SSA_NAME || SSA_NAME_IS_DEFAULT_DEF (use))
+	continue;
+      gimple g = get_gimple_for_ssa_name (use);
+      if (g == NULL)
+	continue;
+      if (depth > 6 && !stmt_ends_bb_p (g))
+	{
+	  if (deep_ter_debug_map == NULL)
+	    deep_ter_debug_map = new hash_map<tree, tree>;
+
+	  tree &vexpr = deep_ter_debug_map->get_or_insert (use);
+	  if (vexpr != NULL)
+	    continue;
+	  vexpr = make_node (DEBUG_EXPR_DECL);
+	  gimple def_temp = gimple_build_debug_bind (vexpr, use, g);
+	  DECL_ARTIFICIAL (vexpr) = 1;
+	  TREE_TYPE (vexpr) = TREE_TYPE (use);
+	  DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (use));
+	  gimple_stmt_iterator gsi = gsi_for_stmt (g);
+	  gsi_insert_after (&gsi, def_temp, GSI_NEW_STMT);
+	  avoid_deep_ter_for_debug (def_temp, 0);
+	}
+      else
+	avoid_deep_ter_for_debug (g, depth + 1);
+    }
+}
+
 /* Return an RTX equivalent to the value of the parameter DECL.  */
 
 static rtx
@@ -4654,7 +4696,16 @@ expand_debug_expr (tree exp)
 	gimple g = get_gimple_for_ssa_name (exp);
 	if (g)
 	  {
-	    op0 = expand_debug_expr (gimple_assign_rhs_to_tree (g));
+	    tree t = NULL_TREE;
+	    if (deep_ter_debug_map)
+	      {
+		tree *slot = deep_ter_debug_map->get (exp);
+		if (slot)
+		  t = *slot;
+	      }
+	    if (t == NULL_TREE)
+	      t = gimple_assign_rhs_to_tree (g);
+	    op0 = expand_debug_expr (t);
 	    if (!op0)
 	      return NULL;
 	  }
@@ -4961,6 +5012,25 @@ expand_debug_locations (void)
 	    if (INSN_VAR_LOCATION_STATUS (insn)
 		== VAR_INIT_STATUS_UNINITIALIZED)
 	      val = expand_debug_source_expr (value);
+	    /* The avoid_deep_ter_for_debug function inserts
+	       debug bind stmts after SSA_NAME definition, with the
+	       SSA_NAME as the whole bind location.  Disable temporarily
+	       expansion of that SSA_NAME into the DEBUG_EXPR_DECL
+	       being defined in this DEBUG_INSN.  */
+	    else if (deep_ter_debug_map && TREE_CODE (value) == SSA_NAME)
+	      {
+		tree *slot = deep_ter_debug_map->get (value);
+		if (slot)
+		  {
+		    if (*slot == INSN_VAR_LOCATION_DECL (insn))
+		      *slot = NULL_TREE;
+		    else
+		      slot = NULL;
+		  }
+		val = expand_debug_expr (value);
+		if (slot)
+		  *slot = INSN_VAR_LOCATION_DECL (insn);
+	      }
 	    else
 	      val = expand_debug_expr (value);
 	    gcc_assert (last == get_last_insn ());
@@ -5821,6 +5891,15 @@ pass_expand::execute (function *fun)
   timevar_pop (TV_OUT_OF_SSA);
   SA.partition_to_pseudo = XCNEWVEC (rtx, SA.map->num_partitions);
 
+  if (MAY_HAVE_DEBUG_STMTS && flag_tree_ter)
+    {
+      gimple_stmt_iterator gsi;
+      FOR_EACH_BB_FN (bb, cfun)
+	for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+	  if (gimple_debug_bind_p (gsi_stmt (gsi)))
+	    avoid_deep_ter_for_debug (gsi_stmt (gsi), 0);
+    }
+
   /* Make sure all values used by the optimization passes have sane
      defaults.  */
   reg_renumber = 0;
@@ -6008,6 +6087,12 @@ pass_expand::execute (function *fun)
   if (MAY_HAVE_DEBUG_INSNS)
     expand_debug_locations ();
 
+  if (deep_ter_debug_map)
+    {
+      delete deep_ter_debug_map;
+      deep_ter_debug_map = NULL;
+    }
+
   /* Free stuff we no longer need after GIMPLE optimizations.  */
   free_dominance_info (CDI_DOMINATORS);
   free_dominance_info (CDI_POST_DOMINATORS);
--- gcc/testsuite/gcc.dg/pr64817-1.c.jj	2015-01-30 13:33:05.061143850 +0100
+++ gcc/testsuite/gcc.dg/pr64817-1.c	2015-01-30 13:32:33.000000000 +0100
@@ -0,0 +1,20 @@
+/* PR debug/64817 */
+/* { dg-do compile } */
+/* { dg-options "-O3 -g" } */
+
+int a, b, d;
+
+void
+foo (void)
+{
+  for (b = 0; b < 9; b++)
+    {
+      int e;
+      for (d = 0; d < 5; d++)
+	{
+	  a &= 231;
+	  a ^= 14;
+	}
+      e = (a ^= 1) < 0;
+    }
+}
--- gcc/testsuite/gcc.dg/pr64817-2.c.jj	2015-01-20 10:01:16.345964420 +0100
+++ gcc/testsuite/gcc.dg/pr64817-2.c	2015-01-30 18:37:49.055911292 +0100
@@ -0,0 +1,13 @@
+/* PR debug/64817 */
+/* { dg-do compile } */
+/* { dg-options "-O3 -g" } */
+
+int a;
+
+void
+foo (void)
+{
+  int e;
+  a = ((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((a & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) & 231) ^ 14) ^ 1;
+  e = (a < 0);
+}

	Jakub



More information about the Gcc-patches mailing list