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]

[PATCH] Don't track DEBUG_INSNs with constant values using VALUEs (PR debug/43058)


Hi!

This is one approach to fix PR43058, desirable anyway to decrease
var-tracking compile time slightly.
If we have debug_insn saying varx or D#x has value (const_int 6)
somewhere (or some other constant, as long as it isn't (const which
references registers or non-readonly memory)), storing a value for it
rather than jus the constant itself seems to be a waste, and, on the
testcase below causes it to emit huge amount of var_location notes,
whenever that constant is stored into some register or stack slot,
a note would be added saying that varx lives in that register or memory,
when next call invalidates that register or memory, another note would say
that varx again has value (const_int 6).  As the testcase has 2000 vars,
1000 with .LC0 and 1000 with .LC1 value and there are 1000 calls where
.LC0 is stored into argument register/stack slot, that means hundreds
of notes on each register set to .LC0/.LC1 and hundres of notes on each
call.  This is done only for MO_VAL_LOC, i.e. variables that have been
optimized out and known in some part of code to have constant value -
for debugging purpose it doesn't improve anything if we say that it
sometimes lives in register - modifying the register will not change the
optimized out variable anyway (either nothing at all, or function argument,
or some other variable).

In the source code the vars are only live in a very short block,
unfortunately var-tracking doesn't know that, so assumes it needs to track
lifetime of each var for the rest of the function.
Perhaps if after vt_initialize we added some subpass that would walk the
insns and for each insn walked up the BLOCK tree (interesting would be
only BLOCKs that contain any localized or non-localized vars), noting in
which basic blocks which BLOCKs live.  Then, for each BLOCK see at least
if there are no insns in some bb or anything that bb dominates that have
that BLOCK in scope.  If there would be such bb, we could note somehow
that the all the vars from that BLOCK should not be live in that bb and
onwards.  Perhaps also do that for VALUEs that are only referenced by those
VALUEs we don't want to track anymore.  This could help to decrease
var-tracking cost for huge functions and could result in smaller
.debug_loc.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2010-03-18  Jakub Jelinek  <jakub@redhat.com>

	PR debug/43058
	* var-tracking.c (non_suitable_const): New function.
	(add_uses): For DEBUG_INSNs with constants, don't record any
	value, instead just the constant value itself.
	(compute_bb_dataflow) <case MO_VAL_LOC>: If PAT_VAR_LOCATION_LOC
	is not VAR_LOC_UNKNOWN_P, set var to the constant.
	(emit_notes_in_bb): Likewise.
	(emit_note_insn_var_location): For onepart variables if
	cur_loc is a VOIDmode constant, use DECL_MODE.

	* gcc.dg/pr43058.c: New test.

--- gcc/var-tracking.c.jj	2010-03-16 17:48:15.000000000 +0100
+++ gcc/var-tracking.c	2010-03-17 15:29:42.000000000 +0100
@@ -4738,6 +4738,33 @@ preserve_value (cselib_val *val)
   VEC_safe_push (rtx, heap, preserved_values, val->val_rtx);
 }
 
+/* Helper function for MO_VAL_LOC handling.  Return non-zero if
+   any rtxes not suitable for CONST use not replaced by VALUEs
+   are discovered.  */
+
+static int
+non_suitable_const (rtx *x, void *data ATTRIBUTE_UNUSED)
+{
+  if (*x == NULL_RTX)
+    return 0;
+
+  switch (GET_CODE (*x))
+    {
+    case REG:
+    case DEBUG_EXPR:
+    case PC:
+    case SCRATCH:
+    case CC0:
+    case ASM_INPUT:
+    case ASM_OPERANDS:
+      return 1;
+    case MEM:
+      return !MEM_READONLY_P (*x);
+    default:
+      return 0;
+    }
+}
+
 /* Add uses (register and memory references) LOC which will be tracked
    to VTI (bb)->mos.  INSN is instruction which the LOC is part of.  */
 
@@ -4794,8 +4821,12 @@ add_uses (rtx *ploc, void *data)
 		}
 	    }
 
-	  if (!VAR_LOC_UNKNOWN_P (vloc)
-	      && (val = find_use_val (vloc, GET_MODE (oloc), cui)))
+	  if (CONSTANT_P (vloc)
+	      && (GET_CODE (vloc) != CONST
+		  || for_each_rtx (&vloc, non_suitable_const, NULL)))
+	    /* For constants don't look up any value.  */;
+	  else if (!VAR_LOC_UNKNOWN_P (vloc)
+		   && (val = find_use_val (vloc, GET_MODE (oloc), cui)))
 	    {
 	      enum machine_mode mode2;
 	      enum micro_operation_type type2;
@@ -5508,6 +5539,11 @@ compute_bb_dataflow (basic_block bb)
 				     VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
 				     INSERT);
 		}
+	      else if (!VAR_LOC_UNKNOWN_P (PAT_VAR_LOCATION_LOC (vloc)))
+		set_variable_part (out, PAT_VAR_LOCATION_LOC (vloc),
+				   dv_from_decl (var), 0,
+				   VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
+				   INSERT);
 	    }
 	    break;
 
@@ -6902,6 +6938,8 @@ emit_note_insn_var_location (void **varp
 	}
       loc[n_var_parts] = loc2;
       mode = GET_MODE (var->var_part[i].cur_loc);
+      if (mode == VOIDmode && dv_onepart_p (var->dv))
+	mode = DECL_MODE (decl);
       for (lc = var->var_part[i].loc_chain; lc; lc = lc->next)
 	if (var->var_part[i].cur_loc == lc->loc)
 	  {
@@ -7423,6 +7461,11 @@ emit_notes_in_bb (basic_block bb, datafl
 				     VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
 				     INSERT);
 		}
+	      else if (!VAR_LOC_UNKNOWN_P (PAT_VAR_LOCATION_LOC (vloc)))
+		set_variable_part (set, PAT_VAR_LOCATION_LOC (vloc),
+				   dv_from_decl (var), 0,
+				   VAR_INIT_STATUS_INITIALIZED, NULL_RTX,
+				   INSERT);
 
 	      emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set->vars);
 	    }
--- gcc/testsuite/gcc.dg/pr43058.c.jj	2010-03-17 15:00:28.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr43058.c	2010-03-17 14:52:46.000000000 +0100
@@ -0,0 +1,20 @@
+/* PR debug/43058 */
+/* { dg-do compile } */
+/* { dg-options "-g -O2" } */
+
+extern void *f1 (void *, void *, void *);
+extern void *f2 (const char *, int, int, int, void *(*) ());
+extern void *f3 (const char *);
+extern void *f4 (void *s);
+extern void *f5 (void *);
+
+void test (void)
+{
+#define X1 f1 (f2 ("a", 1, 0, 0, f5), \
+	       f4 (({ const char *a = "b"; f3 (a); })), \
+	       ({ const char *a = "c"; f3 (a); }));
+#define X2 X1 X1 X1 X1 X1 X1 X1 X1 X1 X1
+#define X3 X2 X2 X2 X2 X2 X2 X2 X2 X2 X2
+#define X4 X3 X3 X3 X3 X3 X3 X3 X3 X3 X3
+  X4 X4
+}

	Jakub


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