+2014-12-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/64322
+ * tree-vrp.c (extract_range_from_binary_expr_1): Attempt to derive
+ range for RSHIFT_EXPR even if vr0 range is not VR_RANGE or is symbolic.
+
2014-12-17 Tobias Burnus <burnus@net-b.de>
PR fortran/54687
2014-12-17 Jakub Jelinek <jakub@redhat.com>
+ PR tree-optimization/64322
+ * gcc.dg/tree-ssa/vrp95.c: New test.
+
PR sanitizer/64289
* c-c++-common/ubsan/pr64289.c: New test.
--- /dev/null
+/* PR tree-optimization/64322 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+
+extern void link_error ();
+extern void required_check ();
+
+long long int
+foo (long long int x)
+{
+ x >>= sizeof (long long int) * __CHAR_BIT__ - 1;
+ if (x != 0 && x != -1)
+ link_error ();
+ return x;
+}
+
+unsigned long long int
+bar (unsigned long long int x)
+{
+ x >>= sizeof (long long int) * __CHAR_BIT__ - 1;
+ if (x != 0 && x != 1)
+ link_error ();
+ return x;
+}
+
+long long int
+baz (long long int x)
+{
+ x = (x >> sizeof (long long int) * __CHAR_BIT__ - 1) << 1;
+ x = x / 0x100000000LL;
+ if (x != 0)
+ link_error ();
+ return x;
+}
+
+unsigned long long int
+range (unsigned long long int x, int y)
+{
+ y &= 3;
+ x >>= sizeof (long long int) * __CHAR_BIT__ - 1 - y;
+ if (x > 15)
+ link_error ();
+ if (x == 15)
+ required_check ();
+ return x;
+}
+
+/* { dg-final { scan-tree-dump-not "link_error" "vrp1" } } */
+/* { dg-final { scan-tree-dump "required_check" "vrp1" } } */
+/* { dg-final { cleanup-tree-dump "vrp1" } } */
&& code != MAX_EXPR
&& code != PLUS_EXPR
&& code != MINUS_EXPR
+ && code != RSHIFT_EXPR
&& (vr0.type == VR_VARYING
|| vr1.type == VR_VARYING
|| vr0.type != vr1.type
{
if (code == RSHIFT_EXPR)
{
+ /* Even if vr0 is VARYING or otherwise not usable, we can derive
+ useful ranges just from the shift count. E.g.
+ x >> 63 for signed 64-bit x is always [-1, 0]. */
+ if (vr0.type != VR_RANGE || symbolic_range_p (&vr0))
+ {
+ vr0.type = type = VR_RANGE;
+ vr0.min = vrp_val_min (expr_type);
+ vr0.max = vrp_val_max (expr_type);
+ }
extract_range_from_multiplicative_op_1 (vr, code, &vr0, &vr1);
return;
}