From: Michael Matz Date: Tue, 23 Feb 2010 16:41:52 +0000 (+0000) Subject: re PR debug/43077 (VTA issues caused by SSA expand) X-Git-Tag: releases/gcc-4.5.0~643 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2a8e30fbf34c8364dc0710b374f34038634c90a6;p=thirdparty%2Fgcc.git re PR debug/43077 (VTA issues caused by SSA expand) 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7d6c3068af10..ce7caff698ab 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2010-02-23 Michael Matz + + 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 PR 43123 diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 53beecd57fd6..d9b5774c006a 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -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)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bc1ff1f15ba4..6fe4b8d9836b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-02-23 Jakub Jelinek + + PR debug/43077 + * gcc.dg/guality/pr43077-1.c: New test. + 2010-02-23 Manuel López-Ibáñez 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 index 000000000000..d8d5eebe07ff --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr43077-1.c @@ -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; +}