diff options
author | Andrew MacLeod <amacleod@redhat.com> | 2020-10-09 10:46:50 +0200 |
---|---|---|
committer | Aldy Hernandez <aldyh@redhat.com> | 2020-10-09 10:57:51 +0200 |
commit | 1cde5d85bec20877bed063fc0046b9885231a0ae (patch) | |
tree | b9c68e4d5a6df39394df2f5df72b1da31fad180f | |
parent | a0e6e49ddedb05e2e112e5c19a2228efd016e871 (diff) | |
download | gcc-1cde5d85bec20877bed063fc0046b9885231a0ae.zip gcc-1cde5d85bec20877bed063fc0046b9885231a0ae.tar.gz gcc-1cde5d85bec20877bed063fc0046b9885231a0ae.tar.bz2 |
Fix for PR97317.
gcc/ChangeLog:
PR tree-optimization/97317
* range-op.cc (operator_cast::op1_range): Handle casts where the precision
of the RHS is only 1 greater than the precision of the LHS.
gcc/testsuite/ChangeLog:
* gcc.dg/pr97317.c: New test.
-rw-r--r-- | gcc/range-op.cc | 25 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr97317.c | 11 |
2 files changed, 29 insertions, 7 deletions
diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 22bc23c..d1a11b3 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -1849,14 +1849,25 @@ operator_cast::op1_range (irange &r, tree type, type, converted_lhs, lim_range); - // And union this with the entire outer types negative range. - int_range_max neg (type, - wi::min_value (TYPE_PRECISION (type), - SIGNED), - lim - 1); - neg.union_ (lhs_neg); + // lhs_neg now has all the negative versions of the LHS. + // Now union in all the values from SIGNED MIN (0x80000) to + // lim-1 in order to fill in all the ranges with the upper + // bits set. + + // PR 97317. If the lhs has only 1 bit less precision than the rhs, + // we don't need to create a range from min to lim-1 + // calculate neg range traps trying to create [lim, lim - 1]. + wide_int min_val = wi::min_value (TYPE_PRECISION (type), SIGNED); + if (lim != min_val) + { + int_range_max neg (type, + wi::min_value (TYPE_PRECISION (type), + SIGNED), + lim - 1); + lhs_neg.union_ (neg); + } // And finally, munge the signed and unsigned portions. - r.union_ (neg); + r.union_ (lhs_neg); } // And intersect with any known value passed in the extra operand. r.intersect (op2); diff --git a/gcc/testsuite/gcc.dg/pr97317.c b/gcc/testsuite/gcc.dg/pr97317.c new file mode 100644 index 0000000..f07327a --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97317.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +struct a { + unsigned c : 17; +}; +struct a b; +int d(void) { + short e = b.c; + return e ? 0 : b.c; +} |