[48/77] Make subroutines of num_sign_bit_copies operate on scalar_int_mode
Similarly to the nonzero_bits patch, this one moves the mode class check and VOIDmode handling from num_sign_bit_copies1 to num_sign_bit_copies itself, then changes the subroutines to operate on scalar_int_modes. 2017-08-30 Richard Sandiford <richard.sandiford@linaro.org> Alan Hayward <alan.hayward@arm.com> David Sherwood <david.sherwood@arm.com> gcc/ * rtlanal.c (num_sign_bit_copies): Handle VOIDmode here rather than in subroutines. Return 1 for non-integer modes. (cached_num_sign_bit_copies): Change the type of the mode parameter to scalar_int_mode. (num_sign_bit_copies1): Likewise. Remove early exit for other mode classes. Handle CONST_INT_P first and then check whether X also has a scalar integer mode. Check the same thing for inner registers of a SUBREG and for values that are being extended or truncated. Co-Authored-By: Alan Hayward <alan.hayward@arm.com> Co-Authored-By: David Sherwood <david.sherwood@arm.com> From-SVN: r251500
This commit is contained in:
parent
22527b59db
commit
f8265fb8e8
@ -1,3 +1,16 @@
|
||||
2017-08-30 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
Alan Hayward <alan.hayward@arm.com>
|
||||
David Sherwood <david.sherwood@arm.com>
|
||||
|
||||
* rtlanal.c (num_sign_bit_copies): Handle VOIDmode here rather
|
||||
than in subroutines. Return 1 for non-integer modes.
|
||||
(cached_num_sign_bit_copies): Change the type of the mode parameter
|
||||
to scalar_int_mode.
|
||||
(num_sign_bit_copies1): Likewise. Remove early exit for other mode
|
||||
classes. Handle CONST_INT_P first and then check whether X also
|
||||
has a scalar integer mode. Check the same thing for inner registers
|
||||
of a SUBREG and for values that are being extended or truncated.
|
||||
|
||||
2017-08-30 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
Alan Hayward <alan.hayward@arm.com>
|
||||
David Sherwood <david.sherwood@arm.com>
|
||||
|
167
gcc/rtlanal.c
167
gcc/rtlanal.c
@ -49,11 +49,12 @@ static unsigned HOST_WIDE_INT cached_nonzero_bits (const_rtx, scalar_int_mode,
|
||||
static unsigned HOST_WIDE_INT nonzero_bits1 (const_rtx, scalar_int_mode,
|
||||
const_rtx, machine_mode,
|
||||
unsigned HOST_WIDE_INT);
|
||||
static unsigned int cached_num_sign_bit_copies (const_rtx, machine_mode, const_rtx,
|
||||
machine_mode,
|
||||
static unsigned int cached_num_sign_bit_copies (const_rtx, scalar_int_mode,
|
||||
const_rtx, machine_mode,
|
||||
unsigned int);
|
||||
static unsigned int num_sign_bit_copies1 (const_rtx, machine_mode, const_rtx,
|
||||
machine_mode, unsigned int);
|
||||
static unsigned int num_sign_bit_copies1 (const_rtx, scalar_int_mode,
|
||||
const_rtx, machine_mode,
|
||||
unsigned int);
|
||||
|
||||
rtx_subrtx_bound_info rtx_all_subrtx_bounds[NUM_RTX_CODE];
|
||||
rtx_subrtx_bound_info rtx_nonconst_subrtx_bounds[NUM_RTX_CODE];
|
||||
@ -4248,7 +4249,12 @@ nonzero_bits (const_rtx x, machine_mode mode)
|
||||
unsigned int
|
||||
num_sign_bit_copies (const_rtx x, machine_mode mode)
|
||||
{
|
||||
return cached_num_sign_bit_copies (x, mode, NULL_RTX, VOIDmode, 0);
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (x);
|
||||
scalar_int_mode int_mode;
|
||||
if (!is_a <scalar_int_mode> (mode, &int_mode))
|
||||
return 1;
|
||||
return cached_num_sign_bit_copies (x, int_mode, NULL_RTX, VOIDmode, 0);
|
||||
}
|
||||
|
||||
/* Return true if nonzero_bits1 might recurse into both operands
|
||||
@ -4815,8 +4821,8 @@ num_sign_bit_copies_binary_arith_p (const_rtx x)
|
||||
first or the second level. */
|
||||
|
||||
static unsigned int
|
||||
cached_num_sign_bit_copies (const_rtx x, machine_mode mode, const_rtx known_x,
|
||||
machine_mode known_mode,
|
||||
cached_num_sign_bit_copies (const_rtx x, scalar_int_mode mode,
|
||||
const_rtx known_x, machine_mode known_mode,
|
||||
unsigned int known_ret)
|
||||
{
|
||||
if (x == known_x && mode == known_mode)
|
||||
@ -4861,44 +4867,46 @@ cached_num_sign_bit_copies (const_rtx x, machine_mode mode, const_rtx known_x,
|
||||
}
|
||||
|
||||
/* Return the number of bits at the high-order end of X that are known to
|
||||
be equal to the sign bit. X will be used in mode MODE; if MODE is
|
||||
VOIDmode, X will be used in its own mode. The returned value will always
|
||||
be between 1 and the number of bits in MODE. */
|
||||
be equal to the sign bit. X will be used in mode MODE. The returned
|
||||
value will always be between 1 and the number of bits in MODE. */
|
||||
|
||||
static unsigned int
|
||||
num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
|
||||
num_sign_bit_copies1 (const_rtx x, scalar_int_mode mode, const_rtx known_x,
|
||||
machine_mode known_mode,
|
||||
unsigned int known_ret)
|
||||
{
|
||||
enum rtx_code code = GET_CODE (x);
|
||||
machine_mode inner_mode;
|
||||
unsigned int bitwidth = GET_MODE_PRECISION (mode);
|
||||
int num0, num1, result;
|
||||
unsigned HOST_WIDE_INT nonzero;
|
||||
|
||||
/* If we weren't given a mode, use the mode of X. If the mode is still
|
||||
VOIDmode, we don't know anything. Likewise if one of the modes is
|
||||
floating-point. */
|
||||
|
||||
if (mode == VOIDmode)
|
||||
mode = GET_MODE (x);
|
||||
|
||||
gcc_checking_assert (mode != BLKmode);
|
||||
|
||||
if (mode == VOIDmode || FLOAT_MODE_P (mode) || FLOAT_MODE_P (GET_MODE (x))
|
||||
|| VECTOR_MODE_P (GET_MODE (x)) || VECTOR_MODE_P (mode))
|
||||
return 1;
|
||||
|
||||
/* For a smaller mode, just ignore the high bits. */
|
||||
unsigned int bitwidth = GET_MODE_PRECISION (mode);
|
||||
if (bitwidth < GET_MODE_PRECISION (GET_MODE (x)))
|
||||
if (CONST_INT_P (x))
|
||||
{
|
||||
num0 = cached_num_sign_bit_copies (x, GET_MODE (x),
|
||||
known_x, known_mode, known_ret);
|
||||
return MAX (1,
|
||||
num0 - (int) (GET_MODE_PRECISION (GET_MODE (x)) - bitwidth));
|
||||
/* If the constant is negative, take its 1's complement and remask.
|
||||
Then see how many zero bits we have. */
|
||||
nonzero = UINTVAL (x) & GET_MODE_MASK (mode);
|
||||
if (bitwidth <= HOST_BITS_PER_WIDE_INT
|
||||
&& (nonzero & (HOST_WIDE_INT_1U << (bitwidth - 1))) != 0)
|
||||
nonzero = (~nonzero) & GET_MODE_MASK (mode);
|
||||
|
||||
return (nonzero == 0 ? bitwidth : bitwidth - floor_log2 (nonzero) - 1);
|
||||
}
|
||||
|
||||
if (GET_MODE (x) != VOIDmode && bitwidth > GET_MODE_PRECISION (GET_MODE (x)))
|
||||
scalar_int_mode xmode, inner_mode;
|
||||
if (!is_a <scalar_int_mode> (GET_MODE (x), &xmode))
|
||||
return 1;
|
||||
|
||||
unsigned int xmode_width = GET_MODE_PRECISION (xmode);
|
||||
|
||||
/* For a smaller mode, just ignore the high bits. */
|
||||
if (bitwidth < xmode_width)
|
||||
{
|
||||
num0 = cached_num_sign_bit_copies (x, xmode,
|
||||
known_x, known_mode, known_ret);
|
||||
return MAX (1, num0 - (int) (xmode_width - bitwidth));
|
||||
}
|
||||
|
||||
if (bitwidth > xmode_width)
|
||||
{
|
||||
/* If this machine does not do all register operations on the entire
|
||||
register and MODE is wider than the mode of X, we can say nothing
|
||||
@ -4909,8 +4917,8 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
|
||||
/* Likewise on machines that do, if the mode of the object is smaller
|
||||
than a word and loads of that size don't sign extend, we can say
|
||||
nothing about the high order bits. */
|
||||
if (GET_MODE_PRECISION (GET_MODE (x)) < BITS_PER_WORD
|
||||
&& load_extend_op (GET_MODE (x)) != SIGN_EXTEND)
|
||||
if (xmode_width < BITS_PER_WORD
|
||||
&& load_extend_op (xmode) != SIGN_EXTEND)
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -4927,7 +4935,7 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
|
||||
we can do this only if the target does not support different pointer
|
||||
or address modes depending on the address space. */
|
||||
if (target_default_pointer_address_modes_p ()
|
||||
&& ! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
|
||||
&& ! POINTERS_EXTEND_UNSIGNED && xmode == Pmode
|
||||
&& mode == Pmode && REG_POINTER (x)
|
||||
&& !targetm.have_ptr_extend ())
|
||||
return GET_MODE_PRECISION (Pmode) - GET_MODE_PRECISION (ptr_mode) + 1;
|
||||
@ -4952,21 +4960,10 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
|
||||
|
||||
case MEM:
|
||||
/* Some RISC machines sign-extend all loads of smaller than a word. */
|
||||
if (load_extend_op (GET_MODE (x)) == SIGN_EXTEND)
|
||||
return MAX (1, ((int) bitwidth
|
||||
- (int) GET_MODE_PRECISION (GET_MODE (x)) + 1));
|
||||
if (load_extend_op (xmode) == SIGN_EXTEND)
|
||||
return MAX (1, ((int) bitwidth - (int) xmode_width + 1));
|
||||
break;
|
||||
|
||||
case CONST_INT:
|
||||
/* If the constant is negative, take its 1's complement and remask.
|
||||
Then see how many zero bits we have. */
|
||||
nonzero = UINTVAL (x) & GET_MODE_MASK (mode);
|
||||
if (bitwidth <= HOST_BITS_PER_WIDE_INT
|
||||
&& (nonzero & (HOST_WIDE_INT_1U << (bitwidth - 1))) != 0)
|
||||
nonzero = (~nonzero) & GET_MODE_MASK (mode);
|
||||
|
||||
return (nonzero == 0 ? bitwidth : bitwidth - floor_log2 (nonzero) - 1);
|
||||
|
||||
case SUBREG:
|
||||
/* If this is a SUBREG for a promoted object that is sign-extended
|
||||
and we are looking at it in a wider mode, we know that at least the
|
||||
@ -4976,37 +4973,38 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
|
||||
{
|
||||
num0 = cached_num_sign_bit_copies (SUBREG_REG (x), mode,
|
||||
known_x, known_mode, known_ret);
|
||||
return MAX ((int) bitwidth
|
||||
- (int) GET_MODE_PRECISION (GET_MODE (x)) + 1,
|
||||
num0);
|
||||
return MAX ((int) bitwidth - (int) xmode_width + 1, num0);
|
||||
}
|
||||
|
||||
/* For a smaller object, just ignore the high bits. */
|
||||
inner_mode = GET_MODE (SUBREG_REG (x));
|
||||
if (bitwidth <= GET_MODE_PRECISION (inner_mode))
|
||||
if (is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (x)), &inner_mode))
|
||||
{
|
||||
num0 = cached_num_sign_bit_copies (SUBREG_REG (x), VOIDmode,
|
||||
known_x, known_mode, known_ret);
|
||||
return
|
||||
MAX (1, num0 - (int) (GET_MODE_PRECISION (inner_mode) - bitwidth));
|
||||
/* For a smaller object, just ignore the high bits. */
|
||||
if (bitwidth <= GET_MODE_PRECISION (inner_mode))
|
||||
{
|
||||
num0 = cached_num_sign_bit_copies (SUBREG_REG (x), inner_mode,
|
||||
known_x, known_mode,
|
||||
known_ret);
|
||||
return MAX (1, num0 - (int) (GET_MODE_PRECISION (inner_mode)
|
||||
- bitwidth));
|
||||
}
|
||||
|
||||
/* For paradoxical SUBREGs on machines where all register operations
|
||||
affect the entire register, just look inside. Note that we are
|
||||
passing MODE to the recursive call, so the number of sign bit
|
||||
copies will remain relative to that mode, not the inner mode. */
|
||||
|
||||
/* This works only if loads sign extend. Otherwise, if we get a
|
||||
reload for the inner part, it may be loaded from the stack, and
|
||||
then we lose all sign bit copies that existed before the store
|
||||
to the stack. */
|
||||
|
||||
if (WORD_REGISTER_OPERATIONS
|
||||
&& load_extend_op (inner_mode) == SIGN_EXTEND
|
||||
&& paradoxical_subreg_p (x)
|
||||
&& (MEM_P (SUBREG_REG (x)) || REG_P (SUBREG_REG (x))))
|
||||
return cached_num_sign_bit_copies (SUBREG_REG (x), mode,
|
||||
known_x, known_mode, known_ret);
|
||||
}
|
||||
|
||||
/* For paradoxical SUBREGs on machines where all register operations
|
||||
affect the entire register, just look inside. Note that we are
|
||||
passing MODE to the recursive call, so the number of sign bit copies
|
||||
will remain relative to that mode, not the inner mode. */
|
||||
|
||||
/* This works only if loads sign extend. Otherwise, if we get a
|
||||
reload for the inner part, it may be loaded from the stack, and
|
||||
then we lose all sign bit copies that existed before the store
|
||||
to the stack. */
|
||||
|
||||
if (WORD_REGISTER_OPERATIONS
|
||||
&& load_extend_op (inner_mode) == SIGN_EXTEND
|
||||
&& paradoxical_subreg_p (x)
|
||||
&& (MEM_P (SUBREG_REG (x)) || REG_P (SUBREG_REG (x))))
|
||||
return cached_num_sign_bit_copies (SUBREG_REG (x), mode,
|
||||
known_x, known_mode, known_ret);
|
||||
break;
|
||||
|
||||
case SIGN_EXTRACT:
|
||||
@ -5015,15 +5013,18 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
|
||||
break;
|
||||
|
||||
case SIGN_EXTEND:
|
||||
return (bitwidth - GET_MODE_PRECISION (GET_MODE (XEXP (x, 0)))
|
||||
+ cached_num_sign_bit_copies (XEXP (x, 0), VOIDmode,
|
||||
known_x, known_mode, known_ret));
|
||||
if (is_a <scalar_int_mode> (GET_MODE (XEXP (x, 0)), &inner_mode))
|
||||
return (bitwidth - GET_MODE_PRECISION (inner_mode)
|
||||
+ cached_num_sign_bit_copies (XEXP (x, 0), inner_mode,
|
||||
known_x, known_mode, known_ret));
|
||||
break;
|
||||
|
||||
case TRUNCATE:
|
||||
/* For a smaller object, just ignore the high bits. */
|
||||
num0 = cached_num_sign_bit_copies (XEXP (x, 0), VOIDmode,
|
||||
inner_mode = as_a <scalar_int_mode> (GET_MODE (XEXP (x, 0)));
|
||||
num0 = cached_num_sign_bit_copies (XEXP (x, 0), inner_mode,
|
||||
known_x, known_mode, known_ret);
|
||||
return MAX (1, (num0 - (int) (GET_MODE_PRECISION (GET_MODE (XEXP (x, 0)))
|
||||
return MAX (1, (num0 - (int) (GET_MODE_PRECISION (inner_mode)
|
||||
- bitwidth)));
|
||||
|
||||
case NOT:
|
||||
@ -5200,7 +5201,7 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
|
||||
known_x, known_mode, known_ret);
|
||||
if (CONST_INT_P (XEXP (x, 1))
|
||||
&& INTVAL (XEXP (x, 1)) > 0
|
||||
&& INTVAL (XEXP (x, 1)) < GET_MODE_PRECISION (GET_MODE (x)))
|
||||
&& INTVAL (XEXP (x, 1)) < xmode_width)
|
||||
num0 = MIN ((int) bitwidth, num0 + INTVAL (XEXP (x, 1)));
|
||||
|
||||
return num0;
|
||||
@ -5210,7 +5211,7 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
|
||||
if (!CONST_INT_P (XEXP (x, 1))
|
||||
|| INTVAL (XEXP (x, 1)) < 0
|
||||
|| INTVAL (XEXP (x, 1)) >= (int) bitwidth
|
||||
|| INTVAL (XEXP (x, 1)) >= GET_MODE_PRECISION (GET_MODE (x)))
|
||||
|| INTVAL (XEXP (x, 1)) >= xmode_width)
|
||||
return 1;
|
||||
|
||||
num0 = cached_num_sign_bit_copies (XEXP (x, 0), mode,
|
||||
|
Loading…
x
Reference in New Issue
Block a user