]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR debug/41343 (sysdeps/ieee754/dbl-64/dosincos.c from glibc causes excessive...
authorAlexandre Oliva <aoliva@redhat.com>
Mon, 12 Oct 2009 18:58:38 +0000 (18:58 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Mon, 12 Oct 2009 18:58:38 +0000 (18:58 +0000)
gcc/ChangeLog:
PR debug/41343
PR debug/41447
PR debug/41264
PR debug/41338
* tree.def (DEBUG_EXPR_DECL): New.
* rtl.def (DEBUG_EXPR): New.
* gengtype.c (adjust_field_rtx_def): Handle it.
* tree-ssa.c (propagate_var_def_into_debug_stmts): Rename to...
(insert_debug_temp_for_var_def): ... this.  Drop support for
moving.  Take iterator for def stmt; insert debug stmt before it.
Scan early for use count and kind in debug stmts.
(propagate_defs_into_debug_stmts): Rename to...
(insert_debug_temps_for_defs): ... this.  Likewise.
* tree.h (DEBUG_TEMP_UID): New.
* tree.c (next_debug_decl_uid): New.
(make_node_stat): Count debug decls separately.
(copy_node_stat): Likewise.
* cfgexpand.c (expand_debug_expr): Handle DEBUG_EXPR_DECL.
* var-tracking.c (dv_is_decl_p): Recognize it.
(VALUE_RECURSED_INTO): Apply to DEBUG_EXPRs too.
(track_expr_p): Track expanded DEBUG_EXPR_DECLs.
(vt_expand_loc_callback): Expand DEBUG_EXPRs.
(emit_note_insn_var_location): Don't emit notes for DEBUG_EXPR_DECLs.
* cselib.c (rtx_equal_for_cselib_p): Handle DEBUG_EXPR.
(cselib_hash_rtx): Likewise.
(cselib_expand_value_rtx_1): Use callback for DEBUG_EXPR.
* tree-ssa-operands.c (get_expr_operands): Skip DEBUG_EXPR_DECLs in
debug bind stmts.
* emit-rtl.c (verify_rtx_sharing): Handle DEBUG_EXPR and VALUE.
(copy_rtx_if_shared_1, reset_used_flags, set_used_flags): Likewise.
* rtl.c (copy_rtx): Likewise.
(rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_EXPR.
* print-rtl.c (print_rtx): Likewise.
* sched-vis.c (print_value): Likewise.
(print_insn): Handle DEBUG_EXPR_DECL.
* tree-dump.c (dequeue_and_dump): Likewise.
* tree-pretty-print.c (dump_decl_name, dump_generic_node): Likewise.
* gimple-iterator (gsi_replace): Check for same lhs.
(gsi_remove): Insert debug temps.
* tree-ssa-loop-im.c (rewrite_reciprocal): Replace with same lhs.
(move_computations_stmt): Drop explicit propagation into debug stmts.
(rewrite_bittest): Likewise.  Use gsi_remove for propagation.
* tree-ssa-reassoc.c (rewrite_expr_tree, linearize_expr): Likewise.
* tree-ssa-sink.c (statement_sink_location): Likewise.
* tree-ssa-forwprop (forward_propagate_addr_expr): Likewise.
* tree-ssanames.c (release_ssa_name): Adjust for rename.
* tree-flow.h: Likewise.
* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Don't mark
debug temps without values.
(eliminate_unnecessary_stmts): Don't discard just-inserted
debug stmts.
gcc/testsuite/ChangeLog:
PR debug/41343
PR debug/41447
PR debug/41264
PR debug/41338
* gcc.dg/guality/pr41447-1.c: New.
* gcc.dg/debug/pr41264-1.c: New.
* gcc.dg/debug/pr41343-1.c: New.

From-SVN: r152681

29 files changed:
gcc/ChangeLog
gcc/cfgexpand.c
gcc/cselib.c
gcc/emit-rtl.c
gcc/gengtype.c
gcc/gimple-iterator.c
gcc/print-rtl.c
gcc/rtl.c
gcc/rtl.def
gcc/sched-vis.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/debug/pr41264-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/debug/pr41343-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/guality/pr41447-1.c [new file with mode: 0644]
gcc/tree-dump.c
gcc/tree-flow.h
gcc/tree-pretty-print.c
gcc/tree-ssa-dce.c
gcc/tree-ssa-forwprop.c
gcc/tree-ssa-loop-im.c
gcc/tree-ssa-operands.c
gcc/tree-ssa-reassoc.c
gcc/tree-ssa-sink.c
gcc/tree-ssa.c
gcc/tree-ssanames.c
gcc/tree.c
gcc/tree.def
gcc/tree.h
gcc/var-tracking.c

index 7b6c08007954d351e1cb8185e6242af36d902955..9e066b4d1f657f5bb670009bb4f95813b4188e80 100644 (file)
@@ -1,3 +1,57 @@
+2009-10-12  Alexandre Oliva  <aoliva@redhat.com>
+
+       PR debug/41343
+       PR debug/41447
+       PR debug/41264
+       PR debug/41338
+       * tree.def (DEBUG_EXPR_DECL): New.
+       * rtl.def (DEBUG_EXPR): New.
+       * gengtype.c (adjust_field_rtx_def): Handle it.
+       * tree-ssa.c (propagate_var_def_into_debug_stmts): Rename to...
+       (insert_debug_temp_for_var_def): ... this.  Drop support for
+       moving.  Take iterator for def stmt; insert debug stmt before it.
+       Scan early for use count and kind in debug stmts.
+       (propagate_defs_into_debug_stmts): Rename to...
+       (insert_debug_temps_for_defs): ... this.  Likewise.
+       * tree.h (DEBUG_TEMP_UID): New.
+       * tree.c (next_debug_decl_uid): New.
+       (make_node_stat): Count debug decls separately.
+       (copy_node_stat): Likewise.
+       * cfgexpand.c (expand_debug_expr): Handle DEBUG_EXPR_DECL.
+       * var-tracking.c (dv_is_decl_p): Recognize it.
+       (VALUE_RECURSED_INTO): Apply to DEBUG_EXPRs too.
+       (track_expr_p): Track expanded DEBUG_EXPR_DECLs.
+       (vt_expand_loc_callback): Expand DEBUG_EXPRs.
+       (emit_note_insn_var_location): Don't emit notes for DEBUG_EXPR_DECLs.
+       * cselib.c (rtx_equal_for_cselib_p): Handle DEBUG_EXPR.
+       (cselib_hash_rtx): Likewise.
+       (cselib_expand_value_rtx_1): Use callback for DEBUG_EXPR.
+       * tree-ssa-operands.c (get_expr_operands): Skip DEBUG_EXPR_DECLs in
+       debug bind stmts.
+       * emit-rtl.c (verify_rtx_sharing): Handle DEBUG_EXPR and VALUE.
+       (copy_rtx_if_shared_1, reset_used_flags, set_used_flags): Likewise.
+       * rtl.c (copy_rtx): Likewise.
+       (rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_EXPR.
+       * print-rtl.c (print_rtx): Likewise.
+       * sched-vis.c (print_value): Likewise.
+       (print_insn): Handle DEBUG_EXPR_DECL.
+       * tree-dump.c (dequeue_and_dump): Likewise.
+       * tree-pretty-print.c (dump_decl_name, dump_generic_node): Likewise.
+       * gimple-iterator (gsi_replace): Check for same lhs.
+       (gsi_remove): Insert debug temps.
+       * tree-ssa-loop-im.c (rewrite_reciprocal): Replace with same lhs.
+       (move_computations_stmt): Drop explicit propagation into debug stmts.
+       (rewrite_bittest): Likewise.  Use gsi_remove for propagation.
+       * tree-ssa-reassoc.c (rewrite_expr_tree, linearize_expr): Likewise.
+       * tree-ssa-sink.c (statement_sink_location): Likewise.
+       * tree-ssa-forwprop (forward_propagate_addr_expr): Likewise.
+       * tree-ssanames.c (release_ssa_name): Adjust for rename.
+       * tree-flow.h: Likewise.
+       * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Don't mark
+       debug temps without values.
+       (eliminate_unnecessary_stmts): Don't discard just-inserted
+       debug stmts.
+
 2009-10-12  Hans-Peter Nilsson  <hp@axis.com>
 
        PR target/26515
index 2117ee3bc527d15345c797c2ad340cd83d26452e..31832e71c87f1de634c5dbfef45a10a7b20083cd 100644 (file)
@@ -2361,6 +2361,18 @@ expand_debug_expr (tree exp)
       op1 = wrap_constant (GET_MODE_INNER (mode), op1);
       return gen_rtx_CONCAT (mode, op0, op1);
 
+    case DEBUG_EXPR_DECL:
+      op0 = DECL_RTL_IF_SET (exp);
+
+      if (op0)
+       return op0;
+
+      op0 = gen_rtx_DEBUG_EXPR (mode);
+      XTREE (op0, 0) = exp;
+      SET_DECL_RTL (exp, op0);
+
+      return op0;
+
     case VAR_DECL:
     case PARM_DECL:
     case FUNCTION_DECL:
index e6e5c143dad73502ce658dd6d2c1aa6cbcce9467..c26742ddf1a08dc4a18b2cba80a2c2eb2f68f844 100644 (file)
@@ -585,6 +585,7 @@ rtx_equal_for_cselib_p (rtx x, rtx y)
     {
     case CONST_DOUBLE:
     case CONST_FIXED:
+    case DEBUG_EXPR:
       return 0;
 
     case LABEL_REF:
@@ -703,6 +704,10 @@ cselib_hash_rtx (rtx x, int create)
 
       return e->value;
 
+    case DEBUG_EXPR:
+      hash += ((unsigned) DEBUG_EXPR << 7) + DEBUG_TEMP_UID (XTREE (x, 0));
+      return hash ? hash : (unsigned int) DEBUG_EXPR;
+
     case CONST_INT:
       hash += ((unsigned) CONST_INT << 7) + INTVAL (x);
       return hash ? hash : (unsigned int) CONST_INT;
@@ -1213,6 +1218,13 @@ cselib_expand_value_rtx_1 (rtx orig, struct expand_value_data *evd,
        result = expand_loc (CSELIB_VAL_PTR (orig)->locs, evd, max_depth);
        return result;
       }
+
+    case DEBUG_EXPR:
+      if (evd->callback)
+       return evd->callback (orig, evd->regs_active, max_depth,
+                             evd->callback_arg);
+      return orig;
+
     default:
       break;
     }
index b3672e3e5adf166fda5d77a28cf698728b5d95ba..b8682984eca9861dd9e2373d37c63c9f2445b2bd 100644 (file)
@@ -2393,6 +2393,8 @@ verify_rtx_sharing (rtx orig, rtx insn)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2593,6 +2595,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2712,6 +2716,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2783,6 +2789,8 @@ set_used_flags (rtx x)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
index e5b43dde96e13209e1a37f95896cb096a9212225..8e882f171f9d29e7eab174d02768eb3505a11f1a 100644 (file)
@@ -1117,6 +1117,8 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
                t = scalar_tp, subname = "rt_int";
              else if (i == VALUE && aindex == 0)
                t = scalar_tp, subname = "rt_int";
+             else if (i == DEBUG_EXPR && aindex == 0)
+               t = tree_tp, subname = "rt_tree";
              else if (i == REG && aindex == 1)
                t = scalar_tp, subname = "rt_int";
              else if (i == REG && aindex == 2)
index 66927d67c2c88f42b52d968980b9600796bae47e..c3ca0e37501baf56db86193c6cf6a196bc6507a3 100644 (file)
@@ -358,7 +358,8 @@ gsi_split_seq_before (gimple_stmt_iterator *i)
 
 /* Replace the statement pointed-to by GSI to STMT.  If UPDATE_EH_INFO
    is true, the exception handling information of the original
-   statement is moved to the new statement.  */
+   statement is moved to the new statement.  Assignments must only be
+   replaced with assignments to the same LHS.  */
 
 void
 gsi_replace (gimple_stmt_iterator *gsi, gimple stmt, bool update_eh_info)
@@ -368,6 +369,9 @@ gsi_replace (gimple_stmt_iterator *gsi, gimple stmt, bool update_eh_info)
   if (stmt == orig_stmt)
     return;
 
+  gcc_assert (!gimple_has_lhs (orig_stmt)
+             || gimple_get_lhs (orig_stmt) == gimple_get_lhs (stmt));
+
   gimple_set_location (stmt, gimple_location (orig_stmt));
   gimple_set_bb (stmt, gsi_bb (*gsi));
 
@@ -470,6 +474,8 @@ gsi_remove (gimple_stmt_iterator *i, bool remove_permanently)
   gimple_seq_node cur, next, prev;
   gimple stmt = gsi_stmt (*i);
 
+  insert_debug_temps_for_defs (i);
+
   /* Free all the data flow information for STMT.  */
   gimple_set_bb (stmt, NULL);
   delink_stmt_imm_use (stmt);
index a75442eb6c7cd369c760a070da59e509d91b9a10..5ba5e634a66a59e915f9ec714ffde4208e19bb6b 100644 (file)
@@ -316,6 +316,12 @@ print_rtx (const_rtx in_rtx)
            fprintf (outfile, " %i", val->value);
            dump_addr (outfile, " @", in_rtx);
            dump_addr (outfile, "/", (void*)val);
+#endif
+         }
+       else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
+         {
+#ifndef GENERATOR_FILE
+           fprintf (outfile, " D#%i", DEBUG_TEMP_UID (XTREE (in_rtx, 0)));
 #endif
          }
        break;
index feeb40bf61bfbf3836896c96fbbfd4f39d8022d7..53a4992f4829b5330e949a4ece40d4dfeb42118a 100644 (file)
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -232,6 +232,8 @@ copy_rtx (rtx orig)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -381,6 +383,7 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb)
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
@@ -496,6 +499,7 @@ rtx_equal_p (const_rtx x, const_rtx y)
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
index 2aa76b1f6c8ea22fd421a1064d44c69fdbdbaa0e..acb7ee915b87d0c7c4b1348f124679bdf819c171 100644 (file)
@@ -88,6 +88,10 @@ DEF_RTL_EXPR(UNKNOWN, "UnKnown", "*", RTX_EXTRA)
    DECL codes in trees.  */
 DEF_RTL_EXPR(VALUE, "value", "0", RTX_OBJ)
 
+/* The RTL generated for a DEBUG_EXPR_DECL.  It links back to the
+   DEBUG_EXPR_DECL in the first operand.  */
+DEF_RTL_EXPR(DEBUG_EXPR, "debug_expr", "0", RTX_OBJ)
+
 /* ---------------------------------------------------------------------
    Expressions used in constructing lists.
    --------------------------------------------------------------------- */
index 89230efa34c71ffdcdcee1cc7d7f6af6f30e310c..d95235ee3ec87d7ab4f79576c0040c30ae7adcba 100644 (file)
@@ -521,6 +521,10 @@ print_value (char *buf, const_rtx x, int verbose)
       cur = safe_concat (buf, cur, t);
       cur = safe_concat (buf, cur, "]");
       break;
+    case DEBUG_EXPR:
+      sprintf (t, "D#%i", DEBUG_TEMP_UID (XTREE (x, 0)));
+      cur = safe_concat (buf, cur, t);
+      break;
     default:
       print_exp (t, x, verbose);
       cur = safe_concat (buf, cur, t);
@@ -670,11 +674,18 @@ print_insn (char *buf, const_rtx x, int verbose)
        if (DECL_P (INSN_VAR_LOCATION_DECL (insn)))
          {
            tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (insn));
+           char idbuf[32];
            if (id)
              name = IDENTIFIER_POINTER (id);
+           else if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn))
+                    == DEBUG_EXPR_DECL)
+             {
+               sprintf (idbuf, "D#%i",
+                        DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (insn)));
+               name = idbuf;
+             }
            else
              {
-               char idbuf[32];
                sprintf (idbuf, "D.%i",
                         DECL_UID (INSN_VAR_LOCATION_DECL (insn)));
                name = idbuf;
index d6448ec1f9c35ac4ce6a91cf3db25f801158a2c9..7e2c9ab6ff49d60b00bbc25a6c6cad4bb554c216 100644 (file)
@@ -1,3 +1,13 @@
+2009-10-12  Alexandre Oliva  <aoliva@redhat.com>
+
+       PR debug/41343
+       PR debug/41447
+       PR debug/41264
+       PR debug/41338
+       * gcc.dg/guality/pr41447-1.c: New.
+       * gcc.dg/debug/pr41264-1.c: New.
+       * gcc.dg/debug/pr41343-1.c: New.
+
 2009-10-12  Hans-Peter Nilsson  <hp@axis.com>
 
        PR target/26515
diff --git a/gcc/testsuite/gcc.dg/debug/pr41264-1.c b/gcc/testsuite/gcc.dg/debug/pr41264-1.c
new file mode 100644 (file)
index 0000000..b5555b5
--- /dev/null
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+
+typedef unsigned int hashval_t;
+static hashval_t __attribute__((always_inline))
+iterative_hash_host_wide_int (long val, hashval_t val2)
+{
+  hashval_t a = (hashval_t) val;
+  int zero = 0;
+  hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 8 + zero));
+
+  a -= b; a -= val2; a ^= (val2>>13);
+  b -= val2; b -= a; b ^= (a<< 8);
+  val2 -= a; val2 -= b; val2 ^= ((b&0xffffffff)>>13);
+  a -= b; a -= val2; a ^= ((val2&0xffffffff)>>12);
+  b -= val2; b -= a; b = (b ^ (a<<16)) & 0xffffffff;
+  val2 -= a; val2 -= b; val2 = (val2 ^ (b>> 5)) & 0xffffffff;
+  a -= b; a -= val2; a = (a ^ (val2>> 3)) & 0xffffffff;
+  b -= val2; b -= a; b = (b ^ (a<<10)) & 0xffffffff;
+  val2 -= a; val2 -= b; val2 = (val2 ^ (b>>15)) & 0xffffffff;
+  return val2;
+}
+
+hashval_t
+bla (int nunits, int mode)
+{
+  hashval_t hashcode = 0;
+
+
+  hashcode = iterative_hash_host_wide_int (14, hashcode);
+  hashcode = iterative_hash_host_wide_int (nunits, hashcode);
+  hashcode = iterative_hash_host_wide_int (mode, hashcode);
+  if (nunits)
+    return 0;
+  else
+    return hashcode;
+}
diff --git a/gcc/testsuite/gcc.dg/debug/pr41343-1.c b/gcc/testsuite/gcc.dg/debug/pr41343-1.c
new file mode 100644 (file)
index 0000000..6d56380
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+
+#define X(new,old) int i ## new = i ## old + i ## old;
+#define Y(pfx) X(pfx ## 1, pfx) \
+  X(pfx ## 2, pfx ## 1) \
+  X(pfx ## 3, pfx ## 2) \
+  X(pfx ## 4, pfx ## 3) \
+  X(pfx ## 5, pfx ## 4) \
+  X(pfx ## 6, pfx ## 5) \
+  X(pfx ## 7, pfx ## 6) \
+  X(pfx ## 8, pfx ## 7) \
+  X(pfx ## 9, pfx ## 8)
+
+void foo (int i1)
+{
+  Y(1)
+  Y(11)
+  Y(111)
+  asm ("" : : "X" (i1));
+}
diff --git a/gcc/testsuite/gcc.dg/guality/pr41447-1.c b/gcc/testsuite/gcc.dg/guality/pr41447-1.c
new file mode 100644 (file)
index 0000000..675b030
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do run { xfail *-*-* } } */
+/* { dg-options "-g -O2" } */
+
+#include "guality.h"
+
+int a;
+
+int foo()
+{
+  int tmp = a;
+  int tmp2 = a;
+  int tmp3;
+  int res;
+  GUALCHKVAL (a);
+  GUALCHKVAL (tmp);
+  GUALCHKVAL (tmp2);
+  a = 0;
+  tmp3 = tmp2;
+  GUALCHKVAL (a);
+  GUALCHKVAL (tmp);
+  GUALCHKVAL (tmp2);
+  GUALCHKVAL (tmp3);
+  res = tmp - tmp2 + 1;
+  return res;
+}
index 61ccc6ce792f6612290e8b7e37a02ecdfefc1875..7b7a85f50825fe3153d88d970b24785c64f46f08 100644 (file)
@@ -511,6 +511,10 @@ dequeue_and_dump (dump_info_p di)
       dump_child ("cnst", DECL_INITIAL (t));
       break;
 
+    case DEBUG_EXPR_DECL:
+      dump_int (di, "-uid", DEBUG_TEMP_UID (t));
+      /* Fall through.  */
+
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
index 8e790aec7847e57c1ccda8e67bf1988aea5b2e3a..85f1f5ef60a5f30d916cd41577b06ac3f2319021 100644 (file)
@@ -637,10 +637,8 @@ typedef bool (*walk_use_def_chains_fn) (tree, gimple, void *);
 
 extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
 
-void propagate_defs_into_debug_stmts (gimple, basic_block,
-                                     const gimple_stmt_iterator *);
-void propagate_var_def_into_debug_stmts (tree, basic_block,
-                                        const gimple_stmt_iterator *);
+void insert_debug_temps_for_defs (gimple_stmt_iterator *);
+void insert_debug_temp_for_var_def (gimple_stmt_iterator *, tree);
 void release_defs_bitset (bitmap toremove);
 
 /* In tree-into-ssa.c  */
index a325d75d91442cfba71c783c7d506dd2aa6cce05..cfc20a178ea1c03d0b5c4c7778cc55eaea214025 100644 (file)
@@ -183,6 +183,8 @@ dump_decl_name (pretty_printer *buffer, tree node, int flags)
     {
       if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1)
         pp_printf (buffer, "L.%d", (int) LABEL_DECL_UID (node));
+      else if (TREE_CODE (node) == DEBUG_EXPR_DECL)
+       pp_printf (buffer, "D#%i", DEBUG_TEMP_UID (node));
       else
        {
          char c = TREE_CODE (node) == CONST_DECL ? 'C' : 'D';
@@ -1051,6 +1053,7 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
+    case DEBUG_EXPR_DECL:
     case NAMESPACE_DECL:
       dump_decl_name (buffer, node, flags);
       break;
index 67d0472cc59668c603900702bc87d06b1dfd2b8c..7dd07c1ca2c780ed5e998713967e92ea7d31e72a 100644 (file)
@@ -325,7 +325,13 @@ mark_stmt_if_obviously_necessary (gimple stmt, bool aggressive)
       break;
 
     case GIMPLE_DEBUG:
-      mark_stmt_necessary (stmt, false);
+      /* Debug temps without a value are not useful.  ??? If we could
+        easily locate the debug temp bind stmt for a use thereof,
+        would could refrain from marking all debug temps here, and
+        mark them only if they're used.  */
+      if (gimple_debug_bind_has_value_p (stmt)
+         || TREE_CODE (gimple_debug_bind_get_var (stmt)) != DEBUG_EXPR_DECL)
+       mark_stmt_necessary (stmt, false);
       return;
 
     case GIMPLE_GOTO:
@@ -1071,7 +1077,7 @@ eliminate_unnecessary_stmts (void)
 {
   bool something_changed = false;
   basic_block bb;
-  gimple_stmt_iterator gsi;
+  gimple_stmt_iterator gsi, psi;
   gimple stmt;
   tree call;
   VEC (basic_block, heap) *h;
@@ -1111,10 +1117,13 @@ eliminate_unnecessary_stmts (void)
       bb = VEC_pop (basic_block, h);
 
       /* Remove dead statements.  */
-      for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi);)
+      for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi = psi)
        {
          stmt = gsi_stmt (gsi);
 
+         psi = gsi;
+         gsi_prev (&psi);
+
          stats.total++;
 
          /* If GSI is not necessary then remove it.  */
@@ -1122,14 +1131,6 @@ eliminate_unnecessary_stmts (void)
            {
              remove_dead_stmt (&gsi, bb);
              something_changed = true;
-
-             /* If stmt was the last stmt in the block, we want to
-                move gsi to the stmt that became the last stmt, but
-                gsi_prev would crash.  */
-             if (gsi_end_p (gsi))
-               gsi = gsi_last_bb (bb);
-             else
-               gsi_prev (&gsi);
            }
          else if (is_gimple_call (stmt))
            {
@@ -1159,10 +1160,7 @@ eliminate_unnecessary_stmts (void)
                    }
                  notice_special_calls (stmt);
                }
-             gsi_prev (&gsi);
            }
-         else
-           gsi_prev (&gsi);
        }
     }
 
index 87795a282233af7256f4fa7fb86d3fa335d8e2c7..6ba800d8288773b2743362c51605b378741e5814 100644 (file)
@@ -939,7 +939,6 @@ forward_propagate_addr_expr (tree name, tree rhs)
   gimple use_stmt;
   bool all = true;
   bool single_use_p = has_single_use (name);
-  bool debug = false;
 
   FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
     {
@@ -950,9 +949,7 @@ forward_propagate_addr_expr (tree name, tree rhs)
         there is nothing we can do.  */
       if (gimple_code (use_stmt) != GIMPLE_ASSIGN)
        {
-         if (is_gimple_debug (use_stmt))
-           debug = true;
-         else
+         if (!is_gimple_debug (use_stmt))
            all = false;
          continue;
        }
@@ -995,9 +992,6 @@ forward_propagate_addr_expr (tree name, tree rhs)
        }
     }
 
-  if (all && debug)
-    propagate_var_def_into_debug_stmts (name, NULL, NULL);
-
   return all;
 }
 
index 738249445b0288df7d7f1f9ae49adec1ad2710a3..6c6a9f17a1d5ea68de5e2a3695ecc480bcd28a9d 100644 (file)
@@ -764,6 +764,7 @@ rewrite_reciprocal (gimple_stmt_iterator *bsi)
   gimple stmt, stmt1, stmt2;
   tree var, name, lhs, type;
   tree real_one;
+  gimple_stmt_iterator gsi;
 
   stmt = gsi_stmt (*bsi);
   lhs = gimple_assign_lhs (stmt);
@@ -798,8 +799,9 @@ rewrite_reciprocal (gimple_stmt_iterator *bsi)
   /* Replace division stmt with reciprocal and multiply stmts.
      The multiply stmt is not invariant, so update iterator
      and avoid rescanning.  */
-  gsi_replace (bsi, stmt1, true);
-  gsi_insert_after (bsi, stmt2, GSI_NEW_STMT);
+  gsi = *bsi;
+  gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
+  gsi_replace (&gsi, stmt2, true);
 
   /* Continue processing with invariant reciprocal statement.  */
   return stmt1;
@@ -858,6 +860,8 @@ rewrite_bittest (gimple_stmt_iterator *bsi)
   if (outermost_invariant_loop (b, loop_containing_stmt (stmt1)) != NULL
       && outermost_invariant_loop (a, loop_containing_stmt (stmt1)) == NULL)
     {
+      gimple_stmt_iterator rsi;
+
       /* 1 << B */
       var = create_tmp_var (TREE_TYPE (a), "shifttmp");
       add_referenced_var (var);
@@ -878,9 +882,14 @@ rewrite_bittest (gimple_stmt_iterator *bsi)
       SET_USE (use, name);
       gimple_cond_set_rhs (use_stmt, build_int_cst_type (TREE_TYPE (name), 0));
 
-      gsi_insert_before (bsi, stmt1, GSI_SAME_STMT);
-      propagate_defs_into_debug_stmts (gsi_stmt (*bsi), NULL, NULL);
-      gsi_replace (bsi, stmt2, true);
+      /* Don't use gsi_replace here, none of the new assignments sets
+        the variable originally set in stmt.  Move bsi to stmt1, and
+        then remove the original stmt, so that we get a chance to
+        retain debug info for it.  */
+      rsi = *bsi;
+      gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
+      gsi_insert_before (&rsi, stmt2, GSI_SAME_STMT);
+      gsi_remove (&rsi, true);
 
       return stmt1;
     }
@@ -1060,7 +1069,6 @@ move_computations_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
 
       mark_virtual_ops_for_renaming (stmt);
       gsi_insert_on_edge (loop_preheader_edge (level), stmt);
-      propagate_defs_into_debug_stmts (gsi_stmt (bsi), NULL, NULL);
       gsi_remove (&bsi, false);
     }
 }
index 28e6ec65826f164edfd203932fd270f559391e2a..6af31a437ea50a2c7f69b4540672bbabf8f1ea68 100644 (file)
@@ -894,6 +894,10 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags)
       add_stmt_operand (expr_p, stmt, flags);
       return;
 
+    case DEBUG_EXPR_DECL:
+      gcc_assert (gimple_debug_bind_p (stmt));
+      return;
+
     case MISALIGNED_INDIRECT_REF:
       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
       /* fall through */
index 55ce2f65a4f65ecb93340ece8844382d73948ce7..5136aee5d32ba7bfef2829ada1a656a6c25f27c7 100644 (file)
@@ -1405,7 +1405,6 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex,
            {
              stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
              gsirhs1 = gsi_for_stmt (stmt2);
-             propagate_defs_into_debug_stmts (stmt2, gimple_bb (stmt), &gsinow);
              gsi_move_before (&gsirhs1, &gsinow);
              gsi_prev (&gsinow);
              stmt1 = stmt2;
@@ -1452,7 +1451,6 @@ linearize_expr (gimple stmt)
 
   gsinow = gsi_for_stmt (stmt);
   gsirhs = gsi_for_stmt (binrhs);
-  propagate_defs_into_debug_stmts (binrhs, gimple_bb (stmt), &gsinow);
   gsi_move_before (&gsirhs, &gsinow);
 
   gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
index a9b4b67679b431fb29aef36c56fb8b036527d2df..be3fb7145fdadbe027cb5f9d019b48429ec49be0 100644 (file)
@@ -385,9 +385,6 @@ statement_sink_location (gimple stmt, basic_block frombb,
 
       *togsi = gsi_after_labels (commondom);
 
-      if (debug_stmts)
-       propagate_defs_into_debug_stmts (stmt, commondom, togsi);
-
       return true;
     }
 
@@ -406,8 +403,6 @@ statement_sink_location (gimple stmt, basic_block frombb,
 
       *togsi = gsi_for_stmt (use);
 
-      propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
-
       return true;
     }
 
@@ -441,8 +436,6 @@ statement_sink_location (gimple stmt, basic_block frombb,
 
   *togsi = gsi_after_labels (sinkbb);
 
-  propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
-
   return true;
 }
 
index 9015d19c189e2108a8831d09ed8fad6a82bea33a..9858b109d037e0e0acc4c44772c2c0b059ef5823 100644 (file)
@@ -295,152 +295,198 @@ find_released_ssa_name (tree *tp, int *walk_subtrees, void *data_)
   return NULL_TREE;
 }
 
-/* Given a VAR whose definition STMT is to be moved to the iterator
-   position TOGSIP in the TOBB basic block, verify whether we're
-   moving it across any of the debug statements that use it, and
-   adjust them as needed.  If TOBB is NULL, then the definition is
-   understood as being removed, and TOGSIP is unused.  */
+/* Insert a DEBUG BIND stmt before the DEF of VAR if VAR is referenced
+   by other DEBUG stmts, and replace uses of the DEF with the
+   newly-created debug temp.  */
+
 void
-propagate_var_def_into_debug_stmts (tree var,
-                                   basic_block tobb,
-                                   const gimple_stmt_iterator *togsip)
+insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var)
 {
   imm_use_iterator imm_iter;
-  gimple stmt;
   use_operand_p use_p;
+  gimple stmt;
+  gimple def_stmt = NULL;
+  int usecount = 0;
   tree value = NULL;
-  bool no_value = false;
 
   if (!MAY_HAVE_DEBUG_STMTS)
     return;
 
-  FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
+  /* First of all, check whether there are debug stmts that reference
+     this variable and, if there are, decide whether we should use a
+     debug temp.  */
+  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
     {
-      basic_block bb;
-      gimple_stmt_iterator si;
+      stmt = USE_STMT (use_p);
 
-      if (!is_gimple_debug (stmt))
+      if (!gimple_debug_bind_p (stmt))
        continue;
 
-      if (tobb)
+      if (usecount++)
+       break;
+
+      if (gimple_debug_bind_get_value (stmt) != var)
        {
-         bb = gimple_bb (stmt);
+         /* Count this as an additional use, so as to make sure we
+            use a temp unless VAR's definition has a SINGLE_RHS that
+            can be shared.  */
+         usecount++;
+         break;
+       }
+    }
 
-         if (bb != tobb)
-           {
-             gcc_assert (dom_info_available_p (CDI_DOMINATORS));
-             if (dominated_by_p (CDI_DOMINATORS, bb, tobb))
-               continue;
-           }
-         else
-           {
-             si = *togsip;
+  if (!usecount)
+    return;
 
-             if (gsi_end_p (si))
-               continue;
+  if (gsi)
+    def_stmt = gsi_stmt (*gsi);
+  else
+    def_stmt = SSA_NAME_DEF_STMT (var);
 
-             do
-               {
-                 gsi_prev (&si);
-                 if (gsi_end_p (si))
-                   break;
-               }
-             while (gsi_stmt (si) != stmt);
+  /* If we didn't get an insertion point, and the stmt has already
+     been removed, we won't be able to insert the debug bind stmt, so
+     we'll have to drop debug information.  */
+  if (is_gimple_assign (def_stmt))
+    {
+      bool no_value = false;
 
-             if (gsi_end_p (si))
-               continue;
-           }
+      if (!dom_info_available_p (CDI_DOMINATORS))
+       {
+         struct walk_stmt_info wi;
+
+         memset (&wi, 0, sizeof (wi));
+
+         /* When removing blocks without following reverse dominance
+            order, we may sometimes encounter SSA_NAMEs that have
+            already been released, referenced in other SSA_DEFs that
+            we're about to release.  Consider:
+
+            <bb X>:
+            v_1 = foo;
+
+            <bb Y>:
+            w_2 = v_1 + bar;
+            # DEBUG w => w_2
+
+            If we deleted BB X first, propagating the value of w_2
+            won't do us any good.  It's too late to recover their
+            original definition of v_1: when it was deleted, it was
+            only referenced in other DEFs, it couldn't possibly know
+            it should have been retained, and propagating every
+            single DEF just in case it might have to be propagated
+            into a DEBUG STMT would probably be too wasteful.
+
+            When dominator information is not readily available, we
+            check for and accept some loss of debug information.  But
+            if it is available, there's no excuse for us to remove
+            blocks in the wrong order, so we don't even check for
+            dead SSA NAMEs.  SSA verification shall catch any
+            errors.  */
+         if ((!gsi && !gimple_bb (def_stmt))
+             || !walk_gimple_op (def_stmt, find_released_ssa_name,
+                                 &wi))
+           no_value = true;
        }
 
-      /* Here we compute (lazily) the value assigned to VAR, but we
-        remember if we tried before and failed, so that we don't try
-        again.  */
-      if (!value && !no_value)
+      if (!no_value)
+       value = gimple_assign_rhs_to_tree (def_stmt);
+    }
+
+  if (value)
+    {
+      /* If there's a single use of VAR, and VAR is the entire debug
+        expression (usecount would have been incremented again
+        otherwise), and the definition involves only constants and
+        SSA names, then we can propagate VALUE into this single use,
+        avoiding the temp.
+
+        We can also avoid using a temp if VALUE can be shared and
+        propagated into all uses, without generating expressions that
+        wouldn't be valid gimple RHSs.
+
+        Other cases that would require unsharing or non-gimple RHSs
+        are deferred to a debug temp, although we could avoid temps
+        at the expense of duplication of expressions.  */
+
+      if (CONSTANT_CLASS_P (value)
+         || (usecount == 1
+             && (!gimple_assign_single_p (def_stmt)
+                 || is_gimple_min_invariant (value)))
+         || is_gimple_reg (value))
+       value = unshare_expr (value);
+      else
        {
-         gimple def_stmt = SSA_NAME_DEF_STMT (var);
+         gimple def_temp;
+         tree vexpr = make_node (DEBUG_EXPR_DECL);
 
-         if (is_gimple_assign (def_stmt))
-           {
-             if (!dom_info_available_p (CDI_DOMINATORS))
-               {
-                 struct walk_stmt_info wi;
-
-                 memset (&wi, 0, sizeof (wi));
-
-                 /* When removing blocks without following reverse
-                    dominance order, we may sometimes encounter SSA_NAMEs
-                    that have already been released, referenced in other
-                    SSA_DEFs that we're about to release.  Consider:
-
-                    <bb X>:
-                    v_1 = foo;
-
-                    <bb Y>:
-                    w_2 = v_1 + bar;
-                    # DEBUG w => w_2
-
-                    If we deleted BB X first, propagating the value of
-                    w_2 won't do us any good.  It's too late to recover
-                    their original definition of v_1: when it was
-                    deleted, it was only referenced in other DEFs, it
-                    couldn't possibly know it should have been retained,
-                    and propagating every single DEF just in case it
-                    might have to be propagated into a DEBUG STMT would
-                    probably be too wasteful.
-
-                    When dominator information is not readily
-                    available, we check for and accept some loss of
-                    debug information.  But if it is available,
-                    there's no excuse for us to remove blocks in the
-                    wrong order, so we don't even check for dead SSA
-                    NAMEs.  SSA verification shall catch any
-                    errors.  */
-                 if (!walk_gimple_op (def_stmt, find_released_ssa_name, &wi))
-                   no_value = true;
-               }
+         def_temp = gimple_build_debug_bind (vexpr,
+                                             unshare_expr (value),
+                                             def_stmt);
+
+         DECL_ARTIFICIAL (vexpr) = 1;
+         TREE_TYPE (vexpr) = TREE_TYPE (value);
+         if (DECL_P (value))
+           DECL_MODE (vexpr) = DECL_MODE (value);
+         else
+           DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (value));
 
-             if (!no_value)
-               value = gimple_assign_rhs_to_tree (def_stmt);
+         if (gsi)
+           gsi_insert_before (gsi, def_temp, GSI_SAME_STMT);
+         else
+           {
+             gimple_stmt_iterator ngsi = gsi_for_stmt (def_stmt);
+             gsi_insert_before (&ngsi, def_temp, GSI_SAME_STMT);
            }
 
-         if (!value)
-           no_value = true;
+         value = vexpr;
        }
+    }
 
-      if (no_value)
-       gimple_debug_bind_reset_value (stmt);
-      else
+  FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
+    {
+      if (!gimple_debug_bind_p (stmt))
+       continue;
+
+      if (value)
        FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
-         SET_USE (use_p, unshare_expr (value));
+         /* unshare_expr is not needed here.  vexpr is either a
+            SINGLE_RHS, that can be safely shared, some other RHS
+            that was unshared when we found it had a single debug
+            use, or a DEBUG_EXPR_DECL, that can be safely
+            shared.  */
+         SET_USE (use_p, value);
+      else
+       gimple_debug_bind_reset_value (stmt);
 
       update_stmt (stmt);
     }
 }
 
 
-/* Given a STMT to be moved to the iterator position TOBSIP in the
-   TOBB basic block, verify whether we're moving it across any of the
-   debug statements that use it.  If TOBB is NULL, then the definition
-   is understood as being removed, and TOBSIP is unused.  */
+/* Insert a DEBUG BIND stmt before STMT for each DEF referenced by
+   other DEBUG stmts, and replace uses of the DEF with the
+   newly-created debug temp.  */
 
 void
-propagate_defs_into_debug_stmts (gimple def, basic_block tobb,
-                                const gimple_stmt_iterator *togsip)
+insert_debug_temps_for_defs (gimple_stmt_iterator *gsi)
 {
+  gimple stmt;
   ssa_op_iter op_iter;
   def_operand_p def_p;
 
   if (!MAY_HAVE_DEBUG_STMTS)
     return;
 
-  FOR_EACH_SSA_DEF_OPERAND (def_p, def, op_iter, SSA_OP_DEF)
+  stmt = gsi_stmt (*gsi);
+
+  FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, op_iter, SSA_OP_DEF)
     {
       tree var = DEF_FROM_PTR (def_p);
 
       if (TREE_CODE (var) != SSA_NAME)
        continue;
 
-      propagate_var_def_into_debug_stmts (var, tobb, togsip);
+      insert_debug_temp_for_var_def (gsi, var);
     }
 }
 
index 45183218a2c86cf1751e968a56d15e204c4e9556..bb0880260ffcce8f7830c764c3e87628a444dc85 100644 (file)
@@ -206,7 +206,7 @@ release_ssa_name (tree var)
       use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
 
       if (MAY_HAVE_DEBUG_STMTS)
-       propagate_var_def_into_debug_stmts (var, NULL, NULL);
+       insert_debug_temp_for_var_def (NULL, var);
 
 #ifdef ENABLE_CHECKING
       verify_imm_links (stderr, var);
index 4c3f52bd7b76e9424f0f1b2b59f3558ed8a2f1f3..9e463c048726d9b502b796c2b599a0d9f78ca8b8 100644 (file)
@@ -152,6 +152,9 @@ static const char * const tree_node_kind_names[] = {
 static GTY(()) int next_decl_uid;
 /* Unique id for next type created.  */
 static GTY(()) int next_type_uid = 1;
+/* Unique id for next debug decl created.  Use negative numbers,
+   to catch erroneous uses.  */
+static GTY(()) int next_debug_decl_uid;
 
 /* Since we cannot rehash a type after it is in the table, we have to
    keep the hash code.  */
@@ -872,7 +875,10 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
            DECL_ALIGN (t) = 1;
        }
       DECL_SOURCE_LOCATION (t) = input_location;
-      DECL_UID (t) = next_decl_uid++;
+      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
+       DECL_UID (t) = --next_debug_decl_uid;
+      else
+       DECL_UID (t) = next_decl_uid++;
       if (TREE_CODE (t) == LABEL_DECL)
        LABEL_DECL_UID (t) = -1;
 
@@ -948,7 +954,10 @@ copy_node_stat (tree node MEM_STAT_DECL)
 
   if (TREE_CODE_CLASS (code) == tcc_declaration)
     {
-      DECL_UID (t) = next_decl_uid++;
+      if (code == DEBUG_EXPR_DECL)
+       DECL_UID (t) = --next_debug_decl_uid;
+      else
+       DECL_UID (t) = next_decl_uid++;
       if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
          && DECL_HAS_VALUE_EXPR_P (node))
        {
index c1ba96aa9663fc811700b656bd4dbc5eaa95434f..01d91b76a6fc3a736194bf8eb4bbdd604f48964f 100644 (file)
@@ -351,6 +351,10 @@ DEFTREECODE (PARM_DECL, "parm_decl", tcc_declaration, 0)
 DEFTREECODE (TYPE_DECL, "type_decl", tcc_declaration, 0)
 DEFTREECODE (RESULT_DECL, "result_decl", tcc_declaration, 0)
 
+/* A "declaration" of a debug temporary.  It should only appear in
+   DEBUG stmts.  */
+DEFTREECODE (DEBUG_EXPR_DECL, "debug_expr_decl", tcc_declaration, 0)
+
 /* A namespace declaration.  Namespaces appear in DECL_CONTEXT of other
    _DECLs, providing a hierarchy of names.  */
 DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0)
index 20463b4a18b572c5b99e418d4a7e473e25849f03..2487a1ce9fedaf5966e04020da8b795729004078 100644 (file)
@@ -2455,6 +2455,10 @@ struct function;
 /* Every ..._DECL node gets a unique number.  */
 #define DECL_UID(NODE) (DECL_MINIMAL_CHECK (NODE)->decl_minimal.uid)
 
+/* DEBUG_EXPR_DECLs get negative UID numbers, to catch erroneous
+   uses.  */
+#define DEBUG_TEMP_UID(NODE) (-DECL_UID (TREE_CHECK ((NODE), DEBUG_EXPR_DECL)))
+
 /* These two fields describe where in the source code the declaration
    was.  If the declaration appears in several places (as for a C
    function that is declared first and then defined later), this
index bdd3bdee34ef765dcc5f59adf9a8764f478896a3..840128cf7c817249f053d7397b1a6a97ab735294 100644 (file)
@@ -732,6 +732,7 @@ dv_is_decl_p (decl_or_value dv)
     case (int)PARM_DECL:
     case (int)RESULT_DECL:
     case (int)FUNCTION_DECL:
+    case (int)DEBUG_EXPR_DECL:
     case (int)COMPONENT_REF:
       return true;
 
@@ -2222,7 +2223,7 @@ dataflow_set_union (dataflow_set *dst, dataflow_set *src)
 
 /* Whether the value is currently being expanded.  */
 #define VALUE_RECURSED_INTO(x) \
-  (RTL_FLAG_CHECK1 ("VALUE_RECURSED_INTO", (x), VALUE)->used)
+  (RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
 /* Whether the value is in changed_variables hash table.  */
 #define VALUE_CHANGED(x) \
   (RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
@@ -4112,6 +4113,9 @@ track_expr_p (tree expr, bool need_rtl)
   rtx decl_rtl;
   tree realdecl;
 
+  if (TREE_CODE (expr) == DEBUG_EXPR_DECL)
+    return DECL_RTL_SET_P (expr);
+
   /* If EXPR is not a parameter or a variable do not track it.  */
   if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
     return 0;
@@ -6271,11 +6275,12 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
   decl_or_value dv;
   variable var;
   location_chain loc;
-  rtx result;
+  rtx result, subreg, xret;
 
-  if (GET_CODE (x) == SUBREG)
+  switch (GET_CODE (x))
     {
-      rtx subreg = SUBREG_REG (x);
+    case SUBREG:
+      subreg = SUBREG_REG (x);
 
       if (GET_CODE (SUBREG_REG (x)) != VALUE)
        return x;
@@ -6297,22 +6302,31 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
        result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
 
       return result;
-    }
 
-  if (GET_CODE (x) != VALUE)
-    return x;
+    case DEBUG_EXPR:
+      dv = dv_from_decl (XTREE (x, 0));
+      xret = NULL;
+      break;
+
+    case VALUE:
+      dv = dv_from_value (x);
+      xret = x;
+      break;
+
+    default:
+      return x;
+    }
 
   if (VALUE_RECURSED_INTO (x))
-    return x;
+    return NULL;
 
-  dv = dv_from_value (x);
   var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
 
   if (!var)
-    return x;
+    return xret;
 
   if (var->n_var_parts == 0)
-    return x;
+    return xret;
 
   gcc_assert (var->n_var_parts == 1);
 
@@ -6332,7 +6346,7 @@ vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
   if (result)
     return result;
   else
-    return x;
+    return xret;
 }
 
 /* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
@@ -6382,6 +6396,9 @@ emit_note_insn_var_location (void **varp, void *data)
 
   decl = dv_as_decl (var->dv);
 
+  if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
+    goto clear;
+
   gcc_assert (decl);
 
   complete = true;