aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Macleod <amacleod@gcc.gnu.org>2018-04-09 15:05:06 +0000
committerAndrew Macleod <amacleod@gcc.gnu.org>2018-04-09 15:05:06 +0000
commitd739eb8b490b481c9b75a12274f08afd695c8041 (patch)
tree27ae28242932ccb291ed28d5a24e3d266fc257c1
parent7681f3099930134fbc76a201bb6d38aa385302a8 (diff)
downloadgcc-d739eb8b490b481c9b75a12274f08afd695c8041.zip
gcc-d739eb8b490b481c9b75a12274f08afd695c8041.tar.gz
gcc-d739eb8b490b481c9b75a12274f08afd695c8041.tar.bz2
Implement intersect_mask to perform an intersection of a range with a bitmask.
From-SVN: r259236
-rw-r--r--gcc/range.c40
-rw-r--r--gcc/range.h2
2 files changed, 42 insertions, 0 deletions
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);