X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcombine.c;h=2e81efcb0274c92c2e244d3b3bf12ccc4ec3d5b4;hb=9702264ef825c6e62581a8a2daf2c5405e480bbf;hp=7f3f6da2cea188e71acfa87e3ec4004cc0c434e3;hpb=b572c3c961eadd3a7dc0fbdbf938d595816e61e2;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/combine.c b/gcc/combine.c index 7f3f6da2cea..2e81efcb027 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -1,6 +1,6 @@ /* Optimize by combining instructions for GNU compiler. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -92,7 +92,6 @@ along with GCC; see the file COPYING3. If not see #include "expr.h" #include "insn-attr.h" #include "recog.h" -#include "real.h" #include "toplev.h" #include "target.h" #include "optabs.h" @@ -391,7 +390,7 @@ static int contains_muldiv (rtx); static rtx try_combine (rtx, rtx, rtx, int *); static void undo_all (void); static void undo_commit (void); -static rtx *find_split_point (rtx *, rtx); +static rtx *find_split_point (rtx *, rtx, bool); static rtx subst (rtx, rtx, rtx, int, int); static rtx combine_simplify_rtx (rtx, enum machine_mode, int); static rtx simplify_if_then_else (rtx); @@ -1343,7 +1342,7 @@ setup_incoming_promotions (rtx first) for (arg = DECL_ARGUMENTS (current_function_decl); arg; arg = TREE_CHAIN (arg)) { - rtx reg = DECL_INCOMING_RTL (arg); + rtx x, reg = DECL_INCOMING_RTL (arg); int uns1, uns3; enum machine_mode mode1, mode2, mode3, mode4; @@ -1375,30 +1374,38 @@ setup_incoming_promotions (rtx first) /* The mode of the register in which the argument is being passed. */ mode4 = GET_MODE (reg); - /* Eliminate sign extensions in the callee when possible. Only - do this when: - (a) a mode promotion has occurred; - (b) the mode of the register is the same as the mode of - the argument as it is passed; and - (c) the signedness does not change across any of the promotions; and - (d) when no language-level promotions (which we cannot guarantee - will have been done by an external caller) are necessary, - unless we know that this function is only ever called from - the current compilation unit -- all of whose call sites will - do the mode1 --> mode2 promotion. */ - if (mode1 != mode3 - && mode3 == mode4 - && uns1 == uns3 - && (mode1 == mode2 || strictly_local)) - { - /* Record that the value was promoted from mode1 to mode3, - so that any sign extension at the head of the current - function may be eliminated. */ - rtx x; - x = gen_rtx_CLOBBER (mode1, const0_rtx); - x = gen_rtx_fmt_e ((uns3 ? ZERO_EXTEND : SIGN_EXTEND), mode3, x); - record_value_for_reg (reg, first, x); - } + /* Eliminate sign extensions in the callee when: + (a) A mode promotion has occurred; */ + if (mode1 == mode3) + continue; + /* (b) The mode of the register is the same as the mode of + the argument as it is passed; */ + if (mode3 != mode4) + continue; + /* (c) There's no language level extension; */ + if (mode1 == mode2) + ; + /* (c.1) All callers are from the current compilation unit. If that's + the case we don't have to rely on an ABI, we only have to know + what we're generating right now, and we know that we will do the + mode1 to mode2 promotion with the given sign. */ + else if (!strictly_local) + continue; + /* (c.2) The combination of the two promotions is useful. This is + true when the signs match, or if the first promotion is unsigned. + In the later case, (sign_extend (zero_extend x)) is the same as + (zero_extend (zero_extend x)), so make sure to force UNS3 true. */ + else if (uns1) + uns3 = true; + else if (uns3) + continue; + + /* Record that the value was promoted from mode1 to mode3, + so that any sign extension at the head of the current + function may be eliminated. */ + x = gen_rtx_CLOBBER (mode1, const0_rtx); + x = gen_rtx_fmt_e ((uns3 ? ZERO_EXTEND : SIGN_EXTEND), mode3, x); + record_value_for_reg (reg, first, x); } } @@ -2068,14 +2075,14 @@ likely_spilled_retval_p (rtx insn) unsigned regno, nregs; /* We assume here that no machine mode needs more than 32 hard registers when the value overlaps with a register - for which FUNCTION_VALUE_REGNO_P is true. */ + for which TARGET_FUNCTION_VALUE_REGNO_P is true. */ unsigned mask; struct likely_spilled_retval_info info; if (!NONJUMP_INSN_P (use) || GET_CODE (PATTERN (use)) != USE || insn == use) return 0; reg = XEXP (PATTERN (use), 0); - if (!REG_P (reg) || !FUNCTION_VALUE_REGNO_P (REGNO (reg))) + if (!REG_P (reg) || !targetm.calls.function_value_regno_p (REGNO (reg))) return 0; regno = REGNO (reg); nregs = hard_regno_nregs[regno][GET_MODE (reg)]; @@ -2278,10 +2285,12 @@ struct rtx_subst_pair substituted. */ static rtx -propagate_for_debug_subst (rtx from ATTRIBUTE_UNUSED, void *data) +propagate_for_debug_subst (rtx from, const_rtx old_rtx, void *data) { struct rtx_subst_pair *pair = (struct rtx_subst_pair *)data; + if (!rtx_equal_p (from, old_rtx)) + return NULL_RTX; if (!pair->adjusted) { pair->adjusted = true; @@ -2300,6 +2309,7 @@ static void propagate_for_debug (rtx insn, rtx last, rtx dest, rtx src, bool move) { rtx next, move_pos = move ? last : NULL_RTX, loc; + bool first_p; #ifdef AUTO_INC_DEC struct rtx_subst_pair p; @@ -2308,6 +2318,7 @@ propagate_for_debug (rtx insn, rtx last, rtx dest, rtx src, bool move) p.after = move; #endif + first_p = true; next = NEXT_INSN (insn); while (next != last) { @@ -2315,6 +2326,11 @@ propagate_for_debug (rtx insn, rtx last, rtx dest, rtx src, bool move) next = NEXT_INSN (insn); if (DEBUG_INSN_P (insn)) { + if (first_p) + { + src = make_compound_operation (src, SET); + first_p = false; + } #ifdef AUTO_INC_DEC loc = simplify_replace_fn_rtx (INSN_VAR_LOCATION_LOC (insn), dest, propagate_for_debug_subst, &p); @@ -2655,10 +2671,16 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) i2dest = SET_DEST (temp); i2dest_killed = dead_or_set_p (i2, i2dest); + /* Replace the source in I2 with the new constant and make the + resulting insn the new pattern for I3. Then skip to where we + validate the pattern. Everything was set up above. */ SUBST (SET_SRC (temp), immed_double_const (olo, ohi, GET_MODE (SET_DEST (temp)))); newpat = PATTERN (i2); + + /* The dest of I3 has been replaced with the dest of I2. */ + changed_i3_dest = 1; goto validate_replacement; } } @@ -3030,8 +3052,6 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) } } - /* We come here when we are replacing a destination in I2 with the - destination of I3. */ validate_replacement: /* Note which hard regs this insn has as inputs. */ @@ -3253,7 +3273,8 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) /* If we can split it and use I2DEST, go ahead and see if that helps things be recognized. Verify that none of the registers are set between I2 and I3. */ - if (insn_code_number < 0 && (split = find_split_point (&newpat, i3)) != 0 + if (insn_code_number < 0 + && (split = find_split_point (&newpat, i3, false)) != 0 #ifdef HAVE_cc0 && REG_P (i2dest) #endif @@ -3279,6 +3300,14 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) i2scratch = true; + /* *SPLIT may be part of I2SRC, so make sure we have the + original expression around for later debug processing. + We should not need I2SRC any more in other cases. */ + if (MAY_HAVE_DEBUG_INSNS) + i2src = copy_rtx (i2src); + else + i2src = NULL; + /* Get NEWDEST as a register in the proper mode. We have already validated that we can do this. */ if (GET_MODE (i2dest) != split_mode && split_mode != VOIDmode) @@ -3775,7 +3804,13 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) call_usage = copy_rtx (call_usage); if (substed_i2) - replace_rtx (call_usage, i2dest, i2src); + { + /* I2SRC must still be meaningful at this point. Some splitting + operations can invalidate I2SRC, but those operations do not + apply to calls. */ + gcc_assert (i2src); + replace_rtx (call_usage, i2dest, i2src); + } if (substed_i1) replace_rtx (call_usage, i1dest, i1src); @@ -4130,7 +4165,7 @@ undo_commit (void) two insns. */ static rtx * -find_split_point (rtx *loc, rtx insn) +find_split_point (rtx *loc, rtx insn, bool set_src) { rtx x = *loc; enum rtx_code code = GET_CODE (x); @@ -4150,7 +4185,7 @@ find_split_point (rtx *loc, rtx insn) if (MEM_P (SUBREG_REG (x))) return loc; #endif - return find_split_point (&SUBREG_REG (x), insn); + return find_split_point (&SUBREG_REG (x), insn, false); case MEM: #ifdef HAVE_lo_sum @@ -4267,12 +4302,12 @@ find_split_point (rtx *loc, rtx insn) #endif /* See if we can split SET_SRC as it stands. */ - split = find_split_point (&SET_SRC (x), insn); + split = find_split_point (&SET_SRC (x), insn, true); if (split && split != &SET_SRC (x)) return split; /* See if we can split SET_DEST as it stands. */ - split = find_split_point (&SET_DEST (x), insn); + split = find_split_point (&SET_DEST (x), insn, false); if (split && split != &SET_DEST (x)) return split; @@ -4316,7 +4351,7 @@ find_split_point (rtx *loc, rtx insn) SUBST (SET_DEST (x), dest); - split = find_split_point (&SET_SRC (x), insn); + split = find_split_point (&SET_SRC (x), insn, true); if (split && split != &SET_SRC (x)) return split; } @@ -4352,7 +4387,7 @@ find_split_point (rtx *loc, rtx insn) if (extraction != 0) { SUBST (SET_SRC (x), extraction); - return find_split_point (loc, insn); + return find_split_point (loc, insn, false); } } break; @@ -4374,7 +4409,7 @@ find_split_point (rtx *loc, rtx insn) XEXP (SET_SRC (x), 0), GEN_INT (pos)))); - split = find_split_point (&SET_SRC (x), insn); + split = find_split_point (&SET_SRC (x), insn, true); if (split && split != &SET_SRC (x)) return split; } @@ -4433,7 +4468,7 @@ find_split_point (rtx *loc, rtx insn) GEN_INT (pos)), GEN_INT (((HOST_WIDE_INT) 1 << len) - 1))); - split = find_split_point (&SET_SRC (x), insn); + split = find_split_point (&SET_SRC (x), insn, true); if (split && split != &SET_SRC (x)) return split; } @@ -4448,7 +4483,7 @@ find_split_point (rtx *loc, rtx insn) - len - pos)), GEN_INT (GET_MODE_BITSIZE (mode) - len))); - split = find_split_point (&SET_SRC (x), insn); + split = find_split_point (&SET_SRC (x), insn, true); if (split && split != &SET_SRC (x)) return split; } @@ -4488,7 +4523,7 @@ find_split_point (rtx *loc, rtx insn) GET_MODE (x), XEXP (XEXP (x, 0), 0), XEXP (XEXP (x, 1), 0)))); - return find_split_point (loc, insn); + return find_split_point (loc, insn, set_src); } /* Many RISC machines have a large set of logical insns. If the @@ -4502,6 +4537,14 @@ find_split_point (rtx *loc, rtx insn) } break; + case PLUS: + case MINUS: + /* Split at a multiply-accumulate instruction. However if this is + the SET_SRC, we likely do not have such an instruction and it's + worthless to try this split. */ + if (!set_src && GET_CODE (XEXP (x, 0)) == MULT) + return loc; + default: break; } @@ -4511,7 +4554,7 @@ find_split_point (rtx *loc, rtx insn) { case RTX_BITFIELD_OPS: /* This is ZERO_EXTRACT and SIGN_EXTRACT. */ case RTX_TERNARY: - split = find_split_point (&XEXP (x, 2), insn); + split = find_split_point (&XEXP (x, 2), insn, false); if (split) return split; /* ... fall through ... */ @@ -4519,7 +4562,7 @@ find_split_point (rtx *loc, rtx insn) case RTX_COMM_ARITH: case RTX_COMPARE: case RTX_COMM_COMPARE: - split = find_split_point (&XEXP (x, 1), insn); + split = find_split_point (&XEXP (x, 1), insn, false); if (split) return split; /* ... fall through ... */ @@ -4529,7 +4572,7 @@ find_split_point (rtx *loc, rtx insn) if (GET_CODE (x) != AND && GET_CODE (XEXP (x, 0)) == AND) return &XEXP (x, 0); - split = find_split_point (&XEXP (x, 0), insn); + split = find_split_point (&XEXP (x, 0), insn, false); if (split) return split; return loc; @@ -6779,8 +6822,10 @@ make_extraction (enum machine_mode mode, rtx inner, HOST_WIDE_INT pos, if (mode == tmode) return new_rtx; - if (CONST_INT_P (new_rtx)) - return gen_int_mode (INTVAL (new_rtx), mode); + if (CONST_INT_P (new_rtx) + || GET_CODE (new_rtx) == CONST_DOUBLE) + return simplify_unary_operation (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, + mode, new_rtx, tmode); /* If we know that no extraneous bits are set, and that the high bit is not set, convert the extraction to the cheaper of @@ -7298,15 +7343,14 @@ make_compound_operation (rtx x, enum rtx_code in_code) tem = make_compound_operation (SUBREG_REG (x), in_code); { - rtx simplified; - simplified = simplify_subreg (GET_MODE (x), tem, GET_MODE (tem), - SUBREG_BYTE (x)); + rtx simplified = simplify_subreg (mode, tem, GET_MODE (SUBREG_REG (x)), + SUBREG_BYTE (x)); if (simplified) tem = simplified; if (GET_CODE (tem) != GET_CODE (SUBREG_REG (x)) - && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (tem)) + && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) && subreg_lowpart_p (x)) { rtx newer = force_to_mode (tem, mode, ~(HOST_WIDE_INT) 0,