diff options
Diffstat (limited to 'gcc/reload1.c')
-rw-r--r-- | gcc/reload1.c | 147 |
1 files changed, 81 insertions, 66 deletions
diff --git a/gcc/reload1.c b/gcc/reload1.c index a543297fa4b..4d657be69ba 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -8377,6 +8377,7 @@ reload_combine () rtx insn, set; int first_index_reg = 1, last_index_reg = 0; int i; + unsigned int r; int last_label_ruid; int min_labelno, n_labels; HARD_REG_SET ever_live_at_start, *label_live; @@ -8389,15 +8390,14 @@ reload_combine () /* To avoid wasting too much time later searching for an index register, determine the minimum and maximum index register numbers. */ - for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i) - { - if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i)) - { - if (! last_index_reg) - last_index_reg = i; - first_index_reg = i; - } - } + for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) + if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r)) + { + if (! last_index_reg) + last_index_reg = r; + first_index_reg = i; + } + /* If no index register is available, we can quit now. */ if (first_index_reg > last_index_reg) return; @@ -8410,6 +8410,7 @@ reload_combine () n_labels = max_label_num () - min_labelno; label_live = (HARD_REG_SET *) xmalloc (n_labels * sizeof (HARD_REG_SET)); CLEAR_HARD_REG_SET (ever_live_at_start); + for (i = n_basic_blocks - 1; i >= 0; i--) { insn = BLOCK_HEAD (i); @@ -8417,8 +8418,10 @@ reload_combine () { HARD_REG_SET live; - REG_SET_TO_HARD_REG_SET (live, BASIC_BLOCK (i)->global_live_at_start); - compute_use_by_pseudos (&live, BASIC_BLOCK (i)->global_live_at_start); + REG_SET_TO_HARD_REG_SET (live, + BASIC_BLOCK (i)->global_live_at_start); + compute_use_by_pseudos (&live, + BASIC_BLOCK (i)->global_live_at_start); COPY_HARD_REG_SET (LABEL_LIVE (insn), live); IOR_HARD_REG_SET (ever_live_at_start, live); } @@ -8426,13 +8429,13 @@ reload_combine () /* Initialize last_label_ruid, reload_combine_ruid and reg_state. */ last_label_ruid = reload_combine_ruid = 0; - for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i) + for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) { - reg_state[i].store_ruid = reload_combine_ruid; - if (fixed_regs[i]) - reg_state[i].use_index = -1; + reg_state[r].store_ruid = reload_combine_ruid; + if (fixed_regs[r]) + reg_state[r].use_index = -1; else - reg_state[i].use_index = RELOAD_COMBINE_MAX_USES; + reg_state[r].use_index = RELOAD_COMBINE_MAX_USES; } for (insn = get_last_insn (); insn; insn = PREV_INSN (insn)) @@ -8444,14 +8447,14 @@ reload_combine () is and then later disable any optimization that would cross it. */ if (GET_CODE (insn) == CODE_LABEL) last_label_ruid = reload_combine_ruid; - if (GET_CODE (insn) == BARRIER) - { - for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i) - if (! fixed_regs[i]) - reg_state[i].use_index = RELOAD_COMBINE_MAX_USES; - } + else if (GET_CODE (insn) == BARRIER) + for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) + if (! fixed_regs[r]) + reg_state[r].use_index = RELOAD_COMBINE_MAX_USES; + if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') continue; + reload_combine_ruid++; /* Look for (set (REGX) (CONST_INT)) @@ -8481,7 +8484,7 @@ reload_combine () rtx base = XEXP (plus, 1); rtx prev = prev_nonnote_insn (insn); rtx prev_set = prev ? single_set (prev) : NULL_RTX; - int regno = REGNO (reg); + unsigned int regno = REGNO (reg); rtx const_reg = NULL_RTX; rtx reg_sum = NULL_RTX; @@ -8508,31 +8511,35 @@ reload_combine () two registers. */ for (i = first_index_reg; i <= last_index_reg; i++) { - if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i) + if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], + i) && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES && reg_state[i].store_ruid <= reg_state[regno].use_ruid && HARD_REGNO_NREGS (i, GET_MODE (reg)) == 1) { rtx index_reg = gen_rtx_REG (GET_MODE (reg), i); + const_reg = index_reg; reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base); break; } } } + /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that (REGY), i.e. BASE, is not clobbered before the last use we'll create. */ - if (prev_set + if (prev_set != 0 && GET_CODE (SET_SRC (prev_set)) == CONST_INT && rtx_equal_p (SET_DEST (prev_set), reg) && reg_state[regno].use_index >= 0 - && reg_state[REGNO (base)].store_ruid <= reg_state[regno].use_ruid - && reg_sum) + && (reg_state[REGNO (base)].store_ruid + <= reg_state[regno].use_ruid) + && reg_sum != 0) { int i; - /* Change destination register and - if necessary - the + /* Change destination register and, if necessary, the constant value in PREV, the constant loading instruction. */ validate_change (prev, &SET_DEST (prev_set), const_reg, 1); if (reg_state[regno].offset != const0_rtx) @@ -8541,6 +8548,7 @@ reload_combine () GEN_INT (INTVAL (SET_SRC (prev_set)) + INTVAL (reg_state[regno].offset)), 1); + /* Now for every use of REG that we have recorded, replace REG with REG_SUM. */ for (i = reg_state[regno].use_index; @@ -8559,67 +8567,72 @@ reload_combine () NOTE_SOURCE_FILE (insn) = 0; if (reg_state[regno].offset != const0_rtx) - { - /* Previous REG_EQUIV / REG_EQUAL notes for PREV - are now invalid. */ - for (np = ®_NOTES (prev); *np; ) - { - if (REG_NOTE_KIND (*np) == REG_EQUAL - || REG_NOTE_KIND (*np) == REG_EQUIV) - *np = XEXP (*np, 1); - else - np = &XEXP (*np, 1); - } - } + /* Previous REG_EQUIV / REG_EQUAL notes for PREV + are now invalid. */ + for (np = ®_NOTES (prev); *np; ) + { + if (REG_NOTE_KIND (*np) == REG_EQUAL + || REG_NOTE_KIND (*np) == REG_EQUIV) + *np = XEXP (*np, 1); + else + np = &XEXP (*np, 1); + } + reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES; - reg_state[REGNO (const_reg)].store_ruid = reload_combine_ruid; + reg_state[REGNO (const_reg)].store_ruid + = reload_combine_ruid; continue; } } } - note_stores (PATTERN (insn), reload_combine_note_store, NULL); + + note_stores (PATTERN (insn), reload_combine_note_store, NULL); + if (GET_CODE (insn) == CALL_INSN) { rtx link; - for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i) - { - if (call_used_regs[i]) - { - reg_state[i].use_index = RELOAD_COMBINE_MAX_USES; - reg_state[i].store_ruid = reload_combine_ruid; - } - } + for (r = 0; r < FIRST_PSEUDO_REGISTER; r++) + if (call_used_regs[r]) + { + reg_state[r].use_index = RELOAD_COMBINE_MAX_USES; + reg_state[r].store_ruid = reload_combine_ruid; + } + for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1)) - { - rtx use = XEXP (link, 0); - int regno = REGNO (XEXP (use, 0)); - if (GET_CODE (use) == CLOBBER) - { - reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES; - reg_state[regno].store_ruid = reload_combine_ruid; - } - else - reg_state[regno].use_index = -1; - } + if (GET_CODE (XEXP (XEXP (link, 0), 0)) == REG) + { + unsigned int regno = REGNO (XEXP (XEXP (link, 0), 0)); + + if (GET_CODE (XEXP (link, 0)) == CLOBBER) + { + reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES; + reg_state[regno].store_ruid = reload_combine_ruid; + } + else + reg_state[regno].use_index = -1; + } } - if (GET_CODE (insn) == JUMP_INSN && GET_CODE (PATTERN (insn)) != RETURN) + + else if (GET_CODE (insn) == JUMP_INSN + && GET_CODE (PATTERN (insn)) != RETURN) { /* Non-spill registers might be used at the call destination in some unknown fashion, so we have to mark the unknown use. */ HARD_REG_SET *live; + if ((condjump_p (insn) || condjump_in_parallel_p (insn)) && JUMP_LABEL (insn)) live = &LABEL_LIVE (JUMP_LABEL (insn)); else live = &ever_live_at_start; + for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i) - { - if (TEST_HARD_REG_BIT (*live, i)) - reg_state[i].use_index = -1; - } + if (TEST_HARD_REG_BIT (*live, i)) + reg_state[i].use_index = -1; } + reload_combine_note_use (&PATTERN (insn), insn); for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) { @@ -8633,12 +8646,14 @@ reload_combine () } } } + free (label_live); } /* Check if DST is a register or a subreg of a register; if it is, update reg_state[regno].store_ruid and reg_state[regno].use_index accordingly. Called via note_stores from reload_combine. */ + static void reload_combine_note_store (dst, set, data) rtx dst, set; |