X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fexpmed.c;h=231a33e5d9faa30e39e788060bec314a94364b9b;hb=bac09543806711a7b00ccd6cf918aee971f00306;hp=c6c8058cc9ea755e7a9596cc10c4ad8cd46b753c;hpb=de17a47baa567274fa46d2cdae91b39b9abcb8d5;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/expmed.c b/gcc/expmed.c index c6c8058cc9e..231a33e5d9f 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -54,6 +54,9 @@ static void do_cmp_and_jump (rtx, rtx, enum rtx_code, enum machine_mode, rtx); static rtx expand_smod_pow2 (enum machine_mode, rtx, HOST_WIDE_INT); static rtx expand_sdiv_pow2 (enum machine_mode, rtx, HOST_WIDE_INT); +/* Test whether a value is zero of a power of two. */ +#define EXACT_POWER_OF_2_OR_ZERO_P(x) (((x) & ((x) - 1)) == 0) + /* Nonzero means divides or modulus operations are relatively cheap for powers of two, so don't use branches; emit the operation instead. Usually, this will mean that the MD file will emit non-branch @@ -588,16 +591,18 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, offset = 0; } - /* If VALUE is a floating-point mode, access it as an integer of the - corresponding size. This can occur on a machine with 64 bit registers - that uses SFmode for float. This can also occur for unaligned float - structure fields. */ + /* If VALUE has a floating-point or complex mode, access it as an + integer of the corresponding size. This can occur on a machine + with 64 bit registers that uses SFmode for float. It can also + occur for unaligned float or complex fields. */ orig_value = value; - if (GET_MODE_CLASS (GET_MODE (value)) != MODE_INT + if (GET_MODE (value) != VOIDmode + && GET_MODE_CLASS (GET_MODE (value)) != MODE_INT && GET_MODE_CLASS (GET_MODE (value)) != MODE_PARTIAL_INT) - value = gen_lowpart ((GET_MODE (value) == VOIDmode - ? word_mode : int_mode_for_mode (GET_MODE (value))), - value); + { + value = gen_reg_rtx (int_mode_for_mode (GET_MODE (value))); + emit_move_insn (gen_lowpart (GET_MODE (orig_value), value), orig_value); + } /* Now OFFSET is nonzero only if OP0 is memory and is therefore always measured in bytes. */ @@ -2655,7 +2660,7 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t, op_latency = add_cost[mode]; new_limit.cost = best_cost.cost - op_cost; - new_limit.cost = best_cost.cost - op_latency; + new_limit.latency = best_cost.latency - op_latency; synth_mult (alg_in, t / d, &new_limit, mode); alg_in->cost.cost += op_cost; @@ -3024,11 +3029,25 @@ expand_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, if (const_op1 && GET_CODE (const_op1) == CONST_INT && (unsignedp || !flag_trapv)) { - int mult_cost = rtx_cost (gen_rtx_MULT (mode, op0, op1), SET); + HOST_WIDE_INT coeff = INTVAL (const_op1); + int mult_cost; - if (choose_mult_variant (mode, INTVAL (const_op1), &algorithm, &variant, + /* Special case powers of two. */ + if (EXACT_POWER_OF_2_OR_ZERO_P (coeff)) + { + if (coeff == 0) + return const0_rtx; + if (coeff == 1) + return op0; + return expand_shift (LSHIFT_EXPR, mode, op0, + build_int_cst (NULL_TREE, floor_log2 (coeff)), + target, unsignedp); + } + + mult_cost = rtx_cost (gen_rtx_MULT (mode, op0, op1), SET); + if (choose_mult_variant (mode, coeff, &algorithm, &variant, mult_cost)) - return expand_mult_const (mode, op0, INTVAL (const_op1), target, + return expand_mult_const (mode, op0, coeff, target, &algorithm, variant); } @@ -3627,8 +3646,6 @@ expand_sdiv_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d) (x mod 12) == (((x & 1023) + ((x >> 8) & ~3)) * 0x15555558 >> 2 * 3) >> 28 */ -#define EXACT_POWER_OF_2_OR_ZERO_P(x) (((x) & ((x) - 1)) == 0) - rtx expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode, rtx op0, rtx op1, rtx target, int unsignedp)