/* Support routines for value ranges.
   Copyright (C) 2019-2023 Free Software Foundation, Inc.
   Major hacks by Aldy Hernandez <aldyh@redhat.com> and
   Andrew MacLeod <amacleod@redhat.com>.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.

GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "gimple.h"
#include "ssa.h"
#include "tree-pretty-print.h"
#include "value-range-pretty-print.h"
#include "fold-const.h"
#include "gimple-range.h"

void
irange::accept (const vrange_visitor &v) const
{
  v.visit (*this);
}

void
unsupported_range::accept (const vrange_visitor &v) const
{
  v.visit (*this);
}

// Convenience function only available for integers and pointers.

wide_int
Value_Range::lower_bound () const
{
  if (is_a <irange> (*m_vrange))
    return as_a <irange> (*m_vrange).lower_bound ();
  gcc_unreachable ();
}

// Convenience function only available for integers and pointers.

wide_int
Value_Range::upper_bound () const
{
  if (is_a <irange> (*m_vrange))
    return as_a <irange> (*m_vrange).upper_bound ();
  gcc_unreachable ();
}

void
Value_Range::dump (FILE *out) const
{
  if (m_vrange)
    m_vrange->dump (out);
  else
    fprintf (out, "NULL");
}

DEBUG_FUNCTION void
debug (const Value_Range &r)
{
  r.dump (stderr);
  fprintf (stderr, "\n");
}

DEBUG_FUNCTION void
debug (const irange_bitmask &bm)
{
  bm.dump (stderr);
  fprintf (stderr, "\n");
}

// Default vrange definitions.

bool
vrange::contains_p (tree) const
{
  return varying_p ();
}

bool
vrange::singleton_p (tree *) const
{
  return false;
}

void
vrange::set (tree min, tree, value_range_kind)
{
  set_varying (TREE_TYPE (min));
}

tree
vrange::type () const
{
  return void_type_node;
}

bool
vrange::supports_type_p (const_tree) const
{
  return false;
}

void
vrange::set_undefined ()
{
  m_kind = VR_UNDEFINED;
}

void
vrange::set_varying (tree)
{
  m_kind = VR_VARYING;
}

bool
vrange::union_ (const vrange &r)
{
  if (r.undefined_p () || varying_p ())
    return false;
  if (undefined_p () || r.varying_p ())
    {
      operator= (r);
      return true;
    }
  gcc_unreachable ();
  return false;
}

bool
vrange::intersect (const vrange &r)
{
  if (undefined_p () || r.varying_p ())
    return false;
  if (r.undefined_p ())
    {
      set_undefined ();
      return true;
    }
  if (varying_p ())
    {
      operator= (r);
      return true;
    }
  gcc_unreachable ();
  return false;
}

bool
vrange::zero_p () const
{
  return false;
}

bool
vrange::nonzero_p () const
{
  return false;
}

void
vrange::set_nonzero (tree type)
{
  set_varying (type);
}

void
vrange::set_zero (tree type)
{
  set_varying (type);
}

void
vrange::set_nonnegative (tree type)
{
  set_varying (type);
}

bool
vrange::fits_p (const vrange &) const
{
  return true;
}

// Assignment operator for generic ranges.  Copying incompatible types
// is not allowed.

vrange &
vrange::operator= (const vrange &src)
{
  if (is_a <irange> (src))
    as_a <irange> (*this) = as_a <irange> (src);
  else if (is_a <frange> (src))
    as_a <frange> (*this) = as_a <frange> (src);
  else
    {
      gcc_checking_assert (is_a <unsupported_range> (src));
      m_kind = src.m_kind;
    }
  return *this;
}

// Equality operator for generic ranges.

bool
vrange::operator== (const vrange &src) const
{
  if (is_a <irange> (src))
    return as_a <irange> (*this) == as_a <irange> (src);
  if (is_a <frange> (src))
    return as_a <frange> (*this) == as_a <frange> (src);
  gcc_unreachable ();
}

// Wrapper for vrange_printer to dump a range to a file.

void
vrange::dump (FILE *file) const
{
  pretty_printer buffer;
  pp_needs_newline (&buffer) = true;
  buffer.buffer->stream = file;
  vrange_printer vrange_pp (&buffer);
  this->accept (vrange_pp);
  pp_flush (&buffer);
}

void
irange_bitmask::dump (FILE *file) const
{
  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
  pretty_printer buffer;

  pp_needs_newline (&buffer) = true;
  buffer.buffer->stream = file;
  pp_string (&buffer, "MASK ");
  print_hex (m_mask, buf);
  pp_string (&buffer, buf);
  pp_string (&buffer, " VALUE ");
  print_hex (m_value, buf);
  pp_string (&buffer, buf);
  pp_flush (&buffer);
}

namespace inchash
{

void
add_vrange (const vrange &v, inchash::hash &hstate,
	     unsigned int)
{
  if (v.undefined_p ())
    {
      hstate.add_int (VR_UNDEFINED);
      return;
    }
  // Types are ignored throughout to inhibit two ranges being equal
  // but having different hash values.  This can happen when two
  // ranges are equal and their types are different (but
  // types_compatible_p is true).
  if (is_a <irange> (v))
    {
      const irange &r = as_a <irange> (v);
      if (r.varying_p ())
	hstate.add_int (VR_VARYING);
      else
	hstate.add_int (VR_RANGE);
      for (unsigned i = 0; i < r.num_pairs (); ++i)
	{
	  hstate.add_wide_int (r.lower_bound (i));
	  hstate.add_wide_int (r.upper_bound (i));
	}
      irange_bitmask bm = r.get_bitmask ();
      hstate.add_wide_int (bm.value ());
      hstate.add_wide_int (bm.mask ());
      return;
    }
  if (is_a <frange> (v))
    {
      const frange &r = as_a <frange> (v);
      if (r.known_isnan ())
	hstate.add_int (VR_NAN);
      else
	{
	  hstate.add_int (r.varying_p () ? VR_VARYING : VR_RANGE);
	  hstate.add_real_value (r.lower_bound ());
	  hstate.add_real_value (r.upper_bound ());
	}
      nan_state nan = r.get_nan_state ();
      hstate.add_int (nan.pos_p ());
      hstate.add_int (nan.neg_p ());
      return;
    }
  gcc_unreachable ();
}

} //namespace inchash

bool
irange::supports_type_p (const_tree type) const
{
  return supports_p (type);
}

// Return TRUE if R fits in THIS.

bool
irange::fits_p (const vrange &r) const
{
  return m_max_ranges >= as_a <irange> (r).num_pairs ();
}

void
irange::set_nonnegative (tree type)
{
  set (type,
       wi::zero (TYPE_PRECISION (type)),
       wi::to_wide (TYPE_MAX_VALUE (type)));
}

void
frange::accept (const vrange_visitor &v) const
{
  v.visit (*this);
}

// Flush denormal endpoints to the appropriate 0.0.

void
frange::flush_denormals_to_zero ()
{
  if (undefined_p () || known_isnan ())
    return;

  machine_mode mode = TYPE_MODE (type ());
  // Flush [x, -DENORMAL] to [x, -0.0].
  if (real_isdenormal (&m_max, mode) && real_isneg (&m_max))
    {
      if (HONOR_SIGNED_ZEROS (m_type))
	m_max = dconstm0;
      else
	m_max = dconst0;
    }
  // Flush [+DENORMAL, x] to [+0.0, x].
  if (real_isdenormal (&m_min, mode) && !real_isneg (&m_min))
    m_min = dconst0;
}

// Setter for franges.

void
frange::set (tree type,
	     const REAL_VALUE_TYPE &min, const REAL_VALUE_TYPE &max,
	     const nan_state &nan, value_range_kind kind)
{
  switch (kind)
    {
    case VR_UNDEFINED:
      set_undefined ();
      return;
    case VR_VARYING:
    case VR_ANTI_RANGE:
      set_varying (type);
      return;
    case VR_RANGE:
      break;
    default:
      gcc_unreachable ();
    }

  gcc_checking_assert (!real_isnan (&min) && !real_isnan (&max));

  m_kind = kind;
  m_type = type;
  m_min = min;
  m_max = max;
  if (HONOR_NANS (m_type))
    {
      m_pos_nan = nan.pos_p ();
      m_neg_nan = nan.neg_p ();
    }
  else
    {
      m_pos_nan = false;
      m_neg_nan = false;
    }

  if (!MODE_HAS_SIGNED_ZEROS (TYPE_MODE (m_type)))
    {
      if (real_iszero (&m_min, 1))
	m_min.sign = 0;
      if (real_iszero (&m_max, 1))
	m_max.sign = 0;
    }
  else if (!HONOR_SIGNED_ZEROS (m_type))
    {
      if (real_iszero (&m_max, 1))
	m_max.sign = 0;
      if (real_iszero (&m_min, 0))
	m_min.sign = 1;
    }

  // For -ffinite-math-only we can drop ranges outside the
  // representable numbers to min/max for the type.
  if (!HONOR_INFINITIES (m_type))
    {
      REAL_VALUE_TYPE min_repr = frange_val_min (m_type);
      REAL_VALUE_TYPE max_repr = frange_val_max (m_type);
      if (real_less (&m_min, &min_repr))
	m_min = min_repr;
      else if (real_less (&max_repr, &m_min))
	m_min = max_repr;
      if (real_less (&max_repr, &m_max))
	m_max = max_repr;
      else if (real_less (&m_max, &min_repr))
	m_max = min_repr;
    }

  // Check for swapped ranges.
  gcc_checking_assert (real_compare (LE_EXPR, &min, &max));

  normalize_kind ();
}

// Setter for an frange defaulting the NAN possibility to +-NAN when
// HONOR_NANS.

void
frange::set (tree type,
	     const REAL_VALUE_TYPE &min, const REAL_VALUE_TYPE &max,
	     value_range_kind kind)
{
  set (type, min, max, nan_state (true), kind);
}

void
frange::set (tree min, tree max, value_range_kind kind)
{
  set (TREE_TYPE (min),
       *TREE_REAL_CST_PTR (min), *TREE_REAL_CST_PTR (max), kind);
}

// Normalize range to VARYING or UNDEFINED, or vice versa.  Return
// TRUE if anything changed.
//
// A range with no known properties can be dropped to VARYING.
// Similarly, a VARYING with any properties should be dropped to a
// VR_RANGE.  Normalizing ranges upon changing them ensures there is
// only one representation for a given range.

bool
frange::normalize_kind ()
{
  if (m_kind == VR_RANGE
      && frange_val_is_min (m_min, m_type)
      && frange_val_is_max (m_max, m_type))
    {
      if (!HONOR_NANS (m_type) || (m_pos_nan && m_neg_nan))
	{
	  set_varying (m_type);
	  return true;
	}
    }
  else if (m_kind == VR_VARYING)
    {
      if (HONOR_NANS (m_type) && (!m_pos_nan || !m_neg_nan))
	{
	  m_kind = VR_RANGE;
	  m_min = frange_val_min (m_type);
	  m_max = frange_val_max (m_type);
	  if (flag_checking)
	    verify_range ();
	  return true;
	}
    }
  else if (m_kind == VR_NAN && !m_pos_nan && !m_neg_nan)
    set_undefined ();
  return false;
}

// Union or intersect the zero endpoints of two ranges.  For example:
//   [-0,  x] U [+0,  x] => [-0,  x]
//   [ x, -0] U [ x, +0] => [ x, +0]
//   [-0,  x] ^ [+0,  x] => [+0,  x]
//   [ x, -0] ^ [ x, +0] => [ x, -0]
//
// UNION_P is true when performing a union, or false when intersecting.

bool
frange::combine_zeros (const frange &r, bool union_p)
{
  gcc_checking_assert (!undefined_p () && !known_isnan ());

  bool changed = false;
  if (real_iszero (&m_min) && real_iszero (&r.m_min)
      && real_isneg (&m_min) != real_isneg (&r.m_min))
    {
      m_min.sign = union_p;
      changed = true;
    }
  if (real_iszero (&m_max) && real_iszero (&r.m_max)
      && real_isneg (&m_max) != real_isneg (&r.m_max))
    {
      m_max.sign = !union_p;
      changed = true;
    }
  // If the signs are swapped, the resulting range is empty.
  if (m_min.sign == 0 && m_max.sign == 1)
    {
      if (maybe_isnan ())
	m_kind = VR_NAN;
      else
	set_undefined ();
      changed = true;
    }
  return changed;
}

// Union two ranges when one is known to be a NAN.

bool
frange::union_nans (const frange &r)
{
  gcc_checking_assert (known_isnan () || r.known_isnan ());

  bool changed = false;
  if (known_isnan () && m_kind != r.m_kind)
    {
      m_kind = r.m_kind;
      m_min = r.m_min;
      m_max = r.m_max;
      changed = true;
    }
  if (m_pos_nan != r.m_pos_nan || m_neg_nan != r.m_neg_nan)
    {
      m_pos_nan |= r.m_pos_nan;
      m_neg_nan |= r.m_neg_nan;
      changed = true;
    }
  if (changed)
    {
      normalize_kind ();
      return true;
    }
  return false;
}

bool
frange::union_ (const vrange &v)
{
  const frange &r = as_a <frange> (v);

  if (r.undefined_p () || varying_p ())
    return false;
  if (undefined_p () || r.varying_p ())
    {
      *this = r;
      return true;
    }

  // Combine NAN info.
  if (known_isnan () || r.known_isnan ())
    return union_nans (r);
  bool changed = false;
  if (m_pos_nan != r.m_pos_nan || m_neg_nan != r.m_neg_nan)
    {
      m_pos_nan |= r.m_pos_nan;
      m_neg_nan |= r.m_neg_nan;
      changed = true;
    }

  // Combine endpoints.
  if (real_less (&r.m_min, &m_min))
    {
      m_min = r.m_min;
      changed = true;
    }
  if (real_less (&m_max, &r.m_max))
    {
      m_max = r.m_max;
      changed = true;
    }

  if (HONOR_SIGNED_ZEROS (m_type))
    changed |= combine_zeros (r, true);

  changed |= normalize_kind ();
  return changed;
}

// Intersect two ranges when one is known to be a NAN.

bool
frange::intersect_nans (const frange &r)
{
  gcc_checking_assert (known_isnan () || r.known_isnan ());

  m_pos_nan &= r.m_pos_nan;
  m_neg_nan &= r.m_neg_nan;
  if (maybe_isnan ())
    m_kind = VR_NAN;
  else
    set_undefined ();
  if (flag_checking)
    verify_range ();
  return true;
}

bool
frange::intersect (const vrange &v)
{
  const frange &r = as_a <frange> (v);

  if (undefined_p () || r.varying_p ())
    return false;
  if (r.undefined_p ())
    {
      set_undefined ();
      return true;
    }
  if (varying_p ())
    {
      *this = r;
      return true;
    }

  // Combine NAN info.
  if (known_isnan () || r.known_isnan ())
    return intersect_nans (r);
  bool changed = false;
  if (m_pos_nan != r.m_pos_nan || m_neg_nan != r.m_neg_nan)
    {
      m_pos_nan &= r.m_pos_nan;
      m_neg_nan &= r.m_neg_nan;
      changed = true;
    }

  // Combine endpoints.
  if (real_less (&m_min, &r.m_min))
    {
      m_min = r.m_min;
      changed = true;
    }
  if (real_less (&r.m_max, &m_max))
    {
      m_max = r.m_max;
      changed = true;
    }
  // If the endpoints are swapped, the resulting range is empty.
  if (real_less (&m_max, &m_min))
    {
      if (maybe_isnan ())
	m_kind = VR_NAN;
      else
	set_undefined ();
      if (flag_checking)
	verify_range ();
      return true;
    }

  if (HONOR_SIGNED_ZEROS (m_type))
    changed |= combine_zeros (r, false);

  changed |= normalize_kind ();
  return changed;
}

frange &
frange::operator= (const frange &src)
{
  m_kind = src.m_kind;
  m_type = src.m_type;
  m_min = src.m_min;
  m_max = src.m_max;
  m_pos_nan = src.m_pos_nan;
  m_neg_nan = src.m_neg_nan;

  if (flag_checking)
    verify_range ();
  return *this;
}

bool
frange::operator== (const frange &src) const
{
  if (m_kind == src.m_kind)
    {
      if (undefined_p ())
	return true;

      if (varying_p ())
	return types_compatible_p (m_type, src.m_type);

      bool nan1 = known_isnan ();
      bool nan2 = src.known_isnan ();
      if (nan1 || nan2)
	{
	  if (nan1 && nan2)
	    return (m_pos_nan == src.m_pos_nan
		    && m_neg_nan == src.m_neg_nan);
	  return false;
	}

      return (real_identical (&m_min, &src.m_min)
	      && real_identical (&m_max, &src.m_max)
	      && m_pos_nan == src.m_pos_nan
	      && m_neg_nan == src.m_neg_nan
	      && types_compatible_p (m_type, src.m_type));
    }
  return false;
}

// Return TRUE if range contains R.

bool
frange::contains_p (const REAL_VALUE_TYPE &r) const
{
  gcc_checking_assert (m_kind != VR_ANTI_RANGE);

  if (undefined_p ())
    return false;

  if (varying_p ())
    return true;

  if (real_isnan (&r))
    {
      // No NAN in range.
      if (!m_pos_nan && !m_neg_nan)
	return false;
      // Both +NAN and -NAN are present.
      if (m_pos_nan && m_neg_nan)
	return true;
      return m_neg_nan == r.sign;
    }
  if (known_isnan ())
    return false;

  if (real_compare (GE_EXPR, &r, &m_min) && real_compare (LE_EXPR, &r, &m_max))
    {
      // Make sure the signs are equal for signed zeros.
      if (HONOR_SIGNED_ZEROS (m_type) && real_iszero (&r))
	return r.sign == m_min.sign || r.sign == m_max.sign;
      return true;
    }
  return false;
}

// If range is a singleton, place it in RESULT and return TRUE.  If
// RESULT is NULL, just return TRUE.
//
// A NAN can never be a singleton.

bool
frange::internal_singleton_p (REAL_VALUE_TYPE *result) const
{
  if (m_kind == VR_RANGE && real_identical (&m_min, &m_max))
    {
      // Return false for any singleton that may be a NAN.
      if (HONOR_NANS (m_type) && maybe_isnan ())
	return false;

      if (MODE_COMPOSITE_P (TYPE_MODE (m_type)))
	{
	  // For IBM long doubles, if the value is +-Inf or is exactly
	  // representable in double, the other double could be +0.0
	  // or -0.0.  Since this means there is more than one way to
	  // represent a value, return false to avoid propagating it.
	  // See libgcc/config/rs6000/ibm-ldouble-format for details.
	  if (real_isinf (&m_min))
	    return false;
	  REAL_VALUE_TYPE r;
	  real_convert (&r, DFmode, &m_min);
	  if (real_identical (&r, &m_min))
	    return false;
	}

      if (result)
	*result = m_min;
      return true;
    }
  return false;
}

bool
frange::singleton_p (tree *result) const
{
  if (internal_singleton_p ())
    {
      if (result)
	*result = build_real (m_type, m_min);
      return true;
    }
  return false;
}

bool
frange::singleton_p (REAL_VALUE_TYPE &r) const
{
  return internal_singleton_p (&r);
}

bool
frange::supports_type_p (const_tree type) const
{
  return supports_p (type);
}

void
frange::verify_range ()
{
  if (!undefined_p ())
    gcc_checking_assert (HONOR_NANS (m_type) || !maybe_isnan ());
  switch (m_kind)
    {
    case VR_UNDEFINED:
      gcc_checking_assert (!m_type);
      return;
    case VR_VARYING:
      gcc_checking_assert (m_type);
      gcc_checking_assert (frange_val_is_min (m_min, m_type));
      gcc_checking_assert (frange_val_is_max (m_max, m_type));
      if (HONOR_NANS (m_type))
	gcc_checking_assert (m_pos_nan && m_neg_nan);
      else
	gcc_checking_assert (!m_pos_nan && !m_neg_nan);
      return;
    case VR_RANGE:
      gcc_checking_assert (m_type);
      break;
    case VR_NAN:
      gcc_checking_assert (m_type);
      gcc_checking_assert (m_pos_nan || m_neg_nan);
      return;
    default:
      gcc_unreachable ();
    }

  // NANs cannot appear in the endpoints of a range.
  gcc_checking_assert (!real_isnan (&m_min) && !real_isnan (&m_max));

  // Make sure we don't have swapped ranges.
  gcc_checking_assert (!real_less (&m_max, &m_min));

  // [ +0.0, -0.0 ] is nonsensical.
  gcc_checking_assert (!(real_iszero (&m_min, 0) && real_iszero (&m_max, 1)));

  // If all the properties are clear, we better not span the entire
  // domain, because that would make us varying.
  if (m_pos_nan && m_neg_nan)
    gcc_checking_assert (!frange_val_is_min (m_min, m_type)
			 || !frange_val_is_max (m_max, m_type));
}

// We can't do much with nonzeros yet.
void
frange::set_nonzero (tree type)
{
  set_varying (type);
}

// We can't do much with nonzeros yet.
bool
frange::nonzero_p () const
{
  return false;
}

// Set range to [+0.0, +0.0] if honoring signed zeros, or [0.0, 0.0]
// otherwise.

void
frange::set_zero (tree type)
{
  if (HONOR_SIGNED_ZEROS (type))
    {
      set (type, dconstm0, dconst0);
      clear_nan ();
    }
  else
    set (type, dconst0, dconst0);
}

// Return TRUE for any zero regardless of sign.

bool
frange::zero_p () const
{
  return (m_kind == VR_RANGE
	  && real_iszero (&m_min)
	  && real_iszero (&m_max));
}

// Set the range to non-negative numbers, that is [+0.0, +INF].
//
// The NAN in the resulting range (if HONOR_NANS) has a varying sign
// as there are no guarantees in IEEE 754 wrt to the sign of a NAN,
// except for copy, abs, and copysign.  It is the responsibility of
// the caller to set the NAN's sign if desired.

void
frange::set_nonnegative (tree type)
{
  set (type, dconst0, frange_val_max (type));
}

// Here we copy between any two irange's.

irange &
irange::operator= (const irange &src)
{
  int needed = src.num_pairs ();
  maybe_resize (needed);

  unsigned x;
  unsigned lim = src.m_num_ranges;
  if (lim > m_max_ranges)
    lim = m_max_ranges;

  for (x = 0; x < lim * 2; ++x)
    m_base[x] = src.m_base[x];

  // If the range didn't fit, the last range should cover the rest.
  if (lim != src.m_num_ranges)
    m_base[x - 1] = src.m_base[src.m_num_ranges * 2 - 1];

  m_num_ranges = lim;
  m_type = src.m_type;
  m_kind = src.m_kind;
  m_bitmask = src.m_bitmask;
  if (m_max_ranges == 1)
    normalize_kind ();
  if (flag_checking)
    verify_range ();
  return *this;
}

value_range_kind
get_legacy_range (const irange &r, tree &min, tree &max)
{
  if (r.undefined_p ())
    {
      min = NULL_TREE;
      max = NULL_TREE;
      return VR_UNDEFINED;
    }

  tree type = r.type ();
  if (r.varying_p ())
    {
      min = wide_int_to_tree (type, r.lower_bound ());
      max = wide_int_to_tree (type, r.upper_bound ());
      return VR_VARYING;
    }

  unsigned int precision = TYPE_PRECISION (type);
  signop sign = TYPE_SIGN (type);
  if (r.num_pairs () > 1
      && precision > 1
      && r.lower_bound () == wi::min_value (precision, sign)
      && r.upper_bound () == wi::max_value (precision, sign))
    {
      int_range<3> inv (r);
      inv.invert ();
      min = wide_int_to_tree (type, inv.lower_bound (0));
      max = wide_int_to_tree (type, inv.upper_bound (0));
      return VR_ANTI_RANGE;
    }

  min = wide_int_to_tree (type, r.lower_bound ());
  max = wide_int_to_tree (type, r.upper_bound ());
  return VR_RANGE;
}

/* Set value range to the canonical form of {VRTYPE, MIN, MAX, EQUIV}.
   This means adjusting VRTYPE, MIN and MAX representing the case of a
   wrapping range with MAX < MIN covering [MIN, type_max] U [type_min, MAX]
   as anti-rage ~[MAX+1, MIN-1].  Likewise for wrapping anti-ranges.
   In corner cases where MAX+1 or MIN-1 wraps this will fall back
   to varying.
   This routine exists to ease canonicalization in the case where we
   extract ranges from var + CST op limit.  */

void
irange::set (tree type, const wide_int &min, const wide_int &max,
	     value_range_kind kind)
{
  unsigned prec = TYPE_PRECISION (type);
  signop sign = TYPE_SIGN (type);
  wide_int min_value = wi::min_value (prec, sign);
  wide_int max_value = wi::max_value (prec, sign);

  m_type = type;
  m_bitmask.set_unknown (prec);

  if (kind == VR_RANGE)
    {
      m_base[0] = min;
      m_base[1] = max;
      m_num_ranges = 1;
      if (min == min_value && max == max_value)
	m_kind = VR_VARYING;
      else
	m_kind = VR_RANGE;
    }
  else
    {
      gcc_checking_assert (kind == VR_ANTI_RANGE);
      gcc_checking_assert (m_max_ranges > 1);

      m_kind = VR_UNDEFINED;
      m_num_ranges = 0;
      wi::overflow_type ovf;
      wide_int lim;
      if (sign == SIGNED)
	lim = wi::add (min, -1, sign, &ovf);
      else
	lim = wi::sub (min, 1, sign, &ovf);

      if (!ovf)
	{
	  m_kind = VR_RANGE;
	  m_base[0] = min_value;
	  m_base[1] = lim;
	  ++m_num_ranges;
	}
      if (sign == SIGNED)
	lim = wi::sub (max, -1, sign, &ovf);
      else
	lim = wi::add (max, 1, sign, &ovf);
      if (!ovf)
	{
	  m_kind = VR_RANGE;
	  m_base[m_num_ranges * 2] = lim;
	  m_base[m_num_ranges * 2 + 1] = max_value;
	  ++m_num_ranges;
	}
    }

  if (flag_checking)
    verify_range ();
}

void
irange::set (tree min, tree max, value_range_kind kind)
{
  if (POLY_INT_CST_P (min) || POLY_INT_CST_P (max))
    {
      set_varying (TREE_TYPE (min));
      return;
    }

  gcc_checking_assert (TREE_CODE (min) == INTEGER_CST);
  gcc_checking_assert (TREE_CODE (max) == INTEGER_CST);

  return set (TREE_TYPE (min), wi::to_wide (min), wi::to_wide (max), kind);
}

// Check the validity of the range.

void
irange::verify_range ()
{
  gcc_checking_assert (m_discriminator == VR_IRANGE);
  if (m_kind == VR_UNDEFINED)
    {
      gcc_checking_assert (m_num_ranges == 0);
      return;
    }
  gcc_checking_assert (m_num_ranges <= m_max_ranges);

  // Legacy allowed these to represent VARYING for unknown types.
  // Leave this in for now, until all users are converted.  Eventually
  // we should abort in set_varying.
  if (m_kind == VR_VARYING && m_type == error_mark_node)
    return;

  unsigned prec = TYPE_PRECISION (m_type);
  if (m_kind == VR_VARYING)
    {
      gcc_checking_assert (m_bitmask.unknown_p ());
      gcc_checking_assert (m_num_ranges == 1);
      gcc_checking_assert (varying_compatible_p ());
      gcc_checking_assert (lower_bound ().get_precision () == prec);
      gcc_checking_assert (upper_bound ().get_precision () == prec);
      return;
    }
  gcc_checking_assert (m_num_ranges != 0);
  gcc_checking_assert (!varying_compatible_p ());
  for (unsigned i = 0; i < m_num_ranges; ++i)
    {
      wide_int lb = lower_bound (i);
      wide_int ub = upper_bound (i);
      gcc_checking_assert (lb.get_precision () == prec);
      gcc_checking_assert (ub.get_precision () == prec);
      int c = wi::cmp (lb, ub, TYPE_SIGN (m_type));
      gcc_checking_assert (c == 0 || c == -1);
    }
  m_bitmask.verify_mask ();
}

bool
irange::operator== (const irange &other) const
{
  if (m_num_ranges != other.m_num_ranges)
    return false;

  if (m_num_ranges == 0)
    return true;

  signop sign1 = TYPE_SIGN (type ());
  signop sign2 = TYPE_SIGN (other.type ());

  for (unsigned i = 0; i < m_num_ranges; ++i)
    {
      widest_int lb = widest_int::from (lower_bound (i), sign1);
      widest_int ub = widest_int::from (upper_bound (i), sign1);
      widest_int lb_other = widest_int::from (other.lower_bound (i), sign2);
      widest_int ub_other = widest_int::from (other.upper_bound (i), sign2);
      if (lb != lb_other || ub != ub_other)
	return false;
    }

  irange_bitmask bm1 = get_bitmask ();
  irange_bitmask bm2 = other.get_bitmask ();
  widest_int tmp1 = widest_int::from (bm1.mask (), sign1);
  widest_int tmp2 = widest_int::from (bm2.mask (), sign2);
  if (tmp1 != tmp2)
    return false;
  if (bm1.unknown_p ())
    return true;
  tmp1 = widest_int::from (bm1.value (), sign1);
  tmp2 = widest_int::from (bm2.value (), sign2);
  return tmp1 == tmp2;
}

/* If range is a singleton, place it in RESULT and return TRUE.  */

bool
irange::singleton_p (tree *result) const
{
  if (num_pairs () == 1 && lower_bound () == upper_bound ())
    {
      if (result)
	*result = wide_int_to_tree (type (), lower_bound ());
      return true;
    }
  return false;
}

bool
irange::singleton_p (wide_int &w) const
{
  if (num_pairs () == 1 && lower_bound () == upper_bound ())
    {
      w = lower_bound ();
      return true;
    }
  return false;
}

/* Return 1 if CST is inside value range.
	  0 if CST is not inside value range.

   Benchmark compile/20001226-1.c compilation time after changing this
   function.  */

bool
irange::contains_p (const wide_int &cst) const
{
  if (undefined_p ())
    return false;

  // See if we can exclude CST based on the known 0 bits.
  if (!m_bitmask.unknown_p ()
      && cst != 0
      && wi::bit_and (m_bitmask.get_nonzero_bits (), cst) == 0)
    return false;

  signop sign = TYPE_SIGN (type ());
  for (unsigned r = 0; r < m_num_ranges; ++r)
    {
      if (wi::lt_p (cst, lower_bound (r), sign))
	return false;
      if (wi::le_p (cst, upper_bound (r), sign))
	return true;
    }

  return false;
}

// Perform an efficient union with R when both ranges have only a single pair.
// Excluded are VARYING and UNDEFINED ranges.

bool
irange::irange_single_pair_union (const irange &r)
{
  gcc_checking_assert (!undefined_p () && !varying_p ());
  gcc_checking_assert (!r.undefined_p () && !varying_p ());

  signop sign = TYPE_SIGN (m_type);
  // Check if current lower bound is also the new lower bound.
  if (wi::le_p (m_base[0], r.m_base[0], sign))
    {
      // If current upper bound is new upper bound, we're done.
      if (wi::le_p (r.m_base[1], m_base[1], sign))
	return union_bitmask (r);
      // Otherwise R has the new upper bound.
      // Check for overlap/touching ranges, or single target range.
      if (m_max_ranges == 1
	  || (widest_int::from (m_base[1], sign) + 1
	      >= widest_int::from (r.m_base[0], TYPE_SIGN (r.m_type))))
	m_base[1] = r.m_base[1];
      else
	{
	  // This is a dual range result.
	  m_base[2] = r.m_base[0];
	  m_base[3] = r.m_base[1];
	  m_num_ranges = 2;
	}
      // The range has been altered, so normalize it even if nothing
      // changed in the mask.
      if (!union_bitmask (r))
	normalize_kind ();
      if (flag_checking)
	verify_range ();
      return true;
    }

  // Set the new lower bound to R's lower bound.
  wide_int lb = m_base[0];
  m_base[0] = r.m_base[0];

  // If R fully contains THIS range, just set the upper bound.
  if (wi::ge_p (r.m_base[1], m_base[1], sign))
    m_base[1] = r.m_base[1];
  // Check for overlapping ranges, or target limited to a single range.
  else if (m_max_ranges == 1
	   || (widest_int::from (r.m_base[1], TYPE_SIGN (r.m_type)) + 1
	       >= widest_int::from (lb, sign)))
    ;
  else
    {
      // Left with 2 pairs.
      m_num_ranges = 2;
      m_base[2] = lb;
      m_base[3] = m_base[1];
      m_base[1] = r.m_base[1];
    }
  // The range has been altered, so normalize it even if nothing
  // changed in the mask.
  if (!union_bitmask (r))
    normalize_kind ();
  if (flag_checking)
    verify_range ();
  return true;
}

// Return TRUE if anything changes.

bool
irange::union_ (const vrange &v)
{
  const irange &r = as_a <irange> (v);

  if (r.undefined_p ())
    return false;

  if (undefined_p ())
    {
      operator= (r);
      if (flag_checking)
	verify_range ();
      return true;
    }

  if (varying_p ())
    return false;

  if (r.varying_p ())
    {
      set_varying (type ());
      return true;
    }

  // Special case one range union one range.
  if (m_num_ranges == 1 && r.m_num_ranges == 1)
    return irange_single_pair_union (r);

  // If this ranges fully contains R, then we need do nothing.
  if (irange_contains_p (r))
    return union_bitmask (r);

  // Do not worry about merging and such by reserving twice as many
  // pairs as needed, and then simply sort the 2 ranges into this
  // intermediate form.
  //
  // The intermediate result will have the property that the beginning
  // of each range is <= the beginning of the next range.  There may
  // be overlapping ranges at this point.  I.e. this would be valid
  // [-20, 10], [-10, 0], [0, 20], [40, 90] as it satisfies this
  // constraint : -20 < -10 < 0 < 40.  When the range is rebuilt into r,
  // the merge is performed.
  //
  // [Xi,Yi]..[Xn,Yn]  U  [Xj,Yj]..[Xm,Ym]   -->  [Xk,Yk]..[Xp,Yp]
  auto_vec<wide_int, 20> res (m_num_ranges * 2 + r.m_num_ranges * 2);
  unsigned i = 0, j = 0, k = 0;
  signop sign = TYPE_SIGN (m_type);

  while (i < m_num_ranges * 2 && j < r.m_num_ranges * 2)
    {
      // lower of Xi and Xj is the lowest point.
      if (widest_int::from (m_base[i], sign)
	  <= widest_int::from (r.m_base[j], sign))
	{
	  res.quick_push (m_base[i]);
	  res.quick_push (m_base[i + 1]);
	  k += 2;
	  i += 2;
	}
      else
	{
	  res.quick_push (r.m_base[j]);
	  res.quick_push (r.m_base[j + 1]);
	  k += 2;
	  j += 2;
	}
    }
  for ( ; i < m_num_ranges * 2; i += 2)
    {
      res.quick_push (m_base[i]);
      res.quick_push (m_base[i + 1]);
      k += 2;
    }
  for ( ; j < r.m_num_ranges * 2; j += 2)
    {
      res.quick_push (r.m_base[j]);
      res.quick_push (r.m_base[j + 1]);
      k += 2;
    }

  // Now normalize the vector removing any overlaps.
  i = 2;
  for (j = 2; j < k ; j += 2)
    {
      // Current upper+1 is >= lower bound next pair, then we merge ranges.
      if (widest_int::from (res[i - 1], sign) + 1
	  >= widest_int::from (res[j], sign))
	{
	  // New upper bounds is greater of current or the next one.
	  if (widest_int::from (res[j + 1], sign)
	      > widest_int::from (res[i - 1], sign))
	    res[i - 1] = res[j + 1];
	}
      else
	{
	  // This is a new distinct range, but no point in copying it
	  // if it is already in the right place.
	  if (i != j)
	    {
	      res[i++] = res[j];
	      res[i++] = res[j + 1];
	    }
	  else
	    i += 2;
	}
    }

  // At this point, the vector should have i ranges, none overlapping.
  // Now it simply needs to be copied, and if there are too many
  // ranges, merge some.  We wont do any analysis as to what the
  // "best" merges are, simply combine the final ranges into one.
  maybe_resize (i / 2);
  if (i > m_max_ranges * 2)
    {
      res[m_max_ranges * 2 - 1] = res[i - 1];
      i = m_max_ranges * 2;
    }

  for (j = 0; j < i ; j++)
    m_base[j] = res [j];
  m_num_ranges = i / 2;

  m_kind = VR_RANGE;
  // The range has been altered, so normalize it even if nothing
  // changed in the mask.
  if (!union_bitmask (r))
    normalize_kind ();
  if (flag_checking)
    verify_range ();
  return true;
}

// Return TRUE if THIS fully contains R.  No undefined or varying cases.

bool
irange::irange_contains_p (const irange &r) const
{
  gcc_checking_assert (!undefined_p () && !varying_p ());
  gcc_checking_assert (!r.undefined_p () && !varying_p ());

  // In order for THIS to fully contain R, all of the pairs within R must
  // be fully contained by the pairs in this object.
  signop sign = TYPE_SIGN (m_type);
  unsigned ri = 0;
  unsigned i = 0;
  wide_int rl = r.m_base[0];
  wide_int ru = r.m_base[1];
  wide_int l = m_base[0];
  wide_int u = m_base[1];
  while (1)
    {
      // If r is contained within this range, move to the next R
      if (wi::ge_p (rl, l, sign)
	  && wi::le_p (ru, u, sign))
	{
	  // This pair is OK, Either done, or bump to the next.
	  if (++ri >= r.num_pairs ())
	    return true;
	  rl = r.m_base[ri * 2];
	  ru = r.m_base[ri * 2 + 1];
	  continue;
	}
      // Otherwise, check if this's pair occurs before R's.
      if (wi::lt_p (u, rl, sign))
	{
	  // There's still at least one pair of R left.
	  if (++i >= num_pairs ())
	    return false;
	  l = m_base[i * 2];
	  u = m_base[i * 2 + 1];
	  continue;
	}
      return false;
    }
  return false;
}


// Return TRUE if anything changes.

bool
irange::intersect (const vrange &v)
{
  const irange &r = as_a <irange> (v);
  gcc_checking_assert (undefined_p () || r.undefined_p ()
		       || range_compatible_p (type (), r.type ()));

  if (undefined_p ())
    return false;
  if (r.undefined_p ())
    {
      set_undefined ();
      return true;
    }
  if (r.varying_p ())
    return false;
  if (varying_p ())
    {
      operator= (r);
      return true;
    }

  if (r.num_pairs () == 1)
    {
      bool res = intersect (r.lower_bound (), r.upper_bound ());
      if (undefined_p ())
	return true;

      res |= intersect_bitmask (r);
      if (res)
	normalize_kind ();
      return res;
    }

  // If R fully contains this, then intersection will change nothing.
  if (r.irange_contains_p (*this))
    return intersect_bitmask (r);

  // ?? We could probably come up with something smarter than the
  // worst case scenario here.
  int needed = num_pairs () + r.num_pairs ();
  maybe_resize (needed);

  signop sign = TYPE_SIGN (m_type);
  unsigned bld_pair = 0;
  unsigned bld_lim = m_max_ranges;
  int_range_max r2 (*this);
  unsigned r2_lim = r2.num_pairs ();
  unsigned i2 = 0;
  for (unsigned i = 0; i < r.num_pairs (); )
    {
      // If r1's upper is < r2's lower, we can skip r1's pair.
      wide_int ru = r.m_base[i * 2 + 1];
      wide_int r2l = r2.m_base[i2 * 2];
      if (wi::lt_p (ru, r2l, sign))
	{
	  i++;
	  continue;
	}
      // Likewise, skip r2's pair if its excluded.
      wide_int r2u = r2.m_base[i2 * 2 + 1];
      wide_int rl = r.m_base[i * 2];
      if (wi::lt_p (r2u, rl, sign))
	{
	  i2++;
	  if (i2 < r2_lim)
	    continue;
	  // No more r2, break.
	  break;
	}

      // Must be some overlap.  Find the highest of the lower bounds,
      // and set it, unless the build limits lower bounds is already
      // set.
      if (bld_pair < bld_lim)
	{
	  if (wi::ge_p (rl, r2l, sign))
	    m_base[bld_pair * 2] = rl;
	  else
	    m_base[bld_pair * 2] = r2l;
	}
      else
	// Decrease and set a new upper.
	bld_pair--;

      // ...and choose the lower of the upper bounds.
      if (wi::le_p (ru, r2u, sign))
	{
	  m_base[bld_pair * 2 + 1] = ru;
	  bld_pair++;
	  // Move past the r1 pair and keep trying.
	  i++;
	  continue;
	}
      else
	{
	  m_base[bld_pair * 2 + 1] = r2u;
	  bld_pair++;
	  i2++;
	  if (i2 < r2_lim)
	    continue;
	  // No more r2, break.
	  break;
	}
      // r2 has the higher lower bound.
    }

  // At the exit of this loop, it is one of 2 things:
  // ran out of r1, or r2, but either means we are done.
  m_num_ranges = bld_pair;
  if (m_num_ranges == 0)
    {
      set_undefined ();
      return true;
    }

  m_kind = VR_RANGE;
  // The range has been altered, so normalize it even if nothing
  // changed in the mask.
  if (!intersect_bitmask (r))
    normalize_kind ();
  if (flag_checking)
    verify_range ();
  return true;
}


// Multirange intersect for a specified wide_int [lb, ub] range.
// Return TRUE if intersect changed anything.
//
// NOTE: It is the caller's responsibility to intersect the mask.

bool
irange::intersect (const wide_int& lb, const wide_int& ub)
{
  // Undefined remains undefined.
  if (undefined_p ())
    return false;

  tree range_type = type();
  signop sign = TYPE_SIGN (range_type);

  gcc_checking_assert (TYPE_PRECISION (range_type) == wi::get_precision (lb));
  gcc_checking_assert (TYPE_PRECISION (range_type) == wi::get_precision (ub));

  // If this range is fully contained, then intersection will do nothing.
  if (wi::ge_p (lower_bound (), lb, sign)
      && wi::le_p (upper_bound (), ub, sign))
    return false;

  unsigned bld_index = 0;
  unsigned pair_lim = num_pairs ();
  for (unsigned i = 0; i < pair_lim; i++)
    {
      wide_int pairl = m_base[i * 2];
      wide_int pairu = m_base[i * 2 + 1];
      // Once UB is less than a pairs lower bound, we're done.
      if (wi::lt_p (ub, pairl, sign))
	break;
      // if LB is greater than this pairs upper, this pair is excluded.
      if (wi::lt_p (pairu, lb, sign))
	continue;

      // Must be some overlap.  Find the highest of the lower bounds,
      // and set it
      if (wi::gt_p (lb, pairl, sign))
	m_base[bld_index * 2] = lb;
      else
	m_base[bld_index * 2] = pairl;

      // ...and choose the lower of the upper bounds and if the base pair
      // has the lower upper bound, need to check next pair too.
      if (wi::lt_p (ub, pairu, sign))
	{
	  m_base[bld_index++ * 2 + 1] = ub;
	  break;
	}
      else
	m_base[bld_index++ * 2 + 1] = pairu;
    }

  m_num_ranges = bld_index;
  if (m_num_ranges == 0)
    {
      set_undefined ();
      return true;
    }

  m_kind = VR_RANGE;
  // The caller must normalize and verify the range, as the bitmask
  // still needs to be handled.
  return true;
}


// 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)
{
  if (TYPE_SIGN (type) == SIGNED)
    return wi::add (x, -1, SIGNED, &overflow);
  else
    return wi::sub (x, 1, UNSIGNED, &overflow);
}

// 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 ()
{
  gcc_checking_assert (!undefined_p () && !varying_p ());

  // We always need one more set of bounds to represent an inverse, so
  // if we're at the limit, we can't properly represent things.
  //
  // For instance, to represent the inverse of a 2 sub-range set
  // [5, 10][20, 30], we would need a 3 sub-range set
  // [-MIN, 4][11, 19][31, MAX].
  //
  // In this case, return the most conservative thing.
  //
  // However, if any of the extremes of the range are -MIN/+MAX, we
  // know we will not need an extra bound.  For example:
  //
  // 	INVERT([-MIN,20][30,40]) => [21,29][41,+MAX]
  // 	INVERT([-MIN,20][30,MAX]) => [21,29]
  tree ttype = type ();
  unsigned prec = TYPE_PRECISION (ttype);
  signop sign = TYPE_SIGN (ttype);
  wide_int type_min = wi::min_value (prec, sign);
  wide_int type_max = wi::max_value (prec, sign);
  m_bitmask.set_unknown (prec);

  // At this point, we need one extra sub-range to represent the
  // inverse.
  maybe_resize (m_num_ranges + 1);

  // The algorithm is as follows.  To calculate INVERT ([a,b][c,d]), we
  // generate [-MIN, a-1][b+1, c-1][d+1, MAX].
  //
  // If there is an over/underflow in the calculation for any
  // sub-range, we eliminate that subrange.  This allows us to easily
  // calculate INVERT([-MIN, 5]) with: [-MIN, -MIN-1][6, MAX].  And since
  // we eliminate the underflow, only [6, MAX] remains.
  unsigned i = 0;
  wi::overflow_type ovf;
  // Construct leftmost range.
  int_range_max orig_range (*this);
  unsigned nitems = 0;
  wide_int tmp;
  // If this is going to underflow on the MINUS 1, don't even bother
  // checking.  This also handles subtracting one from an unsigned 0,
  // which doesn't set the underflow bit.
  if (type_min != orig_range.lower_bound ())
    {
      m_base[nitems++] = type_min;
      tmp = subtract_one (orig_range.lower_bound (), ttype, ovf);
      m_base[nitems++] = tmp;
      if (ovf)
	nitems = 0;
    }
  i++;
  // Construct middle ranges if applicable.
  if (orig_range.num_pairs () > 1)
    {
      unsigned j = i;
      for (; j < (orig_range.num_pairs () * 2) - 1; j += 2)
	{
	  // The middle ranges cannot have MAX/MIN, so there's no need
	  // to check for unsigned overflow on the +1 and -1 here.
	  tmp = wi::add (orig_range.m_base[j], 1, sign, &ovf);
	  m_base[nitems++] = tmp;
	  tmp = subtract_one (orig_range.m_base[j + 1], ttype, ovf);
	  m_base[nitems++] = tmp;
	  if (ovf)
	    nitems -= 2;
	}
      i = j;
    }
  // Construct rightmost range.
  //
  // However, if this will overflow on the PLUS 1, don't even bother.
  // This also handles adding one to an unsigned MAX, which doesn't
  // set the overflow bit.
  if (type_max != orig_range.m_base[i])
    {
      tmp = add_one (orig_range.m_base[i], ttype, ovf);
      m_base[nitems++] = tmp;
      m_base[nitems++] = type_max;
      if (ovf)
	nitems -= 2;
    }
  m_num_ranges = nitems / 2;

  // We disallow undefined or varying coming in, so the result can
  // only be a VR_RANGE.
  gcc_checking_assert (m_kind == VR_RANGE);

  if (flag_checking)
    verify_range ();
}

// Return the bitmask inherent in the range.

irange_bitmask
irange::get_bitmask_from_range () const
{
  unsigned prec = TYPE_PRECISION (type ());
  wide_int min = lower_bound ();
  wide_int max = upper_bound ();

  // All the bits of a singleton are known.
  if (min == max)
    {
      wide_int mask = wi::zero (prec);
      wide_int value = lower_bound ();
      return irange_bitmask (value, mask);
    }

  wide_int xorv = min ^ max;

  if (xorv != 0)
    xorv = wi::mask (prec - wi::clz (xorv), false, prec);

  return irange_bitmask (wi::zero (prec), min | xorv);
}

// If the the mask can be trivially converted to a range, do so and
// return TRUE.

bool
irange::set_range_from_bitmask ()
{
  gcc_checking_assert (!undefined_p ());
  if (m_bitmask.unknown_p ())
    return false;

  // If all the bits are known, this is a singleton.
  if (m_bitmask.mask () == 0)
    {
      set (m_type, m_bitmask.value (), m_bitmask.value ());
      return true;
    }

  unsigned popcount = wi::popcount (m_bitmask.get_nonzero_bits ());

  // If we have only one bit set in the mask, we can figure out the
  // range immediately.
  if (popcount == 1)
    {
      // Make sure we don't pessimize the range.
      if (!contains_p (m_bitmask.get_nonzero_bits ()))
	return false;

      bool has_zero = contains_zero_p (*this);
      wide_int nz = m_bitmask.get_nonzero_bits ();
      set (m_type, nz, nz);
      m_bitmask.set_nonzero_bits (nz);
      if (has_zero)
	{
	  int_range<2> zero;
	  zero.set_zero (type ());
	  union_ (zero);
	}
      if (flag_checking)
	verify_range ();
      return true;
    }
  else if (popcount == 0)
    {
      set_zero (type ());
      return true;
    }
  return false;
}

void
irange::update_bitmask (const irange_bitmask &bm)
{
  gcc_checking_assert (!undefined_p ());

  // Drop VARYINGs with known bits to a plain range.
  if (m_kind == VR_VARYING && !bm.unknown_p ())
    m_kind = VR_RANGE;

  m_bitmask = bm;
  if (!set_range_from_bitmask ())
    normalize_kind ();
  if (flag_checking)
    verify_range ();
}

// Return the bitmask of known bits that includes the bitmask inherent
// in the range.

irange_bitmask
irange::get_bitmask () const
{
  gcc_checking_assert (!undefined_p ());

  // The mask inherent in the range is calculated on-demand.  For
  // example, [0,255] does not have known bits set by default.  This
  // saves us considerable time, because setting it at creation incurs
  // a large penalty for irange::set.  At the time of writing there
  // was a 5% slowdown in VRP if we kept the mask precisely up to date
  // at all times.  Instead, we default to -1 and set it when
  // explicitly requested.  However, this function will always return
  // the correct mask.
  //
  // This also means that the mask may have a finer granularity than
  // the range and thus contradict it.  Think of the mask as an
  // enhancement to the range.  For example:
  //
  // [3, 1000] MASK 0xfffffffe VALUE 0x0
  //
  // 3 is in the range endpoints, but is excluded per the known 0 bits
  // in the mask.
  //
  // See also the note in irange_bitmask::intersect.
  irange_bitmask bm = get_bitmask_from_range ();
  if (!m_bitmask.unknown_p ())
    bm.intersect (m_bitmask);
  return bm;
}

// Set the nonzero bits in R into THIS.  Return TRUE and
// normalize the range if anything changed.

void
irange::set_nonzero_bits (const wide_int &bits)
{
  gcc_checking_assert (!undefined_p ());
  irange_bitmask bm (wi::zero (TYPE_PRECISION (type ())), bits);
  update_bitmask (bm);
}

// Return the nonzero bits in R.

wide_int
irange::get_nonzero_bits () const
{
  gcc_checking_assert (!undefined_p ());
  irange_bitmask bm = get_bitmask ();
  return bm.value () | bm.mask ();
}

// Intersect the bitmask in R into THIS and normalize the range.
// Return TRUE if the intersection changed anything.

bool
irange::intersect_bitmask (const irange &r)
{
  gcc_checking_assert (!undefined_p () && !r.undefined_p ());

  if (m_bitmask == r.m_bitmask)
    return false;

  irange_bitmask bm = get_bitmask ();
  irange_bitmask save = bm;
  if (!bm.intersect (r.get_bitmask ()))
    return false;

  m_bitmask = bm;

  // Updating m_bitmask may still yield a semantic bitmask (as
  // returned by get_bitmask) which is functionally equivalent to what
  // we originally had.  In which case, there's still no change.
  if (save == get_bitmask ())
    return false;

  if (!set_range_from_bitmask ())
    normalize_kind ();
  if (flag_checking)
    verify_range ();
  return true;
}

// Union the bitmask in R into THIS.  Return TRUE and normalize the
// range if anything changed.

bool
irange::union_bitmask (const irange &r)
{
  gcc_checking_assert (!undefined_p () && !r.undefined_p ());

  if (m_bitmask == r.m_bitmask)
    return false;

  irange_bitmask bm = get_bitmask ();
  irange_bitmask save = bm;
  if (!bm.union_ (r.get_bitmask ()))
    return false;

  m_bitmask = bm;

  // Updating m_bitmask may still yield a semantic bitmask (as
  // returned by get_bitmask) which is functionally equivalent to what
  // we originally had.  In which case, there's still no change.
  if (save == get_bitmask ())
    return false;

  // No need to call set_range_from_mask, because we'll never
  // narrow the range.  Besides, it would cause endless recursion
  // because of the union_ in set_range_from_mask.
  normalize_kind ();
  return true;
}

void
irange_bitmask::verify_mask () const
{
  gcc_assert (m_value.get_precision () == m_mask.get_precision ());
}

void
dump_value_range (FILE *file, const vrange *vr)
{
  vr->dump (file);
}

DEBUG_FUNCTION void
debug (const vrange *vr)
{
  dump_value_range (stderr, vr);
  fprintf (stderr, "\n");
}

DEBUG_FUNCTION void
debug (const vrange &vr)
{
  debug (&vr);
}

DEBUG_FUNCTION void
debug (const value_range *vr)
{
  dump_value_range (stderr, vr);
  fprintf (stderr, "\n");
}

DEBUG_FUNCTION void
debug (const value_range &vr)
{
  dump_value_range (stderr, &vr);
  fprintf (stderr, "\n");
}

/* Return true, if VAL1 and VAL2 are equal values for VRP purposes.  */

bool
vrp_operand_equal_p (const_tree val1, const_tree val2)
{
  if (val1 == val2)
    return true;
  if (!val1 || !val2 || !operand_equal_p (val1, val2, 0))
    return false;
  return true;
}

void
gt_ggc_mx (irange *x)
{
  if (!x->undefined_p ())
    gt_ggc_mx (x->m_type);
}

void
gt_pch_nx (irange *x)
{
  if (!x->undefined_p ())
    gt_pch_nx (x->m_type);
}

void
gt_pch_nx (irange *x, gt_pointer_operator op, void *cookie)
{
  for (unsigned i = 0; i < x->m_num_ranges; ++i)
    {
      op (&x->m_base[i * 2], NULL, cookie);
      op (&x->m_base[i * 2 + 1], NULL, cookie);
    }
}

void
gt_ggc_mx (frange *x)
{
  gt_ggc_mx (x->m_type);
}

void
gt_pch_nx (frange *x)
{
  gt_pch_nx (x->m_type);
}

void
gt_pch_nx (frange *x, gt_pointer_operator op, void *cookie)
{
  op (&x->m_type, NULL, cookie);
}

void
gt_ggc_mx (vrange *x)
{
  if (is_a <irange> (*x))
    return gt_ggc_mx ((irange *) x);
  if (is_a <frange> (*x))
    return gt_ggc_mx ((frange *) x);
  gcc_unreachable ();
}

void
gt_pch_nx (vrange *x)
{
  if (is_a <irange> (*x))
    return gt_pch_nx ((irange *) x);
  if (is_a <frange> (*x))
    return gt_pch_nx ((frange *) x);
  gcc_unreachable ();
}

void
gt_pch_nx (vrange *x, gt_pointer_operator op, void *cookie)
{
  if (is_a <irange> (*x))
    gt_pch_nx ((irange *) x, op, cookie);
  else if (is_a <frange> (*x))
    gt_pch_nx ((frange *) x, op, cookie);
  else
    gcc_unreachable ();
}

#define DEFINE_INT_RANGE_INSTANCE(N)					\
  template int_range<N>::int_range(tree_node *,				\
				   const wide_int &,			\
				   const wide_int &,			\
				   value_range_kind);			\
  template int_range<N>::int_range(tree);				\
  template int_range<N>::int_range(const irange &);		\
  template int_range<N>::int_range(const int_range &);			\
  template int_range<N>& int_range<N>::operator= (const int_range &);

DEFINE_INT_RANGE_INSTANCE(1)
DEFINE_INT_RANGE_INSTANCE(2)
DEFINE_INT_RANGE_INSTANCE(3)
DEFINE_INT_RANGE_INSTANCE(255)

#if CHECKING_P
#include "selftest.h"

#define INT(x) wi::shwi ((x), TYPE_PRECISION (integer_type_node))
#define UINT(x) wi::uhwi ((x), TYPE_PRECISION (unsigned_type_node))
#define SCHAR(x) wi::shwi ((x), TYPE_PRECISION (signed_char_type_node))

namespace selftest
{

static int_range<2>
range (tree type, int a, int b, value_range_kind kind = VR_RANGE)
{
  wide_int w1, w2;
  if (TYPE_UNSIGNED (type))
    {
      w1 = wi::uhwi (a, TYPE_PRECISION (type));
      w2 = wi::uhwi (b, TYPE_PRECISION (type));
    }
  else
    {
      w1 = wi::shwi (a, TYPE_PRECISION (type));
      w2 = wi::shwi (b, TYPE_PRECISION (type));
    }
  return int_range<2> (type, w1, w2, kind);
}

static int_range<2>
range_int (int a, int b, value_range_kind kind = VR_RANGE)
{
  return range (integer_type_node, a, b, kind);
}

static int_range<2>
range_uint (int a, int b, value_range_kind kind = VR_RANGE)
{
  return range (unsigned_type_node, a, b, kind);
}

static int_range<2>
range_uint128 (int a, int b, value_range_kind kind = VR_RANGE)
{
  tree u128_type_node = build_nonstandard_integer_type (128, 1);
  return range (u128_type_node, a, b, kind);
}

static int_range<2>
range_uchar (int a, int b, value_range_kind kind = VR_RANGE)
{
  return range (unsigned_char_type_node, a, b, kind);
}

static int_range<2>
range_char (int a, int b, value_range_kind kind = VR_RANGE)
{
  return range (signed_char_type_node, a, b, kind);
}

static int_range<3>
build_range3 (int a, int b, int c, int d, int e, int f)
{
  int_range<3> i1 = range_int (a, b);
  int_range<3> i2 = range_int (c, d);
  int_range<3> i3 = range_int (e, f);
  i1.union_ (i2);
  i1.union_ (i3);
  return i1;
}

static void
range_tests_irange3 ()
{
  int_range<3> r0, r1, r2;
  int_range<3> i1, i2, i3;

  // ([10,20] U [5,8]) U [1,3] ==> [1,3][5,8][10,20].
  r0 = range_int (10, 20);
  r1 = range_int (5, 8);
  r0.union_ (r1);
  r1 = range_int (1, 3);
  r0.union_ (r1);
  ASSERT_TRUE (r0 == build_range3 (1, 3, 5, 8, 10, 20));

  // [1,3][5,8][10,20] U [-5,0] => [-5,3][5,8][10,20].
  r1 = range_int (-5, 0);
  r0.union_ (r1);
  ASSERT_TRUE (r0 == build_range3 (-5, 3, 5, 8, 10, 20));

  // [10,20][30,40] U [50,60] ==> [10,20][30,40][50,60].
  r1 = range_int (50, 60);
  r0 = range_int (10, 20);
  r0.union_ (range_int (30, 40));
  r0.union_ (r1);
  ASSERT_TRUE (r0 == build_range3 (10, 20, 30, 40, 50, 60));
  // [10,20][30,40][50,60] U [70, 80] ==> [10,20][30,40][50,60][70,80].
  r1 = range_int (70, 80);
  r0.union_ (r1);

  r2 = build_range3 (10, 20, 30, 40, 50, 60);
  r2.union_ (range_int (70, 80));
  ASSERT_TRUE (r0 == r2);

  // [10,20][30,40][50,60] U [6,35] => [6,40][50,60].
  r0 = build_range3 (10, 20, 30, 40, 50, 60);
  r1 = range_int (6, 35);
  r0.union_ (r1);
  r1 = range_int (6, 40);
  r1.union_ (range_int (50, 60));
  ASSERT_TRUE (r0 == r1);

  // [10,20][30,40][50,60] U [6,60] => [6,60].
  r0 = build_range3 (10, 20, 30, 40, 50, 60);
  r1 = range_int (6, 60);
  r0.union_ (r1);
  ASSERT_TRUE (r0 == range_int (6, 60));

  // [10,20][30,40][50,60] U [6,70] => [6,70].
  r0 = build_range3 (10, 20, 30, 40, 50, 60);
  r1 = range_int (6, 70);
  r0.union_ (r1);
  ASSERT_TRUE (r0 == range_int (6, 70));

  // [10,20][30,40][50,60] U [35,70] => [10,20][30,70].
  r0 = build_range3 (10, 20, 30, 40, 50, 60);
  r1 = range_int (35, 70);
  r0.union_ (r1);
  r1 = range_int (10, 20);
  r1.union_ (range_int (30, 70));
  ASSERT_TRUE (r0 == r1);

  // [10,20][30,40][50,60] U [15,35] => [10,40][50,60].
  r0 = build_range3 (10, 20, 30, 40, 50, 60);
  r1 = range_int (15, 35);
  r0.union_ (r1);
  r1 = range_int (10, 40);
  r1.union_ (range_int (50, 60));
  ASSERT_TRUE (r0 == r1);

  // [10,20][30,40][50,60] U [35,35] => [10,20][30,40][50,60].
  r0 = build_range3 (10, 20, 30, 40, 50, 60);
  r1 = range_int (35, 35);
  r0.union_ (r1);
  ASSERT_TRUE (r0 == build_range3 (10, 20, 30, 40, 50, 60));
}

static void
range_tests_int_range_max ()
{
  int_range_max big;
  unsigned int nrange;

  // Build a huge multi-range range.
  for (nrange = 0; nrange < 50; ++nrange)
    {
      int_range<1> tmp = range_int (nrange*10, nrange *10 + 5);
      big.union_ (tmp);
    }
  ASSERT_TRUE (big.num_pairs () == nrange);

  // Verify that we can copy it without loosing precision.
  int_range_max copy (big);
  ASSERT_TRUE (copy.num_pairs () == nrange);

  // Inverting it should produce one more sub-range.
  big.invert ();
  ASSERT_TRUE (big.num_pairs () == nrange + 1);

  int_range<1> tmp = range_int (5, 37);
  big.intersect (tmp);
  ASSERT_TRUE (big.num_pairs () == 4);

  // Test that [10,10][20,20] does NOT contain 15.
  {
    int_range_max i1 = range_int (10, 10);
    int_range_max i2 = range_int (20, 20);
    i1.union_ (i2);
    ASSERT_FALSE (i1.contains_p (INT (15)));
  }
}

// Simulate -fstrict-enums where the domain of a type is less than the
// underlying type.

static void
range_tests_strict_enum ()
{
  // The enum can only hold [0, 3].
  tree rtype = copy_node (unsigned_type_node);
  TYPE_MIN_VALUE (rtype) = build_int_cstu (rtype, 0);
  TYPE_MAX_VALUE (rtype) = build_int_cstu (rtype, 3);

  // Test that even though vr1 covers the strict enum domain ([0, 3]),
  // it does not cover the domain of the underlying type.
  int_range<1> vr1 = range (rtype, 0, 1);
  int_range<1> vr2 = range (rtype, 2, 3);
  vr1.union_ (vr2);
  ASSERT_TRUE (vr1 == range (rtype, 0, 3));
  ASSERT_FALSE (vr1.varying_p ());

  // Test that copying to a multi-range does not change things.
  int_range<2> ir1 (vr1);
  ASSERT_TRUE (ir1 == vr1);
  ASSERT_FALSE (ir1.varying_p ());

  // The same test as above, but using TYPE_{MIN,MAX}_VALUE instead of [0,3].
  vr1 = int_range<2> (rtype,
		      wi::to_wide (TYPE_MIN_VALUE (rtype)),
		      wi::to_wide (TYPE_MAX_VALUE (rtype)));
  ir1 = vr1;
  ASSERT_TRUE (ir1 == vr1);
  ASSERT_FALSE (ir1.varying_p ());
}

static void
range_tests_misc ()
{
  tree u128_type = build_nonstandard_integer_type (128, /*unsigned=*/1);
  int_range<2> i1, i2, i3;
  int_range<2> r0, r1, rold;

  // Test 1-bit signed integer union.
  // [-1,-1] U [0,0] = VARYING.
  tree one_bit_type = build_nonstandard_integer_type (1, 0);
  wide_int one_bit_min = irange_val_min (one_bit_type);
  wide_int one_bit_max = irange_val_max (one_bit_type);
  {
    int_range<2> min = int_range<2> (one_bit_type, one_bit_min, one_bit_min);
    int_range<2> max = int_range<2> (one_bit_type, one_bit_max, one_bit_max);
    max.union_ (min);
    ASSERT_TRUE (max.varying_p ());
  }
  // Test that we can set a range of true+false for a 1-bit signed int.
  r0 = range_true_and_false (one_bit_type);

  // Test inversion of 1-bit signed integers.
  {
    int_range<2> min = int_range<2> (one_bit_type, one_bit_min, one_bit_min);
    int_range<2> max = int_range<2> (one_bit_type, one_bit_max, one_bit_max);
    int_range<2> t;
    t = min;
    t.invert ();
    ASSERT_TRUE (t == max);
    t = max;
    t.invert ();
    ASSERT_TRUE (t == min);
  }

  // Test that NOT(255) is [0..254] in 8-bit land.
  int_range<1> not_255 = range_uchar (255, 255, VR_ANTI_RANGE);
  ASSERT_TRUE (not_255 == range_uchar (0, 254));

  // Test that NOT(0) is [1..255] in 8-bit land.
  int_range<2> not_zero = range_nonzero (unsigned_char_type_node);
  ASSERT_TRUE (not_zero == range_uchar (1, 255));

  // Check that [0,127][0x..ffffff80,0x..ffffff]
  //  => ~[128, 0x..ffffff7f].
  r0 = range_uint128 (0, 127);
  wide_int high = wi::minus_one (128);
  // low = -1 - 127 => 0x..ffffff80.
  wide_int low = wi::sub (high, wi::uhwi (127, 128));
  r1 = int_range<1> (u128_type, low, high); // [0x..ffffff80, 0x..ffffffff]
  // r0 = [0,127][0x..ffffff80,0x..fffffff].
  r0.union_ (r1);
  // r1 = [128, 0x..ffffff7f].
  r1 = int_range<1> (u128_type,
		     wi::uhwi (128, 128),
		     wi::sub (wi::minus_one (128), wi::uhwi (128, 128)));
  r0.invert ();
  ASSERT_TRUE (r0 == r1);

  r0.set_varying (integer_type_node);
  wide_int minint = r0.lower_bound ();
  wide_int maxint = r0.upper_bound ();

  r0.set_varying (short_integer_type_node);

  r0.set_varying (unsigned_type_node);
  wide_int maxuint = r0.upper_bound ();

  // Check that ~[0,5] => [6,MAX] for unsigned int.
  r0 = range_uint (0, 5);
  r0.invert ();
  ASSERT_TRUE (r0 == int_range<1> (unsigned_type_node,
				   wi::uhwi (6, TYPE_PRECISION (unsigned_type_node)),
				   maxuint));

  // Check that ~[10,MAX] => [0,9] for unsigned int.
  r0 = int_range<1> (unsigned_type_node,
		     wi::uhwi (10, TYPE_PRECISION (unsigned_type_node)),
		     maxuint);
  r0.invert ();
  ASSERT_TRUE (r0 == range_uint (0, 9));

  // Check that ~[0,5] => [6,MAX] for unsigned 128-bit numbers.
  r0 = range_uint128 (0, 5, VR_ANTI_RANGE);
  r1 = int_range<1> (u128_type, wi::uhwi (6, 128), wi::minus_one (128));
  ASSERT_TRUE (r0 == r1);

  // Check that [~5] is really [-MIN,4][6,MAX].
  r0 = range_int (5, 5, VR_ANTI_RANGE);
  r1 = int_range<1> (integer_type_node, minint, INT (4));
  r1.union_ (int_range<1> (integer_type_node, INT (6), maxint));
  ASSERT_FALSE (r1.undefined_p ());
  ASSERT_TRUE (r0 == r1);

  r1 = range_int (5, 5);
  int_range<2> r2 (r1);
  ASSERT_TRUE (r1 == r2);

  r1 = range_int (5, 10);

  r1 = range_int (5, 10);
  ASSERT_TRUE (r1.contains_p (INT (7)));

  r1 = range_char (0, 20);
  ASSERT_TRUE (r1.contains_p (SCHAR(15)));
  ASSERT_FALSE (r1.contains_p (SCHAR(300)));

  // NOT([10,20]) ==> [-MIN,9][21,MAX].
  r0 = r1 = range_int (10, 20);
  r2 = int_range<1> (integer_type_node, minint, INT(9));
  r2.union_ (int_range<1> (integer_type_node, INT(21), maxint));
  ASSERT_FALSE (r2.undefined_p ());
  r1.invert ();
  ASSERT_TRUE (r1 == r2);
  // Test that NOT(NOT(x)) == x.
  r2.invert ();
  ASSERT_TRUE (r0 == r2);

  // Test that booleans and their inverse work as expected.
  r0 = range_zero (boolean_type_node);
  ASSERT_TRUE (r0 == range_false ());
  r0.invert ();
  ASSERT_TRUE (r0 == range_true ());

  // Make sure NULL and non-NULL of pointer types work, and that
  // inverses of them are consistent.
  tree voidp = build_pointer_type (void_type_node);
  r0 = range_zero (voidp);
  r1 = r0;
  r0.invert ();
  r0.invert ();
  ASSERT_TRUE (r0 == r1);

  // [10,20] U [15, 30] => [10, 30].
  r0 = range_int (10, 20);
  r1 = range_int (15, 30);
  r0.union_ (r1);
  ASSERT_TRUE (r0 == range_int (10, 30));

  // [15,40] U [] => [15,40].
  r0 = range_int (15, 40);
  r1.set_undefined ();
  r0.union_ (r1);
  ASSERT_TRUE (r0 == range_int (15, 40));

  // [10,20] U [10,10] => [10,20].
  r0 = range_int (10, 20);
  r1 = range_int (10, 10);
  r0.union_ (r1);
  ASSERT_TRUE (r0 == range_int (10, 20));

  // [10,20] U [9,9] => [9,20].
  r0 = range_int (10, 20);
  r1 = range_int (9, 9);
  r0.union_ (r1);
  ASSERT_TRUE (r0 == range_int (9, 20));

  // [10,20] ^ [15,30] => [15,20].
  r0 = range_int (10, 20);
  r1 = range_int (15, 30);
  r0.intersect (r1);
  ASSERT_TRUE (r0 == range_int (15, 20));

  // Test the internal sanity of wide_int's wrt HWIs.
  ASSERT_TRUE (wi::max_value (TYPE_PRECISION (boolean_type_node),
			      TYPE_SIGN (boolean_type_node))
	       == wi::uhwi (1, TYPE_PRECISION (boolean_type_node)));

  // Test zero_p().
  r0 = range_int (0, 0);
  ASSERT_TRUE (r0.zero_p ());

  // Test nonzero_p().
  r0 = range_int (0, 0);
  r0.invert ();
  ASSERT_TRUE (r0.nonzero_p ());

  // r0 = ~[1,1]
  r0 = range_int (1, 1, VR_ANTI_RANGE);
  // r1 = ~[3,3]
  r1 = range_int (3, 3, VR_ANTI_RANGE);

  // vv = [0,0][2,2][4, MAX]
  int_range<3> vv = r0;
  vv.intersect (r1);

  ASSERT_TRUE (vv.contains_p (UINT (2)));
  ASSERT_TRUE (vv.num_pairs () == 3);

  r0 = range_int (1, 1);
  // And union it with  [0,0][2,2][4,MAX] multi range
  r0.union_ (vv);
  // The result should be [0,2][4,MAX], or ~[3,3]  but it must contain 2
  ASSERT_TRUE (r0.contains_p (INT (2)));
}

static void
range_tests_nonzero_bits ()
{
  int_range<2> r0, r1;

  // Adding nonzero bits to a varying drops the varying.
  r0.set_varying (integer_type_node);
  r0.set_nonzero_bits (INT (255));
  ASSERT_TRUE (!r0.varying_p ());
  // Dropping the nonzero bits brings us back to varying.
  r0.set_nonzero_bits (INT (-1));
  ASSERT_TRUE (r0.varying_p ());

  // Test contains_p with nonzero bits.
  r0.set_zero (integer_type_node);
  ASSERT_TRUE (r0.contains_p (INT (0)));
  ASSERT_FALSE (r0.contains_p (INT (1)));
  r0.set_nonzero_bits (INT (0xfe));
  ASSERT_FALSE (r0.contains_p (INT (0x100)));
  ASSERT_FALSE (r0.contains_p (INT (0x3)));

  // Union of nonzero bits.
  r0.set_varying (integer_type_node);
  r0.set_nonzero_bits (INT (0xf0));
  r1.set_varying (integer_type_node);
  r1.set_nonzero_bits (INT (0xf));
  r0.union_ (r1);
  ASSERT_TRUE (r0.get_nonzero_bits () == 0xff);

  // Intersect of nonzero bits.
  r0 = range_int (0, 255);
  r0.set_nonzero_bits (INT (0xfe));
  r1.set_varying (integer_type_node);
  r1.set_nonzero_bits (INT (0xf0));
  r0.intersect (r1);
  ASSERT_TRUE (r0.get_nonzero_bits () == 0xf0);

  // Intersect where the mask of nonzero bits is implicit from the range.
  r0.set_varying (integer_type_node);
  r1 = range_int (0, 255);
  r0.intersect (r1);
  ASSERT_TRUE (r0.get_nonzero_bits () == 0xff);

  // The union of a mask of 0xff..ffff00 with a mask of 0xff spans the
  // entire domain, and makes the range a varying.
  r0.set_varying (integer_type_node);
  wide_int x = wi::shwi (0xff, TYPE_PRECISION (integer_type_node));
  x = wi::bit_not (x);
  r0.set_nonzero_bits (x); 	// 0xff..ff00
  r1.set_varying (integer_type_node);
  r1.set_nonzero_bits (INT (0xff));
  r0.union_ (r1);
  ASSERT_TRUE (r0.varying_p ());

  // Test that setting a nonzero bit of 1 does not pessimize the range.
  r0.set_zero (integer_type_node);
  r0.set_nonzero_bits (INT (1));
  ASSERT_TRUE (r0.zero_p ());
}

// Build an frange from string endpoints.

static inline frange
frange_float (const char *lb, const char *ub, tree type = float_type_node)
{
  REAL_VALUE_TYPE min, max;
  gcc_assert (real_from_string (&min, lb) == 0);
  gcc_assert (real_from_string (&max, ub) == 0);
  return frange (type, min, max);
}

static void
range_tests_nan ()
{
  frange r0, r1;
  REAL_VALUE_TYPE q, r;
  bool signbit;

  // Equal ranges but with differing NAN bits are not equal.
  if (HONOR_NANS (float_type_node))
    {
      r1 = frange_float ("10", "12");
      r0 = r1;
      ASSERT_EQ (r0, r1);
      r0.clear_nan ();
      ASSERT_NE (r0, r1);
      r0.update_nan ();
      ASSERT_EQ (r0, r1);

      // [10, 20] NAN ^ [30, 40] NAN = NAN.
      r0 = frange_float ("10", "20");
      r1 = frange_float ("30", "40");
      r0.intersect (r1);
      ASSERT_TRUE (r0.known_isnan ());

      // [3,5] U [5,10] NAN = ... NAN
      r0 = frange_float ("3", "5");
      r0.clear_nan ();
      r1 = frange_float ("5", "10");
      r0.union_ (r1);
      ASSERT_TRUE (r0.maybe_isnan ());
    }

  // [5,6] U NAN = [5,6] NAN.
  r0 = frange_float ("5", "6");
  r0.clear_nan ();
  r1.set_nan (float_type_node);
  r0.union_ (r1);
  real_from_string (&q, "5");
  real_from_string (&r, "6");
  ASSERT_TRUE (real_identical (&q, &r0.lower_bound ()));
  ASSERT_TRUE (real_identical (&r, &r0.upper_bound ()));
  ASSERT_TRUE (r0.maybe_isnan ());

  // NAN U NAN = NAN
  r0.set_nan (float_type_node);
  r1.set_nan (float_type_node);
  r0.union_ (r1);
  ASSERT_TRUE (r0.known_isnan ());

  // [INF, INF] NAN ^ NAN = NAN
  r0.set_nan (float_type_node);
  r1 = frange_float ("+Inf", "+Inf");
  if (!HONOR_NANS (float_type_node))
    r1.update_nan ();
  r0.intersect (r1);
  ASSERT_TRUE (r0.known_isnan ());

  // NAN ^ NAN = NAN
  r0.set_nan (float_type_node);
  r1.set_nan (float_type_node);
  r0.intersect (r1);
  ASSERT_TRUE (r0.known_isnan ());

  // +NAN ^ -NAN = UNDEFINED
  r0.set_nan (float_type_node, false);
  r1.set_nan (float_type_node, true);
  r0.intersect (r1);
  ASSERT_TRUE (r0.undefined_p ());

  // VARYING ^ NAN = NAN.
  r0.set_nan (float_type_node);
  r1.set_varying (float_type_node);
  r0.intersect (r1);
  ASSERT_TRUE (r0.known_isnan ());

  // [3,4] ^ NAN = UNDEFINED.
  r0 = frange_float ("3", "4");
  r0.clear_nan ();
  r1.set_nan (float_type_node);
  r0.intersect (r1);
  ASSERT_TRUE (r0.undefined_p ());

  // [-3, 5] ^ NAN = UNDEFINED
  r0 = frange_float ("-3", "5");
  r0.clear_nan ();
  r1.set_nan (float_type_node);
  r0.intersect (r1);
  ASSERT_TRUE (r0.undefined_p ());

  // Setting the NAN bit to yes does not make us a known NAN.
  r0.set_varying (float_type_node);
  r0.update_nan ();
  ASSERT_FALSE (r0.known_isnan ());

  // NAN is in a VARYING.
  r0.set_varying (float_type_node);
  real_nan (&r, "", 1, TYPE_MODE (float_type_node));
  REAL_VALUE_TYPE nan = r;
  ASSERT_TRUE (r0.contains_p (nan));

  // -NAN is in a VARYING.
  r0.set_varying (float_type_node);
  q = real_value_negate (&r);
  REAL_VALUE_TYPE neg_nan = q;
  ASSERT_TRUE (r0.contains_p (neg_nan));

  // Clearing the NAN on a [] NAN is the empty set.
  r0.set_nan (float_type_node);
  r0.clear_nan ();
  ASSERT_TRUE (r0.undefined_p ());

  // [10,20] NAN ^ [21,25] NAN = [NAN]
  r0 = frange_float ("10", "20");
  r0.update_nan ();
  r1 = frange_float ("21", "25");
  r1.update_nan ();
  r0.intersect (r1);
  ASSERT_TRUE (r0.known_isnan ());

  // NAN U [5,6] should be [5,6] +-NAN.
  r0.set_nan (float_type_node);
  r1 = frange_float ("5", "6");
  r1.clear_nan ();
  r0.union_ (r1);
  real_from_string (&q, "5");
  real_from_string (&r, "6");
  ASSERT_TRUE (real_identical (&q, &r0.lower_bound ()));
  ASSERT_TRUE (real_identical (&r, &r0.upper_bound ()));
  ASSERT_TRUE (!r0.signbit_p (signbit));
  ASSERT_TRUE (r0.maybe_isnan ());

  // NAN U NAN shouldn't change anything.
  r0.set_nan (float_type_node);
  r1.set_nan (float_type_node);
  ASSERT_FALSE (r0.union_ (r1));

  // [3,5] NAN U NAN shouldn't change anything.
  r0 = frange_float ("3", "5");
  r1.set_nan (float_type_node);
  ASSERT_FALSE (r0.union_ (r1));

  // [3,5] U NAN *does* trigger a change.
  r0 = frange_float ("3", "5");
  r0.clear_nan ();
  r1.set_nan (float_type_node);
  ASSERT_TRUE (r0.union_ (r1));
}

static void
range_tests_signed_zeros ()
{
  REAL_VALUE_TYPE zero = dconst0;
  REAL_VALUE_TYPE neg_zero = zero;
  neg_zero.sign = 1;
  frange r0, r1;
  bool signbit;

  // [0,0] contains [0,0] but not [-0,-0] and vice versa.
  r0 = frange_float ("0.0", "0.0");
  r1 = frange_float ("-0.0", "-0.0");
  ASSERT_TRUE (r0.contains_p (zero));
  ASSERT_TRUE (!r0.contains_p (neg_zero));
  ASSERT_TRUE (r1.contains_p (neg_zero));
  ASSERT_TRUE (!r1.contains_p (zero));

  // Test contains_p() when we know the sign of the zero.
  r0 = frange_float ("0.0", "0.0");
  ASSERT_TRUE (r0.contains_p (zero));
  ASSERT_FALSE (r0.contains_p (neg_zero));
  r0 = frange_float ("-0.0", "-0.0");
  ASSERT_TRUE (r0.contains_p (neg_zero));
  ASSERT_FALSE (r0.contains_p (zero));

  r0 = frange_float ("-0.0", "0.0");
  ASSERT_TRUE (r0.contains_p (neg_zero));
  ASSERT_TRUE (r0.contains_p (zero));

  r0 = frange_float ("-3", "5");
  ASSERT_TRUE (r0.contains_p (neg_zero));
  ASSERT_TRUE (r0.contains_p (zero));

  // The intersection of zeros that differ in sign is a NAN (or
  // undefined if not honoring NANs).
  r0 = frange_float ("-0.0", "-0.0");
  r1 = frange_float ("0.0", "0.0");
  r0.intersect (r1);
  if (HONOR_NANS (float_type_node))
    ASSERT_TRUE (r0.known_isnan ());
  else
    ASSERT_TRUE (r0.undefined_p ());

  // The union of zeros that differ in sign is a zero with unknown sign.
  r0 = frange_float ("0.0", "0.0");
  r1 = frange_float ("-0.0", "-0.0");
  r0.union_ (r1);
  ASSERT_TRUE (r0.zero_p () && !r0.signbit_p (signbit));

  // [-0, +0] has an unknown sign.
  r0 = frange_float ("-0.0", "0.0");
  ASSERT_TRUE (r0.zero_p () && !r0.signbit_p (signbit));

  // [-0, +0] ^ [0, 0] is [0, 0]
  r0 = frange_float ("-0.0", "0.0");
  r1 = frange_float ("0.0", "0.0");
  r0.intersect (r1);
  ASSERT_TRUE (r0.zero_p ());

  r0 = frange_float ("+0", "5");
  r0.clear_nan ();
  ASSERT_TRUE (r0.signbit_p (signbit) && !signbit);

  r0 = frange_float ("-0", "5");
  r0.clear_nan ();
  ASSERT_TRUE (!r0.signbit_p (signbit));

  r0 = frange_float ("-0", "10");
  r1 = frange_float ("0", "5");
  r0.intersect (r1);
  ASSERT_TRUE (real_iszero (&r0.lower_bound (), false));

  r0 = frange_float ("-0", "5");
  r1 = frange_float ("0", "5");
  r0.union_ (r1);
  ASSERT_TRUE (real_iszero (&r0.lower_bound (), true));

  r0 = frange_float ("-5", "-0");
  r0.update_nan ();
  r1 = frange_float ("0", "0");
  r1.update_nan ();
  r0.intersect (r1);
  if (HONOR_NANS (float_type_node))
    ASSERT_TRUE (r0.known_isnan ());
  else
    ASSERT_TRUE (r0.undefined_p ());

  r0.set_nonnegative (float_type_node);
  if (HONOR_NANS (float_type_node))
    ASSERT_TRUE (r0.maybe_isnan ());

  // Numbers containing zero should have an unknown SIGNBIT.
  r0 = frange_float ("0", "10");
  r0.clear_nan ();
  ASSERT_TRUE (r0.signbit_p (signbit) && !signbit);
}

static void
range_tests_signbit ()
{
  frange r0, r1;
  bool signbit;

  // Negative numbers should have the SIGNBIT set.
  r0 = frange_float ("-5", "-1");
  r0.clear_nan ();
  ASSERT_TRUE (r0.signbit_p (signbit) && signbit);
  // Positive numbers should have the SIGNBIT clear.
  r0 = frange_float ("1", "10");
  r0.clear_nan ();
  ASSERT_TRUE (r0.signbit_p (signbit) && !signbit);
  // Numbers spanning both positive and negative should have an
  // unknown SIGNBIT.
  r0 = frange_float ("-10", "10");
  r0.clear_nan ();
  ASSERT_TRUE (!r0.signbit_p (signbit));
  r0.set_varying (float_type_node);
  ASSERT_TRUE (!r0.signbit_p (signbit));
}

static void
range_tests_floats ()
{
  frange r0, r1;

  if (HONOR_NANS (float_type_node))
    range_tests_nan ();
  range_tests_signbit ();

  if (HONOR_SIGNED_ZEROS (float_type_node))
    range_tests_signed_zeros ();

  // A range of [-INF,+INF] is actually VARYING if no other properties
  // are set.
  r0 = frange_float ("-Inf", "+Inf");
  ASSERT_TRUE (r0.varying_p ());
  // ...unless it has some special property...
  if (HONOR_NANS (r0.type ()))
    {
      r0.clear_nan ();
      ASSERT_FALSE (r0.varying_p ());
    }

  // For most architectures, where float and double are different
  // sizes, having the same endpoints does not necessarily mean the
  // ranges are equal.
  if (!types_compatible_p (float_type_node, double_type_node))
    {
      r0 = frange_float ("3.0", "3.0", float_type_node);
      r1 = frange_float ("3.0", "3.0", double_type_node);
      ASSERT_NE (r0, r1);
    }

  // [3,5] U [10,12] = [3,12].
  r0 = frange_float ("3", "5");
  r1 = frange_float ("10", "12");
  r0.union_ (r1);
  ASSERT_EQ (r0, frange_float ("3", "12"));

  // [5,10] U [4,8] = [4,10]
  r0 = frange_float ("5", "10");
  r1 = frange_float ("4", "8");
  r0.union_ (r1);
  ASSERT_EQ (r0, frange_float ("4", "10"));

  // [3,5] U [4,10] = [3,10]
  r0 = frange_float ("3", "5");
  r1 = frange_float ("4", "10");
  r0.union_ (r1);
  ASSERT_EQ (r0, frange_float ("3", "10"));

  // [4,10] U [5,11] = [4,11]
  r0 = frange_float ("4", "10");
  r1 = frange_float ("5", "11");
  r0.union_ (r1);
  ASSERT_EQ (r0, frange_float ("4", "11"));

  // [3,12] ^ [10,12] = [10,12].
  r0 = frange_float ("3", "12");
  r1 = frange_float ("10", "12");
  r0.intersect (r1);
  ASSERT_EQ (r0, frange_float ("10", "12"));

  // [10,12] ^ [11,11] = [11,11]
  r0 = frange_float ("10", "12");
  r1 = frange_float ("11", "11");
  r0.intersect (r1);
  ASSERT_EQ (r0, frange_float ("11", "11"));

  // [10,20] ^ [5,15] = [10,15]
  r0 = frange_float ("10", "20");
  r1 = frange_float ("5",  "15");
  r0.intersect (r1);
  ASSERT_EQ (r0, frange_float ("10", "15"));

  // [10,20] ^ [15,25] = [15,20]
  r0 = frange_float ("10", "20");
  r1 = frange_float ("15", "25");
  r0.intersect (r1);
  ASSERT_EQ (r0, frange_float ("15", "20"));

  // [10,20] ^ [21,25] = []
  r0 = frange_float ("10", "20");
  r0.clear_nan ();
  r1 = frange_float ("21", "25");
  r1.clear_nan ();
  r0.intersect (r1);
  ASSERT_TRUE (r0.undefined_p ());

  if (HONOR_INFINITIES (float_type_node))
    {
      // Make sure [-Inf, -Inf] doesn't get normalized.
      r0 = frange_float ("-Inf", "-Inf");
      ASSERT_TRUE (real_isinf (&r0.lower_bound (), true));
      ASSERT_TRUE (real_isinf (&r0.upper_bound (), true));
    }

  // Test that reading back a global range yields the same result as
  // what we wrote into it.
  tree ssa = make_temp_ssa_name (float_type_node, NULL, "blah");
  r0.set_varying (float_type_node);
  r0.clear_nan ();
  set_range_info (ssa, r0);
  get_global_range_query ()->range_of_expr (r1, ssa);
  ASSERT_EQ (r0, r1);
}

// Run floating range tests for various combinations of NAN and INF
// support.

static void
range_tests_floats_various ()
{
  int save_finite_math_only = flag_finite_math_only;

  // Test -ffinite-math-only.
  flag_finite_math_only = 1;
  range_tests_floats ();
  // Test -fno-finite-math-only.
  flag_finite_math_only = 0;
  range_tests_floats ();

  flag_finite_math_only = save_finite_math_only;
}

void
range_tests ()
{
  range_tests_irange3 ();
  range_tests_int_range_max ();
  range_tests_strict_enum ();
  range_tests_nonzero_bits ();
  range_tests_floats_various ();
  range_tests_misc ();
}

} // namespace selftest

#endif // CHECKING_P