- other = simplify_gen_unary (NOT, GET_MODE (x), other, GET_MODE (x));
- }
-
- /* We may be able to continuing distributing the result, so call
- ourselves recursively on the inner operation before forming the
- outer operation, which we return. */
- return gen_binary (inner_code, GET_MODE (x),
- apply_distributive_law (tem), other);
-}
-\f
-/* We have X, a logical `and' of VAROP with the constant CONSTOP, to be done
- in MODE.
-
- Return an equivalent form, if different from X. Otherwise, return X. If
- X is zero, we are to always construct the equivalent form. */
-
-static rtx
-simplify_and_const_int (x, mode, varop, constop)
- rtx x;
- enum machine_mode mode;
- rtx varop;
- unsigned HOST_WIDE_INT constop;
-{
- unsigned HOST_WIDE_INT nonzero;
- int i;
-
- /* Simplify VAROP knowing that we will be only looking at some of the
- bits in it.
-
- Note by passing in CONSTOP, we guarantee that the bits not set in
- CONSTOP are not significant and will never be examined. We must
- ensure that is the case by explicitly masking out those bits
- before returning. */
- varop = force_to_mode (varop, mode, constop, NULL_RTX, 0);
-
- /* If VAROP is a CLOBBER, we will fail so return it. */
- if (GET_CODE (varop) == CLOBBER)
- return varop;
-
- /* If VAROP is a CONST_INT, then we need to apply the mask in CONSTOP
- to VAROP and return the new constant. */
- if (GET_CODE (varop) == CONST_INT)
- return GEN_INT (trunc_int_for_mode (INTVAL (varop) & constop, mode));
-
- /* See what bits may be nonzero in VAROP. Unlike the general case of
- a call to nonzero_bits, here we don't care about bits outside
- MODE. */
-
- nonzero = nonzero_bits (varop, mode) & GET_MODE_MASK (mode);
-
- /* Turn off all bits in the constant that are known to already be zero.
- Thus, if the AND isn't needed at all, we will have CONSTOP == NONZERO_BITS
- which is tested below. */
-
- constop &= nonzero;
-
- /* If we don't have any bits left, return zero. */
- if (constop == 0)
- return const0_rtx;
-
- /* If VAROP is a NEG of something known to be zero or 1 and CONSTOP is
- a power of two, we can replace this with an ASHIFT. */
- if (GET_CODE (varop) == NEG && nonzero_bits (XEXP (varop, 0), mode) == 1
- && (i = exact_log2 (constop)) >= 0)
- return simplify_shift_const (NULL_RTX, ASHIFT, mode, XEXP (varop, 0), i);
-
- /* If VAROP is an IOR or XOR, apply the AND to both branches of the IOR
- or XOR, then try to apply the distributive law. This may eliminate
- operations if either branch can be simplified because of the AND.
- It may also make some cases more complex, but those cases probably
- won't match a pattern either with or without this. */
-
- if (GET_CODE (varop) == IOR || GET_CODE (varop) == XOR)
- return
- gen_lowpart_for_combine
- (mode,
- apply_distributive_law
- (gen_binary (GET_CODE (varop), GET_MODE (varop),
- simplify_and_const_int (NULL_RTX, GET_MODE (varop),
- XEXP (varop, 0), constop),
- simplify_and_const_int (NULL_RTX, GET_MODE (varop),
- XEXP (varop, 1), constop))));
-
- /* If VAROP is PLUS, and the constant is a mask of low bite, distribute
- the AND and see if one of the operands simplifies to zero. If so, we
- may eliminate it. */
-
- if (GET_CODE (varop) == PLUS
- && exact_log2 (constop + 1) >= 0)
- {
- rtx o0, o1;
-
- o0 = simplify_and_const_int (NULL_RTX, mode, XEXP (varop, 0), constop);
- o1 = simplify_and_const_int (NULL_RTX, mode, XEXP (varop, 1), constop);
- if (o0 == const0_rtx)
- return o1;
- if (o1 == const0_rtx)
- return o0;
- }
-
- /* Get VAROP in MODE. Try to get a SUBREG if not. Don't make a new SUBREG
- if we already had one (just check for the simplest cases). */
- if (x && GET_CODE (XEXP (x, 0)) == SUBREG
- && GET_MODE (XEXP (x, 0)) == mode
- && SUBREG_REG (XEXP (x, 0)) == varop)
- varop = XEXP (x, 0);
- else
- varop = gen_lowpart_for_combine (mode, varop);
-
- /* If we can't make the SUBREG, try to return what we were given. */
- if (GET_CODE (varop) == CLOBBER)
- return x ? x : varop;
-
- /* If we are only masking insignificant bits, return VAROP. */
- if (constop == nonzero)
- x = varop;
- else
- {
- /* Otherwise, return an AND. */
- constop = trunc_int_for_mode (constop, mode);
- /* See how much, if any, of X we can use. */
- if (x == 0 || GET_CODE (x) != AND || GET_MODE (x) != mode)
- x = gen_binary (AND, mode, varop, GEN_INT (constop));
-
- else
- {
- if (GET_CODE (XEXP (x, 1)) != CONST_INT
- || (unsigned HOST_WIDE_INT) INTVAL (XEXP (x, 1)) != constop)
- SUBST (XEXP (x, 1), GEN_INT (constop));
-
- SUBST (XEXP (x, 0), varop);
- }
- }
-
- return x;
-}
-\f
-#define nonzero_bits_with_known(X, MODE) \
- cached_nonzero_bits (X, MODE, known_x, known_mode, known_ret)
-
-/* The function cached_nonzero_bits is a wrapper around nonzero_bits1.
- It avoids exponential behavior in nonzero_bits1 when X has
- identical subexpressions on the first or the second level. */
-
-static unsigned HOST_WIDE_INT
-cached_nonzero_bits (x, mode, known_x, known_mode, known_ret)
- rtx x;
- enum machine_mode mode;
- rtx known_x;
- enum machine_mode known_mode;
- unsigned HOST_WIDE_INT known_ret;
-{
- if (x == known_x && mode == known_mode)
- return known_ret;
-
- /* Try to find identical subexpressions. If found call
- nonzero_bits1 on X with the subexpressions as KNOWN_X and the
- precomputed value for the subexpression as KNOWN_RET. */
-
- if (GET_RTX_CLASS (GET_CODE (x)) == '2'
- || GET_RTX_CLASS (GET_CODE (x)) == 'c')
- {
- rtx x0 = XEXP (x, 0);
- rtx x1 = XEXP (x, 1);
-
- /* Check the first level. */
- if (x0 == x1)
- return nonzero_bits1 (x, mode, x0, mode,
- nonzero_bits_with_known (x0, mode));
-
- /* Check the second level. */
- if ((GET_RTX_CLASS (GET_CODE (x0)) == '2'
- || GET_RTX_CLASS (GET_CODE (x0)) == 'c')
- && (x1 == XEXP (x0, 0) || x1 == XEXP (x0, 1)))
- return nonzero_bits1 (x, mode, x1, mode,
- nonzero_bits_with_known (x1, mode));
-
- if ((GET_RTX_CLASS (GET_CODE (x1)) == '2'
- || GET_RTX_CLASS (GET_CODE (x1)) == 'c')
- && (x0 == XEXP (x1, 0) || x0 == XEXP (x1, 1)))
- return nonzero_bits1 (x, mode, x0, mode,
- nonzero_bits_with_known (x0, mode));
- }
-
- return nonzero_bits1 (x, mode, known_x, known_mode, known_ret);
-}
-
-/* We let num_sign_bit_copies recur into nonzero_bits as that is useful.
- We don't let nonzero_bits recur into num_sign_bit_copies, because that
- is less useful. We can't allow both, because that results in exponential
- run time recursion. There is a nullstone testcase that triggered
- this. This macro avoids accidental uses of num_sign_bit_copies. */
-#define cached_num_sign_bit_copies()
-
-/* Given an expression, X, compute which bits in X can be nonzero.
- We don't care about bits outside of those defined in MODE.
-
- For most X this is simply GET_MODE_MASK (GET_MODE (MODE)), but if X is
- a shift, AND, or zero_extract, we can do better. */
-
-static unsigned HOST_WIDE_INT
-nonzero_bits1 (x, mode, known_x, known_mode, known_ret)
- rtx x;
- enum machine_mode mode;
- rtx known_x;
- enum machine_mode known_mode;
- unsigned HOST_WIDE_INT known_ret;
-{
- unsigned HOST_WIDE_INT nonzero = GET_MODE_MASK (mode);
- unsigned HOST_WIDE_INT inner_nz;
- enum rtx_code code;
- unsigned int mode_width = GET_MODE_BITSIZE (mode);
- rtx tem;
-
- /* For floating-point values, assume all bits are needed. */
- if (FLOAT_MODE_P (GET_MODE (x)) || FLOAT_MODE_P (mode))
- return nonzero;
-
- /* If X is wider than MODE, use its mode instead. */
- if (GET_MODE_BITSIZE (GET_MODE (x)) > mode_width)
- {
- mode = GET_MODE (x);
- nonzero = GET_MODE_MASK (mode);
- mode_width = GET_MODE_BITSIZE (mode);
- }
-
- if (mode_width > HOST_BITS_PER_WIDE_INT)
- /* Our only callers in this case look for single bit values. So
- just return the mode mask. Those tests will then be false. */
- return nonzero;
-
-#ifndef WORD_REGISTER_OPERATIONS
- /* If MODE is wider than X, but both are a single word for both the host
- and target machines, we can compute this from which bits of the
- object might be nonzero in its own mode, taking into account the fact
- that on many CISC machines, accessing an object in a wider mode
- causes the high-order bits to become undefined. So they are
- not known to be zero. */
-
- if (GET_MODE (x) != VOIDmode && GET_MODE (x) != mode
- && GET_MODE_BITSIZE (GET_MODE (x)) <= BITS_PER_WORD
- && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
- && GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (GET_MODE (x)))
- {
- nonzero &= nonzero_bits_with_known (x, GET_MODE (x));
- nonzero |= GET_MODE_MASK (mode) & ~GET_MODE_MASK (GET_MODE (x));
- return nonzero;
- }
-#endif
-
- code = GET_CODE (x);
- switch (code)
- {
- case REG:
-#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
- /* If pointers extend unsigned and this is a pointer in Pmode, say that
- all the bits above ptr_mode are known to be zero. */
- if (POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
- && REG_POINTER (x))
- nonzero &= GET_MODE_MASK (ptr_mode);
-#endif
-
- /* Include declared information about alignment of pointers. */
- /* ??? We don't properly preserve REG_POINTER changes across
- pointer-to-integer casts, so we can't trust it except for
- things that we know must be pointers. See execute/960116-1.c. */
- if ((x == stack_pointer_rtx
- || x == frame_pointer_rtx
- || x == arg_pointer_rtx)
- && REGNO_POINTER_ALIGN (REGNO (x)))
- {
- unsigned HOST_WIDE_INT alignment
- = REGNO_POINTER_ALIGN (REGNO (x)) / BITS_PER_UNIT;
-
-#ifdef PUSH_ROUNDING
- /* If PUSH_ROUNDING is defined, it is possible for the
- stack to be momentarily aligned only to that amount,
- so we pick the least alignment. */
- if (x == stack_pointer_rtx && PUSH_ARGS)
- alignment = MIN (PUSH_ROUNDING (1), alignment);
-#endif
-
- nonzero &= ~(alignment - 1);
- }
-
- /* If X is a register whose nonzero bits value is current, use it.
- Otherwise, if X is a register whose value we can find, use that
- value. Otherwise, use the previously-computed global nonzero bits
- for this register. */
-
- if (reg_last_set_value[REGNO (x)] != 0
- && (reg_last_set_mode[REGNO (x)] == mode
- || (GET_MODE_CLASS (reg_last_set_mode[REGNO (x)]) == MODE_INT
- && GET_MODE_CLASS (mode) == MODE_INT))
- && (reg_last_set_label[REGNO (x)] == label_tick
- || (REGNO (x) >= FIRST_PSEUDO_REGISTER
- && REG_N_SETS (REGNO (x)) == 1
- && ! REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start,
- REGNO (x))))
- && INSN_CUID (reg_last_set[REGNO (x)]) < subst_low_cuid)
- return reg_last_set_nonzero_bits[REGNO (x)] & nonzero;
-
- tem = get_last_value (x);
-
- if (tem)
- {
-#ifdef SHORT_IMMEDIATES_SIGN_EXTEND
- /* If X is narrower than MODE and TEM is a non-negative
- constant that would appear negative in the mode of X,
- sign-extend it for use in reg_nonzero_bits because some
- machines (maybe most) will actually do the sign-extension
- and this is the conservative approach.
-
- ??? For 2.5, try to tighten up the MD files in this regard
- instead of this kludge. */
-
- if (GET_MODE_BITSIZE (GET_MODE (x)) < mode_width
- && GET_CODE (tem) == CONST_INT
- && INTVAL (tem) > 0
- && 0 != (INTVAL (tem)
- & ((HOST_WIDE_INT) 1
- << (GET_MODE_BITSIZE (GET_MODE (x)) - 1))))
- tem = GEN_INT (INTVAL (tem)
- | ((HOST_WIDE_INT) (-1)
- << GET_MODE_BITSIZE (GET_MODE (x))));
-#endif
- return nonzero_bits_with_known (tem, mode) & nonzero;
- }
- else if (nonzero_sign_valid && reg_nonzero_bits[REGNO (x)])
- {
- unsigned HOST_WIDE_INT mask = reg_nonzero_bits[REGNO (x)];
-
- if (GET_MODE_BITSIZE (GET_MODE (x)) < mode_width)
- /* We don't know anything about the upper bits. */
- mask |= GET_MODE_MASK (mode) ^ GET_MODE_MASK (GET_MODE (x));
- return nonzero & mask;
- }
- else
- return nonzero;
-
- case CONST_INT:
-#ifdef SHORT_IMMEDIATES_SIGN_EXTEND
- /* If X is negative in MODE, sign-extend the value. */
- if (INTVAL (x) > 0 && mode_width < BITS_PER_WORD
- && 0 != (INTVAL (x) & ((HOST_WIDE_INT) 1 << (mode_width - 1))))
- return (INTVAL (x) | ((HOST_WIDE_INT) (-1) << mode_width));
-#endif
-
- return INTVAL (x);
-
- case MEM:
-#ifdef LOAD_EXTEND_OP
- /* In many, if not most, RISC machines, reading a byte from memory
- zeros the rest of the register. Noticing that fact saves a lot
- of extra zero-extends. */
- if (LOAD_EXTEND_OP (GET_MODE (x)) == ZERO_EXTEND)
- nonzero &= GET_MODE_MASK (GET_MODE (x));
-#endif
- break;
-
- case EQ: case NE:
- case UNEQ: case LTGT:
- case GT: case GTU: case UNGT:
- case LT: case LTU: case UNLT:
- case GE: case GEU: case UNGE:
- case LE: case LEU: case UNLE:
- case UNORDERED: case ORDERED:
-
- /* If this produces an integer result, we know which bits are set.
- Code here used to clear bits outside the mode of X, but that is
- now done above. */
-
- if (GET_MODE_CLASS (mode) == MODE_INT
- && mode_width <= HOST_BITS_PER_WIDE_INT)
- nonzero = STORE_FLAG_VALUE;
- break;
-
- case NEG:
-#if 0
- /* Disabled to avoid exponential mutual recursion between nonzero_bits
- and num_sign_bit_copies. */
- if (num_sign_bit_copies (XEXP (x, 0), GET_MODE (x))
- == GET_MODE_BITSIZE (GET_MODE (x)))
- nonzero = 1;
-#endif
-
- if (GET_MODE_SIZE (GET_MODE (x)) < mode_width)
- nonzero |= (GET_MODE_MASK (mode) & ~GET_MODE_MASK (GET_MODE (x)));
- break;
-
- case ABS:
-#if 0
- /* Disabled to avoid exponential mutual recursion between nonzero_bits
- and num_sign_bit_copies. */
- if (num_sign_bit_copies (XEXP (x, 0), GET_MODE (x))
- == GET_MODE_BITSIZE (GET_MODE (x)))
- nonzero = 1;
-#endif
- break;
-
- case TRUNCATE:
- nonzero &= (nonzero_bits_with_known (XEXP (x, 0), mode)
- & GET_MODE_MASK (mode));
- break;
-
- case ZERO_EXTEND:
- nonzero &= nonzero_bits_with_known (XEXP (x, 0), mode);
- if (GET_MODE (XEXP (x, 0)) != VOIDmode)
- nonzero &= GET_MODE_MASK (GET_MODE (XEXP (x, 0)));
- break;
-
- case SIGN_EXTEND:
- /* If the sign bit is known clear, this is the same as ZERO_EXTEND.
- Otherwise, show all the bits in the outer mode but not the inner
- may be nonzero. */
- inner_nz = nonzero_bits_with_known (XEXP (x, 0), mode);
- if (GET_MODE (XEXP (x, 0)) != VOIDmode)
- {
- inner_nz &= GET_MODE_MASK (GET_MODE (XEXP (x, 0)));
- if (inner_nz
- & (((HOST_WIDE_INT) 1
- << (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - 1))))
- inner_nz |= (GET_MODE_MASK (mode)
- & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0))));
- }
-
- nonzero &= inner_nz;
- break;
-
- case AND:
- nonzero &= (nonzero_bits_with_known (XEXP (x, 0), mode)
- & nonzero_bits_with_known (XEXP (x, 1), mode));
- break;
-
- case XOR: case IOR:
- case UMIN: case UMAX: case SMIN: case SMAX:
- {
- unsigned HOST_WIDE_INT nonzero0 =
- nonzero_bits_with_known (XEXP (x, 0), mode);
-
- /* Don't call nonzero_bits for the second time if it cannot change
- anything. */
- if ((nonzero & nonzero0) != nonzero)
- nonzero &= (nonzero0
- | nonzero_bits_with_known (XEXP (x, 1), mode));
- }
- break;
-
- case PLUS: case MINUS:
- case MULT:
- case DIV: case UDIV:
- case MOD: case UMOD:
- /* We can apply the rules of arithmetic to compute the number of
- high- and low-order zero bits of these operations. We start by
- computing the width (position of the highest-order nonzero bit)
- and the number of low-order zero bits for each value. */
- {
- unsigned HOST_WIDE_INT nz0 =
- nonzero_bits_with_known (XEXP (x, 0), mode);
- unsigned HOST_WIDE_INT nz1 =
- nonzero_bits_with_known (XEXP (x, 1), mode);
- int sign_index = GET_MODE_BITSIZE (GET_MODE (x)) - 1;
- int width0 = floor_log2 (nz0) + 1;
- int width1 = floor_log2 (nz1) + 1;
- int low0 = floor_log2 (nz0 & -nz0);
- int low1 = floor_log2 (nz1 & -nz1);
- HOST_WIDE_INT op0_maybe_minusp
- = (nz0 & ((HOST_WIDE_INT) 1 << sign_index));
- HOST_WIDE_INT op1_maybe_minusp
- = (nz1 & ((HOST_WIDE_INT) 1 << sign_index));
- unsigned int result_width = mode_width;
- int result_low = 0;
-
- switch (code)
- {
- case PLUS:
- result_width = MAX (width0, width1) + 1;
- result_low = MIN (low0, low1);
- break;
- case MINUS:
- result_low = MIN (low0, low1);
- break;
- case MULT:
- result_width = width0 + width1;
- result_low = low0 + low1;
- break;
- case DIV:
- if (width1 == 0)
- break;
- if (! op0_maybe_minusp && ! op1_maybe_minusp)
- result_width = width0;
- break;
- case UDIV:
- if (width1 == 0)
- break;
- result_width = width0;
- break;
- case MOD:
- if (width1 == 0)
- break;
- if (! op0_maybe_minusp && ! op1_maybe_minusp)
- result_width = MIN (width0, width1);
- result_low = MIN (low0, low1);
- break;
- case UMOD:
- if (width1 == 0)
- break;
- result_width = MIN (width0, width1);
- result_low = MIN (low0, low1);
- break;
- default:
- abort ();
- }
-
- if (result_width < mode_width)
- nonzero &= ((HOST_WIDE_INT) 1 << result_width) - 1;
-
- if (result_low > 0)
- nonzero &= ~(((HOST_WIDE_INT) 1 << result_low) - 1);
-
-#ifdef POINTERS_EXTEND_UNSIGNED
- /* If pointers extend unsigned and this is an addition or subtraction
- to a pointer in Pmode, all the bits above ptr_mode are known to be
- zero. */
- if (POINTERS_EXTEND_UNSIGNED > 0 && GET_MODE (x) == Pmode
- && (code == PLUS || code == MINUS)
- && GET_CODE (XEXP (x, 0)) == REG && REG_POINTER (XEXP (x, 0)))
- nonzero &= GET_MODE_MASK (ptr_mode);
-#endif
- }
- break;
-
- case ZERO_EXTRACT:
- if (GET_CODE (XEXP (x, 1)) == CONST_INT
- && INTVAL (XEXP (x, 1)) < HOST_BITS_PER_WIDE_INT)
- nonzero &= ((HOST_WIDE_INT) 1 << INTVAL (XEXP (x, 1))) - 1;
- break;
-
- case SUBREG:
- /* If this is a SUBREG formed for a promoted variable that has
- been zero-extended, we know that at least the high-order bits
- are zero, though others might be too. */
-
- if (SUBREG_PROMOTED_VAR_P (x) && SUBREG_PROMOTED_UNSIGNED_P (x) > 0)
- nonzero = (GET_MODE_MASK (GET_MODE (x))
- & nonzero_bits_with_known (SUBREG_REG (x), GET_MODE (x)));
-
- /* If the inner mode is a single word for both the host and target
- machines, we can compute this from which bits of the inner
- object might be nonzero. */
- if (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) <= BITS_PER_WORD
- && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))
- <= HOST_BITS_PER_WIDE_INT))
- {
- nonzero &= nonzero_bits_with_known (SUBREG_REG (x), mode);
-
-#if defined (WORD_REGISTER_OPERATIONS) && defined (LOAD_EXTEND_OP)
- /* If this is a typical RISC machine, we only have to worry
- about the way loads are extended. */
- if ((LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) == SIGN_EXTEND
- ? (((nonzero
- & (((unsigned HOST_WIDE_INT) 1
- << (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) - 1))))
- != 0))
- : LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) != ZERO_EXTEND)
- || GET_CODE (SUBREG_REG (x)) != MEM)
-#endif
- {
- /* On many CISC machines, accessing an object in a wider mode
- causes the high-order bits to become undefined. So they are
- not known to be zero. */
- if (GET_MODE_SIZE (GET_MODE (x))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
- nonzero |= (GET_MODE_MASK (GET_MODE (x))
- & ~GET_MODE_MASK (GET_MODE (SUBREG_REG (x))));
- }
- }
- break;
-
- case ASHIFTRT:
- case LSHIFTRT:
- case ASHIFT:
- case ROTATE:
- /* The nonzero bits are in two classes: any bits within MODE
- that aren't in GET_MODE (x) are always significant. The rest of the
- nonzero bits are those that are significant in the operand of
- the shift when shifted the appropriate number of bits. This
- shows that high-order bits are cleared by the right shift and
- low-order bits by left shifts. */
- if (GET_CODE (XEXP (x, 1)) == CONST_INT
- && INTVAL (XEXP (x, 1)) >= 0
- && INTVAL (XEXP (x, 1)) < HOST_BITS_PER_WIDE_INT)
- {
- enum machine_mode inner_mode = GET_MODE (x);
- unsigned int width = GET_MODE_BITSIZE (inner_mode);
- int count = INTVAL (XEXP (x, 1));
- unsigned HOST_WIDE_INT mode_mask = GET_MODE_MASK (inner_mode);
- unsigned HOST_WIDE_INT op_nonzero =
- nonzero_bits_with_known (XEXP (x, 0), mode);
- unsigned HOST_WIDE_INT inner = op_nonzero & mode_mask;
- unsigned HOST_WIDE_INT outer = 0;
-
- if (mode_width > width)
- outer = (op_nonzero & nonzero & ~mode_mask);
-
- if (code == LSHIFTRT)
- inner >>= count;
- else if (code == ASHIFTRT)
- {
- inner >>= count;
-
- /* If the sign bit may have been nonzero before the shift, we
- need to mark all the places it could have been copied to
- by the shift as possibly nonzero. */
- if (inner & ((HOST_WIDE_INT) 1 << (width - 1 - count)))
- inner |= (((HOST_WIDE_INT) 1 << count) - 1) << (width - count);
- }
- else if (code == ASHIFT)
- inner <<= count;
- else
- inner = ((inner << (count % width)
- | (inner >> (width - (count % width)))) & mode_mask);
-
- nonzero &= (outer | inner);
- }
- break;
-
- case FFS:
- case POPCOUNT:
- /* This is at most the number of bits in the mode. */
- nonzero = ((HOST_WIDE_INT) 2 << (floor_log2 (mode_width))) - 1;
- break;
-
- case CLZ:
- /* If CLZ has a known value at zero, then the nonzero bits are
- that value, plus the number of bits in the mode minus one. */
- if (CLZ_DEFINED_VALUE_AT_ZERO (mode, nonzero))
- nonzero |= ((HOST_WIDE_INT) 1 << (floor_log2 (mode_width))) - 1;
- else
- nonzero = -1;
- break;
-
- case CTZ:
- /* If CTZ has a known value at zero, then the nonzero bits are
- that value, plus the number of bits in the mode minus one. */
- if (CTZ_DEFINED_VALUE_AT_ZERO (mode, nonzero))
- nonzero |= ((HOST_WIDE_INT) 1 << (floor_log2 (mode_width))) - 1;
- else
- nonzero = -1;
- break;
-
- case PARITY:
- nonzero = 1;
- break;
-
- case IF_THEN_ELSE:
- nonzero &= (nonzero_bits_with_known (XEXP (x, 1), mode)
- | nonzero_bits_with_known (XEXP (x, 2), mode));
- break;
-
- default:
- break;
- }
-
- return nonzero;
-}
-
-/* See the macro definition above. */
-#undef cached_num_sign_bit_copies
-\f
-#define num_sign_bit_copies_with_known(X, M) \
- cached_num_sign_bit_copies (X, M, known_x, known_mode, known_ret)
-
-/* The function cached_num_sign_bit_copies is a wrapper around
- num_sign_bit_copies1. It avoids exponential behavior in
- num_sign_bit_copies1 when X has identical subexpressions on the
- first or the second level. */
-
-static unsigned int
-cached_num_sign_bit_copies (x, mode, known_x, known_mode, known_ret)
- rtx x;
- enum machine_mode mode;
- rtx known_x;
- enum machine_mode known_mode;
- unsigned int known_ret;
-{
- if (x == known_x && mode == known_mode)
- return known_ret;
-
- /* Try to find identical subexpressions. If found call
- num_sign_bit_copies1 on X with the subexpressions as KNOWN_X and
- the precomputed value for the subexpression as KNOWN_RET. */
-
- if (GET_RTX_CLASS (GET_CODE (x)) == '2'
- || GET_RTX_CLASS (GET_CODE (x)) == 'c')
- {
- rtx x0 = XEXP (x, 0);
- rtx x1 = XEXP (x, 1);
-
- /* Check the first level. */
- if (x0 == x1)
- return
- num_sign_bit_copies1 (x, mode, x0, mode,
- num_sign_bit_copies_with_known (x0, mode));
-
- /* Check the second level. */
- if ((GET_RTX_CLASS (GET_CODE (x0)) == '2'
- || GET_RTX_CLASS (GET_CODE (x0)) == 'c')
- && (x1 == XEXP (x0, 0) || x1 == XEXP (x0, 1)))
- return
- num_sign_bit_copies1 (x, mode, x1, mode,
- num_sign_bit_copies_with_known (x1, mode));
-
- if ((GET_RTX_CLASS (GET_CODE (x1)) == '2'
- || GET_RTX_CLASS (GET_CODE (x1)) == 'c')
- && (x0 == XEXP (x1, 0) || x0 == XEXP (x1, 1)))
- return
- num_sign_bit_copies1 (x, mode, x0, mode,
- num_sign_bit_copies_with_known (x0, mode));