From: Jan Hubicka Date: Fri, 31 May 2002 11:43:18 +0000 (+0200) Subject: gcse.c (gcse_emit_move_after): New. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=10d1bb3675d063e88ada643bdaa8f51e01f47e5f;p=gcc.git gcse.c (gcse_emit_move_after): New. * gcse.c (gcse_emit_move_after): New. (pre_delete, hoist_store): Use it. * reload1.c (emit_input_reload_insns): Use constrain_operands instead of constraint_accepts_reg_p to verify optimization. (constraint_accepts_reg_p): Kill * reload1.c (reload_cse_delete_noop_set): Kill. (reload_cse_simplify): use delte_insn_and_edges. From-SVN: r54105 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b2027582869..77386f33af3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +Fri May 31 13:37:54 CEST 2002 Jan Hubicka + + * gcse.c (gcse_emit_move_after): New. + (pre_delete, hoist_store): Use it. + + * reload1.c (emit_input_reload_insns): Use constrain_operands + instead of constraint_accepts_reg_p to verify optimization. + (constraint_accepts_reg_p): Kill + + * reload1.c (reload_cse_delete_noop_set): Kill. + (reload_cse_simplify): use delte_insn_and_edges. + 2002-05-31 Zdenek Dvorak * cfgloop.c (flow_loops_find): Initialize first and last fields diff --git a/gcc/gcse.c b/gcc/gcse.c index f279dde90af..4d7c1541133 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -700,6 +700,7 @@ static void store_motion PARAMS ((void)); static void free_insn_expr_list_list PARAMS ((rtx *)); static void clear_modify_mem_tables PARAMS ((void)); static void free_modify_mem_tables PARAMS ((void)); +static rtx gcse_emit_move_after PARAMS ((rtx, rtx, rtx)); /* Entry point for global common subexpression elimination. F is the first instruction in the function. */ @@ -4948,6 +4949,33 @@ pre_insert_copies () } } +/* Emit move from SRC to DEST noting the equivalence with expression computed + in INSN. */ +static rtx +gcse_emit_move_after (src, dest, insn) + rtx src, dest, insn; +{ + rtx new; + rtx set = single_set (insn); + rtx note; + rtx eqv; + + /* This should never fail since we're creating a reg->reg copy + we've verified to be valid. */ + + new = emit_insn_after (gen_rtx_SET (VOIDmode, dest, src), insn); + + /* Note the equivalence for local CSE pass. */ + if ((note = find_reg_equal_equiv_note (insn))) + eqv = XEXP (note, 0); + else + eqv = SET_SRC (set); + + set_unique_reg_note (new, REG_EQUAL, copy_insn_1 (src)); + + return new; +} + /* Delete redundant computations. Deletion is done by changing the insn to copy the `reaching_reg' of the expression into the result of the SET. It is left to later passes @@ -4991,21 +5019,12 @@ pre_delete () expr->reaching_reg = gen_reg_rtx (GET_MODE (SET_DEST (set))); - /* In theory this should never fail since we're creating - a reg->reg copy. - - However, on the x86 some of the movXX patterns actually - contain clobbers of scratch regs. This may cause the - insn created by validate_change to not match any pattern - and thus cause validate_change to fail. */ - if (validate_change (insn, &SET_SRC (set), - expr->reaching_reg, 0)) - { - occr->deleted_p = 1; - SET_BIT (pre_redundant_insns, INSN_CUID (insn)); - changed = 1; - gcse_subst_count++; - } + gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn); + delete_insn (insn); + occr->deleted_p = 1; + SET_BIT (pre_redundant_insns, INSN_CUID (insn)); + changed = 1; + gcse_subst_count++; if (gcse_file) { @@ -5827,23 +5846,13 @@ hoist_code () expr->reaching_reg = gen_reg_rtx (GET_MODE (SET_DEST (set))); - /* In theory this should never fail since we're creating - a reg->reg copy. - - However, on the x86 some of the movXX patterns - actually contain clobbers of scratch regs. This may - cause the insn created by validate_change to not - match any pattern and thus cause validate_change to - fail. */ - if (validate_change (insn, &SET_SRC (set), - expr->reaching_reg, 0)) + gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn); + delete_insn (insn); + occr->deleted_p = 1; + if (!insn_inserted_p) { - occr->deleted_p = 1; - if (!insn_inserted_p) - { - insert_insn_end_bb (index_map[i], bb, 0); - insn_inserted_p = 1; - } + insert_insn_end_bb (index_map[i], bb, 0); + insn_inserted_p = 1; } } } diff --git a/gcc/gengenrtl.c b/gcc/gengenrtl.c index 07de2170f4a..31e5910f237 100644 --- a/gcc/gengenrtl.c +++ b/gcc/gengenrtl.c @@ -119,6 +119,9 @@ accessor_from_format (c) case 'B': return "XBBDEF"; + + default: + abort (); } } diff --git a/gcc/reload1.c b/gcc/reload1.c index 685957023c4..1ce3199cd98 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -440,7 +440,6 @@ static void delete_output_reload PARAMS ((rtx, int, int)); static void delete_address_reloads PARAMS ((rtx, rtx)); static void delete_address_reloads_1 PARAMS ((rtx, rtx, rtx)); static rtx inc_for_reload PARAMS ((rtx, rtx, rtx, int)); -static int constraint_accepts_reg_p PARAMS ((const char *, rtx)); static void reload_cse_regs_1 PARAMS ((rtx)); static int reload_cse_noop_set_p PARAMS ((rtx)); static int reload_cse_simplify_set PARAMS ((rtx, rtx)); @@ -458,7 +457,6 @@ static HOST_WIDE_INT sext_for_mode PARAMS ((enum machine_mode, HOST_WIDE_INT)); static void failed_reload PARAMS ((rtx, int)); static int set_reload_reg PARAMS ((int, int)); -static void reload_cse_delete_noop_set PARAMS ((rtx, rtx)); static void reload_cse_simplify PARAMS ((rtx)); void fixup_abnormal_edges PARAMS ((void)); extern void dump_needs PARAMS ((struct insn_chain *)); @@ -6383,38 +6381,43 @@ emit_input_reload_insns (chain, rl, old, j) && SET_DEST (PATTERN (temp)) == old /* Make sure we can access insn_operand_constraint. */ && asm_noperands (PATTERN (temp)) < 0 - /* This is unsafe if prev insn rejects our reload reg. */ - && constraint_accepts_reg_p (insn_data[recog_memoized (temp)].operand[0].constraint, - reloadreg) /* This is unsafe if operand occurs more than once in current insn. Perhaps some occurrences aren't reloaded. */ - && count_occurrences (PATTERN (insn), old, 0) == 1 - /* Don't risk splitting a matching pair of operands. */ - && ! reg_mentioned_p (old, SET_SRC (PATTERN (temp)))) + && count_occurrences (PATTERN (insn), old, 0) == 1) { + rtx old = SET_DEST (PATTERN (temp)); /* Store into the reload register instead of the pseudo. */ SET_DEST (PATTERN (temp)) = reloadreg; - /* If the previous insn is an output reload, the source is - a reload register, and its spill_reg_store entry will - contain the previous destination. This is now - invalid. */ - if (GET_CODE (SET_SRC (PATTERN (temp))) == REG - && REGNO (SET_SRC (PATTERN (temp))) < FIRST_PSEUDO_REGISTER) + /* Verify that resulting insn is valid. */ + extract_insn (temp); + if (constrain_operands (1)) { - spill_reg_store[REGNO (SET_SRC (PATTERN (temp)))] = 0; - spill_reg_stored_to[REGNO (SET_SRC (PATTERN (temp)))] = 0; - } + /* If the previous insn is an output reload, the source is + a reload register, and its spill_reg_store entry will + contain the previous destination. This is now + invalid. */ + if (GET_CODE (SET_SRC (PATTERN (temp))) == REG + && REGNO (SET_SRC (PATTERN (temp))) < FIRST_PSEUDO_REGISTER) + { + spill_reg_store[REGNO (SET_SRC (PATTERN (temp)))] = 0; + spill_reg_stored_to[REGNO (SET_SRC (PATTERN (temp)))] = 0; + } - /* If these are the only uses of the pseudo reg, - pretend for GDB it lives in the reload reg we used. */ - if (REG_N_DEATHS (REGNO (old)) == 1 - && REG_N_SETS (REGNO (old)) == 1) + /* If these are the only uses of the pseudo reg, + pretend for GDB it lives in the reload reg we used. */ + if (REG_N_DEATHS (REGNO (old)) == 1 + && REG_N_SETS (REGNO (old)) == 1) + { + reg_renumber[REGNO (old)] = REGNO (rl->reg_rtx); + alter_reg (REGNO (old), -1); + } + special = 1; + } + else { - reg_renumber[REGNO (old)] = REGNO (rl->reg_rtx); - alter_reg (REGNO (old), -1); + SET_DEST (PATTERN (temp)) = old; } - special = 1; } } @@ -7980,75 +7983,6 @@ inc_for_reload (reloadreg, in, value, inc_amount) return store; } -/* Return 1 if we are certain that the constraint-string STRING allows - the hard register REG. Return 0 if we can't be sure of this. */ - -static int -constraint_accepts_reg_p (string, reg) - const char *string; - rtx reg; -{ - int value = 0; - int regno = true_regnum (reg); - int c; - - /* Initialize for first alternative. */ - value = 0; - /* Check that each alternative contains `g' or `r'. */ - while (1) - switch (c = *string++) - { - case 0: - /* If an alternative lacks `g' or `r', we lose. */ - return value; - case ',': - /* If an alternative lacks `g' or `r', we lose. */ - if (value == 0) - return 0; - /* Initialize for next alternative. */ - value = 0; - break; - case 'g': - case 'r': - /* Any general reg wins for this alternative. */ - if (TEST_HARD_REG_BIT (reg_class_contents[(int) GENERAL_REGS], regno)) - value = 1; - break; - default: - /* Any reg in specified class wins for this alternative. */ - { - enum reg_class class = REG_CLASS_FROM_LETTER (c); - - if (TEST_HARD_REG_BIT (reg_class_contents[(int) class], regno)) - value = 1; - } - } -} - -/* INSN is a no-op; delete it. - If this sets the return value of the function, we must keep a USE around, - in case this is in a different basic block than the final USE. Otherwise, - we could loose important register lifeness information on - SMALL_REGISTER_CLASSES machines, where return registers might be used as - spills: subsequent passes assume that spill registers are dead at the end - of a basic block. - VALUE must be the return value in such a case, NULL otherwise. */ -static void -reload_cse_delete_noop_set (insn, value) - rtx insn, value; -{ - bool purge = BLOCK_FOR_INSN (insn)->end == insn; - if (value) - { - PATTERN (insn) = gen_rtx_USE (VOIDmode, value); - INSN_CODE (insn) = -1; - REG_NOTES (insn) = NULL_RTX; - } - else - delete_insn (insn); - if (purge) - purge_dead_edges (BLOCK_FOR_INSN (insn)); -} /* See whether a single set SET is a noop. */ static int @@ -8082,7 +8016,7 @@ reload_cse_simplify (insn) if (REG_P (value) && ! REG_FUNCTION_VALUE_P (value)) value = 0; - reload_cse_delete_noop_set (insn, value); + delete_insn_and_edges (insn); return; } @@ -8119,7 +8053,7 @@ reload_cse_simplify (insn) if (i < 0) { - reload_cse_delete_noop_set (insn, value); + delete_insn_and_edges (insn); /* We're done with this insn. */ return; }