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]

[vta, vta4.4, trunk?] calls affect location lists before they return


This patch fixes the other glitch I reported in the VTA guality
assessment.

Clobbers caused by calls take effect at the return site, rather than
while the call is ongoing.  If you're within the call, move up the stack
and inspect a variable that, before the call, was available in some
call-clobbered register, you may get an incorrect value, because GCC
says it's still available until the call returns.

This patch arranges for such clobbers to take effect before the call
returns, so that the clobbered location no longer appears to be valid.
In the current code, we don't emit multiple overlapping locations, but
with the change taking effect earlier, we emit an alternate location,
when one is available, so that it is the one selected before the call
returns.

Perhaps an example is in order:


        mov arg1 <- auto47
.L7:
        call foo
.L8:

Location lists for the variable held in auto47 (call-saved) might
currently look like:

??? <= pc < .L7 : temp47
.L7 <= pc < .L8 : arg1
.L8 <= pc < ??? : temp47

whereas with this patch it will be:

???   <= pc < .L7   : temp47
.L7   <= pc < .L8-1 : arg1
.L8-1 <= pc < ???   : temp47

so that, if you're at the call instruction, you can still find the
variable at arg1, but while the call is ongoing and after it returns,
you'll find it in temp47.

I suppose it might make sense to change the -1 to -(length of call - 1),
but it feels like overkill.  Thoughts?

Anyhow, I'm going ahead and checking this in the active VTA branches.
Is this ok for the trunk?

for  gcc/ChangeLog.vta
from  Alexandre Oliva  <aoliva@redhat.com>

	* rtl.h (NOTE_DURING_CALL_P): New.
	* var-tracking.c (enum emit_note_where): Add
	EMIT_NOTE_AFTER_CALL_INSN.
	(emit_note_insn_var_location): Mark during-call notes.
	(emit_notes_in_bb): Emit MO_CALL notes as during call.
	* dwarf2out.c (dwarf2out_var_location): Take during-call mark into
	account.

Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c.orig	2009-06-13 18:36:50.000000000 -0300
+++ gcc/dwarf2out.c	2009-06-13 19:34:45.000000000 -0300
@@ -15918,10 +15918,11 @@ dwarf2out_set_name (tree decl, tree name
 static void
 dwarf2out_var_location (rtx loc_note)
 {
-  char loclabel[MAX_ARTIFICIAL_LABEL_BYTES];
+  char loclabel[MAX_ARTIFICIAL_LABEL_BYTES + 2];
   struct var_loc_node *newloc;
   rtx next_real;
   static const char *last_label;
+  static const char *last_postcall_label;
   static bool last_in_cold_section_p;
   tree decl;
 
@@ -15937,27 +15938,38 @@ dwarf2out_var_location (rtx loc_note)
   newloc = GGC_CNEW (struct var_loc_node);
   /* If there were no real insns between note we processed last time
      and this note, use the label we emitted last time.  */
-  if (last_var_location_insn != NULL_RTX
-      && last_var_location_insn == next_real
-      && last_in_cold_section_p == in_cold_section_p)
-    newloc->label = last_label;
-  else
+  if (last_var_location_insn == NULL_RTX
+      || last_var_location_insn != next_real
+      || last_in_cold_section_p != in_cold_section_p)
     {
       ASM_GENERATE_INTERNAL_LABEL (loclabel, "LVL", loclabel_num);
       ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LVL", loclabel_num);
       loclabel_num++;
-      newloc->label = ggc_strdup (loclabel);
+      last_label = ggc_strdup (loclabel);
+      if (!NOTE_DURING_CALL_P (loc_note))
+	last_postcall_label = NULL;
     }
   newloc->var_loc_note = loc_note;
   newloc->next = NULL;
 
+  if (!NOTE_DURING_CALL_P (loc_note))
+    newloc->label = last_label;
+  else
+    {
+      if (!last_postcall_label)
+	{
+	  sprintf (loclabel, "%s-1", last_label);
+	  last_postcall_label = ggc_strdup (loclabel);
+	}
+      newloc->label = last_postcall_label;
+    }
+
   if (cfun && in_cold_section_p)
     newloc->section_label = crtl->subsections.cold_section_label;
   else
     newloc->section_label = text_section_label;
 
   last_var_location_insn = next_real;
-  last_label = newloc->label;
   last_in_cold_section_p = in_cold_section_p;
   decl = NOTE_VAR_LOCATION_DECL (loc_note);
   add_var_loc_to_decl (decl, newloc);
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h.orig	2009-06-13 18:36:50.000000000 -0300
+++ gcc/rtl.h	2009-06-13 18:36:52.000000000 -0300
@@ -918,6 +918,11 @@ extern const char * const reg_note_name[
 #define VAR_LOC_UNKNOWN_P(X) \
   (GET_CODE (X) == CLOBBER && XEXP ((X), 0) == const0_rtx)
 
+/* 1 if RTX is emitted after a call, but it should take effect before
+   the call returns.  */
+#define NOTE_DURING_CALL_P(RTX)				\
+  (RTL_FLAG_CHECK1("NOTE_VAR_LOCATION_DURING_CALL_P", (RTX), NOTE)->call)
+
 /* Possible initialization status of a variable.   When requested
    by the user, this information is tracked and recorded in the DWARF
    debug information, along with the variable's location.  */
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c.orig	2009-06-13 18:36:50.000000000 -0300
+++ gcc/var-tracking.c	2009-06-13 18:36:52.000000000 -0300
@@ -141,11 +141,14 @@ micro_operation_type_name[] = {
   "MO_ADJUST"
 };
 
-/* Where shall the note be emitted?  BEFORE or AFTER the instruction.  */
+/* Where shall the note be emitted?  BEFORE or AFTER the instruction.
+   Notes emitted as AFTER_CALL are to take effect during the call,
+   rather than after the call.  */
 enum emit_note_where
 {
   EMIT_NOTE_BEFORE_INSN,
-  EMIT_NOTE_AFTER_INSN
+  EMIT_NOTE_AFTER_INSN,
+  EMIT_NOTE_AFTER_CALL_INSN
 };
 
 /* Structure holding information about micro operation.  */
@@ -5930,8 +5933,12 @@ emit_note_insn_var_location (void **varp
   if ((unsigned HOST_WIDE_INT) last_limit < TREE_INT_CST_LOW (type_size_unit))
     complete = false;
 
-  if (where == EMIT_NOTE_AFTER_INSN)
-    note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
+  if (where != EMIT_NOTE_BEFORE_INSN)
+    {
+      note = emit_note_after (NOTE_INSN_VAR_LOCATION, insn);
+      if (where == EMIT_NOTE_AFTER_CALL_INSN)
+	NOTE_DURING_CALL_P (note) = true;
+    }
   else
     note = emit_note_before (NOTE_INSN_VAR_LOCATION, insn);
 
@@ -6166,7 +6173,7 @@ emit_notes_in_bb (basic_block bb)
 	{
 	  case MO_CALL:
 	    dataflow_set_clear_at_call (&set);
-	    emit_notes_for_changes (insn, EMIT_NOTE_AFTER_INSN, set.vars);
+	    emit_notes_for_changes (insn, EMIT_NOTE_AFTER_CALL_INSN, set.vars);
 	    break;
 
 	  case MO_USE:

-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

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