Commit ac699a04 by Jakub Jelinek Committed by Jakub Jelinek

re PR tree-optimization/80558 (VRP not handling x & -2 well)

	PR tree-optimization/80558
	* tree-vrp.c (extract_range_from_binary_expr_1): Optimize
	[x, y] op z into [x op, y op z] for op & or | if conditions
	are met.

	* gcc.dg/tree-ssa/vrp115.c: New test.

From-SVN: r247641
parent 655b5fc8
2017-05-05 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/80558
* tree-vrp.c (extract_range_from_binary_expr_1): Optimize
[x, y] op z into [x op, y op z] for op & or | if conditions
are met.
2017-05-05 Andre Vieira <andre.simoesdiasvieira@arm.com> 2017-05-05 Andre Vieira <andre.simoesdiasvieira@arm.com>
Prakhar Bahuguna <prakhar.bahuguna@arm.com> Prakhar Bahuguna <prakhar.bahuguna@arm.com>
......
2017-05-05 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/80558
* gcc.dg/tree-ssa/vrp115.c: New test.
2017-05-05 Andre Vieira <andre.simoesdiasvieira@arm.com> 2017-05-05 Andre Vieira <andre.simoesdiasvieira@arm.com>
Thomas Preud'homme <thomas.preudhomme@arm.com> Thomas Preud'homme <thomas.preudhomme@arm.com>
Prakhar Bahuguna <prakhar.bahuguna@arm.com> Prakhar Bahuguna <prakhar.bahuguna@arm.com>
......
/* PR tree-optimization/80558 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-evrp" } */
/* { dg-final { scan-tree-dump-not "link_error" "evrp" } } */
void link_error (void);
void
f1 (int x)
{
if (x >= 5 && x <= 19)
{
x &= -2;
if (x < 4 || x > 18)
link_error ();
}
}
void
f2 (int x)
{
if (x >= 5 && x <= 19)
{
x |= 7;
if (x < 7 || x > 23)
link_error ();
}
}
void
f3 (int x)
{
if (x >= -18 && x <= 19)
{
x |= 7;
if (x < -17 || x > 23)
link_error ();
}
}
void
f4 (int x)
{
if (x >= 1603 && x <= 2015)
{
x &= 496;
if (x < 64 || x > 464)
link_error ();
}
}
...@@ -2865,8 +2865,59 @@ extract_range_from_binary_expr_1 (value_range *vr, ...@@ -2865,8 +2865,59 @@ extract_range_from_binary_expr_1 (value_range *vr,
&may_be_nonzero1, &may_be_nonzero1,
&must_be_nonzero1); &must_be_nonzero1);
if (code == BIT_AND_EXPR || code == BIT_IOR_EXPR)
{
value_range *vr0p = NULL, *vr1p = NULL;
if (range_int_cst_singleton_p (&vr1))
{
vr0p = &vr0;
vr1p = &vr1;
}
else if (range_int_cst_singleton_p (&vr0))
{
vr0p = &vr1;
vr1p = &vr0;
}
/* For op & or | attempt to optimize:
[x, y] op z into [x op z, y op z]
if z is a constant which (for op | its bitwise not) has n
consecutive least significant bits cleared followed by m 1
consecutive bits set immediately above it and either
m + n == precision, or (x >> (m + n)) == (y >> (m + n)).
The least significant n bits of all the values in the range are
cleared or set, the m bits above it are preserved and any bits
above these are required to be the same for all values in the
range. */
if (vr0p && range_int_cst_p (vr0p))
{
wide_int w = vr1p->min;
int m = 0, n = 0;
if (code == BIT_IOR_EXPR)
w = ~w;
if (wi::eq_p (w, 0))
n = TYPE_PRECISION (expr_type);
else
{
n = wi::ctz (w);
w = ~(w | wi::mask (n, false, w.get_precision ()));
if (wi::eq_p (w, 0))
m = TYPE_PRECISION (expr_type) - n;
else
m = wi::ctz (w) - n;
}
wide_int mask = wi::mask (m + n, true, w.get_precision ());
if (wi::eq_p (mask & vr0p->min, mask & vr0p->max))
{
min = int_const_binop (code, vr0p->min, vr1p->min);
max = int_const_binop (code, vr0p->max, vr1p->min);
}
}
}
type = VR_RANGE; type = VR_RANGE;
if (code == BIT_AND_EXPR) if (min && max)
/* Optimized above already. */;
else if (code == BIT_AND_EXPR)
{ {
min = wide_int_to_tree (expr_type, min = wide_int_to_tree (expr_type,
must_be_nonzero0 & must_be_nonzero1); must_be_nonzero0 & must_be_nonzero1);
......
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