diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-10-18 22:45:01 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-10-18 22:45:01 +0000 |
commit | 4b05206ee786b567549ae4449c71b9e3a23e9acc (patch) | |
tree | b0c124b89ea7d242ab3f64d6e1c138f7212d1c0c /gcc/expmed.c | |
parent | 568e9a9cc465c10dfb4c6aeb30084fb1939b1a5b (diff) | |
download | gcc-4b05206ee786b567549ae4449c71b9e3a23e9acc.tar.gz |
PR middle-end/18045
* expmed.c (expand_smod_pow2): Handle modes whose size
is greater than that of HOST_WIDE_INT.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@89253 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expmed.c')
-rw-r--r-- | gcc/expmed.c | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c index 98981b8f247..2601361f60e 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -3193,7 +3193,7 @@ expand_mult_highpart (enum machine_mode mode, rtx op0, static rtx expand_smod_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d) { - unsigned HOST_WIDE_INT mask; + unsigned HOST_WIDE_INT masklow, maskhigh; rtx result, temp, shift, label; int logd; @@ -3209,14 +3209,14 @@ expand_smod_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d) if (signmask) { signmask = force_reg (mode, signmask); - mask = ((HOST_WIDE_INT) 1 << logd) - 1; + masklow = ((HOST_WIDE_INT) 1 << logd) - 1; shift = GEN_INT (GET_MODE_BITSIZE (mode) - logd); /* Use the rtx_cost of a LSHIFTRT instruction to determine which instruction sequence to use. If logical right shifts are expensive the use 2 XORs, 2 SUBs and an AND, otherwise use a LSHIFTRT, 1 ADD, 1 SUB and an AND. */ - + temp = gen_rtx_LSHIFTRT (mode, result, shift); if (lshr_optab->handlers[mode].insn_code == CODE_FOR_nothing || rtx_cost (temp, SET) > COSTS_N_INSNS (2)) @@ -3225,7 +3225,7 @@ expand_smod_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d) NULL_RTX, 1, OPTAB_LIB_WIDEN); temp = expand_binop (mode, sub_optab, temp, signmask, NULL_RTX, 1, OPTAB_LIB_WIDEN); - temp = expand_binop (mode, and_optab, temp, GEN_INT (mask), + temp = expand_binop (mode, and_optab, temp, GEN_INT (masklow), NULL_RTX, 1, OPTAB_LIB_WIDEN); temp = expand_binop (mode, xor_optab, temp, signmask, NULL_RTX, 1, OPTAB_LIB_WIDEN); @@ -3240,7 +3240,7 @@ expand_smod_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d) temp = expand_binop (mode, add_optab, op0, signmask, NULL_RTX, 1, OPTAB_LIB_WIDEN); - temp = expand_binop (mode, and_optab, temp, GEN_INT (mask), + temp = expand_binop (mode, and_optab, temp, GEN_INT (masklow), NULL_RTX, 1, OPTAB_LIB_WIDEN); temp = expand_binop (mode, sub_optab, temp, signmask, NULL_RTX, 1, OPTAB_LIB_WIDEN); @@ -3254,11 +3254,19 @@ expand_smod_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d) can avoid an explicit compare operation in the following comparison against zero. */ - mask = (HOST_WIDE_INT) -1 << (GET_MODE_BITSIZE (mode) - 1) - | (((HOST_WIDE_INT) 1 << logd) - 1); + masklow = ((HOST_WIDE_INT) 1 << logd) - 1; + if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) + { + masklow |= (HOST_WIDE_INT) -1 << (GET_MODE_BITSIZE (mode) - 1); + maskhigh = -1; + } + else + maskhigh = (HOST_WIDE_INT) -1 + << (GET_MODE_BITSIZE (mode) - HOST_BITS_PER_WIDE_INT - 1); - temp = expand_binop (mode, and_optab, op0, GEN_INT (mask), result, - 1, OPTAB_LIB_WIDEN); + temp = expand_binop (mode, and_optab, op0, + immed_double_const (masklow, maskhigh, mode), + result, 1, OPTAB_LIB_WIDEN); if (temp != result) emit_move_insn (result, temp); @@ -3267,9 +3275,11 @@ expand_smod_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d) temp = expand_binop (mode, sub_optab, result, const1_rtx, result, 0, OPTAB_LIB_WIDEN); - mask = (HOST_WIDE_INT) -1 << logd; - temp = expand_binop (mode, ior_optab, temp, GEN_INT (mask), result, - 1, OPTAB_LIB_WIDEN); + masklow = (HOST_WIDE_INT) -1 << logd; + maskhigh = -1; + temp = expand_binop (mode, ior_optab, temp, + immed_double_const (masklow, maskhigh, mode), + result, 1, OPTAB_LIB_WIDEN); temp = expand_binop (mode, add_optab, temp, const1_rtx, result, 0, OPTAB_LIB_WIDEN); if (temp != result) |