GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* This file contains low level functions to manipulate the CFG and
analyze it. All other modules should not transform the data structure
#include "alloc-pool.h"
#include "df.h"
#include "cfgloop.h"
+#include "tree-flow.h"
/* The obstack on which the flow graph components are allocated. */
/* Called once at initialization time. */
void
-init_flow (void)
+init_flow (struct function *the_fun)
{
- if (!cfun->cfg)
- cfun->cfg = GGC_CNEW (struct control_flow_graph);
- n_edges = 0;
- ENTRY_BLOCK_PTR = GGC_CNEW (struct basic_block_def);
- ENTRY_BLOCK_PTR->index = ENTRY_BLOCK;
- EXIT_BLOCK_PTR = GGC_CNEW (struct basic_block_def);
- EXIT_BLOCK_PTR->index = EXIT_BLOCK;
- ENTRY_BLOCK_PTR->next_bb = EXIT_BLOCK_PTR;
- EXIT_BLOCK_PTR->prev_bb = ENTRY_BLOCK_PTR;
+ if (!the_fun->cfg)
+ the_fun->cfg = GGC_CNEW (struct control_flow_graph);
+ n_edges_for_function (the_fun) = 0;
+ ENTRY_BLOCK_PTR_FOR_FUNCTION (the_fun)
+ = GGC_CNEW (struct basic_block_def);
+ ENTRY_BLOCK_PTR_FOR_FUNCTION (the_fun)->index = ENTRY_BLOCK;
+ EXIT_BLOCK_PTR_FOR_FUNCTION (the_fun)
+ = GGC_CNEW (struct basic_block_def);
+ EXIT_BLOCK_PTR_FOR_FUNCTION (the_fun)->index = EXIT_BLOCK;
+ ENTRY_BLOCK_PTR_FOR_FUNCTION (the_fun)->next_bb
+ = EXIT_BLOCK_PTR_FOR_FUNCTION (the_fun);
+ EXIT_BLOCK_PTR_FOR_FUNCTION (the_fun)->prev_bb
+ = ENTRY_BLOCK_PTR_FOR_FUNCTION (the_fun);
}
\f
/* Helper function for remove_edge and clear_edges. Frees edge structure
disconnect_src (e);
disconnect_dest (e);
+ /* This is probably not needed, but it doesn't hurt. */
+ redirect_edge_var_map_clear (e);
+
free_edge (e);
}
s->probability = REG_BR_PROB_BASE;
s->count += e->count;
remove_edge (e);
+ redirect_edge_var_map_dup (s, e);
e = s;
}
else
fprintf (file, ", loop_depth %d, count ", bb->loop_depth);
fprintf (file, HOST_WIDEST_INT_PRINT_DEC, bb->count);
fprintf (file, ", freq %i", bb->frequency);
- if (maybe_hot_bb_p (bb))
+ /* Both maybe_hot_bb_p & probably_never_executed_bb_p functions
+ crash without cfun. */
+ if (cfun && maybe_hot_bb_p (bb))
fprintf (file, ", maybe hot");
- if (probably_never_executed_bb_p (bb))
+ if (cfun && probably_never_executed_bb_p (bb))
fprintf (file, ", probably never executed");
fprintf (file, ".\n");
fprintf (file, "%d registers.\n", max);
for (i = FIRST_PSEUDO_REGISTER; i < max; i++)
{
- enum reg_class class, altclass;
+ enum reg_class rclass, altclass;
if (regstat_n_sets_and_refs)
fprintf (file, "\nRegister %d used %d times across %d insns",
fprintf (file, "; crosses 1 call");
else if (REG_N_CALLS_CROSSED (i))
fprintf (file, "; crosses %d calls", REG_N_CALLS_CROSSED (i));
+ if (REG_FREQ_CALLS_CROSSED (i))
+ fprintf (file, "; crosses call with %d frequency", REG_FREQ_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);
+ rclass = reg_preferred_class (i);
altclass = reg_alternate_class (i);
- if (class != GENERAL_REGS || altclass != ALL_REGS)
+ if (rclass != GENERAL_REGS || altclass != ALL_REGS)
{
- if (altclass == ALL_REGS || class == ALL_REGS)
- fprintf (file, "; pref %s", reg_class_names[(int) class]);
+ if (altclass == ALL_REGS || rclass == ALL_REGS)
+ fprintf (file, "; pref %s", reg_class_names[(int) rclass]);
else if (altclass == NO_REGS)
- fprintf (file, "; %s or none", reg_class_names[(int) class]);
+ fprintf (file, "; %s or none", reg_class_names[(int) rclass]);
else
fprintf (file, "; pref %s, else %s",
- reg_class_names[(int) class],
+ reg_class_names[(int) rclass],
reg_class_names[(int) altclass]);
}
dump_reg_info (file);
fprintf (file, "\n%d basic blocks, %d edges.\n", n_basic_blocks, n_edges);
- FOR_EACH_BB (bb)
+ FOR_ALL_BB (bb)
{
dump_bb_info (bb, true, true, flags, "", file);
check_bb_profile (bb, file);
dump_edge_info (FILE *file, edge e, int do_succ)
{
basic_block side = (do_succ ? e->dest : e->src);
-
- if (side == ENTRY_BLOCK_PTR)
+ /* both ENTRY_BLOCK_PTR & EXIT_BLOCK_PTR depend upon cfun. */
+ if (cfun && side == ENTRY_BLOCK_PTR)
fputs (" ENTRY", file);
- else if (side == EXIT_BLOCK_PTR)
+ else if (cfun && side == EXIT_BLOCK_PTR)
fputs (" EXIT", file);
else
fprintf (file, " %d", side->index);
bool first = true;
static const char * const bb_bitnames[] =
{
- "dirty", "new", "reachable", "visited", "irreducible_loop", "superblock"
+ "new", "reachable", "irreducible_loop", "superblock",
+ "nosched", "hot", "cold", "dup", "xlabel", "rtl",
+ "fwdr", "nothrd"
};
const unsigned n_bitnames = sizeof (bb_bitnames) / sizeof (char *);
edge e;
FOR_EACH_EDGE (c, ei, bb->succs)
{
- c->probability = RDIV (c->probability * scale, 65536);
- if (c->probability > REG_BR_PROB_BASE)
+ /* Protect from overflow due to additional scaling. */
+ if (c->probability > prob)
c->probability = REG_BR_PROB_BASE;
+ else
+ {
+ c->probability = RDIV (c->probability * scale, 65536);
+ if (c->probability > REG_BR_PROB_BASE)
+ c->probability = REG_BR_PROB_BASE;
+ }
}
}
static hashval_t
bb_copy_original_hash (const void *p)
{
- struct htab_bb_copy_original_entry *data
- = ((struct htab_bb_copy_original_entry *)p);
+ const struct htab_bb_copy_original_entry *data
+ = ((const struct htab_bb_copy_original_entry *)p);
return data->index1;
}
static int
bb_copy_original_eq (const void *p, const void *q)
{
- struct htab_bb_copy_original_entry *data
- = ((struct htab_bb_copy_original_entry *)p);
- struct htab_bb_copy_original_entry *data2
- = ((struct htab_bb_copy_original_entry *)q);
+ const struct htab_bb_copy_original_entry *data
+ = ((const struct htab_bb_copy_original_entry *)p);
+ const struct htab_bb_copy_original_entry *data2
+ = ((const struct htab_bb_copy_original_entry *)q);
return data->index1 == data2->index1;
}