X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fexpmed.c;h=7ee5964853b7b10e212ca755b857d88814ff3097;hb=9a5e8086de4743586d52ab102990455554db39db;hp=9ceee9f923a22adbe9ee75080b9dd1647cb562c6;hpb=1cf939b94e15514881a6f288f2ed9d32a4340d9f;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/expmed.c b/gcc/expmed.c index 9ceee9f923a..7ee5964853b 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -59,8 +59,8 @@ static rtx expand_sdiv_pow2 (enum machine_mode, rtx, HOST_WIDE_INT); Usually, this will mean that the MD file will emit non-branch sequences. */ -static int sdiv_pow2_cheap[NUM_MACHINE_MODES]; -static int smod_pow2_cheap[NUM_MACHINE_MODES]; +static bool sdiv_pow2_cheap[NUM_MACHINE_MODES]; +static bool smod_pow2_cheap[NUM_MACHINE_MODES]; #ifndef SLOW_UNALIGNED_ACCESS #define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) STRICT_ALIGNMENT @@ -109,7 +109,7 @@ init_expmed (void) { struct { - struct rtx_def reg; + struct rtx_def reg; rtunion reg_fld[2]; struct rtx_def plus; rtunion plus_fld1; struct rtx_def neg; struct rtx_def udiv; rtunion udiv_fld1; @@ -2075,11 +2075,11 @@ expand_shift (enum tree_code code, enum machine_mode mode, rtx shifted, tree type = TREE_TYPE (amount); tree new_amount = make_tree (type, op1); tree other_amount - = fold (build (MINUS_EXPR, type, - convert (type, - build_int_2 (GET_MODE_BITSIZE (mode), - 0)), - amount)); + = fold (build2 (MINUS_EXPR, type, + convert (type, + build_int_2 (GET_MODE_BITSIZE (mode), + 0)), + amount)); shifted = force_reg (mode, shifted); @@ -3194,6 +3194,31 @@ expand_sdiv_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d) return expand_shift (RSHIFT_EXPR, mode, temp, shift, NULL_RTX, 0); } +#ifdef HAVE_conditional_move + if (BRANCH_COST >= 2) + { + rtx temp2; + + start_sequence (); + temp2 = copy_to_mode_reg (mode, op0); + temp = expand_binop (mode, add_optab, temp2, GEN_INT (d-1), + NULL_RTX, 0, OPTAB_LIB_WIDEN); + temp = force_reg (mode, temp); + + /* Construct "temp2 = (temp2 < 0) ? temp : temp2". */ + temp2 = emit_conditional_move (temp2, LT, temp2, const0_rtx, + mode, temp, temp2, mode, 0); + if (temp2) + { + rtx seq = get_insns (); + end_sequence (); + emit_insn (seq); + return expand_shift (RSHIFT_EXPR, mode, temp2, shift, NULL_RTX, 0); + } + end_sequence (); + } +#endif + if (BRANCH_COST >= 2) { int ushift = GET_MODE_BITSIZE (mode) - logd; @@ -4312,10 +4337,24 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode, target = 0; if (quotient == 0) - /* No divide instruction either. Use library for remainder. */ - remainder = sign_expand_binop (compute_mode, umod_optab, smod_optab, - op0, op1, target, - unsignedp, OPTAB_LIB_WIDEN); + { + /* No divide instruction either. Use library for remainder. */ + remainder = sign_expand_binop (compute_mode, umod_optab, smod_optab, + op0, op1, target, + unsignedp, OPTAB_LIB_WIDEN); + /* No remainder function. Try a quotient-and-remainder + function, keeping the remainder. */ + if (!remainder) + { + remainder = gen_reg_rtx (compute_mode); + if (!expand_twoval_binop_libfunc + (unsignedp ? udivmod_optab : sdivmod_optab, + op0, op1, + NULL_RTX, remainder, + unsignedp ? UMOD : MOD)) + remainder = NULL_RTX; + } + } else { /* We divided. Now finish doing X - Y * (X / Y). */ @@ -4386,37 +4425,37 @@ make_tree (tree type, rtx x) } case PLUS: - return fold (build (PLUS_EXPR, type, make_tree (type, XEXP (x, 0)), - make_tree (type, XEXP (x, 1)))); + return fold (build2 (PLUS_EXPR, type, make_tree (type, XEXP (x, 0)), + make_tree (type, XEXP (x, 1)))); case MINUS: - return fold (build (MINUS_EXPR, type, make_tree (type, XEXP (x, 0)), - make_tree (type, XEXP (x, 1)))); + return fold (build2 (MINUS_EXPR, type, make_tree (type, XEXP (x, 0)), + make_tree (type, XEXP (x, 1)))); case NEG: return fold (build1 (NEGATE_EXPR, type, make_tree (type, XEXP (x, 0)))); case MULT: - return fold (build (MULT_EXPR, type, make_tree (type, XEXP (x, 0)), - make_tree (type, XEXP (x, 1)))); + return fold (build2 (MULT_EXPR, type, make_tree (type, XEXP (x, 0)), + make_tree (type, XEXP (x, 1)))); case ASHIFT: - return fold (build (LSHIFT_EXPR, type, make_tree (type, XEXP (x, 0)), - make_tree (type, XEXP (x, 1)))); + return fold (build2 (LSHIFT_EXPR, type, make_tree (type, XEXP (x, 0)), + make_tree (type, XEXP (x, 1)))); case LSHIFTRT: t = lang_hooks.types.unsigned_type (type); return fold (convert (type, - build (RSHIFT_EXPR, t, - make_tree (t, XEXP (x, 0)), - make_tree (type, XEXP (x, 1))))); + build2 (RSHIFT_EXPR, t, + make_tree (t, XEXP (x, 0)), + make_tree (type, XEXP (x, 1))))); case ASHIFTRT: t = lang_hooks.types.signed_type (type); return fold (convert (type, - build (RSHIFT_EXPR, t, - make_tree (t, XEXP (x, 0)), - make_tree (type, XEXP (x, 1))))); + build2 (RSHIFT_EXPR, t, + make_tree (t, XEXP (x, 0)), + make_tree (type, XEXP (x, 1))))); case DIV: if (TREE_CODE (type) != REAL_TYPE) @@ -4425,15 +4464,15 @@ make_tree (tree type, rtx x) t = type; return fold (convert (type, - build (TRUNC_DIV_EXPR, t, - make_tree (t, XEXP (x, 0)), - make_tree (t, XEXP (x, 1))))); + build2 (TRUNC_DIV_EXPR, t, + make_tree (t, XEXP (x, 0)), + make_tree (t, XEXP (x, 1))))); case UDIV: t = lang_hooks.types.unsigned_type (type); return fold (convert (type, - build (TRUNC_DIV_EXPR, t, - make_tree (t, XEXP (x, 0)), - make_tree (t, XEXP (x, 1))))); + build2 (TRUNC_DIV_EXPR, t, + make_tree (t, XEXP (x, 0)), + make_tree (t, XEXP (x, 1))))); case SIGN_EXTEND: case ZERO_EXTEND: @@ -4483,11 +4522,11 @@ const_mult_add_overflow_p (rtx x, rtx mult, rtx add, enum machine_mode mode, int add_type = (GET_MODE (add) == VOIDmode ? mult_type : lang_hooks.types.type_for_mode (GET_MODE (add), unsignedp)); - result = fold (build (PLUS_EXPR, mult_type, - fold (build (MULT_EXPR, mult_type, - make_tree (mult_type, x), - make_tree (mult_type, mult))), - make_tree (add_type, add))); + result = fold (build2 (PLUS_EXPR, mult_type, + fold (build2 (MULT_EXPR, mult_type, + make_tree (mult_type, x), + make_tree (mult_type, mult))), + make_tree (add_type, add))); return TREE_CONSTANT_OVERFLOW (result); } @@ -4508,11 +4547,11 @@ expand_mult_add (rtx x, rtx target, rtx mult, rtx add, enum machine_mode mode, tree add_type = (GET_MODE (add) == VOIDmode ? type: lang_hooks.types.type_for_mode (GET_MODE (add), unsignedp)); - tree result = fold (build (PLUS_EXPR, type, - fold (build (MULT_EXPR, type, - make_tree (type, x), - make_tree (type, mult))), - make_tree (add_type, add))); + tree result = fold (build2 (PLUS_EXPR, type, + fold (build2 (MULT_EXPR, type, + make_tree (type, x), + make_tree (type, mult))), + make_tree (add_type, add))); return expand_expr (result, target, VOIDmode, 0); }