Commit f917ae96 by Eric Botcazou Committed by Eric Botcazou

re PR rtl-optimization/19296 (Range check on short miscompiled at -O)

	PR rtl-optimization/19296
	* combine.c (simplify_comparison): Rewrite the condition under
	which a non-paradoxical SUBREG of a PLUS can be lifted when
	compared against a constant.

From-SVN: r93818
parent 06da3c24
2005-01-18 Eric Botcazou <ebotcazou@libertysurf.fr>
PR rtl-optimization/19296
* combine.c (simplify_comparison): Rewrite the condition under
which a non-paradoxical SUBREG of a PLUS can be lifted when
compared against a constant.
2005-01-18 Andi Kleen <ak@muc.de>
* c-typeck.c: (convert_for_assignment): Check warn_pointer_sign.
......
......@@ -10041,34 +10041,61 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
break;
case SUBREG:
/* Check for the case where we are comparing A - C1 with C2,
both constants are smaller than 1/2 the maximum positive
value in MODE, and the comparison is equality or unsigned.
In that case, if A is either zero-extended to MODE or has
sufficient sign bits so that the high-order bit in MODE
is a copy of the sign in the inner mode, we can prove that it is
safe to do the operation in the wider mode. This simplifies
many range checks. */
/* Check for the case where we are comparing A - C1 with C2, that is
(subreg:MODE (plus (A) (-C1))) op (C2)
with C1 a constant, and try to lift the SUBREG, i.e. to do the
comparison in the wider mode. One of the following two conditions
must be true in order for this to be valid:
1. The mode extension results in the same bit pattern being added
on both sides and the comparison is equality or unsigned. As
C2 has been truncated to fit in MODE, the pattern can only be
all 0s or all 1s.
2. The mode extension results in the sign bit being copied on
each side.
The difficulty here is that we have predicates for A but not for
(A - C1) so we need to check that C1 is within proper bounds so
as to perturbate A as little as possible. */
if (mode_width <= HOST_BITS_PER_WIDE_INT
&& subreg_lowpart_p (op0)
&& GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0))) > mode_width
&& GET_CODE (SUBREG_REG (op0)) == PLUS
&& GET_CODE (XEXP (SUBREG_REG (op0), 1)) == CONST_INT
&& INTVAL (XEXP (SUBREG_REG (op0), 1)) < 0
&& (-INTVAL (XEXP (SUBREG_REG (op0), 1))
< (HOST_WIDE_INT) (GET_MODE_MASK (mode) / 2))
&& (unsigned HOST_WIDE_INT) const_op < GET_MODE_MASK (mode) / 2
&& (0 == (nonzero_bits (XEXP (SUBREG_REG (op0), 0),
GET_MODE (SUBREG_REG (op0)))
& ~GET_MODE_MASK (mode))
|| (num_sign_bit_copies (XEXP (SUBREG_REG (op0), 0),
GET_MODE (SUBREG_REG (op0)))
> (unsigned int)
(GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
- GET_MODE_BITSIZE (mode)))))
{
op0 = SUBREG_REG (op0);
continue;
&& GET_CODE (XEXP (SUBREG_REG (op0), 1)) == CONST_INT)
{
enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
rtx a = XEXP (SUBREG_REG (op0), 0);
HOST_WIDE_INT c1 = -INTVAL (XEXP (SUBREG_REG (op0), 1));
if ((c1 > 0
&& (unsigned HOST_WIDE_INT) c1
< (unsigned HOST_WIDE_INT) 1 << (mode_width - 1)
&& (equality_comparison_p || unsigned_comparison_p)
/* (A - C1) zero-extends if it is positive and sign-extends
if it is negative, C2 both zero- and sign-extends. */
&& ((0 == (nonzero_bits (a, inner_mode)
& ~GET_MODE_MASK (mode))
&& const_op >= 0)
/* (A - C1) sign-extends if it is positive and 1-extends
if it is negative, C2 both sign- and 1-extends. */
|| (num_sign_bit_copies (a, inner_mode)
> (unsigned int) (GET_MODE_BITSIZE (inner_mode)
- mode_width)
&& const_op < 0)))
|| ((unsigned HOST_WIDE_INT) c1
< (unsigned HOST_WIDE_INT) 1 << (mode_width - 2)
/* (A - C1) always sign-extends, like C2. */
&& num_sign_bit_copies (a, inner_mode)
> (unsigned int) (GET_MODE_BITSIZE (inner_mode)
- mode_width - 1)))
{
op0 = SUBREG_REG (op0);
continue;
}
}
/* If the inner mode is narrower and we are extracting the low part,
......
2005-01-18 Eric Botcazou <ebotcazou@libertysurf.fr>
* gcc.dg/short-compare-1.c: New test.
* gcc.dg/short-compare-2.c: Likewise.
2005-01-18 Michael Matz <matz@suse.de>
* gcc.dg/Wno-pointer-sign.c: New test for -Wno-pointer-sign.
......
/* PR rtl-optimization/19296 */
/* Origin: Falk Hueffner <falk@debian.org> */
/* { dg-do run } */
/* { dg-options "-O" } */
/* { dg-options "-O -mtune=i686" { target i?86-*-* } } */
/* { dg-options "-O -m32 -mtune=i686" { target x86_64-*-* } } */
extern void abort(void);
void f(unsigned short ad)
{
if (ad >= 0x4000 && ad < 0xc000)
abort();
}
int main(void)
{
f(0xff00);
return 0;
}
/* PR rtl-optimization/19296 */
/* Origin: Falk Hueffner <falk@debian.org> */
/* Testcase by Andrew Pinski <pinskia@gcc.gnu.org> */
/* { dg-do run } */
/* { dg-options "-O" } */
/* { dg-options "-O -mtune=i686" { target i?86-*-* } } */
/* { dg-options "-O -m32 -mtune=i686" { target x86_64-*-* } } */
extern void abort();
void f(unsigned short ad)
{
if ((short) (ad - 0x4000) >= 0)
abort();
}
int main(void)
{
f(0xc000);
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment