From 172890a2ddc7b280146cb88c9daab2f70b460f4a Mon Sep 17 00:00:00 2001 From: Richard Kenner Date: Fri, 16 Feb 2001 19:29:49 +0000 Subject: [PATCH] gcse.c (hash_scan_set): If cprop, see if REG_EQUAL or REG_EQUIV. * gcse.c (hash_scan_set): If cprop, see if REG_EQUAL or REG_EQUIV. Don't CSE a nop. (hash_scan_insn): Clean up calls to hash_scan_set. (compute_kill_rd): REGNO now unsigned. (try_replace_reg): Rework to use simplify_replace_rtx. (cprop_jump, cprop_cc0_jump): Likewise. (cprop_insn): Call find_reg_equal_equiv_note. Reflect changes to cprop_jump and cprop_cc0_jump. From-SVN: r39774 --- gcc/ChangeLog | 9 ++ gcc/gcse.c | 278 ++++++++++++++++++++++++++-------------------------------- 2 files changed, 131 insertions(+), 156 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 44b5be5..1f9ca43 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -8,6 +8,15 @@ Fri Feb 16 12:41:30 2001 Richard Kenner + * gcse.c (hash_scan_set): If cprop, see if REG_EQUAL or REG_EQUIV. + Don't CSE a nop. + (hash_scan_insn): Clean up calls to hash_scan_set. + (compute_kill_rd): REGNO now unsigned. + (try_replace_reg): Rework to use simplify_replace_rtx. + (cprop_jump, cprop_cc0_jump): Likewise. + (cprop_insn): Call find_reg_equal_equiv_note. + Reflect changes to cprop_jump and cprop_cc0_jump. + * recog.c (validate_replace_rtx): Replace in operands of ZERO_EXTRACT in SET_DEST. diff --git a/gcc/gcse.c b/gcc/gcse.c index a0eece4..5bb8680 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -583,7 +583,7 @@ static void compute_cprop_data PARAMS ((void)); static void find_used_regs PARAMS ((rtx)); static int try_replace_reg PARAMS ((rtx, rtx, rtx)); static struct expr *find_avail_set PARAMS ((int, rtx)); -static int cprop_jump PARAMS ((rtx, rtx, struct reg_use *, rtx)); +static int cprop_jump PARAMS ((rtx, rtx, rtx)); #ifdef HAVE_cc0 static int cprop_cc0_jump PARAMS ((rtx, struct reg_use *, rtx)); #endif @@ -1114,7 +1114,7 @@ record_one_set (regno, insn) int regno; rtx insn; { - /* allocate a new reg_set element and link it onto the list */ + /* Allocate a new reg_set element and link it onto the list. */ struct reg_set *new_reg_info; /* If the table isn't big enough, enlarge it. */ @@ -1334,7 +1334,9 @@ hash_expr (x, mode, do_not_record_p, hash_table_size) hash = hash_expr_1 (x, mode, do_not_record_p); return hash % hash_table_size; } + /* Hash a string. Just add its bytes up. */ + static inline unsigned hash_string_1 (ps) const char *ps; @@ -1857,7 +1859,6 @@ insert_set_in_table (x, insn) /* Set the fields of the expr element. We must copy X because it can be modified when copy propagation is performed on its operands. */ - /* ??? Should this go in a different obstack? */ cur_expr->expr = copy_rtx (x); cur_expr->bitmap_index = n_sets++; cur_expr->next_same_hash = NULL; @@ -1910,22 +1911,31 @@ hash_scan_set (pat, insn, set_p) { rtx src = SET_SRC (pat); rtx dest = SET_DEST (pat); + rtx note; if (GET_CODE (src) == CALL) hash_scan_call (src, insn); - if (GET_CODE (dest) == REG) + else if (GET_CODE (dest) == REG) { - int regno = REGNO (dest); + unsigned int regno = REGNO (dest); rtx tmp; + /* If this is a single set and we are doing constant propagation, + see if a REG_NOTE shows this equivalent to a constant. */ + if (set_p && (note = find_reg_equal_equiv_note (insn)) != 0 + && CONSTANT_P (XEXP (note, 0))) + src = XEXP (note, 0), pat = gen_rtx_SET (VOIDmode, dest, src); + /* Only record sets of pseudo-regs in the hash table. */ if (! set_p && regno >= FIRST_PSEUDO_REGISTER /* Don't GCSE something if we can't do a reg/reg copy. */ && can_copy_p [GET_MODE (dest)] /* Is SET_SRC something we want to gcse? */ - && want_to_gcse_p (src)) + && want_to_gcse_p (src) + /* Don't CSE a nop. */ + && src != dest) { /* An expression is not anticipatable if its operands are modified before this insn. */ @@ -1942,7 +1952,8 @@ hash_scan_set (pat, insn, set_p) && regno >= FIRST_PSEUDO_REGISTER && ((GET_CODE (src) == REG && REGNO (src) >= FIRST_PSEUDO_REGISTER - && can_copy_p [GET_MODE (dest)]) + && can_copy_p [GET_MODE (dest)] + && REGNO (src) != regno) || GET_CODE (src) == CONST_INT || GET_CODE (src) == SYMBOL_REF || GET_CODE (src) == CONST_DOUBLE) @@ -1992,25 +2003,21 @@ hash_scan_insn (insn, set_p, in_libcall_block) rtx pat = PATTERN (insn); int i; + if (in_libcall_block) + return; + /* Pick out the sets of INSN and for other forms of instructions record what's been modified. */ - if (GET_CODE (pat) == SET && ! in_libcall_block) - { - /* Ignore obvious no-ops. */ - if (SET_SRC (pat) != SET_DEST (pat)) - hash_scan_set (pat, insn, set_p); - } + if (GET_CODE (pat) == SET) + hash_scan_set (pat, insn, set_p); else if (GET_CODE (pat) == PARALLEL) for (i = 0; i < XVECLEN (pat, 0); i++) { rtx x = XVECEXP (pat, 0, i); if (GET_CODE (x) == SET) - { - if (GET_CODE (SET_SRC (x)) == CALL) - hash_scan_call (SET_SRC (x), insn); - } + hash_scan_set (x, insn, set_p); else if (GET_CODE (x) == CLOBBER) hash_scan_clobber (x, insn); else if (GET_CODE (x) == CALL) @@ -2611,7 +2618,8 @@ static void compute_kill_rd () { int bb, cuid; - int regno, i; + unsigned int regno; + int i; /* For each block For each set bit in `gen' of the block (i.e each insn which @@ -3603,63 +3611,53 @@ static int try_replace_reg (from, to, insn) rtx from, to, insn; { - rtx note; + rtx note = find_reg_equal_equiv_note (insn); rtx src; - int success; - rtx set; - - note = find_reg_note (insn, REG_EQUAL, NULL_RTX); - - if (!note) - note = find_reg_note (insn, REG_EQUIV, NULL_RTX); - - /* If this fails we could try to simplify the result of the - replacement and attempt to recognize the simplified insn. - - But we need a general simplify_rtx that doesn't have pass - specific state variables. I'm not aware of one at the moment. */ - - success = validate_replace_src (from, to, insn); - set = single_set (insn); + int success = 0; + rtx set = single_set (insn); - /* We've failed to do replacement. Try to add REG_EQUAL note to not loose - information. */ - if (!success && !note) + /* If this is a single set, try to simplify the source of the set given + our substitution. We could perhaps try this for multiple SETs, but + it probably won't buy us anything. */ + if (set != 0) { - if (!set) - return 0; - - note = REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, - copy_rtx (SET_SRC (set)), - REG_NOTES (insn)); + src = simplify_replace_rtx (SET_SRC (set), from, to); + + /* Try this two ways: first just replace SET_SRC. If that doesn't + work and this is a PARALLEL, try to replace the whole pattern + with a new SET. */ + if (validate_change (insn, &SET_SRC (set), src, 0)) + success = 1; + else if (GET_CODE (PATTERN (insn)) == PARALLEL + && validate_change (insn, &PATTERN (insn), + gen_rtx_SET (VOIDmode, SET_DEST (set), + src), + 0)) + success = 1; } - /* Always do the replacement in REQ_EQUAL and REG_EQUIV notes. Also - try to simplify them. */ - if (note) - { - rtx simplified; + /* Otherwise, try to do a global replacement within the insn. */ + if (!success) + success = validate_replace_src (from, to, insn); - if (!validate_replace_rtx_subexp (from, to, insn, &XEXP (note, 0))) - abort(); + /* We've failed to do replacement, have a single SET, and don't already + have a note, two to add a REG_EQUAL note to not lose information. */ + if (!success && note == 0 && set != 0) + note= REG_NOTES (insn) + = gen_rtx_EXPR_LIST (REG_EQUAL, src, REG_NOTES (insn)); - src = XEXP (note, 0); + /* If there is already a NOTE, update the expression in it with our + replacement. */ + else if (note != 0) + XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0), from, to); - /* Try to simplify resulting note. */ - simplified = simplify_rtx (src); - if (simplified) - { - src = simplified; - XEXP (note, 0) = src; - } + /* REG_EQUAL may get simplified into register. + We don't allow that. Remove that note. This code ought + not to hapen, because previous code ought to syntetize + reg-reg move, but be on the safe side. */ + if (note && REG_P (XEXP (note, 0))) + remove_note (insn, note); - /* REG_EQUAL may get simplified into register. - We don't allow that. Remove that note. This code ought - not to hapen, because previous code ought to syntetize - reg-reg move, but be on the safe side. */ - else if (REG_P (src)) - remove_note (insn, note); - } return success; } @@ -3734,82 +3732,57 @@ find_avail_set (regno, insn) } /* Subroutine of cprop_insn that tries to propagate constants into - JUMP_INSNS. INSN must be a conditional jump; COPY is a copy of it - that we can use for substitutions. - REG_USED is the use we will try to replace, SRC is the constant we - will try to substitute for it. - Returns nonzero if a change was made. */ + JUMP_INSNS. INSN must be a conditional jump. FROM is what we will try to + replace, SRC is the constant we will try to substitute for it. Returns + nonzero if a change was made. We know INSN has just a SET. */ static int -cprop_jump (insn, copy, reg_used, src) - rtx insn, copy; - struct reg_use *reg_used; +cprop_jump (insn, from, src) + rtx insn; + rtx from; rtx src; { - rtx set = PATTERN (copy); - rtx temp; - - /* Replace the register with the appropriate constant. */ - replace_rtx (SET_SRC (set), reg_used->reg_rtx, src); - - temp = simplify_ternary_operation (GET_CODE (SET_SRC (set)), - GET_MODE (SET_SRC (set)), - GET_MODE (XEXP (SET_SRC (set), 0)), - XEXP (SET_SRC (set), 0), - XEXP (SET_SRC (set), 1), - XEXP (SET_SRC (set), 2)); + rtx set = PATTERN (insn); + rtx new = simplify_replace_rtx (SET_SRC (set), from, src); /* If no simplification can be made, then try the next register. */ - if (temp == 0) + if (rtx_equal_p (new, SET_SRC (set))) return 0; - SET_SRC (set) = temp; - - /* That may have changed the structure of TEMP, so - force it to be rerecognized if it has not turned - into a nop or unconditional jump. */ - - INSN_CODE (copy) = -1; - if ((SET_DEST (set) == pc_rtx - && (SET_SRC (set) == pc_rtx - || GET_CODE (SET_SRC (set)) == LABEL_REF)) - || recog (PATTERN (copy), copy, NULL) >= 0) + /* If this is now a no-op leave it that way, but update LABEL_NUSED if + necessary. */ + if (new == pc_rtx) { - /* This has either become an unconditional jump - or a nop-jump. We'd like to delete nop jumps - here, but doing so confuses gcse. So we just - make the replacement and let later passes - sort things out. */ - PATTERN (insn) = set; - INSN_CODE (insn) = -1; - - /* One less use of the label this insn used to jump to - if we turned this into a NOP jump. */ - if (SET_SRC (set) == pc_rtx && JUMP_LABEL (insn) != 0) + SET_SRC (set) = new; + + if (JUMP_LABEL (insn) != 0) --LABEL_NUSES (JUMP_LABEL (insn)); + } - /* If this has turned into an unconditional jump, - then put a barrier after it so that the unreachable - code will be deleted. */ - if (GET_CODE (SET_SRC (set)) == LABEL_REF) - emit_barrier_after (insn); + /* Otherwise, this must be a valid instruction. */ + else if (! validate_change (insn, &SET_SRC (set), new, 0)) + return 0; - run_jump_opt_after_gcse = 1; + /* If this has turned into an unconditional jump, + then put a barrier after it so that the unreachable + code will be deleted. */ + if (GET_CODE (SET_SRC (set)) == LABEL_REF) + emit_barrier_after (insn); - const_prop_count++; - if (gcse_file != NULL) - { - fprintf (gcse_file, - "CONST-PROP: Replacing reg %d in insn %d with constant ", - REGNO (reg_used->reg_rtx), INSN_UID (insn)); - print_rtl (gcse_file, src); - fprintf (gcse_file, "\n"); - } + run_jump_opt_after_gcse = 1; - return 1; + const_prop_count++; + if (gcse_file != NULL) + { + fprintf (gcse_file, + "CONST-PROP: Replacing reg %d in insn %d with constant ", + REGNO (from), INSN_UID (insn)); + print_rtl (gcse_file, src); + fprintf (gcse_file, "\n"); } - return 0; + + return 1; } #ifdef HAVE_cc0 @@ -3826,20 +3799,20 @@ cprop_cc0_jump (insn, reg_used, src) struct reg_use *reg_used; rtx src; { + /* First substitute in the SET_SRC of INSN, then substitute that for + CC0 in JUMP. */ rtx jump = NEXT_INSN (insn); - rtx copy = copy_rtx (jump); - rtx set = PATTERN (copy); + rtx new_src = simplify_replace_rtx (SET_SRC (PATTERN (insn)), + reg_used->reg_rtx, src); - /* We need to copy the source of the cc0 setter, as cprop_jump is going to - substitute into it. */ - replace_rtx (SET_SRC (set), cc0_rtx, copy_rtx (SET_SRC (PATTERN (insn)))); - if (! cprop_jump (jump, copy, reg_used, src)) + if (! cprop_jump (jump, cc0_rtx, new_src)) return 0; /* If we succeeded, delete the cc0 setter. */ PUT_CODE (insn, NOTE); NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; NOTE_SOURCE_FILE (insn) = 0; + return 1; } #endif @@ -3858,17 +3831,13 @@ cprop_insn (insn, alter_jumps) /* Only propagate into SETs. Note that a conditional jump is a SET with pc_rtx as the destination. */ - if ((GET_CODE (insn) != INSN - && GET_CODE (insn) != JUMP_INSN) - || GET_CODE (PATTERN (insn)) != SET) + if (GET_CODE (insn) != INSN && GET_CODE (insn) != JUMP_INSN) return 0; reg_use_count = 0; find_used_regs (PATTERN (insn)); - note = find_reg_note (insn, REG_EQUIV, NULL_RTX); - if (!note) - note = find_reg_note (insn, REG_EQUAL, NULL_RTX); + note = find_reg_equal_equiv_note (insn); /* We may win even when propagating constants into notes. */ if (note) @@ -3938,7 +3907,8 @@ cprop_insn (insn, alter_jumps) && GET_CODE (insn) == JUMP_INSN && condjump_p (insn) && ! simplejump_p (insn)) - changed |= cprop_jump (insn, copy_rtx (insn), reg_used, src); + changed |= cprop_jump (insn, reg_used->reg_rtx, src); + #ifdef HAVE_cc0 /* Similar code for machines that use a pair of CC0 setter and conditional jump insn. */ @@ -3947,13 +3917,11 @@ cprop_insn (insn, alter_jumps) && SET_DEST (PATTERN (insn)) == cc0_rtx && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN && condjump_p (NEXT_INSN (insn)) - && ! simplejump_p (NEXT_INSN (insn))) - { - if (cprop_cc0_jump (insn, reg_used, src)) - { - changed = 1; - break; - } + && ! simplejump_p (NEXT_INSN (insn)) + && cprop_cc0_jump (insn, reg_used, src)) + { + changed = 1; + break; } #endif } @@ -4006,17 +3974,15 @@ cprop (alter_jumps) for (insn = BLOCK_HEAD (bb); insn != NULL && insn != NEXT_INSN (BLOCK_END (bb)); insn = NEXT_INSN (insn)) - { - if (INSN_P (insn)) - { - changed |= cprop_insn (insn, alter_jumps); + if (INSN_P (insn)) + { + changed |= cprop_insn (insn, alter_jumps); - /* Keep track of everything modified by this insn. */ - /* ??? Need to be careful w.r.t. mods done to INSN. Don't - call mark_oprs_set if we turned the insn into a NOTE. */ - if (GET_CODE (insn) != NOTE) - mark_oprs_set (insn); - } + /* Keep track of everything modified by this insn. */ + /* ??? Need to be careful w.r.t. mods done to INSN. Don't + call mark_oprs_set if we turned the insn into a NOTE. */ + if (GET_CODE (insn) != NOTE) + mark_oprs_set (insn); } } -- 2.7.4