From 1d7ae250075490263db45819fc43c51125984537 Mon Sep 17 00:00:00 2001 From: Michael Hayes Date: Sun, 7 Jan 2001 03:59:47 +0000 Subject: [PATCH] loop.c (count_loop_regs_set): Delete. * loop.c (count_loop_regs_set): Delete. (load_mems_and_recount_loop_regs_set): Delete. (loop_regs_scan): Merge common code from count_loop_regs_set, scan_loop, and load_mems_and_recount_loop_regs_set. (scan_loop): Call load_mems directly and loop_regs_scan again if new registers created. From-SVN: r38758 --- gcc/ChangeLog | 9 ++ gcc/loop.c | 243 +++++++++++++++++++++----------------------------- 2 files changed, 111 insertions(+), 141 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 559b125db6e..52948081a59 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2001-01-07 Michael Hayes + + * loop.c (count_loop_regs_set): Delete. + (load_mems_and_recount_loop_regs_set): Delete. + (loop_regs_scan): Merge common code from count_loop_regs_set, + scan_loop, and load_mems_and_recount_loop_regs_set. + (scan_loop): Call load_mems directly and loop_regs_scan + again if new registers created. + 2001-01-07 Neil Booth * toplev.c (main): Call the front-end specific post_options diff --git a/gcc/loop.c b/gcc/loop.c index e4ef90a3179..51ca938c736 100644 --- a/gcc/loop.c +++ b/gcc/loop.c @@ -153,8 +153,6 @@ static int consec_sets_invariant_p PARAMS ((const struct loop *, rtx, int, rtx)); static int labels_in_range_p PARAMS ((rtx, int)); static void count_one_set PARAMS ((struct loop_regs *, rtx, rtx, rtx *)); - -static void count_loop_regs_set PARAMS ((const struct loop *, int *)); static void note_addr_stored PARAMS ((rtx, rtx, void *)); static void note_set_pseudo_multiple_uses PARAMS ((rtx, rtx, void *)); static int loop_reg_used_before_p PARAMS ((const struct loop *, rtx, rtx)); @@ -232,8 +230,7 @@ static int last_use_this_basic_block PARAMS ((rtx, rtx)); static void record_initial PARAMS ((rtx, rtx, void *)); static void update_reg_last_use PARAMS ((rtx, rtx)); static rtx next_insn_in_loop PARAMS ((const struct loop *, rtx)); -static void load_mems_and_recount_loop_regs_set PARAMS ((const struct loop*, - int *)); +static void loop_regs_scan PARAMS ((const struct loop*, int, int *)); static void load_mems PARAMS ((const struct loop *)); static int insert_loop_mem PARAMS ((rtx *, void *)); static int replace_loop_mem PARAMS ((rtx *, void *)); @@ -614,39 +611,10 @@ scan_loop (loop, flags) return; } - /* Count number of times each reg is set during this loop. Set - regs->array[I].may_not_optimize if it is not safe to move out the - setting of register I. Set regs->array[I].single_usage. */ - - regs->num = max_reg_num (); - - /* Allocate extra space for REGs that might be created by - load_mems. We allocate a little extra slop as well, in the hopes - that even after the moving of movables creates some new registers - we won't have to reallocate these arrays. However, we do grow - the arrays, if necessary, in load_mems_recount_loop_regs_set. */ - regs->size = regs->num + loop_info->mems_idx + 16; - regs->array = (struct loop_reg *) - xcalloc (regs->size, sizeof (*regs->array)); - - count_loop_regs_set (loop, &insn_count); - - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - { - regs->array[i].may_not_optimize = 1; - regs->array[i].set_in_loop = 1; - } - -#ifdef AVOID_CCMODE_COPIES - /* Don't try to move insns which set CC registers if we should not - create CCmode register copies. */ - for (i = regs->num - 1; i >= FIRST_PSEUDO_REGISTER; i--) - if (GET_MODE_CLASS (GET_MODE (regno_reg_rtx[i])) == MODE_CC) - regs->array[i].may_not_optimize = 1; -#endif - - for (i = 0; i < regs->num; i++) - regs->array[i].n_times_set = regs->array[i].set_in_loop; + /* Allocate extra space for REGs that might be created by load_mems. + We allocate a little extra slop as well, in the hopes that we + won't have to reallocate the regs array. */ + loop_regs_scan (loop, loop_info->mems_idx + 16, &insn_count); if (loop_dump_stream) { @@ -1011,7 +979,11 @@ scan_loop (loop, flags) /* Now that we've moved some things out of the loop, we might be able to hoist even more memory references. */ - load_mems_and_recount_loop_regs_set (loop, &insn_count); + load_mems (loop); + + /* Recalculate regs->array if load_mems has created new registers. */ + if (max_reg_num () > regs->num) + loop_regs_scan (loop, 0, &insn_count); for (update_start = loop_start; PREV_INSN (update_start) @@ -3344,67 +3316,6 @@ count_one_set (regs, insn, x, last_set) } } } - -/* Increment REGS->array[I].SET_IN_LOOP at the index I of each - register that is modified by an insn between FROM and TO. If the - value of an element of REGS->array[I].SET_IN_LOOP becomes 127 or - more, stop incrementing it, to avoid overflow. - - Store in REGS->array[I].SINGLE_USAGE[I] the single insn in which - register I is used, if it is only used once. Otherwise, it is set - to 0 (for no uses) or const0_rtx for more than one use. This - parameter may be zero, in which case this processing is not done. - - Store in *COUNT_PTR the number of actual instruction - in the loop. We use this to decide what is worth moving out. */ - -/* last_set[n] is nonzero iff reg n has been set in the current basic block. - In that case, it is the insn that last set reg n. */ - -static void -count_loop_regs_set (loop, count_ptr) - const struct loop *loop; - int *count_ptr; -{ - struct loop_regs *regs = LOOP_REGS (loop); - register rtx *last_set = (rtx *) xcalloc (regs->num, sizeof (rtx)); - register rtx insn; - register int count = 0; - - for (insn = loop->top ? loop->top : loop->start; insn != loop->end; - insn = NEXT_INSN (insn)) - { - if (INSN_P (insn)) - { - ++count; - - /* Record registers that have exactly one use. */ - find_single_use_in_loop (regs, insn, PATTERN (insn)); - - /* Include uses in REG_EQUAL notes. */ - if (REG_NOTES (insn)) - find_single_use_in_loop (regs, insn, REG_NOTES (insn)); - - if (GET_CODE (PATTERN (insn)) == SET - || GET_CODE (PATTERN (insn)) == CLOBBER) - count_one_set (regs, insn, PATTERN (insn), last_set); - else if (GET_CODE (PATTERN (insn)) == PARALLEL) - { - register int i; - for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--) - count_one_set (regs, insn, XVECEXP (PATTERN (insn), 0, i), - last_set); - } - } - - if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN) - memset ((char *) last_set, 0, regs->num * sizeof (rtx)); - } - *count_ptr = count; - - /* Clean up. */ - free (last_set); -} /* Given a loop that is bounded by LOOP->START and LOOP->END and that is entered at LOOP->SCAN_START, return 1 if the register set in SET @@ -8687,70 +8598,120 @@ insert_loop_mem (mem, data) return 0; } -/* Like load_mems, but also ensures that REGS->array[I].SET_IN_LOOP, - REGS->array[I].MAY_NOT_OPTIMIZE, REGS->array[I].SINGLE_USAGE, and - INSN_COUNT have the correct values after load_mems. */ + +/* Allocate REGS->ARRAY or reallocate it if it is too small. + + Increment REGS->ARRAY[I].SET_IN_LOOP at the index I of each + register that is modified by an insn between FROM and TO. If the + value of an element of REGS->array[I].SET_IN_LOOP becomes 127 or + more, stop incrementing it, to avoid overflow. + + Store in REGS->ARRAY[I].SINGLE_USAGE the single insn in which + register I is used, if it is only used once. Otherwise, it is set + to 0 (for no uses) or const0_rtx for more than one use. This + parameter may be zero, in which case this processing is not done. + + Set REGS->ARRAY[I].MAY_NOT_OPTIMIZE nonzero if we should not + optimize register I. + + Store in *COUNT_PTR the number of actual instructions + in the loop. We use this to decide what is worth moving out. */ static void -load_mems_and_recount_loop_regs_set (loop, insn_count) +loop_regs_scan (loop, extra_size, count_ptr) const struct loop *loop; - int *insn_count; + int extra_size; + int *count_ptr; { struct loop_regs *regs = LOOP_REGS (loop); + int old_nregs; + /* last_set[n] is nonzero iff reg n has been set in the current + basic block. In that case, it is the insn that last set reg n. */ + rtx *last_set; + rtx insn; + int count = 0; + int i; - load_mems (loop); + old_nregs = regs->num; + regs->num = max_reg_num (); - /* Recalculate regs->array since load_mems may have created new - registers. */ - if (max_reg_num () > regs->num) + /* Grow the regs array if not allocated or too small. */ + if (regs->num >= regs->size) { - int i; - int old_nregs; + regs->size = regs->num + extra_size; + + regs->array = (struct loop_reg *) + xrealloc (regs->array, regs->size * sizeof (*regs->array)); - old_nregs = regs->num; - regs->num = max_reg_num (); + /* Zero the new elements. */ + memset (regs->array + old_nregs, 0, + (regs->size - old_nregs) * sizeof (*regs->array)); + } - if (regs->num >= regs->size) + /* Clear previously scanned fields but do not clear n_times_set. */ + for (i = 0; i < old_nregs; i++) + { + regs->array[i].set_in_loop = 0; + regs->array[i].may_not_optimize = 0; + regs->array[i].single_usage = NULL_RTX; + } + + last_set = (rtx *) xcalloc (regs->num, sizeof (rtx)); + + /* Scan the loop, recording register usage. */ + for (insn = loop->top ? loop->top : loop->start; insn != loop->end; + insn = NEXT_INSN (insn)) + { + if (INSN_P (insn)) { - regs->size = regs->num; + ++count; - /* Grow the array. */ - regs->array = (struct loop_reg *) - xrealloc (regs->array, regs->size * sizeof (*regs->array)); + /* Record registers that have exactly one use. */ + find_single_use_in_loop (regs, insn, PATTERN (insn)); - memset (regs->array + old_nregs, 0, - (regs->size - old_nregs) * sizeof (*regs->array)); + /* Include uses in REG_EQUAL notes. */ + if (REG_NOTES (insn)) + find_single_use_in_loop (regs, insn, REG_NOTES (insn)); + + if (GET_CODE (PATTERN (insn)) == SET + || GET_CODE (PATTERN (insn)) == CLOBBER) + count_one_set (regs, insn, PATTERN (insn), last_set); + else if (GET_CODE (PATTERN (insn)) == PARALLEL) + { + register int i; + for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--) + count_one_set (regs, insn, XVECEXP (PATTERN (insn), 0, i), + last_set); + } } - for (i = 0; i < old_nregs; i++) - { - regs->array[i].set_in_loop = 0; - regs->array[i].may_not_optimize = 0; - regs->array[i].single_usage = NULL_RTX; - } + if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN) + memset (last_set, 0, regs->num * sizeof (rtx)); + } - count_loop_regs_set (loop, insn_count); - - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - { - regs->array[i].may_not_optimize = 1; - regs->array[i].set_in_loop = 1; - } + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + { + regs->array[i].may_not_optimize = 1; + regs->array[i].set_in_loop = 1; + } #ifdef AVOID_CCMODE_COPIES - /* Don't try to move insns which set CC registers if we should not - create CCmode register copies. */ - for (i = regs->num - 1; i >= FIRST_PSEUDO_REGISTER; i--) - if (GET_MODE_CLASS (GET_MODE (regno_reg_rtx[i])) == MODE_CC) - regs->array[i].may_not_optimize = 1; + /* Don't try to move insns which set CC registers if we should not + create CCmode register copies. */ + for (i = regs->num - 1; i >= FIRST_PSEUDO_REGISTER; i--) + if (GET_MODE_CLASS (GET_MODE (regno_reg_rtx[i])) == MODE_CC) + regs->array[i].may_not_optimize = 1; #endif + + /* Set regs->array[I].n_times_set for the new registers. */ + for (i = old_nregs; i < regs->num; i++) + regs->array[i].n_times_set = regs->array[i].set_in_loop; - /* Set regs->array[I].n_times_set for the new registers. */ - for (i = old_nregs; i < regs->num; i++) - regs->array[i].n_times_set = regs->array[i].set_in_loop; - } + free (last_set); + *count_ptr = count; } + /* Move MEMs into registers for the duration of the loop. */ static void