[PATCH] Fix null pointer deletion optimization
Jakub Jelinek
jakub@redhat.com
Wed Apr 4 13:03:00 GMT 2001
On Wed, Apr 04, 2001 at 05:11:56PM +0100, Bernd Schmidt wrote:
> On Wed, 4 Apr 2001, Jakub Jelinek wrote:
> > IMHO the only safe way is to delay all delete_insns until this optimization
> > no longer needs an up-to-date CFG. This fixes the testcase.
>
> Don't you risk deleting an insn twice with this patch?
I don't think the chance of deleting something twice is any higher than it
used to be. Anyway, unless it is a user defined label being deleted twice,
delete_insn is protected against multiple deletion (by checking
INSN_DELETED_P and not doing anything if it is set). But delete_null_... is
never deleting CODE_LABELs directly and in order to delete it twice
indirectly, the only JUMP_INSN pointing to it would have to be not flagged
with INSN_DELETED_P (but it will be always).
BTW: I mailed the patch too early, bootstrap failed, because I need to pass
address of varray_type variable, not varray_type variable.
Here is what I'm commiting:
2001-04-04 Jakub Jelinek <jakub@redhat.com>
* gcse.c (delete_null_pointer_checks_1): Add delete_list argument,
push insns to delete to it instead of deleting them.
(delete_null_pointer_checks): Delete insns from delete_list after
all delete_null_pointer_checks_1 passes are done.
--- gcc/gcse.c.jj Wed Apr 4 18:44:09 2001
+++ gcc/gcse.c Wed Apr 4 19:04:29 2001
@@ -626,8 +626,8 @@ static int handle_avail_expr PARAMS ((rt
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 *, sbitmap *,
- sbitmap *,
+static void delete_null_pointer_checks_1 PARAMS ((varray_type *, 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 **));
@@ -4875,7 +4875,9 @@ invalidate_nonnull_info (x, setter, data
they are not our responsibility to free. */
static void
-delete_null_pointer_checks_1 (block_reg, nonnull_avin, nonnull_avout, npi)
+delete_null_pointer_checks_1 (delete_list, block_reg, nonnull_avin,
+ nonnull_avout, npi)
+ varray_type *delete_list;
unsigned int *block_reg;
sbitmap *nonnull_avin;
sbitmap *nonnull_avout;
@@ -5005,9 +5007,12 @@ delete_null_pointer_checks_1 (block_reg,
LABEL_NUSES (JUMP_LABEL (new_jump))++;
emit_barrier_after (new_jump);
}
- delete_insn (last_insn);
+ if (!*delete_list)
+ VARRAY_RTX_INIT (*delete_list, 10, "delete_list");
+
+ VARRAY_PUSH_RTX (*delete_list, last_insn);
if (compare_and_branch == 2)
- delete_insn (earliest);
+ VARRAY_PUSH_RTX (*delete_list, earliest);
/* Don't check this block again. (Note that BLOCK_END is
invalid here; we deleted the last instruction in the
@@ -5046,10 +5051,12 @@ delete_null_pointer_checks (f)
{
sbitmap *nonnull_avin, *nonnull_avout;
unsigned int *block_reg;
+ varray_type delete_list = NULL;
int bb;
int reg;
int regs_per_pass;
int max_reg;
+ unsigned int i;
struct null_pointer_info npi;
/* If we have only a single block, then there's nothing to do. */
@@ -5118,8 +5125,16 @@ delete_null_pointer_checks (f)
{
npi.min_reg = reg;
npi.max_reg = MIN (reg + regs_per_pass, max_reg);
- delete_null_pointer_checks_1 (block_reg, nonnull_avin,
+ delete_null_pointer_checks_1 (&delete_list, block_reg, nonnull_avin,
nonnull_avout, &npi);
+ }
+
+ /* Now delete the instructions all at once. This breaks the CFG. */
+ if (delete_list)
+ {
+ for (i = 0; i < VARRAY_ACTIVE_SIZE (delete_list); i++)
+ delete_insn (VARRAY_RTX (delete_list, i));
+ VARRAY_FREE (delete_list);
}
/* Free the table of registers compared at the end of every block. */
Jakub
More information about the Gcc-patches
mailing list