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 ((unsigned int *,
+static int delete_null_pointer_checks_1 PARAMS ((unsigned int *,
sbitmap *, sbitmap *,
struct null_pointer_info *));
static rtx process_insert_insn PARAMS ((struct expr *));
NPI. NONNULL_AVIN and NONNULL_AVOUT are pre-allocated sbitmaps;
they are not our responsibility to free. */
-static void
+static int
delete_null_pointer_checks_1 (block_reg, nonnull_avin,
nonnull_avout, npi)
unsigned int *block_reg;
basic_block bb, current_block;
sbitmap *nonnull_local = npi->nonnull_local;
sbitmap *nonnull_killed = npi->nonnull_killed;
+ int something_changed = 0;
/* Compute local properties, nonnull and killed. A register will have
the nonnull property if at the end of the current block its value is
emit_barrier_after (new_jump);
}
+ something_changed = 1;
delete_insn (last_insn);
if (compare_and_branch == 2)
delete_insn (earliest);
block.) */
block_reg[bb->index] = 0;
}
+
+ return something_changed;
}
/* Find EQ/NE comparisons against zero which can be (indirectly) evaluated
This could probably be integrated with global cprop with a little work. */
-void
+int
delete_null_pointer_checks (f)
rtx f ATTRIBUTE_UNUSED;
{
int regs_per_pass;
int max_reg;
struct null_pointer_info npi;
+ int something_changed = 0;
/* If we have only a single block, then there's nothing to do. */
if (n_basic_blocks <= 1)
- return;
+ 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)
- return;
+ return 0;
/* We need four bitmaps, each with a bit for each register in each
basic block. */
{
npi.min_reg = reg;
npi.max_reg = MIN (reg + regs_per_pass, max_reg);
- delete_null_pointer_checks_1 (block_reg, nonnull_avin,
- nonnull_avout, &npi);
+ something_changed |= delete_null_pointer_checks_1 (block_reg,
+ nonnull_avin,
+ nonnull_avout,
+ &npi);
}
/* Free the table of registers compared at the end of every block. */
sbitmap_vector_free (npi.nonnull_killed);
sbitmap_vector_free (nonnull_avin);
sbitmap_vector_free (nonnull_avout);
+
+ return something_changed;
}
/* Code Hoisting variables and subroutines. */
static sbitmap *hoist_exprs;
/* Dominator bitmaps. */
-static sbitmap *dominators;
+dominance_info dominators;
/* ??? We could compute post dominators and run this algorithm in
reverse to to perform tail merging, doing so would probably be
hoist_vbeout = sbitmap_vector_alloc (n_blocks, n_exprs);
hoist_exprs = sbitmap_vector_alloc (n_blocks, n_exprs);
transpout = sbitmap_vector_alloc (n_blocks, n_exprs);
-
- dominators = sbitmap_vector_alloc (n_blocks, n_blocks);
}
/* Free vars used for code hoisting analysis. */
sbitmap_vector_free (hoist_exprs);
sbitmap_vector_free (transpout);
- sbitmap_vector_free (dominators);
+ free_dominance_info (dominators);
}
/* Compute the very busy expressions at entry/exit from each block.
compute_local_properties (transp, comp, antloc, 0);
compute_transpout ();
compute_code_hoist_vbeinout ();
- calculate_dominance_info (NULL, dominators, CDI_DOMINATORS);
+ dominators = calculate_dominance_info (CDI_DOMINATORS);
if (gcse_file)
fprintf (gcse_file, "\n");
}
{
/* Ignore self dominance. */
if (bb == dominated
- || ! TEST_BIT (dominators[dominated->index], bb->index))
+ || dominated_by_p (dominators, dominated, bb))
continue;
/* We've found a dominated block, now see if it computes
{
/* Ignore self dominance. */
if (bb == dominated
- || ! TEST_BIT (dominators[dominated->index], bb->index))
+ || ! dominated_by_p (dominators, dominated, bb))
continue;
/* We've found a dominated block, now see if it computes