From 42495ca044a8ecaf057eb4a6c82a47a562576ab8 Mon Sep 17 00:00:00 2001 From: Richard Kenner Date: Fri, 26 Jun 1992 07:06:07 -0400 Subject: [PATCH] *** empty log message *** From-SVN: r1296 --- gcc/combine.c | 51 ++++++++++++--- gcc/cse.c | 165 +++++++++++++++++++++++++++++++++++------------ gcc/fold-const.c | 1 - gcc/genoutput.c | 1 + gcc/stmt.c | 39 ++++++++--- 5 files changed, 196 insertions(+), 61 deletions(-) diff --git a/gcc/combine.c b/gcc/combine.c index 79cc7e14822..eeea4bce52e 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -1471,17 +1471,31 @@ try_combine (i3, i2, i1) && asm_noperands (newpat) < 0) { rtx m_split, *split; + rtx ni2dest = i2dest; /* See if the MD file can split NEWPAT. If it can't, see if letting it - use I2DEST as a scratch register will help. */ + use I2DEST as a scratch register will help. In the latter case, + convert I2DEST to the mode of the source of NEWPAT if we can. */ m_split = split_insns (newpat, i3); if (m_split == 0) - m_split = split_insns (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (2, newpat, - gen_rtx (CLOBBER, VOIDmode, - i2dest))), - i3); + { + /* If I2DEST is a hard register or the only use of a pseudo, + we can change its mode. */ + if (GET_MODE (SET_DEST (newpat)) != GET_MODE (i2dest) + && (REGNO (i2dest) < FIRST_PSEUDO_REGISTER + || (reg_n_sets[REGNO (i2dest)] == 1 && ! added_sets_2 + && ! REG_USERVAR_P (i2dest)))) + ni2dest = gen_rtx (REG, GET_MODE (SET_DEST (newpat)), + REGNO (i2dest)); + + m_split = split_insns (gen_rtx (PARALLEL, VOIDmode, + gen_rtvec (2, newpat, + gen_rtx (CLOBBER, + VOIDmode, + ni2dest))), + i3); + } if (m_split && GET_CODE (m_split) == SEQUENCE && XVECLEN (m_split, 0) == 2 @@ -1492,6 +1506,13 @@ try_combine (i3, i2, i1) newi2pat = PATTERN (XVECEXP (m_split, 0, 0)); newpat = PATTERN (XVECEXP (m_split, 0, 1)); + /* In case we changed the mode of I2DEST, replace it in the + pseudo-register table here. We can't do it above in case this + code doesn't get executed and we do a split the other way. */ + + if (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER) + SUBST (regno_reg_rtx[REGNO (i2dest)], ni2dest); + i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes); if (i2_code_number >= 0) insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes); @@ -2945,6 +2966,18 @@ subst (x, from, to, in_dest, unique_copy) - INTVAL (XEXP (XEXP (x, 1), 1)) - 1); goto restart; } + + /* If we are adding two things that have no bits in common, convert + the addition into an IOR. This will often be further simplified, + for example in cases like ((a & 1) + (a & 2)), which can + become a & 3. */ + + if ((significant_bits (XEXP (x, 0), mode) + & significant_bits (XEXP (x, 1), mode)) == 0) + { + x = gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1)); + goto restart; + } break; case MULT: @@ -4194,8 +4227,8 @@ make_extraction (mode, inner, pos, pos_rtx, len, We try, as much as possible, to re-use rtl expressions to save memory. IN_CODE says what kind of expression we are processing. Normally, it is - SET. In a memory address (inside a MEM or PLUS, the latter being a - kludge), it is MEM. When processing the arguments of a comparison + SET. In a memory address (inside a MEM, PLUS or minus, the latter two + being kludges), it is MEM. When processing the arguments of a comparison or a COMPARE against zero, it is COMPARE. */ static rtx @@ -4215,7 +4248,7 @@ make_compound_operation (x, in_code) address, we stay there. If we have a comparison, set to COMPARE, but once inside, go back to our default of SET. */ - next_code = (code == MEM || code == PLUS ? MEM + next_code = (code == MEM || code == PLUS || code == MINUS ? MEM : ((code == COMPARE || GET_RTX_CLASS (code) == '<') && XEXP (x, 1) == const0_rtx) ? COMPARE : in_code == COMPARE ? SET : in_code); diff --git a/gcc/cse.c b/gcc/cse.c index b05f0149892..c39174d89df 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -2451,8 +2451,9 @@ find_best_addr (insn, loc) && validate_change (insn, loc, fold_rtx (addr, insn), 0)) addr = *loc; - /* If this address is not in the hash table, we can't do any better. - Also, ignore if volatile. */ + /* If this address is not in the hash table, we can't look for equivalences + of the whole address. Also, ignore if volatile. */ + do_not_record = 0; hash_code = HASH (addr, Pmode); addr_volatile = do_not_record; @@ -2465,56 +2466,138 @@ find_best_addr (insn, loc) elt = lookup (addr, hash_code, Pmode); - if (elt == 0) - return; - #ifndef ADDRESS_COST - our_cost = elt->cost; - - /* Find the lowest cost below ours that works. */ - for (elt = elt->first_same_value; elt; elt = elt->next_same_value) - if (elt->cost < our_cost - && (GET_CODE (elt->exp) == REG || exp_equiv_p (elt->exp, elt->exp, 1, 0)) - && validate_change (insn, loc, canon_reg (copy_rtx (elt->exp), 0), 0)) - return; + if (elt) + { + our_cost = elt->cost; + /* Find the lowest cost below ours that works. */ + for (elt = elt->first_same_value; elt; elt = elt->next_same_value) + if (elt->cost < our_cost + && (GET_CODE (elt->exp) == REG + || exp_equiv_p (elt->exp, elt->exp, 1, 0)) + && validate_change (insn, loc, + canon_reg (copy_rtx (elt->exp), 0), 0)) + return; + } #else - /* We need to find the best (under the criteria documented above) entry in - the class that is valid. We use the `flag' field to indicate choices - that were invalid and iterate until we can't find a better one that - hasn't already been tried. */ + if (elt) + { + /* We need to find the best (under the criteria documented above) entry + in the class that is valid. We use the `flag' field to indicate + choices that were invalid and iterate until we can't find a better + one that hasn't already been tried. */ - for (p = elt->first_same_value; p; p = p->next_same_value) - p->flag = 0; + for (p = elt->first_same_value; p; p = p->next_same_value) + p->flag = 0; - while (found_better) + while (found_better) + { + int best_addr_cost = ADDRESS_COST (*loc); + int best_rtx_cost = (elt->cost + 1) >> 1; + struct table_elt *best_elt = elt; + + found_better = 0; + for (p = elt->first_same_value; p; p = p->next_same_value) + if (! p->flag + && (GET_CODE (p->exp) == REG + || exp_equiv_p (p->exp, p->exp, 1, 0)) + && (ADDRESS_COST (p->exp) < best_addr_cost + || (ADDRESS_COST (p->exp) == best_addr_cost + && (p->cost + 1) >> 1 > best_rtx_cost))) + { + found_better = 1; + best_addr_cost = ADDRESS_COST (p->exp); + best_rtx_cost = (p->cost + 1) >> 1; + best_elt = p; + } + + if (found_better) + { + if (validate_change (insn, loc, + canon_reg (copy_rtx (best_elt->exp), 0), 0)) + return; + else + best_elt->flag = 1; + } + } + } + + /* If the address is a binary operation with the first operand a register + and the second a constant, do the same as above, but looking for + equivalences of the register. Then try to simplify before checking for + the best address to use. This catches a few cases: First is when we + have REG+const and the register is another REG+const. We can often merge + the constants and eliminate one insn and one register. It may also be + that a machine has a cheap REG+REG+const. Finally, this improves the + code on the Alpha for unaligned byte stores. */ + + if (flag_expensive_optimizations + && (GET_RTX_CLASS (GET_CODE (*loc)) == '2' + || GET_RTX_CLASS (GET_CODE (*loc)) == 'c') + && GET_CODE (XEXP (*loc, 0)) == REG + && GET_CODE (XEXP (*loc, 1)) == CONST_INT) { - int best_addr_cost = ADDRESS_COST (*loc); - int best_rtx_cost = (elt->cost + 1) >> 1; - struct table_elt *best_elt = elt; + rtx c = XEXP (*loc, 1); + + do_not_record = 0; + hash_code = HASH (XEXP (*loc, 0), Pmode); + do_not_record = save_do_not_record; + hash_arg_in_memory = save_hash_arg_in_memory; + hash_arg_in_struct = save_hash_arg_in_struct; + + elt = lookup (XEXP (*loc, 0), hash_code, Pmode); + if (elt == 0) + return; + + /* We need to find the best (under the criteria documented above) entry + in the class that is valid. We use the `flag' field to indicate + choices that were invalid and iterate until we can't find a better + one that hasn't already been tried. */ - found_better = 0; for (p = elt->first_same_value; p; p = p->next_same_value) - if (! p->flag - && (GET_CODE (p->exp) == REG || exp_equiv_p (p->exp, p->exp, 1, 0)) - && (ADDRESS_COST (p->exp) < best_addr_cost - || (ADDRESS_COST (p->exp) == best_addr_cost - && (p->cost + 1) >> 1 > best_rtx_cost))) - { - found_better = 1; - best_addr_cost = ADDRESS_COST (p->exp); - best_rtx_cost = (p->cost + 1) >> 1; - best_elt = p; - } + p->flag = 0; - if (found_better) + while (found_better) { - if (validate_change (insn, loc, - canon_reg (copy_rtx (best_elt->exp), 0), 0)) - return; - else - best_elt->flag = 1; + int best_addr_cost = ADDRESS_COST (*loc); + int best_rtx_cost = (COST (*loc) + 1) >> 1; + struct table_elt *best_elt = elt; + rtx best_rtx = *loc; + + found_better = 0; + for (p = elt->first_same_value; p; p = p->next_same_value) + if (! p->flag + && (GET_CODE (p->exp) == REG + || exp_equiv_p (p->exp, p->exp, 1, 0))) + { + rtx new = simplify_binary_operation (GET_CODE (*loc), Pmode, + p->exp, c); + + if (new == 0) + new = gen_rtx (GET_CODE (*loc), Pmode, p->exp, c); + + if ((ADDRESS_COST (new) < best_addr_cost + || (ADDRESS_COST (new) == best_addr_cost + && (COST (new) + 1) >> 1 > best_rtx_cost))) + { + found_better = 1; + best_addr_cost = ADDRESS_COST (new); + best_rtx_cost = (COST (new) + 1) >> 1; + best_elt = p; + best_rtx = new; + } + } + + if (found_better) + { + if (validate_change (insn, loc, + canon_reg (copy_rtx (best_rtx), 0), 0)) + return; + else + best_elt->flag = 1; + } } } #endif diff --git a/gcc/fold-const.c b/gcc/fold-const.c index a2691096ba1..99d347db63f 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -2134,7 +2134,6 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs) #if BYTES_BIG_ENDIAN lbitpos = lnbitsize - lbitsize - lbitpos; - rbitpos = rnbitsize - rbitsize - rbitpos; #endif /* Make the mask to be used against the extracted field. */ diff --git a/gcc/genoutput.c b/gcc/genoutput.c index 70173dc97a3..96cad8c4b9a 100644 --- a/gcc/genoutput.c +++ b/gcc/genoutput.c @@ -846,6 +846,7 @@ gen_split (split) mybzero (d->strict_low, sizeof strict_low); d->n_dups = 0; + d->n_alternatives = 0; d->template = 0; d->outfun = 0; d->n_alternatives = 0; diff --git a/gcc/stmt.c b/gcc/stmt.c index d9e49bdad5f..7abf935f407 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -2546,16 +2546,35 @@ expand_end_bindings (vars, mark_ends, dont_jump_in) #if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM if (fixed_regs[ARG_POINTER_REGNUM]) { - /* Now restore our arg pointer from the address at which it was saved - in our stack frame. - If there hasn't be space allocated for it yet, make some now. */ - if (arg_pointer_save_area == 0) - arg_pointer_save_area - = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0); - emit_move_insn (virtual_incoming_args_rtx, - /* We need a pseudo here, - or else instantiate_virtual_regs_1 complains. */ - copy_to_reg (arg_pointer_save_area)); +#ifdef ELIMINABLE_REGS + /* If the argument pointer can be eliminated in favor of the + frame pointer, we don't need to restore it. We assume here + that if such an elimination is present, it can always be used. + This is the case on all known machines; if we don't make this + assumption, we do unnecessary saving on many machines. */ + static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS; + int i; + + for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++) + if (elim_regs[i].from == ARG_POINTER_REGNUM + && elim_regs[i].to == FRAME_POINTER_REGNUM) + break; + + if (i == sizeof elim_regs / sizeof elim_regs [0]) +#endif + { + /* Now restore our arg pointer from the address at which it + was saved in our stack frame. + If there hasn't be space allocated for it yet, make + some now. */ + if (arg_pointer_save_area == 0) + arg_pointer_save_area + = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0); + emit_move_insn (virtual_incoming_args_rtx, + /* We need a pseudo here, or else + instantiate_virtual_regs_1 complains. */ + copy_to_reg (arg_pointer_save_area)); + } } #endif -- 2.30.2