Commit 878eef4a by Jakub Jelinek Committed by Jakub Jelinek

re PR debug/54519 (Debug info quality regression due to (pointless) partial inlining)

	PR debug/54519
	* ipa-split.c (split_function): Add debug args and
	debug source and normal stmts for args_to_skip which are
	gimple regs.
	* tree-inline.c (copy_debug_stmt): When inlining, adjust
	source debug bind stmts to debug binds of corresponding
	DEBUG_EXPR_DECL.

	* gcc.dg/guality/pr54519-1.c: New test.
	* gcc.dg/guality/pr54519-2.c: New test.
	* gcc.dg/guality/pr54519-3.c: New test.
	* gcc.dg/guality/pr54519-4.c: New test.
	* gcc.dg/guality/pr54519-5.c: New test.
	* gcc.dg/guality/pr54519-6.c: New test.

From-SVN: r192139
parent 3b1cd14d
2012-10-05 Jakub Jelinek <jakub@redhat.com>
PR debug/54519
* ipa-split.c (split_function): Add debug args and
debug source and normal stmts for args_to_skip which are
gimple regs.
* tree-inline.c (copy_debug_stmt): When inlining, adjust
source debug bind stmts to debug binds of corresponding
DEBUG_EXPR_DECL.
2012-10-05 Georg-Johann Lay <avr@gjlay.de>
* config/avr/avr.md: Fix indentations of insn C snippets.
......
......@@ -1059,6 +1059,7 @@ split_function (struct split_point *split_point)
gimple last_stmt = NULL;
unsigned int i;
tree arg, ddef;
VEC(tree, gc) **debug_args = NULL;
if (dump_file)
{
......@@ -1232,6 +1233,83 @@ split_function (struct split_point *split_point)
gimple_set_block (call, DECL_INITIAL (current_function_decl));
VEC_free (tree, heap, args_to_pass);
/* For optimized away parameters, add on the caller side
before the call
DEBUG D#X => parm_Y(D)
stmts and associate D#X with parm in decl_debug_args_lookup
vector to say for debug info that if parameter parm had been passed,
it would have value parm_Y(D). */
if (args_to_skip)
for (parm = DECL_ARGUMENTS (current_function_decl), num = 0;
parm; parm = DECL_CHAIN (parm), num++)
if (bitmap_bit_p (args_to_skip, num)
&& is_gimple_reg (parm))
{
tree ddecl;
gimple def_temp;
/* This needs to be done even without MAY_HAVE_DEBUG_STMTS,
otherwise if it didn't exist before, we'd end up with
different SSA_NAME_VERSIONs between -g and -g0. */
arg = get_or_create_ssa_default_def (cfun, parm);
if (!MAY_HAVE_DEBUG_STMTS)
continue;
if (debug_args == NULL)
debug_args = decl_debug_args_insert (node->symbol.decl);
ddecl = make_node (DEBUG_EXPR_DECL);
DECL_ARTIFICIAL (ddecl) = 1;
TREE_TYPE (ddecl) = TREE_TYPE (parm);
DECL_MODE (ddecl) = DECL_MODE (parm);
VEC_safe_push (tree, gc, *debug_args, DECL_ORIGIN (parm));
VEC_safe_push (tree, gc, *debug_args, ddecl);
def_temp = gimple_build_debug_bind (ddecl, unshare_expr (arg),
call);
gsi_insert_after (&gsi, def_temp, GSI_NEW_STMT);
}
/* And on the callee side, add
DEBUG D#Y s=> parm
DEBUG var => D#Y
stmts to the first bb where var is a VAR_DECL created for the
optimized away parameter in DECL_INITIAL block. This hints
in the debug info that var (whole DECL_ORIGIN is the parm PARM_DECL)
is optimized away, but could be looked up at the call site
as value of D#X there. */
if (debug_args != NULL)
{
unsigned int i;
tree var, vexpr;
gimple_stmt_iterator cgsi;
gimple def_temp;
push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
var = BLOCK_VARS (DECL_INITIAL (node->symbol.decl));
i = VEC_length (tree, *debug_args);
cgsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR));
do
{
i -= 2;
while (var != NULL_TREE
&& DECL_ABSTRACT_ORIGIN (var)
!= VEC_index (tree, *debug_args, i))
var = TREE_CHAIN (var);
if (var == NULL_TREE)
break;
vexpr = make_node (DEBUG_EXPR_DECL);
parm = VEC_index (tree, *debug_args, i);
DECL_ARTIFICIAL (vexpr) = 1;
TREE_TYPE (vexpr) = TREE_TYPE (parm);
DECL_MODE (vexpr) = DECL_MODE (parm);
def_temp = gimple_build_debug_source_bind (vexpr, parm,
NULL);
gsi_insert_before (&cgsi, def_temp, GSI_SAME_STMT);
def_temp = gimple_build_debug_bind (var, vexpr, NULL);
gsi_insert_before (&cgsi, def_temp, GSI_SAME_STMT);
}
while (i);
pop_cfun ();
}
/* We avoid address being taken on any variable used by split part,
so return slot optimization is always possible. Moreover this is
required to make DECL_BY_REFERENCE work. */
......
2012-10-05 Jakub Jelinek <jakub@redhat.com>
PR debug/54519
* gcc.dg/guality/pr54519-1.c: New test.
* gcc.dg/guality/pr54519-2.c: New test.
* gcc.dg/guality/pr54519-3.c: New test.
* gcc.dg/guality/pr54519-4.c: New test.
* gcc.dg/guality/pr54519-5.c: New test.
* gcc.dg/guality/pr54519-6.c: New test.
2012-10-05 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/50893
......
/* PR debug/54519 */
/* { dg-do run } */
/* { dg-options "-g" } */
__attribute__((noinline, noclone)) void
fn1 (int x)
{
__asm volatile ("" : "+r" (x) : : "memory");
}
static int
fn2 (int x, int y, int z)
{
int a = 8;
if (x != z)
{
fn1 (x);
fn1 (x); /* { dg-final { gdb-test 20 "x" "36" } } */
if (x == 36) /* { dg-final { gdb-test 20 "y" "25" } } */
fn1 (x); /* { dg-final { gdb-test 20 "z" "6" } } */
fn1 (x); /* { dg-final { gdb-test 23 "x" "98" } } */
if (x == 98) /* { dg-final { gdb-test 23 "y" "117" } } */
fn1 (x); /* { dg-final { gdb-test 23 "z" "8" } } */
fn1 (x);
fn1 (x + a);
}
return y;
}
__attribute__((noinline, noclone)) int
fn3 (int x, int y)
{
return fn2 (x, y, 6);
}
__attribute__((noinline, noclone)) int
fn4 (int x, int y)
{
return fn2 (x, y, 8);
}
int
main ()
{
fn3 (36, 25);
fn4 (98, 117);
return 0;
}
/* PR debug/54519 */
/* { dg-do run } */
/* { dg-options "-g" } */
__attribute__((noinline, noclone)) void
fn1 (int x)
{
__asm volatile ("" : "+r" (x) : : "memory");
}
static int
fn2 (int x, int y)
{
if (y)
{
fn1 (x); /* { dg-final { gdb-test 17 "x" "6" } } */
fn1 (x); /* { dg-final { gdb-test 17 "y" "25" } } */
fn1 (x);
fn1 (x);
y = -2 + x;
y = y * y * y + y;
fn1 (x + y); /* { dg-final { gdb-test 22 "y" "68" } } */
}
return x;
}
__attribute__((noinline, noclone)) int
fn3 (int x, int y)
{
return fn2 (x, y) + y;
}
__attribute__((noinline, noclone)) int
fn4 (int x, int y)
{
return fn2 (x, y) + y;
}
int
main ()
{
fn3 (6, 25);
fn4 (4, 117);
return 0;
}
/* PR debug/54519 */
/* { dg-do run } */
/* { dg-options "-g" } */
__attribute__((noinline, noclone)) void
fn1 (int x)
{
__asm volatile ("" : "+r" (x) : : "memory");
}
static int
fn2 (int x, int y, int z)
{
int a = 8;
if (x != z)
{
fn1 (x);
fn1 (x); /* { dg-final { gdb-test 20 "x" "36" } } */
if (x == 36) /* { dg-final { gdb-test 20 "y" "25" } } */
fn1 (x); /* { dg-final { gdb-test 20 "z" "6" } } */
fn1 (x); /* { dg-final { gdb-test 23 "x" "98" } } */
if (x == 98) /* { dg-final { gdb-test 23 "y" "117" } } */
fn1 (x); /* { dg-final { gdb-test 23 "z" "8" } } */
fn1 (x);
fn1 (x + a);
}
return y;
}
int (*p) (int, int, int) = fn2;
int
main ()
{
__asm volatile ("" : : : "memory");
int (*q) (int, int, int) = p;
__asm volatile ("" : : : "memory");
q (36, 25, 6);
q (98, 117, 8);
q (0, 0, 0);
return 0;
}
/* PR debug/54519 */
/* { dg-do run } */
/* { dg-options "-g" } */
__attribute__((noinline, noclone)) void
fn1 (int x)
{
__asm volatile ("" : "+r" (x) : : "memory");
}
static int
fn2 (int x, int y)
{
if (y)
{
fn1 (x); /* { dg-final { gdb-test 17 "x" "6" } } */
fn1 (x); /* { dg-final { gdb-test 17 "y" "25" } } */
fn1 (x);
fn1 (x);
y = -2 + x;
y = y * y * y + y;
fn1 (x + y); /* { dg-final { gdb-test 22 "y" "68" } } */
}
return x;
}
int (*p) (int, int) = fn2;
int
main ()
{
__asm volatile ("" : : : "memory");
int (*q) (int, int) = p;
__asm volatile ("" : : : "memory");
q (6, 25);
q (4, 117);
q (0, 0);
return 0;
}
/* PR debug/54519 */
/* { dg-do run } */
/* { dg-options "-g" } */
__attribute__((noinline, noclone)) void
fn1 (int x)
{
__asm volatile ("" : "+r" (x) : : "memory");
}
static int
fn2 (int x, int y)
{
if (y)
{
fn1 (x); /* { dg-final { gdb-test 17 "x" "6" } } */
fn1 (x); /* { dg-final { gdb-test 17 "y" "25" } } */
fn1 (x);
fn1 (x);
y = -2 + x;
y = y * y * y + y;
fn1 (x + y); /* { dg-final { gdb-test 22 "y" "68" } } */
}
return x;
}
__attribute__((noinline, noclone)) int
fn3 (int x, int y)
{
return fn2 (x, y);
}
__attribute__((noinline, noclone)) int
fn4 (int x, int y)
{
return fn2 (x, y);
}
int
main ()
{
fn3 (6, 25);
fn4 (4, 117);
return 0;
}
/* PR debug/54519 */
/* { dg-do run } */
/* { dg-options "-g" } */
#include "../nop.h"
static inline void
f1 (int x, int y)
{
asm volatile (NOP); /* { dg-final { gdb-test 11 "x" "2" } } */
asm volatile (NOP); /* { dg-final { gdb-test 11 "y" "0" } } */
}
static inline void
f2 (int z)
{
f1 (z, 0);
f1 (z, 1);
}
int
main ()
{
f2 (2);
f2 (3);
return 0;
}
......@@ -2374,6 +2374,31 @@ copy_debug_stmt (gimple stmt, copy_body_data *id)
gimple_debug_source_bind_set_var (stmt, t);
walk_tree (gimple_debug_source_bind_get_value_ptr (stmt),
remap_gimple_op_r, &wi, NULL);
/* When inlining and source bind refers to one of the optimized
away parameters, change the source bind into normal debug bind
referring to the corresponding DEBUG_EXPR_DECL that should have
been bound before the call stmt. */
t = gimple_debug_source_bind_get_value (stmt);
if (t != NULL_TREE
&& TREE_CODE (t) == PARM_DECL
&& id->gimple_call)
{
VEC(tree, gc) **debug_args = decl_debug_args_lookup (id->src_fn);
unsigned int i;
if (debug_args != NULL)
{
for (i = 0; i < VEC_length (tree, *debug_args); i += 2)
if (VEC_index (tree, *debug_args, i) == DECL_ORIGIN (t)
&& TREE_CODE (VEC_index (tree, *debug_args, i + 1))
== DEBUG_EXPR_DECL)
{
t = VEC_index (tree, *debug_args, i + 1);
stmt->gsbase.subcode = GIMPLE_DEBUG_BIND;
gimple_debug_bind_set_value (stmt, t);
break;
}
}
}
}
processing_debug_stmt = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment