summaryrefslogtreecommitdiff
path: root/gcc/expmed.c
diff options
context:
space:
mode:
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2004-10-18 22:45:01 +0000
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>2004-10-18 22:45:01 +0000
commit4b05206ee786b567549ae4449c71b9e3a23e9acc (patch)
treeb0c124b89ea7d242ab3f64d6e1c138f7212d1c0c /gcc/expmed.c
parent568e9a9cc465c10dfb4c6aeb30084fb1939b1a5b (diff)
downloadgcc-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.c34
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)