aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.4.0/gcc/tree-cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.4.0/gcc/tree-cfg.c')
-rw-r--r--gcc-4.4.0/gcc/tree-cfg.c122
1 files changed, 111 insertions, 11 deletions
diff --git a/gcc-4.4.0/gcc/tree-cfg.c b/gcc-4.4.0/gcc/tree-cfg.c
index c4a746ef5..da7f9d9f0 100644
--- a/gcc-4.4.0/gcc/tree-cfg.c
+++ b/gcc-4.4.0/gcc/tree-cfg.c
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see
#include "value-prof.h"
#include "pointer-set.h"
#include "tree-inline.h"
+#include "vecprim.h"
/* This file contains functions for building the Control Flow Graph (CFG)
for a function tree. */
@@ -82,6 +83,12 @@ static struct cfg_stats_d cfg_stats;
/* Nonzero if we found a computed goto while building basic blocks. */
static bool found_computed_goto;
+/* Vectors to map a discriminator-enhanced locus to a real locus and
+ discriminator value. */
+static VEC(int,heap) *discriminator_location_locations = NULL;
+static VEC(int,heap) *discriminator_location_discriminators = NULL;
+location_t min_discriminator_location = UNKNOWN_LOCATION;
+
/* Hash table to store last discriminator assigned for each locus. */
struct locus_discrim_map
{
@@ -657,6 +664,60 @@ make_edges (void)
fold_cond_expr_cond ();
}
+/* Associate the DISCRIMINATOR with LOCUS, and return a new locus.
+ We associate discriminators with a locus by allocating location_t
+ values beyond those assigned by libcpp. Each new value is mapped
+ directly to a real location_t value, and separately to the
+ discriminator. */
+
+static location_t
+location_with_discriminator (location_t locus, int discriminator)
+{
+ static int next_discriminator_location = 0;
+
+ if (min_discriminator_location == UNKNOWN_LOCATION)
+ {
+ min_discriminator_location = line_table->highest_location + 1;
+ next_discriminator_location = min_discriminator_location;
+ }
+
+ VEC_safe_push (int, heap, discriminator_location_locations, (int) locus);
+ VEC_safe_push (int, heap, discriminator_location_discriminators,
+ discriminator);
+ return next_discriminator_location++;
+}
+
+/* Return TRUE if LOCUS represents a location with a discriminator. */
+
+static inline bool
+has_discriminator (location_t locus)
+{
+ return (min_discriminator_location != UNKNOWN_LOCATION
+ && locus >= min_discriminator_location);
+}
+
+/* Return the real location_t value for LOCUS. */
+
+location_t
+map_discriminator_location (location_t locus)
+{
+ if (! has_discriminator (locus))
+ return locus;
+ return (location_t) VEC_index (int, discriminator_location_locations,
+ locus - min_discriminator_location);
+}
+
+/* Return the discriminator for LOCUS. */
+
+int
+get_discriminator_from_locus (location_t locus)
+{
+ if (! has_discriminator (locus))
+ return 0;
+ return VEC_index (int, discriminator_location_discriminators,
+ locus - min_discriminator_location);
+}
+
/* Trivial hash function for a location_t. ITEM is a pointer to
a hash table entry that maps a location_t to a discriminator. */
@@ -727,22 +788,59 @@ same_line_p (location_t locus1, location_t locus2)
&& strcmp (from.file, to.file) == 0);
}
-/* Assign a unique discriminator value to block BB if it begins at the same
- LOCUS as its predecessor block. */
+/* Assign a unique discriminator value to instructions in block BB that
+ have the same LOCUS as its predecessor block. */
static void
assign_discriminator (location_t locus, basic_block bb)
{
gimple first_in_to_bb, last_in_to_bb;
+ int discriminator = 0;
- if (locus == 0 || bb->discriminator != 0)
+ if (locus == UNKNOWN_LOCATION)
return;
+ if (has_discriminator (locus))
+ locus = map_discriminator_location (locus);
+
+ /* Check the locus of the first (non-label) instruction in the block. */
first_in_to_bb = first_non_label_stmt (bb);
- last_in_to_bb = last_stmt (bb);
- if ((first_in_to_bb && same_line_p (locus, gimple_location (first_in_to_bb)))
- || (last_in_to_bb && same_line_p (locus, gimple_location (last_in_to_bb))))
- bb->discriminator = next_discriminator_for_locus (locus);
+ if (first_in_to_bb)
+ {
+ location_t first_locus = gimple_location (first_in_to_bb);
+ if (! has_discriminator (first_locus)
+ && same_line_p (locus, first_locus))
+ discriminator = next_discriminator_for_locus (locus);
+ }
+
+ /* If the first instruction doesn't trigger a discriminator, check the
+ last instruction of the block. This catches the case where the
+ increment portion of a for loop is placed at the end of the loop
+ body. */
+ if (discriminator == 0)
+ {
+ last_in_to_bb = last_stmt (bb);
+ if (last_in_to_bb)
+ {
+ location_t last_locus = gimple_location (last_in_to_bb);
+ if (! has_discriminator (last_locus)
+ && same_line_p (locus, last_locus))
+ discriminator = next_discriminator_for_locus (locus);
+ }
+ }
+
+ if (discriminator != 0)
+ {
+ location_t new_locus = location_with_discriminator (locus, discriminator);
+ gimple_stmt_iterator gsi;
+
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ if (same_line_p (locus, gimple_location (stmt)))
+ gimple_set_location (stmt, new_locus);
+ }
+ }
}
/* Create the edges for a GIMPLE_COND starting at block BB. */
@@ -2871,7 +2969,7 @@ reinstall_phi_args (edge new_edge, edge old_edge)
gcc_assert (result == gimple_phi_result (phi));
- add_phi_arg (phi, arg, new_edge);
+ add_phi_arg (phi, arg, new_edge, redirect_edge_var_map_location (vm));
}
redirect_edge_var_map_clear (old_edge);
@@ -4756,7 +4854,8 @@ gimple_make_forwarder_block (edge fallthru)
new_phi = create_phi_node (var, bb);
SSA_NAME_DEF_STMT (var) = new_phi;
gimple_phi_set_result (phi, make_ssa_name (SSA_NAME_VAR (var), phi));
- add_phi_arg (new_phi, gimple_phi_result (phi), fallthru);
+ add_phi_arg (new_phi, gimple_phi_result (phi), fallthru,
+ UNKNOWN_LOCATION);
}
/* Add the arguments we have stored on edges. */
@@ -5153,7 +5252,8 @@ add_phi_args_after_copy_edge (edge e_copy)
phi = gsi_stmt (psi);
phi_copy = gsi_stmt (psi_copy);
def = PHI_ARG_DEF_FROM_EDGE (phi, e);
- add_phi_arg (phi_copy, def, e_copy);
+ add_phi_arg (phi_copy, def, e_copy,
+ gimple_phi_arg_location_from_edge (phi, e));
}
}
@@ -7004,7 +7104,7 @@ gimple_lv_adjust_loop_header_phi (basic_block first, basic_block second,
phi1 = gsi_stmt (psi1);
phi2 = gsi_stmt (psi2);
def = PHI_ARG_DEF (phi2, e2->dest_idx);
- add_phi_arg (phi1, def, e);
+ add_phi_arg (phi1, def, e, gimple_phi_arg_location_from_edge (phi2, e2));
}
}