From d739eb8b490b481c9b75a12274f08afd695c8041 Mon Sep 17 00:00:00 2001 From: Andrew Macleod Date: Mon, 9 Apr 2018 15:05:06 +0000 Subject: Implement intersect_mask to perform an intersection of a range with a bitmask. From-SVN: r259236 --- gcc/range.c | 40 ++++++++++++++++++++++++++++++++++++++++ gcc/range.h | 2 ++ 2 files changed, 42 insertions(+) diff --git a/gcc/range.c b/gcc/range.c index 9e7c86b3..186ecff 100644 --- a/gcc/range.c +++ b/gcc/range.c @@ -681,6 +681,46 @@ irange::union_ (const irange &r) return *this; } +// Intersect this range with a bitmask MASK. +// Based on the bits in the mask, each lower bound is rounded up and each +// upper bounds is rounded down. +void +irange::intersect_mask (const wide_int& mask) +{ + signop sign = TYPE_SIGN (type); + unsigned pos = 0; + + // Remove zero from the current range. + // + // seems to be a bug., I can't specify: + // + // irange nz (type, 0, 0, INVERSE); + irange nz (type, 0 ,0); + nz.invert (); + + intersect (nz); + + for (unsigned i = 0; i < nitems; i += 2) + { + wide_int ub = wi::round_down_for_mask (bounds[i + 1], mask); + // Have to check for ub > lb immediately due to signed values + // potentially wrapping. skip if not a valid range. + if (wi::gt_p (bounds[i], ub, sign)) + continue; + wide_int lb = wi::round_up_for_mask (bounds[i], mask); + + // If this is not a valid range, skip it + if (wi::gt_p (lb, ub, sign)) + continue; + bounds[pos++] = lb; + bounds[pos++] = ub ; + } + nitems = pos; + + // 0 is always a possible result, even if it wasn't in the original range. + union_ (irange (type, 0 , 0)); +} + // THIS = THIS ^ [X,Y]. irange & diff --git a/gcc/range.h b/gcc/range.h index 762f949..125a803 100644 --- a/gcc/range.h +++ b/gcc/range.h @@ -142,6 +142,8 @@ class irange const_tree get_type () const { return type; } + void intersect_mask (const wide_int& mask); + irange& operator= (const irange &r); irange& operator= (const_tree t); -- cgit v1.1