From 2118438f49f0c193abe3fa3def350a8129045746 Mon Sep 17 00:00:00 2001 From: Aldy Hernandez Date: Mon, 26 Oct 2020 17:50:37 +0100 Subject: Handle signed 1-bit ranges in irange::invert. The problem here is we are trying to add 1 to a -1 in a signed 1-bit field and coming up with UNDEFINED because of the overflow. Signed 1-bits are annoying because you can't really add or subtract one, because the one is unrepresentable. For invert() we have a special subtract_one() function that handles 1-bit signed fields. This patch implements the analogous add_one() function so that invert works. gcc/ChangeLog: PR tree-optimization/97555 * range-op.cc (range_tests): Test 1-bit signed invert. * value-range.cc (subtract_one): Adjust comment. (add_one): New. (irange::invert): Call add_one. gcc/testsuite/ChangeLog: * gcc.dg/pr97555.c: New test. --- gcc/value-range.cc | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'gcc/value-range.cc') diff --git a/gcc/value-range.cc b/gcc/value-range.cc index 7847104..0e633c1 100644 --- a/gcc/value-range.cc +++ b/gcc/value-range.cc @@ -1772,19 +1772,30 @@ irange::irange_intersect (const irange &r) verify_range (); } +// Signed 1-bits are strange. You can't subtract 1, because you can't +// represent the number 1. This works around that for the invert routine. + static wide_int inline subtract_one (const wide_int &x, tree type, wi::overflow_type &overflow) { - // A signed 1-bit bit-field, has a range of [-1,0] so subtracting +1 - // overflows, since +1 is unrepresentable. This is why we have an - // addition of -1 here. if (TYPE_SIGN (type) == SIGNED) - return wi::add (x, -1 , SIGNED, &overflow); + return wi::add (x, -1, SIGNED, &overflow); else return wi::sub (x, 1, UNSIGNED, &overflow); } -/* Return the inverse of a range. */ +// The analogous function for adding 1. + +static wide_int inline +add_one (const wide_int &x, tree type, wi::overflow_type &overflow) +{ + if (TYPE_SIGN (type) == SIGNED) + return wi::sub (x, -1, SIGNED, &overflow); + else + return wi::add (x, 1, UNSIGNED, &overflow); +} + +// Return the inverse of a range. void irange::invert () @@ -1881,7 +1892,7 @@ irange::invert () // set the overflow bit. if (type_max != wi::to_wide (orig_range.m_base[i])) { - tmp = wi::add (wi::to_wide (orig_range.m_base[i]), 1, sign, &ovf); + tmp = add_one (wi::to_wide (orig_range.m_base[i]), ttype, ovf); m_base[nitems++] = wide_int_to_tree (ttype, tmp); m_base[nitems++] = wide_int_to_tree (ttype, type_max); if (ovf) -- cgit v1.1