aboutsummaryrefslogtreecommitdiff
path: root/gcc/cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cfg.c')
-rw-r--r--gcc/cfg.c221
1 files changed, 142 insertions, 79 deletions
diff --git a/gcc/cfg.c b/gcc/cfg.c
index cbaf8f6..cf3b440 100644
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -1,6 +1,6 @@
/* Control flow graph manipulation code for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GCC.
@@ -66,6 +66,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "ggc.h"
#include "hashtab.h"
#include "alloc-pool.h"
+#include "df.h"
#include "cfgloop.h"
/* The obstack on which the flow graph components are allocated. */
@@ -163,24 +164,28 @@ void
compact_blocks (void)
{
int i;
- basic_block bb;
SET_BASIC_BLOCK (ENTRY_BLOCK, ENTRY_BLOCK_PTR);
SET_BASIC_BLOCK (EXIT_BLOCK, EXIT_BLOCK_PTR);
-
- i = NUM_FIXED_BLOCKS;
- FOR_EACH_BB (bb)
+
+ if (df)
+ df_compact_blocks ();
+ else
{
- SET_BASIC_BLOCK (i, bb);
- bb->index = i;
- i++;
- }
-
- gcc_assert (i == n_basic_blocks);
-
- for (; i < last_basic_block; i++)
- SET_BASIC_BLOCK (i, NULL);
+ basic_block bb;
+
+ i = NUM_FIXED_BLOCKS;
+ FOR_EACH_BB (bb)
+ {
+ SET_BASIC_BLOCK (i, bb);
+ bb->index = i;
+ i++;
+ }
+ gcc_assert (i == n_basic_blocks);
+ for (; i < last_basic_block; i++)
+ SET_BASIC_BLOCK (i, NULL);
+ }
last_basic_block = n_basic_blocks;
}
@@ -205,6 +210,7 @@ static inline void
connect_src (edge e)
{
VEC_safe_push (edge, gc, e->src->succs, e);
+ df_mark_solutions_dirty ();
}
/* Connect E to E->dest. */
@@ -215,6 +221,7 @@ connect_dest (edge e)
basic_block dest = e->dest;
VEC_safe_push (edge, gc, dest->preds, e);
e->dest_idx = EDGE_COUNT (dest->preds) - 1;
+ df_mark_solutions_dirty ();
}
/* Disconnect edge E from E->src. */
@@ -237,6 +244,7 @@ disconnect_src (edge e)
ei_next (&ei);
}
+ df_mark_solutions_dirty ();
gcc_unreachable ();
}
@@ -254,6 +262,7 @@ disconnect_dest (edge e)
to update dest_idx of the edge that moved into the "hole". */
if (dest_idx < EDGE_COUNT (dest->preds))
EDGE_PRED (dest, dest_idx)->dest_idx = dest_idx;
+ df_mark_solutions_dirty ();
}
/* Create an edge connecting SRC and DEST with flags FLAGS. Return newly
@@ -275,7 +284,6 @@ unchecked_make_edge (basic_block src, basic_block dst, int flags)
connect_dest (e);
execute_on_growing_pred (e);
-
return e;
}
@@ -409,15 +417,16 @@ redirect_edge_pred (edge e, basic_block new_pred)
connect_src (e);
}
-/* Clear all basic block flags, with the exception of partitioning. */
+/* Clear all basic block flags, with the exception of partitioning and
+ setjmp_target. */
void
clear_bb_flags (void)
{
basic_block bb;
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
- bb->flags = (BB_PARTITION (bb) | (bb->flags & BB_DISABLE_SCHEDULE)
- | (bb->flags & BB_RTL));
+ bb->flags = (BB_PARTITION (bb)
+ | (bb->flags & (BB_DISABLE_SCHEDULE + BB_RTL + BB_NON_LOCAL_GOTO_TARGET)));
}
/* Check the consistency of profile information. We can't do that
@@ -469,6 +478,41 @@ check_bb_profile (basic_block bb, FILE * file)
}
}
+/* Write information about registers and basic blocks into FILE.
+ This is part of making a debugging dump. */
+
+void
+dump_regset (regset r, FILE *outf)
+{
+ unsigned i;
+ reg_set_iterator rsi;
+
+ if (r == NULL)
+ {
+ fputs (" (nil)", outf);
+ return;
+ }
+
+ EXECUTE_IF_SET_IN_REG_SET (r, 0, i, rsi)
+ {
+ fprintf (outf, " %d", i);
+ if (i < FIRST_PSEUDO_REGISTER)
+ fprintf (outf, " [%s]",
+ reg_names[i]);
+ }
+}
+
+/* Print a human-readable representation of R on the standard error
+ stream. This function is designed to be used from within the
+ debugger. */
+
+void
+debug_regset (regset r)
+{
+ dump_regset (r, stderr);
+ putc ('\n', stderr);
+}
+
/* Emit basic block information for BB. HEADER is true if the user wants
the generic information and the predecessors, FOOTER is true if they want
the successors. FLAGS is the dump flags of interest; TDF_DETAILS emit
@@ -500,6 +544,14 @@ dump_bb_info (basic_block bb, bool header, bool footer, int flags,
fprintf (file, "%sPredecessors: ", prefix);
FOR_EACH_EDGE (e, ei, bb->preds)
dump_edge_info (file, e, 0);
+
+ if ((flags & TDF_DETAILS)
+ && (bb->flags & BB_RTL)
+ && df)
+ {
+ fprintf (file, "\n");
+ df_dump_top (bb, file);
+ }
}
if (footer)
@@ -507,81 +559,92 @@ dump_bb_info (basic_block bb, bool header, bool footer, int flags,
fprintf (file, "\n%sSuccessors: ", prefix);
FOR_EACH_EDGE (e, ei, bb->succs)
dump_edge_info (file, e, 1);
- }
- if ((flags & TDF_DETAILS)
- && (bb->flags & BB_RTL))
- {
- if (bb->il.rtl->global_live_at_start && header)
+ if ((flags & TDF_DETAILS)
+ && (bb->flags & BB_RTL)
+ && df)
{
- fprintf (file, "\n%sRegisters live at start:", prefix);
- dump_regset (bb->il.rtl->global_live_at_start, file);
- }
-
- if (bb->il.rtl->global_live_at_end && footer)
- {
- fprintf (file, "\n%sRegisters live at end:", prefix);
- dump_regset (bb->il.rtl->global_live_at_end, file);
+ fprintf (file, "\n");
+ df_dump_bottom (bb, file);
}
}
putc ('\n', file);
}
+/* Dump the register info to FILE. */
+
+void
+dump_reg_info (FILE *file)
+{
+ unsigned int i, max = max_reg_num ();
+ if (reload_completed)
+ return;
+
+ if (reg_info_p_size < max)
+ max = reg_info_p_size;
+
+ fprintf (file, "%d registers.\n", max);
+ for (i = FIRST_PSEUDO_REGISTER; i < max; i++)
+ {
+ enum reg_class class, altclass;
+
+ if (regstat_n_sets_and_refs)
+ fprintf (file, "\nRegister %d used %d times across %d insns",
+ i, REG_N_REFS (i), REG_LIVE_LENGTH (i));
+ else if (df)
+ fprintf (file, "\nRegister %d used %d times across %d insns",
+ i, DF_REG_USE_COUNT (i) + DF_REG_DEF_COUNT (i), REG_LIVE_LENGTH (i));
+
+ if (REG_BASIC_BLOCK (i) >= NUM_FIXED_BLOCKS)
+ fprintf (file, " in block %d", REG_BASIC_BLOCK (i));
+ if (regstat_n_sets_and_refs)
+ fprintf (file, "; set %d time%s", REG_N_SETS (i),
+ (REG_N_SETS (i) == 1) ? "" : "s");
+ else if (df)
+ fprintf (file, "; set %d time%s", DF_REG_DEF_COUNT (i),
+ (DF_REG_DEF_COUNT (i) == 1) ? "" : "s");
+ if (regno_reg_rtx[i] != NULL && REG_USERVAR_P (regno_reg_rtx[i]))
+ fprintf (file, "; user var");
+ if (REG_N_DEATHS (i) != 1)
+ fprintf (file, "; dies in %d places", REG_N_DEATHS (i));
+ if (REG_N_CALLS_CROSSED (i) == 1)
+ fprintf (file, "; crosses 1 call");
+ else if (REG_N_CALLS_CROSSED (i))
+ fprintf (file, "; crosses %d calls", REG_N_CALLS_CROSSED (i));
+ if (regno_reg_rtx[i] != NULL
+ && PSEUDO_REGNO_BYTES (i) != UNITS_PER_WORD)
+ fprintf (file, "; %d bytes", PSEUDO_REGNO_BYTES (i));
+
+ class = reg_preferred_class (i);
+ altclass = reg_alternate_class (i);
+ if (class != GENERAL_REGS || altclass != ALL_REGS)
+ {
+ if (altclass == ALL_REGS || class == ALL_REGS)
+ fprintf (file, "; pref %s", reg_class_names[(int) class]);
+ else if (altclass == NO_REGS)
+ fprintf (file, "; %s or none", reg_class_names[(int) class]);
+ else
+ fprintf (file, "; pref %s, else %s",
+ reg_class_names[(int) class],
+ reg_class_names[(int) altclass]);
+ }
+
+ if (regno_reg_rtx[i] != NULL && REG_POINTER (regno_reg_rtx[i]))
+ fprintf (file, "; pointer");
+ fprintf (file, ".\n");
+ }
+}
+
+
void
dump_flow_info (FILE *file, int flags)
{
basic_block bb;
/* There are no pseudo registers after reload. Don't dump them. */
- if (reg_n_info && !reload_completed
- && (flags & TDF_DETAILS) != 0)
- {
- unsigned int i, max = max_reg_num ();
- fprintf (file, "%d registers.\n", max);
- for (i = FIRST_PSEUDO_REGISTER; i < max; i++)
- if (REG_N_REFS (i))
- {
- enum reg_class prefclass, altclass;
-
- fprintf (file, "\nRegister %d used %d times across %d insns",
- i, REG_N_REFS (i), REG_LIVE_LENGTH (i));
- if (REG_BASIC_BLOCK (i) >= 0)
- fprintf (file, " in block %d", REG_BASIC_BLOCK (i));
- if (REG_N_SETS (i))
- fprintf (file, "; set %d time%s", REG_N_SETS (i),
- (REG_N_SETS (i) == 1) ? "" : "s");
- if (regno_reg_rtx[i] != NULL && REG_USERVAR_P (regno_reg_rtx[i]))
- fprintf (file, "; user var");
- if (REG_N_DEATHS (i) != 1)
- fprintf (file, "; dies in %d places", REG_N_DEATHS (i));
- if (REG_N_CALLS_CROSSED (i) == 1)
- fprintf (file, "; crosses 1 call");
- else if (REG_N_CALLS_CROSSED (i))
- fprintf (file, "; crosses %d calls", REG_N_CALLS_CROSSED (i));
- if (regno_reg_rtx[i] != NULL
- && PSEUDO_REGNO_BYTES (i) != UNITS_PER_WORD)
- fprintf (file, "; %d bytes", PSEUDO_REGNO_BYTES (i));
-
- prefclass = reg_preferred_class (i);
- altclass = reg_alternate_class (i);
- if (prefclass != GENERAL_REGS || altclass != ALL_REGS)
- {
- if (altclass == ALL_REGS || prefclass == ALL_REGS)
- fprintf (file, "; pref %s", reg_class_names[(int) prefclass]);
- else if (altclass == NO_REGS)
- fprintf (file, "; %s or none", reg_class_names[(int) prefclass]);
- else
- fprintf (file, "; pref %s, else %s",
- reg_class_names[(int) prefclass],
- reg_class_names[(int) altclass]);
- }
-
- if (regno_reg_rtx[i] != NULL && REG_POINTER (regno_reg_rtx[i]))
- fprintf (file, "; pointer");
- fprintf (file, ".\n");
- }
- }
+ if (reg_info_p_size && (flags & TDF_DETAILS) != 0)
+ dump_reg_info (file);
fprintf (file, "\n%d basic blocks, %d edges.\n", n_basic_blocks, n_edges);
FOR_EACH_BB (bb)