diff options
author | Andrew MacLeod <amacleod@redhat.com> | 2021-06-30 14:15:53 -0400 |
---|---|---|
committer | Andrew MacLeod <amacleod@redhat.com> | 2021-07-02 11:34:53 -0400 |
commit | 84f7bab89279ca1234fef88929c74caeda8cb55e (patch) | |
tree | 708a82e60c51b389b97afe85ae048da09d0ba3e3 /gcc | |
parent | 18d0fad77b580d1ac64ed04d94fd3c9795687b91 (diff) | |
download | gcc-84f7bab89279ca1234fef88929c74caeda8cb55e.zip gcc-84f7bab89279ca1234fef88929c74caeda8cb55e.tar.gz gcc-84f7bab89279ca1234fef88929c74caeda8cb55e.tar.bz2 |
Fix build_gt and build_lt for signed 1 bit values.
Signed 1 bit values have a range of [-1, 0] but neither (0 - 1) nor (-1 + 1)
can be represented. For signed values, add or subtract -1 as appropriate.
PR tree-optimization/101223
gcc/
* range-op.cc (build_lt): Add -1 for signed values.
(built_gt): Subtract -1 for signed values.
gcc/testsuite/
* gcc.dg/pr101223.c: New.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/range-op.cc | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr101223.c | 44 |
2 files changed, 60 insertions, 2 deletions
diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 97b9843..f8e4c6d 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -687,7 +687,14 @@ static void build_lt (irange &r, tree type, const wide_int &val) { wi::overflow_type ov; - wide_int lim = wi::sub (val, 1, TYPE_SIGN (type), &ov); + wide_int lim; + signop sgn = TYPE_SIGN (type); + + // Signed 1 bit cannot represent 1 for subtraction. + if (sgn == SIGNED) + lim = wi::add (val, -1, sgn, &ov); + else + lim = wi::sub (val, 1, sgn, &ov); // If val - 1 underflows, check if X < MIN, which is an empty range. if (ov) @@ -710,7 +717,14 @@ static void build_gt (irange &r, tree type, const wide_int &val) { wi::overflow_type ov; - wide_int lim = wi::add (val, 1, TYPE_SIGN (type), &ov); + wide_int lim; + signop sgn = TYPE_SIGN (type); + + // Signed 1 bit cannot represent 1 for addition. + if (sgn == SIGNED) + lim = wi::sub (val, -1, sgn, &ov); + else + lim = wi::add (val, 1, sgn, &ov); // If val + 1 overflows, check is for X > MAX, which is an empty range. if (ov) r.set_undefined (); diff --git a/gcc/testsuite/gcc.dg/pr101223.c b/gcc/testsuite/gcc.dg/pr101223.c new file mode 100644 index 0000000..6d5a247 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr101223.c @@ -0,0 +1,44 @@ +/* PR tree-optimization/101223 */ +/* { dg-do run } */ +/* { dg-options "-O2 " } */ + +struct { + int a : 1; +} b; +int c = 1, d; +int foo1() { + for (; d < 2; d++) { + int e = ~c, f = 0, g; + if (e) { + f = c; + g = b.a; + b.a = f; + if (b.a >= g) + __builtin_abort(); + } + c = f; + b.a = g; + } + return 0; +} + +int foo2() { + for (; d < 2; d++) { + int e = ~c, f = 0, g; + if (e) { + f = c; + g = b.a; + b.a = f; + if (g <= b.a) + __builtin_abort(); + } + c = f; + b.a = g; + } + return 0; +} +int main () +{ + return foo1() + foo2(); +} + |