Someday I'll perform the computation and figure it out. */
/* Total size of the expression hash table, in elements. */
-static int expr_hash_table_size;
+static unsigned int expr_hash_table_size;
+
/* The table itself.
This is an array of `expr_hash_table_size' elements. */
static struct expr **expr_hash_table;
static int max_uid;
/* Get the cuid of an insn. */
+#ifdef ENABLE_CHECKING
+#define INSN_CUID(INSN) (INSN_UID (INSN) > max_uid ? (abort (), 0) : uid_cuid[INSN_UID (INSN)])
+#else
#define INSN_CUID(INSN) (uid_cuid[INSN_UID (INSN)])
+#endif
/* Number of cuids. */
static int max_cuid;
/* Maximum register number in function prior to doing gcse + 1.
Registers created during this pass have regno >= max_gcse_regno.
This is named with "gcse" to not collide with global of same name. */
-static int max_gcse_regno;
+static unsigned int max_gcse_regno;
/* Maximum number of cse-able expressions found. */
static int n_exprs;
/* The basic block being processed. */
int current_block;
/* The first register to be handled in this pass. */
- int min_reg;
+ unsigned int min_reg;
/* One greater than the last register to be handled in this pass. */
- int max_reg;
+ unsigned int max_reg;
sbitmap *nonnull_local;
sbitmap *nonnull_killed;
};
static void alloc_set_hash_table PARAMS ((int));
static void free_set_hash_table PARAMS ((void));
static void compute_set_hash_table PARAMS ((void));
-static void alloc_expr_hash_table PARAMS ((int));
+static void alloc_expr_hash_table PARAMS ((unsigned int));
static void free_expr_hash_table PARAMS ((void));
static void compute_expr_hash_table PARAMS ((void));
static void dump_hash_table PARAMS ((FILE *, const char *, struct expr **,
int, int));
static struct expr *lookup_expr PARAMS ((rtx));
-static struct expr *lookup_set PARAMS ((int, rtx));
-static struct expr *next_set PARAMS ((int, struct expr *));
+static struct expr *lookup_set PARAMS ((unsigned int, rtx));
+static struct expr *next_set PARAMS ((unsigned int, struct expr *));
static void reset_opr_set_tables PARAMS ((void));
static int oprs_not_set_p PARAMS ((rtx, rtx));
static void mark_call PARAMS ((rtx));
static int classic_gcse PARAMS ((void));
static int one_classic_gcse_pass PARAMS ((int));
static void invalidate_nonnull_info PARAMS ((rtx, rtx, void *));
-static void delete_null_pointer_checks_1 PARAMS ((int *, sbitmap *, sbitmap *,
+static void delete_null_pointer_checks_1 PARAMS ((unsigned int *, sbitmap *,
+ sbitmap *,
struct null_pointer_info *));
static rtx process_insert_insn PARAMS ((struct expr *));
static int pre_edge_insert PARAMS ((struct edge_list *, struct expr **));
/* Identify the basic block information for this function, including
successors and predecessors. */
max_gcse_regno = max_reg_num ();
- find_basic_blocks (f, max_gcse_regno, file);
- cleanup_cfg (f);
if (file)
dump_flow_info (file);
/* Return if there's nothing to do. */
if (n_basic_blocks <= 1)
- {
- free_basic_block_vars (0);
- return 0;
- }
+ return 0;
/* Trying to perform global optimizations on flow graphs which have
a high connectivity will take a long time and is unlikely to be
a couple switch statements. So we require a relatively large number
of basic blocks and the ratio of edges to blocks to be high. */
if (n_basic_blocks > 1000 && n_edges / n_basic_blocks >= 20)
- {
- free_basic_block_vars (0);
- return 0;
- }
+ return 0;
/* See what modes support reg/reg copy operations. */
if (! can_copy_init_p)
obstack_free (&gcse_obstack, NULL_PTR);
free_reg_set_mem ();
- free_basic_block_vars (0);
return run_jump_opt_after_gcse;
}
\f
for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
{
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- INSN_CUID (insn) = i++;
+ uid_cuid[INSN_UID (insn)] = i++;
else
- INSN_CUID (insn) = i;
+ uid_cuid[INSN_UID (insn)] = i;
}
/* Create a table mapping cuids to insns. */
sbitmap *antloc;
int setp;
{
- int i, hash_table_size;
+ unsigned int i, hash_table_size;
struct expr **hash_table;
/* Initialize any bitmaps that were passed in. */
sizeof (struct reg_set));
bytes_used += sizeof (struct reg_set);
new_reg_info->insn = insn;
- new_reg_info->next = NULL;
- if (reg_set_table[regno] == NULL)
- reg_set_table[regno] = new_reg_info;
- else
- {
- reg_info_ptr1 = reg_info_ptr2 = reg_set_table[regno];
- /* ??? One could keep a "last" pointer to speed this up. */
- while (reg_info_ptr1 != NULL)
- {
- reg_info_ptr2 = reg_info_ptr1;
- reg_info_ptr1 = reg_info_ptr1->next;
- }
-
- reg_info_ptr2->next = new_reg_info;
- }
+ new_reg_info->next = reg_set_table[regno];
+ reg_set_table[regno] = new_reg_info;
}
/* Called from compute_sets via note_stores to handle one SET or CLOBBER in
final assembler. This also avoids differences in the dump files
between various stages. */
unsigned int h = 0;
- unsigned char *p = (unsigned char *) XSTR (x, 0);
+ const unsigned char *p = (const unsigned char *) XSTR (x, 0);
while (*p)
h += (h << 7) + *p++; /* ??? revisit */
else if (fmt[i] == 's')
{
- register unsigned char *p = (unsigned char *) XSTR (x, i);
+ register const unsigned char *p =
+ (const unsigned char *) XSTR (x, i);
if (p)
while (*p)
for (bb = 0; bb < n_basic_blocks; bb++)
{
rtx insn;
- int regno;
+ unsigned int regno;
int in_libcall_block;
- int i;
+ unsigned int i;
/* First pass over the instructions records information used to
determine when registers and memory are first and last set.
for (i = 0; i < max_gcse_regno; i++)
reg_first_set[i] = reg_last_set[i] = NEVER_SET;
+
mem_first_set = NEVER_SET;
mem_last_set = NEVER_SET;
static void
alloc_expr_hash_table (n_insns)
- int n_insns;
+ unsigned int n_insns;
{
int n;
static struct expr *
lookup_set (regno, pat)
- int regno;
+ unsigned int regno;
rtx pat;
{
unsigned int hash = hash_set (regno, set_hash_table_size);
static struct expr *
next_set (regno, expr)
- int regno;
+ unsigned int regno;
struct expr *expr;
{
do
static void
compute_ae_gen ()
{
- int i;
+ unsigned int i;
struct expr *expr;
struct occr *occr;
compute_ae_kill (ae_gen, ae_kill)
sbitmap *ae_gen, *ae_kill;
{
- int bb, i;
+ int bb;
+ unsigned int i;
struct expr *expr;
for (bb = 0; bb < n_basic_blocks; bb++)
{
/* This is the case when the available expression that reaches
here has already been handled as an available expression. */
- int regnum_for_replacing
+ unsigned int regnum_for_replacing
= REGNO (SET_SRC (PATTERN (insn_computes_expr)));
/* If the register was created by GCSE we can't use `reg_set_table',
if (!found_setting)
{
- int regnum_for_replacing
+ unsigned int regnum_for_replacing
= REGNO (SET_DEST (PATTERN (insn_computes_expr)));
/* This shouldn't happen. */
for (reg_used = ®_use_table[0]; reg_use_count > 0;
reg_used++, reg_use_count--)
{
- int regno = REGNO (reg_used->reg_rtx);
+ unsigned int regno = REGNO (reg_used->reg_rtx);
rtx pat, src;
struct expr *set;
static void
compute_pre_data ()
{
+ int i;
+
compute_local_properties (transp, comp, antloc, 0);
compute_transpout ();
sbitmap_vector_zero (ae_kill, n_basic_blocks);
- compute_ae_kill (comp, ae_kill);
+
+ /* Compute ae_kill for each basic block using:
+
+ ~(TRANSP | COMP)
+
+ This is significantly faster than compute_ae_kill. */
+
+ for (i = 0; i < n_basic_blocks; i++)
+ {
+ sbitmap_a_or_b (ae_kill[i], transp[i], comp[i]);
+ sbitmap_not (ae_kill[i], ae_kill[i]);
+ }
+
edge_list = pre_edge_lcm (gcse_file, n_exprs, transp, comp, antloc,
ae_kill, &pre_insert_map, &pre_delete_map);
}
If we inserted before the CODE_LABEL, then we would be putting
the insn in the wrong basic block. In that case, put the insn
after the CODE_LABEL. Also, respect NOTE_INSN_BASIC_BLOCK. */
- if (GET_CODE (insn) == CODE_LABEL)
- insn = NEXT_INSN (insn);
- else if (GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
+ while (GET_CODE (insn) == CODE_LABEL
+ || (GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK))
insn = NEXT_INSN (insn);
new_insn = emit_block_insn_before (pat, insn, BASIC_BLOCK (bb));
static void
pre_insert_copies ()
{
- int i;
+ unsigned int i;
struct expr *expr;
struct occr *occr;
struct occr *avail;
static int
pre_delete ()
{
- int i, bb, changed;
+ unsigned int i;
+ int bb, changed;
struct expr *expr;
struct occr *occr;
static int
pre_gcse ()
{
- int i, did_insert;
- int changed;
+ unsigned int i;
+ int did_insert, changed;
struct expr **index_map;
struct expr *expr;
compute_transpout ()
{
int bb;
- int i;
+ unsigned int i;
struct expr *expr;
sbitmap_vector_ones (transpout, n_basic_blocks);
rtx setter ATTRIBUTE_UNUSED;
void *data;
{
- int offset, regno;
- struct null_pointer_info* npi = (struct null_pointer_info *) data;
-
- offset = 0;
+ unsigned int regno;
+ struct null_pointer_info *npi = (struct null_pointer_info *) data;
while (GET_CODE (x) == SUBREG)
x = SUBREG_REG (x);
static void
delete_null_pointer_checks_1 (block_reg, nonnull_avin, nonnull_avout, npi)
- int *block_reg;
+ unsigned int *block_reg;
sbitmap *nonnull_avin;
sbitmap *nonnull_avout;
struct null_pointer_info *npi;
void
delete_null_pointer_checks (f)
- rtx f;
+ rtx f ATTRIBUTE_UNUSED;
{
sbitmap *nonnull_avin, *nonnull_avout;
- int *block_reg;
+ unsigned int *block_reg;
int bb;
int reg;
int regs_per_pass;
int max_reg;
struct null_pointer_info npi;
- /* First break the program into basic blocks. */
- find_basic_blocks (f, max_reg_num (), NULL);
- cleanup_cfg (f);
-
/* If we have only a single block, then there's nothing to do. */
if (n_basic_blocks <= 1)
- {
- /* Free storage allocated by find_basic_blocks. */
- free_basic_block_vars (0);
- return;
- }
+ return;
/* Trying to perform global optimizations on flow graphs which have
a high connectivity will take a long time and is unlikely to be
a couple switch statements. So we require a relatively large number
of basic blocks and the ratio of edges to blocks to be high. */
if (n_basic_blocks > 1000 && n_edges / n_basic_blocks >= 20)
- {
- /* Free storage allocated by find_basic_blocks. */
- free_basic_block_vars (0);
- return;
- }
+ return;
/* We need four bitmaps, each with a bit for each register in each
basic block. */
/* Go through the basic blocks, seeing whether or not each block
ends with a conditional branch whose condition is a comparison
against zero. Record the register compared in BLOCK_REG. */
- block_reg = (int *) xcalloc (n_basic_blocks, sizeof (int));
+ block_reg = (unsigned int *) xcalloc (n_basic_blocks, sizeof (int));
for (bb = 0; bb < n_basic_blocks; bb++)
{
rtx last_insn = BLOCK_END (bb);
/* We only want conditional branches. */
if (GET_CODE (last_insn) != JUMP_INSN
- || !condjump_p (last_insn)
- || simplejump_p (last_insn))
+ || !any_condjump_p (last_insn)
+ || !onlyjump_p (last_insn))
continue;
/* LAST_INSN is a conditional jump. Get its condition. */
nonnull_avout, &npi);
}
- /* Free storage allocated by find_basic_blocks. */
- free_basic_block_vars (0);
-
/* Free the table of registers compared at the end of every block. */
free (block_reg);
static void
hoist_code ()
{
- int bb, dominated, i;
+ int bb, dominated;
+ unsigned int i;
struct expr **index_map;
struct expr *expr;