]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR debug/43077 (VTA issues caused by SSA expand)
authorMichael Matz <matz@gcc.gnu.org>
Tue, 23 Feb 2010 16:41:52 +0000 (16:41 +0000)
committerMichael Matz <matz@gcc.gnu.org>
Tue, 23 Feb 2010 16:41:52 +0000 (16:41 +0000)
PR debug/43077
* cfgexpand (expand_debug_expr): Expand TERed ssa names in place.
(expand_gimple_basic_block): Generate and use debug temps if there
are debug uses left after the last real use of TERed ssa names.
Unlink debug immediate uses when they are expanded.

testsuite/
PR debug/43077
* gcc.dg/guality/pr43077-1.c: New test.

From-SVN: r157009

gcc/ChangeLog
gcc/cfgexpand.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/guality/pr43077-1.c [new file with mode: 0644]

index 7d6c3068af102a72396f2816b5dccac20a8db25e..ce7caff698abca1d7a661a86fa5118589d647aa1 100644 (file)
@@ -1,3 +1,11 @@
+2010-02-23  Michael Matz  <matz@suse.de>
+
+       PR debug/43077
+       * cfgexpand (expand_debug_expr): Expand TERed ssa names in place.
+       (expand_gimple_basic_block): Generate and use debug temps if there
+       are debug uses left after the last real use of TERed ssa names.
+       Unlink debug immediate uses when they are expanded.
+
 2010-02-23  Manuel López-Ibáñez  <manu@gcc.gnu.org>
 
        PR 43123
index 53beecd57fd6b4b937928f1832aaac4c9b75f564..d9b5774c006afcc2f5e9659f82bee5de19f05068 100644 (file)
@@ -2338,7 +2338,10 @@ expand_debug_expr (tree exp)
 
        if (inner_mode == VOIDmode)
          {
-           inner_mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+           if (TREE_CODE (exp) == SSA_NAME)
+             inner_mode = TYPE_MODE (TREE_TYPE (exp));
+           else
+             inner_mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
            if (mode == inner_mode)
              return op0;
          }
@@ -2354,6 +2357,7 @@ expand_debug_expr (tree exp)
          }
        else if (FLOAT_MODE_P (mode))
          {
+           gcc_assert (TREE_CODE (exp) != SSA_NAME);
            if (TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))))
              op0 = simplify_gen_unary (UNSIGNED_FLOAT, mode, op0, inner_mode);
            else
@@ -2886,14 +2890,24 @@ expand_debug_expr (tree exp)
 
     case SSA_NAME:
       {
-       int part = var_to_partition (SA.map, exp);
+       gimple g = get_gimple_for_ssa_name (exp);
+       if (g)
+         {
+           op0 = expand_debug_expr (gimple_assign_rhs_to_tree (g));
+           if (!op0)
+             return NULL;
+         }
+       else
+         {
+           int part = var_to_partition (SA.map, exp);
 
-       if (part == NO_PARTITION)
-         return NULL;
+           if (part == NO_PARTITION)
+             return NULL;
 
-       gcc_assert (part >= 0 && (unsigned)part < SA.map->num_partitions);
+           gcc_assert (part >= 0 && (unsigned)part < SA.map->num_partitions);
 
-       op0 = SA.partition_to_pseudo[part];
+           op0 = SA.partition_to_pseudo[part];
+         }
        goto adjust_mode;
       }
 
@@ -3050,6 +3064,105 @@ expand_gimple_basic_block (basic_block bb)
       basic_block new_bb;
 
       stmt = gsi_stmt (gsi);
+
+      /* If this statement is a non-debug one, and we generate debug
+        insns, then this one might be the last real use of a TERed
+        SSA_NAME, but where there are still some debug uses further
+        down.  Expanding the current SSA name in such further debug
+        uses by their RHS might lead to wrong debug info, as coalescing
+        might make the operands of such RHS be placed into the same
+        pseudo as something else.  Like so:
+          a_1 = a_0 + 1;   // Assume a_1 is TERed and a_0 is dead
+          use(a_1);
+          a_2 = ...
+           #DEBUG ... => a_1
+        As a_0 and a_2 don't overlap in lifetime, assume they are coalesced.
+        If we now would expand a_1 by it's RHS (a_0 + 1) in the debug use,
+        the write to a_2 would actually have clobbered the place which
+        formerly held a_0.
+
+        So, instead of that, we recognize the situation, and generate
+        debug temporaries at the last real use of TERed SSA names:
+          a_1 = a_0 + 1;
+           #DEBUG #D1 => a_1
+          use(a_1);
+          a_2 = ...
+           #DEBUG ... => #D1
+        */
+      if (MAY_HAVE_DEBUG_INSNS
+         && SA.values
+         && !is_gimple_debug (stmt))
+       {
+         ssa_op_iter iter;
+         tree op;
+         gimple def;
+
+         location_t sloc = get_curr_insn_source_location ();
+         tree sblock = get_curr_insn_block ();
+
+         /* Look for SSA names that have their last use here (TERed
+            names always have only one real use).  */
+         FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
+           if ((def = get_gimple_for_ssa_name (op)))
+             {
+               imm_use_iterator imm_iter;
+               use_operand_p use_p;
+               bool have_debug_uses = false;
+
+               FOR_EACH_IMM_USE_FAST (use_p, imm_iter, op)
+                 {
+                   if (gimple_debug_bind_p (USE_STMT (use_p)))
+                     {
+                       have_debug_uses = true;
+                       break;
+                     }
+                 }
+
+               if (have_debug_uses)
+                 {
+                   /* OP is a TERed SSA name, with DEF it's defining
+                      statement, and where OP is used in further debug
+                      instructions.  Generate a debug temporary, and
+                      replace all uses of OP in debug insns with that
+                      temporary.  */
+                   gimple debugstmt;
+                   tree value = gimple_assign_rhs_to_tree (def);
+                   tree vexpr = make_node (DEBUG_EXPR_DECL);
+                   rtx val;
+                   enum machine_mode mode;
+
+                   set_curr_insn_source_location (gimple_location (def));
+                   set_curr_insn_block (gimple_block (def));
+
+                   DECL_ARTIFICIAL (vexpr) = 1;
+                   TREE_TYPE (vexpr) = TREE_TYPE (value);
+                   if (DECL_P (value))
+                     mode = DECL_MODE (value);
+                   else
+                     mode = TYPE_MODE (TREE_TYPE (value));
+                   DECL_MODE (vexpr) = mode;
+
+                   val = gen_rtx_VAR_LOCATION
+                       (mode, vexpr, (rtx)value, VAR_INIT_STATUS_INITIALIZED);
+
+                   val = emit_debug_insn (val);
+
+                   FOR_EACH_IMM_USE_STMT (debugstmt, imm_iter, op)
+                     {
+                       if (!gimple_debug_bind_p (debugstmt))
+                         continue;
+
+                       FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
+                         SET_USE (use_p, vexpr);
+
+                       update_stmt (debugstmt);
+                     }
+                 }
+             }
+         set_curr_insn_source_location (sloc);
+         set_curr_insn_block (sblock);
+       }
+
       currently_expanding_gimple_stmt = stmt;
 
       /* Expand this statement, then evaluate the resulting RTL and
@@ -3102,6 +3215,13 @@ expand_gimple_basic_block (basic_block bb)
                  INSN_VAR_LOCATION_LOC (val) = (rtx)value;
                }
 
+             /* In order not to generate too many debug temporaries,
+                we delink all uses of debug statements we already expanded.
+                Therefore debug statements between definition and real
+                use of TERed SSA names will continue to use the SSA name,
+                and not be replaced with debug temps.  */
+             delink_stmt_imm_use (stmt);
+
              gsi = nsi;
              gsi_next (&nsi);
              if (gsi_end_p (nsi))
index bc1ff1f15ba4f29b870d7a6547b313ca2cd57549..6fe4b8d9836b89dbafd8be3483780ba29f7826fb 100644 (file)
@@ -1,3 +1,8 @@
+2010-02-23  Jakub Jelinek  <jakub@redhat.com>
+
+       PR debug/43077
+       * gcc.dg/guality/pr43077-1.c: New test.
+
 2010-02-23  Manuel López-Ibáñez  <manu@gcc.gnu.org>
 
        PR 43123
diff --git a/gcc/testsuite/gcc.dg/guality/pr43077-1.c b/gcc/testsuite/gcc.dg/guality/pr43077-1.c
new file mode 100644 (file)
index 0000000..d8d5eeb
--- /dev/null
@@ -0,0 +1,55 @@
+/* PR debug/43077 */
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+int varb;
+
+int __attribute__((noinline))
+fn1 (void)
+{
+  int vara = (varb == 3);              /* { dg-final { gdb-test 11 "vara" "0" } } */
+  asm volatile ("" : : "g" (vara));    /* { dg-final { gdb-test 11 "varb" "2" } } */
+  return 0;
+}
+
+int __attribute__((noinline))
+fn2 (void)
+{
+  int vara = (varb == 3);              /* { dg-final { gdb-test 19 "vara" "1" } } */
+  asm volatile ("" : : "g" (vara));    /* { dg-final { gdb-test 19 "varb" "3" } } */
+  return 0;
+}
+
+int __attribute__((noinline))
+foo (unsigned long *p, unsigned long *q)
+{
+  int ret;
+  asm volatile ("" : "=r" (ret), "=r" (*p), "=r" (*q) : "0" (1), "1" (2), "2" (3));
+  return ret;
+}
+
+int __attribute__((noinline))
+fn3 (void)
+{
+  unsigned long a = 0, b = 0, c = 0;
+  a = foo (&b, &c);
+                                       /* { dg-final { gdb-test 42 "a" "1" } } */
+                                       /* { dg-final { gdb-test 42 "b" "2" } } */
+                                       /* { dg-final { gdb-test 42 "c" "3" } } */
+  unsigned long vara = a;              /* { dg-final { gdb-test 42 "vara" "1" } } */
+  unsigned long varb = b;              /* { dg-final { gdb-test 42 "varb" "2" } } */
+  unsigned long varc = c;              /* { dg-final { gdb-test 42 "varc" "3" } } */
+  asm volatile ("" : : "g" (vara), "g" (varb), "g" (varc));
+  return a;
+}
+
+int
+main (void)
+{
+  asm volatile ("" : "=r" (varb) : "0" (2));
+  fn1 ();
+  asm volatile ("" : "=r" (varb) : "0" (3));
+  fn2 ();
+  fn3 ();
+  return 0;
+}