diff options
author | Jakub Jelinek <jakub@redhat.com> | 2014-12-17 09:29:12 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2014-12-17 09:29:12 +0000 |
commit | fb2b5c025a9f3a43a4e2f1c162fa58f3d84e52ff (patch) | |
tree | 1a8656d47d66e823737ac3e415884b56dda90702 | |
parent | 419b48903483ae5bdd1dd67103d5a7a3a0c24923 (diff) |
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.
* gcc.dg/tree-ssa/vrp95.c: New test.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@218812 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/vrp95.c | 50 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 10 |
4 files changed, 69 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index badd40e7c54..631d7268013 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9f6fd314747..fbafb565dac 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 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. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp95.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp95.c new file mode 100644 index 00000000000..be208bafd60 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp95.c @@ -0,0 +1,50 @@ +/* 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" } } */ diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index bd238d57700..c49c9424885 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -2434,6 +2434,7 @@ extract_range_from_binary_expr_1 (value_range_t *vr, && code != MAX_EXPR && code != PLUS_EXPR && code != MINUS_EXPR + && code != RSHIFT_EXPR && (vr0.type == VR_VARYING || vr1.type == VR_VARYING || vr0.type != vr1.type @@ -2948,6 +2949,15 @@ extract_range_from_binary_expr_1 (value_range_t *vr, { 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; } |