===================================================================
@@ -2782,6 +2782,18 @@ gimple_assign_load_p (const gimple *gs)
}
+/* Return true if GS is an assignment that loads DECL into its lhs. */
+
+static inline bool
+gimple_assign_load_decl_p (const gimple *gs, tree decl)
+{
+ const gassign *assign = dyn_cast <const gassign *> (gs);
+ return (assign
+ && gimple_assign_single_p (assign)
+ && get_base_address (gimple_assign_rhs1 (assign)) == decl);
+}
+
+
/* Return true if S is a type-cast assignment. */
static inline bool
===================================================================
@@ -39,6 +39,7 @@ extern void redirect_edge_var_map_empty
extern edge ssa_redirect_edge (edge, basic_block);
extern void flush_pending_stmts (edge);
extern void gimple_replace_ssa_lhs (gimple *, tree);
+extern void inherit_target_for_debug_bind (tree, tree);
extern tree target_for_debug_bind (tree);
extern void insert_debug_temp_for_var_def (gimple_stmt_iterator *, tree);
extern void insert_debug_temps_for_defs (gimple_stmt_iterator *);
===================================================================
@@ -232,6 +232,25 @@ gimple_replace_ssa_lhs (gimple *stmt, tr
gimple_set_lhs (stmt, nlhs);
}
+/* Record that assignments to new temporary variable VAR should be treated
+ for debug purposes like an assignment to ORIGIN. More specifically,
+ record that the value of target_for_debug_bind (VAR) should track the
+ value of target_for_debug_bind (ORIGIN).
+
+ This can be useful when replacing all references to ORIGIN with VAR
+ in a particular region of code. */
+
+void
+inherit_target_for_debug_bind (tree var, tree origin)
+{
+ gcc_assert (VAR_P (var)
+ && DECL_IGNORED_P (var)
+ && DECL_ARTIFICIAL (var)
+ && DECL_NAMELESS (var)
+ && !DECL_ABSTRACT_ORIGIN (var));
+ if (target_for_debug_bind (origin))
+ DECL_ABSTRACT_ORIGIN (var) = origin;
+}
/* Given a tree for an expression for which we might want to emit
locations or values in debug information (generally a variable, but
@@ -252,6 +271,12 @@ target_for_debug_bind (tree var)
return NULL_TREE;
}
+ /* Honor choices made through inherit_target_for_debug_bind. */
+ if (VAR_P (var)
+ && DECL_IGNORED_P (var)
+ && !DECL_IGNORED_P (DECL_ORIGIN (var)))
+ var = DECL_ORIGIN (var);
+
if ((!VAR_P (var) || VAR_DECL_IS_VIRTUAL_OPERAND (var))
&& TREE_CODE (var) != PARM_DECL)
return NULL_TREE;
===================================================================
@@ -1916,7 +1916,12 @@ maybe_register_def (def_operand_p def_p,
SET_DEF (def_p, def);
tree tracked_var = target_for_debug_bind (sym);
- if (tracked_var)
+ /* Don't emit "VAR => DEF" for "DEF = VAR". Although not
+ semantically wrong, it leads to more resets when the load
+ from VAR is (or might become) partly speculative. */
+ if (tracked_var
+ && !(track_direct_refs_for_debug_p (tracked_var)
+ && gimple_assign_load_decl_p (stmt, tracked_var)))
{
gimple *note = gimple_build_debug_bind (tracked_var, def, stmt);
/* If stmt ends the bb, insert the debug stmt on the single
===================================================================
@@ -48,6 +48,7 @@ Free Software Foundation; either version
#include "alias.h"
#include "builtins.h"
#include "tree-dfa.h"
+#include "tree-ssa.h"
/* TODO: Support for predicated code motion. I.e.
@@ -1998,6 +1999,24 @@ execute_sm_if_changed (edge ex, tree mem
orig_ex->aux = (void *) p;
}
+ /* ??? As things stand, the value of MEM on entry to the join block
+ can be found at MEM's DECL_RTL. It would therefore be accurate
+ to emit:
+
+ # DEBUG MEM s=> MEM
+
+ on entry to the block. However, there's no guarantee that later
+ optimizations will keep things that way, and they can't reasonably
+ be expected to find and correct the statement.
+
+ E.g. if the store in THEN_BB is later deleted as dead, the debug
+ statement above would reestablish the connection between MEM and
+ its DECL_RTL even though the two are no longer the same.
+
+ We therefore leave things so that the debug location on entry
+ to the join block comes from MEM's DECL_RTL if the flag is set
+ and TMP_VAR otherwise. */
+
if (!loop_has_only_one_exit)
for (gphi_iterator gpi = gsi_start_phis (old_dest);
!gsi_end_p (gpi); gsi_next (&gpi))
@@ -2082,6 +2101,7 @@ execute_sm (struct loop *loop, vec<edge>
tmp_var = create_tmp_reg (TREE_TYPE (ref->mem.ref),
get_lsm_tmp_name (ref->mem.ref, ~0));
+ inherit_target_for_debug_bind (tmp_var, ref->mem.ref);
fmt_data.loop = loop;
fmt_data.orig_loop = loop;
===================================================================
@@ -18,6 +18,7 @@
# Call pass if variable has the desired value, otherwise fail.
#
# Argument 0 is the line number on which to put a breakpoint
+# It can be suffixed by "*N" to test the Nth hit of the breakpoint.
# Argument 1 is the name of the variable to be checked
# possibly prefixed with type: to get the type of the variable
# instead of the value of the variable (the default).
@@ -54,12 +55,18 @@ proc gdb-test { useline args } {
set var $arg1
}
- set line [lindex $args 0]
+ set line_pieces [split [lindex $args 0] "*"]
+ set line [lindex $line_pieces 0]
if { [string range $line 0 0] == "@" } {
set line [string range $line 1 end]
} else {
set line [get-absolute-line $useline $line]
}
+ if { [llength $line_pieces] > 1 } {
+ set count [lindex $line_pieces 1]
+ } else {
+ set count 1
+ }
set gdb_name $::env(GUALITY_GDB_NAME)
set testname "$testcase line $line [lindex $args 1] == [lindex $args 2]"
@@ -69,6 +76,9 @@ proc gdb-test { useline args } {
set fd [open $cmd_file "w"]
puts $fd "break $line"
puts $fd "run"
+ if { $count > 1 } {
+ puts $fd "continue [expr { $count - 1 }]"
+ }
puts $fd "$command $var"
if { $command == "print" } {
# For values, let gdb interpret them by printing them.
===================================================================
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* Works without the --param except at -Os. */
+/* { dg-options "-fno-tree-vectorize --param allow-store-data-races=1 -g" } */
+
+void __attribute__((noipa))
+get_start (int *x)
+{
+ *x = 42;
+}
+
+void __attribute__((noipa))
+consume (int *x)
+{
+ *x += 1;
+}
+
+void __attribute__((noipa))
+test (int *x, int *y, int n)
+{
+ int base;
+ get_start (&base);
+ base += 1; /* { dg-final { gdb-test . "base" "42" } } */
+ get_start (&base); /* { dg-final { gdb-test . "base" "43" } } */
+ for (int i = 0; i < n; ++i)
+ {
+ x[i] = base; /* { dg-final { gdb-test .*10 "base" "51" } } */
+ base += y[i];
+ }
+ y[0] = base; /* { dg-final { gdb-test . "base" "142" } } */
+ consume (&base); /* { dg-final { gdb-test . "base" "142" } } */
+ y[1] = 1; /* { dg-final { gdb-test . "base" "143" } } */
+}
+
+int
+main (void)
+{
+ int x[100], y[100];
+ for (int i = 0; i < 100; ++i)
+ y[i] = 1;
+ test (x, y, 100);
+}
===================================================================
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-options "-fno-tree-vectorize -fno-unroll-loops -g" } */
+
+void __attribute__((noipa))
+get_start (int *x)
+{
+ *x = 42;
+}
+
+void __attribute__((noipa))
+consume (int *x)
+{
+ *x += 1;
+}
+
+void __attribute__((noipa))
+test (int *x, int *y)
+{
+ int base;
+ get_start (&base);
+ base += 1; /* { dg-final { gdb-test . "base" "42" } } */
+ get_start (&base); /* { dg-final { gdb-test . "base" "43" } } */
+ for (int i = 0; i < 100; ++i)
+ {
+ x[i] = base; /* { dg-final { gdb-test .*10 "base" "51" } } */
+ base += y[i];
+ }
+ y[0] = base; /* { dg-final { gdb-test . "base" "142" } } */
+}
+
+int
+main (void)
+{
+ int x[100], y[100];
+ for (int i = 0; i < 100; ++i)
+ y[i] = 1;
+ test (x, y);
+}
===================================================================
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-options "-fno-tree-vectorize -fno-unroll-loops -g" } */
+
+void __attribute__((noipa))
+get_start (int *x)
+{
+ *x = 42;
+}
+
+void __attribute__((noipa))
+test (int *x, int *y)
+{
+ int base;
+ get_start (&base);
+ base += 1; /* { dg-final { gdb-test . "base" "42" } } */
+ get_start (&base);
+ for (int i = 0; i < 100; ++i)
+ {
+ x[i] = base; /* { dg-final { gdb-test .*10 "base" "51" } } */
+ base += y[i];
+ }
+ y[0] = base; /* { dg-final { gdb-test . "base" "142" } } */
+ base += 1;
+ y[1] = base; /* { dg-final { gdb-test . "base" "143" } } */
+}
+
+int
+main (void)
+{
+ int x[100], y[100];
+ for (int i = 0; i < 100; ++i)
+ y[i] = 1;
+ test (x, y);
+}