diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1ea9b2c6da88..1a51101435b2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2003-12-03 Richard Earnshaw + + * gcse.c (reg_clear_last_set): New function. + (reg_set_info): If data is non-null, treat it as an sbitmap of + registers, set the bit for the register being set. + (compute_store_table): Allocate last_set_in with xcalloc. Do not + memset this array on each iteration. Pass reg_set_in_block[bb->index] + to note_stores while computing last_set_in instead of scanning + last_set_in after the first pass through the insns. + Clear last_set_in using reg_clear_last_set instead of explicitly + rescanning after each insn. If checking is enabled, assert that + last_set_in is completely zeroed after each bb has been processed. + 2003-12-02 Geoffrey Keating * df.c (df_uses_record) : The argument of a MEM is read-only, diff --git a/gcc/gcse.c b/gcc/gcse.c index 73f293bf24e7..4481dc762149 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -679,6 +679,7 @@ static void compute_ld_motion_mems (void); static void trim_ld_motion_mems (void); static void update_ld_motion_stores (struct expr *); static void reg_set_info (rtx, rtx, void *); +static void reg_clear_last_set (rtx, rtx, void *); static bool store_ops_ok (rtx, int *); static rtx extract_mentioned_regs (rtx); static rtx extract_mentioned_regs_helper (rtx, rtx); @@ -6921,17 +6922,41 @@ static sbitmap * st_antloc; /* Global holding the number of store expressions we are dealing with. */ static int num_stores; -/* Checks to set if we need to mark a register set. Called from note_stores. */ +/* Checks to set if we need to mark a register set. Called from + note_stores. */ static void reg_set_info (rtx dest, rtx setter ATTRIBUTE_UNUSED, - void *data ATTRIBUTE_UNUSED) + void *data) { + sbitmap bb_reg = data; + if (GET_CODE (dest) == SUBREG) dest = SUBREG_REG (dest); if (GET_CODE (dest) == REG) - regvec[REGNO (dest)] = INSN_UID (compute_store_table_current_insn); + { + regvec[REGNO (dest)] = INSN_UID (compute_store_table_current_insn); + if (bb_reg) + SET_BIT (bb_reg, REGNO (dest)); + } +} + +/* Clear any mark that says that this insn sets dest. Called from + note_stores. */ + +static void +reg_clear_last_set (rtx dest, rtx setter ATTRIBUTE_UNUSED, + void *data) +{ + int *dead_vec = data; + + if (GET_CODE (dest) == SUBREG) + dest = SUBREG_REG (dest); + + if (GET_CODE (dest) == REG && + dead_vec[REGNO (dest)] == INSN_UID (compute_store_table_current_insn)) + dead_vec[REGNO (dest)] = 0; } /* Return zero if some of the registers in list X are killed @@ -7165,14 +7190,13 @@ compute_store_table (void) max_gcse_regno); sbitmap_vector_zero (reg_set_in_block, last_basic_block); pre_ldst_mems = 0; - last_set_in = xmalloc (sizeof (int) * max_gcse_regno); + last_set_in = xcalloc (max_gcse_regno, sizeof (int)); already_set = xmalloc (sizeof (int) * max_gcse_regno); /* Find all the stores we care about. */ FOR_EACH_BB (bb) { /* First compute the registers set in this block. */ - memset (last_set_in, 0, sizeof (int) * max_gcse_regno); regvec = last_set_in; for (insn = bb->head; @@ -7194,19 +7218,17 @@ compute_store_table (void) for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if (clobbers_all || TEST_HARD_REG_BIT (regs_invalidated_by_call, regno)) - last_set_in[regno] = INSN_UID (insn); + { + last_set_in[regno] = INSN_UID (insn); + SET_BIT (reg_set_in_block[bb->index], regno); + } } pat = PATTERN (insn); compute_store_table_current_insn = insn; - note_stores (pat, reg_set_info, NULL); + note_stores (pat, reg_set_info, reg_set_in_block[bb->index]); } - /* Record the set registers. */ - for (regno = 0; regno < max_gcse_regno; regno++) - if (last_set_in[regno]) - SET_BIT (reg_set_in_block[bb->index], regno); - /* Now find the stores. */ memset (already_set, 0, sizeof (int) * max_gcse_regno); regvec = already_set; @@ -7239,11 +7261,32 @@ compute_store_table (void) find_moveable_store (insn, already_set, last_set_in); /* Unmark regs that are no longer set. */ - for (regno = 0; regno < max_gcse_regno; regno++) - if (last_set_in[regno] == INSN_UID (insn)) - last_set_in[regno] = 0; + compute_store_table_current_insn = insn; + note_stores (pat, reg_clear_last_set, last_set_in); + if (GET_CODE (insn) == CALL_INSN) + { + bool clobbers_all = false; +#ifdef NON_SAVING_SETJMP + if (NON_SAVING_SETJMP + && find_reg_note (insn, REG_SETJMP, NULL_RTX)) + clobbers_all = true; +#endif + + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) + if ((clobbers_all + || TEST_HARD_REG_BIT (regs_invalidated_by_call, regno)) + && last_set_in[regno] == INSN_UID (insn)) + last_set_in[regno] = 0; + } } +#ifdef ENABLE_CHECKING + /* last_set_in should now be all-zero. */ + for (regno = 0; regno < max_gcse_regno; regno++) + if (last_set_in[regno] != 0) + abort (); +#endif + /* Clear temporary marks. */ for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr)) {