]> gcc.gnu.org Git - gcc.git/commitdiff
re PR debug/49888 (VTA: -O2 -g variable value changes, it does not change in the...
authorAlexandre Oliva <aoliva@redhat.com>
Wed, 13 Jun 2012 21:43:51 +0000 (21:43 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Wed, 13 Jun 2012 21:43:51 +0000 (21:43 +0000)
gcc/ChangeLog:
PR debug/49888
* var-tracking.c: Include alias.h.
(overlapping_mems): New struct.
(drop_overlapping_mem_locs): New.
(clobber_overlapping_mems): New.
(var_mem_delete_and_set, var_mem_delete): Call it.
(val_bind): Likewise, but only if modified.
(compute_bb_dataflow, emit_notes_in_bb): Call it on MEMs.
* Makefile.in (var-tracking.o): Depend in $(ALIAS_H).
gcc/testsuite/ChangeLog:
PR debug/49888
* gcc.dg/guality/pr49888.c: New.

From-SVN: r188531

gcc/ChangeLog
gcc/Makefile.in
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/guality/pr49888.c [new file with mode: 0644]
gcc/var-tracking.c

index d07a9008f176eb7118a33a666c44fb427377f8c8..c6bf75be581fbadb15008418da5748abb59da685 100644 (file)
@@ -1,3 +1,15 @@
+2012-06-13  Alexandre Oliva  <aoliva@redhat.com>
+
+       PR debug/49888
+       * var-tracking.c: Include alias.h.
+       (overlapping_mems): New struct.
+       (drop_overlapping_mem_locs): New.
+       (clobber_overlapping_mems): New.
+       (var_mem_delete_and_set, var_mem_delete): Call it.
+       (val_bind): Likewise, but only if modified.
+       (compute_bb_dataflow, emit_notes_in_bb): Call it on MEMs.
+       * Makefile.in (var-tracking.o): Depend in $(ALIAS_H).
+
 2012-06-13  Alexandre Oliva  <aoliva@redhat.com>
 
        PR debug/47624
index d95b32e7adc93a9f81a3b3432e79eba5fa419e08..9107a32ead3e4dd879b7649cfbc4a811eb8bb6bc 100644 (file)
@@ -3131,8 +3131,8 @@ var-tracking.o : var-tracking.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(RTL_H) $(TREE_H) hard-reg-set.h insn-config.h reload.h $(FLAGS_H) \
    $(BASIC_BLOCK_H) bitmap.h alloc-pool.h $(FIBHEAP_H) $(HASHTAB_H) \
    $(REGS_H) $(EXPR_H) $(TIMEVAR_H) $(TREE_PASS_H) $(TREE_FLOW_H) \
-   cselib.h $(TARGET_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H) $(DIAGNOSTIC_H) pointer-set.h \
-   $(RECOG_H) $(TM_P_H) $(TREE_PRETTY_PRINT_H)
+   cselib.h $(TARGET_H) $(DIAGNOSTIC_CORE_H) $(PARAMS_H) $(DIAGNOSTIC_H) \
+   pointer-set.h $(RECOG_H) $(TM_P_H) $(TREE_PRETTY_PRINT_H) $(ALIAS_H)
 profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(TREE_H) $(FLAGS_H) $(REGS_H) $(EXPR_H) $(FUNCTION_H) $(BASIC_BLOCK_H) \
    $(DIAGNOSTIC_CORE_H) $(COVERAGE_H) $(TREE_FLOW_H) value-prof.h cfghooks.h \
index 8e6000d1b2658dedb2cb875fb86da34348fbe0a1..fb9b69c3df7790a3811b9809148c09b7650505e1 100644 (file)
@@ -1,3 +1,8 @@
+2012-06-13  Alexandre Oliva  <aoliva@redhat.com>
+
+       PR debug/49888
+       * gcc.dg/guality/pr49888.c: New.
+
 2012-06-13  Alexandre Oliva  <aoliva@redhat.com>
 
        * g++.dg/tree-ssa/ivopts-2.C: Adjust for coalescing.
diff --git a/gcc/testsuite/gcc.dg/guality/pr49888.c b/gcc/testsuite/gcc.dg/guality/pr49888.c
new file mode 100644 (file)
index 0000000..3d1e653
--- /dev/null
@@ -0,0 +1,25 @@
+/* PR debug/49888 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+static int v;
+
+static void __attribute__((noinline, noclone))
+f (int *p)
+{
+  int c = *p;
+  v = c;
+  *p = 1; /* { dg-final { gdb-test 12 "c" "0" } } */
+  /* c may very well be optimized out at this point, so we test !c,
+     which will evaluate to the expected value.  We just want to make
+     sure it doesn't remain bound to *p as it did before, in which
+     case !c would evaluate to 0.  */
+  v = 0; /* { dg-final { gdb-test 17 "!c" "1" } } */
+}
+int
+main ()
+{
+  int a = 0;
+  f (&a);
+  return 0;
+}
index e001df0ab4d5bbf92644da01ed3344cc5a6d3417..e1fed62830937dfc73a3959deb60b7d352abfb3a 100644 (file)
 #include "pointer-set.h"
 #include "recog.h"
 #include "tm_p.h"
+#include "alias.h"
 
 /* var-tracking.c assumes that tree code with the same value as VALUE rtx code
    has no chance to appear in REG_EXPR/MEM_EXPRs and isn't a decl.
@@ -1954,6 +1955,111 @@ var_regno_delete (dataflow_set *set, int regno)
   *reg = NULL;
 }
 
+/* Hold parameters for the hashtab traversal function
+   drop_overlapping_mem_locs, see below.  */
+
+struct overlapping_mems
+{
+  dataflow_set *set;
+  rtx loc, addr;
+};
+
+/* Remove all MEMs that overlap with COMS->LOC from the location list
+   of a hash table entry for a value.  COMS->ADDR must be a
+   canonicalized form of COMS->LOC's address, and COMS->LOC must be
+   canonicalized itself.  */
+
+static int
+drop_overlapping_mem_locs (void **slot, void *data)
+{
+  struct overlapping_mems *coms = (struct overlapping_mems *)data;
+  dataflow_set *set = coms->set;
+  rtx mloc = coms->loc, addr = coms->addr;
+  variable var = (variable) *slot;
+
+  if (var->onepart == ONEPART_VALUE)
+    {
+      location_chain loc, *locp;
+      bool changed = false;
+      rtx cur_loc;
+
+      gcc_assert (var->n_var_parts == 1);
+
+      if (shared_var_p (var, set->vars))
+       {
+         for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
+           if (GET_CODE (loc->loc) == MEM
+               && canon_true_dependence (mloc, GET_MODE (mloc), addr,
+                                         loc->loc, NULL))
+             break;
+
+         if (!loc)
+           return 1;
+
+         slot = unshare_variable (set, slot, var, VAR_INIT_STATUS_UNKNOWN);
+         var = (variable)*slot;
+         gcc_assert (var->n_var_parts == 1);
+       }
+
+      if (VAR_LOC_1PAUX (var))
+       cur_loc = VAR_LOC_FROM (var);
+      else
+       cur_loc = var->var_part[0].cur_loc;
+
+      for (locp = &var->var_part[0].loc_chain, loc = *locp;
+          loc; loc = *locp)
+       {
+         if (GET_CODE (loc->loc) != MEM
+             || !canon_true_dependence (mloc, GET_MODE (mloc), addr,
+                                        loc->loc, NULL))
+           {
+             locp = &loc->next;
+             continue;
+           }
+
+         *locp = loc->next;
+         /* If we have deleted the location which was last emitted
+            we have to emit new location so add the variable to set
+            of changed variables.  */
+         if (cur_loc == loc->loc)
+           {
+             changed = true;
+             var->var_part[0].cur_loc = NULL;
+             if (VAR_LOC_1PAUX (var))
+               VAR_LOC_FROM (var) = NULL;
+           }
+         pool_free (loc_chain_pool, loc);
+       }
+
+      if (!var->var_part[0].loc_chain)
+       {
+         var->n_var_parts--;
+         changed = true;
+       }
+      if (changed)
+       variable_was_changed (var, set);
+    }
+
+  return 1;
+}
+
+/* Remove from SET all VALUE bindings to MEMs that overlap with LOC.  */
+
+static void
+clobber_overlapping_mems (dataflow_set *set, rtx loc)
+{
+  struct overlapping_mems coms;
+
+  coms.set = set;
+  coms.loc = canon_rtx (loc);
+  coms.addr = canon_rtx (get_addr (XEXP (loc, 0)));
+
+  set->traversed_vars = set->vars;
+  htab_traverse (shared_hash_htab (set->vars),
+                drop_overlapping_mem_locs, &coms);
+  set->traversed_vars = NULL;
+}
+
 /* Set the location of DV, OFFSET as the MEM LOC.  */
 
 static void
@@ -1996,6 +2102,7 @@ var_mem_delete_and_set (dataflow_set *set, rtx loc, bool modify,
   tree decl = MEM_EXPR (loc);
   HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
 
+  clobber_overlapping_mems (set, loc);
   decl = var_debug_decl (decl);
 
   if (initialized == VAR_INIT_STATUS_UNKNOWN)
@@ -2016,6 +2123,7 @@ var_mem_delete (dataflow_set *set, rtx loc, bool clobber)
   tree decl = MEM_EXPR (loc);
   HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
 
+  clobber_overlapping_mems (set, loc);
   decl = var_debug_decl (decl);
   if (clobber)
     clobber_variable_part (set, NULL, dv_from_decl (decl), offset, NULL);
@@ -2059,6 +2167,9 @@ val_bind (dataflow_set *set, rtx val, rtx loc, bool modified)
     {
       struct elt_loc_list *l = CSELIB_VAL_PTR (val)->locs;
 
+      if (modified)
+       clobber_overlapping_mems (set, loc);
+
       if (l && GET_CODE (l->loc) == VALUE)
        l = canonical_cselib_val (CSELIB_VAL_PTR (l->loc))->locs;
 
@@ -6371,6 +6482,8 @@ compute_bb_dataflow (basic_block bb)
                }
              else if (REG_P (uloc))
                var_regno_delete (out, REGNO (uloc));
+             else if (MEM_P (uloc))
+               clobber_overlapping_mems (out, uloc);
 
              val_store (out, val, dstv, insn, true);
            }
@@ -8870,6 +8983,8 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set)
                }
              else if (REG_P (uloc))
                var_regno_delete (set, REGNO (uloc));
+             else if (MEM_P (uloc))
+               clobber_overlapping_mems (set, uloc);
 
              val_store (set, val, dstv, insn, true);
 
This page took 0.12285 seconds and 5 git commands to generate.