/* Support routines for vrange storage.
   Copyright (C) 2022 Free Software Foundation, Inc.
   Contributed by Aldy Hernandez <aldyh@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 "fold-const.h"
#include "gimple-range.h"
#include "value-range-storage.h"

// Return a newly allocated slot holding R, or NULL if storing a range
// of R's type is not supported.

void *
vrange_storage::alloc_slot (const vrange &r)
{
  gcc_checking_assert (m_alloc);

  if (is_a <irange> (r))
    return irange_storage_slot::alloc_slot (*m_alloc, as_a <irange> (r));
  if (is_a <frange> (r))
    return frange_storage_slot::alloc_slot (*m_alloc, as_a <frange> (r));
  return NULL;
}

// Set SLOT to R.

void
vrange_storage::set_vrange (void *slot, const vrange &r)
{
  if (is_a <irange> (r))
    {
      irange_storage_slot *s = static_cast <irange_storage_slot *> (slot);
      gcc_checking_assert (s->fits_p (as_a <irange> (r)));
      s->set_irange (as_a <irange> (r));
    }
  else if (is_a <frange> (r))
    {
      frange_storage_slot *s = static_cast <frange_storage_slot *> (slot);
      gcc_checking_assert (s->fits_p (as_a <frange> (r)));
      s->set_frange (as_a <frange> (r));
    }
  else
    gcc_unreachable ();
}

// Restore R from SLOT.  TYPE is the type of R.

void
vrange_storage::get_vrange (const void *slot, vrange &r, tree type)
{
  if (is_a <irange> (r))
    {
      const irange_storage_slot *s
	= static_cast <const irange_storage_slot *> (slot);
      s->get_irange (as_a <irange> (r), type);
    }
  else if (is_a <frange> (r))
    {
      const frange_storage_slot *s
	= static_cast <const frange_storage_slot *> (slot);
      s->get_frange (as_a <frange> (r), type);
    }
  else
    gcc_unreachable ();
}

// Return TRUE if SLOT can fit R.

bool
vrange_storage::fits_p (const void *slot, const vrange &r)
{
  if (is_a <irange> (r))
    {
      const irange_storage_slot *s
	= static_cast <const irange_storage_slot *> (slot);
      return s->fits_p (as_a <irange> (r));
    }
  if (is_a <frange> (r))
    {
      const frange_storage_slot *s
	= static_cast <const frange_storage_slot *> (slot);
      return s->fits_p (as_a <frange> (r));
    }
  gcc_unreachable ();
  return false;
}

// Factory that creates a new irange_storage_slot object containing R.
// This is the only way to construct an irange slot as stack creation
// is disallowed.

irange_storage_slot *
irange_storage_slot::alloc_slot (vrange_allocator &allocator, const irange &r)
{
  size_t size = irange_storage_slot::size (r);
  irange_storage_slot *p
    = static_cast <irange_storage_slot *> (allocator.alloc (size));
  new (p) irange_storage_slot (r);
  return p;
}

// Initialize the current slot with R.

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

  unsigned prec = TYPE_PRECISION (r.type ());
  unsigned n = num_wide_ints_needed (r);
  if (n > MAX_INTS)
    {
      int_range<MAX_PAIRS> squash (r);
      m_ints.set_precision (prec, num_wide_ints_needed (squash));
      set_irange (squash);
    }
  else
    {
      m_ints.set_precision (prec, n);
      set_irange (r);
    }
}

// Store R into the current slot.

void
irange_storage_slot::set_irange (const irange &r)
{
  gcc_checking_assert (fits_p (r));

  m_ints[0] = r.get_nonzero_bits ();

  unsigned pairs = r.num_pairs ();
  for (unsigned i = 0; i < pairs; ++i)
    {
      m_ints[i*2 + 1] = r.lower_bound (i);
      m_ints[i*2 + 2] = r.upper_bound (i);
    }
}

// Restore a range of TYPE from the current slot into R.

void
irange_storage_slot::get_irange (irange &r, tree type) const
{
  gcc_checking_assert (TYPE_PRECISION (type) == m_ints.get_precision ());

  r.set_undefined ();
  unsigned nelements = m_ints.num_elements ();
  for (unsigned i = 1; i < nelements; i += 2)
    {
      int_range<2> tmp (type, m_ints[i], m_ints[i + 1]);
      r.union_ (tmp);
    }
  r.set_nonzero_bits (get_nonzero_bits ());
}

// Return the size in bytes to allocate a slot that can hold R.

size_t
irange_storage_slot::size (const irange &r)
{
  gcc_checking_assert (!r.undefined_p ());

  unsigned prec = TYPE_PRECISION (r.type ());
  unsigned n = num_wide_ints_needed (r);
  if (n > MAX_INTS)
    n = MAX_INTS;
  return (sizeof (irange_storage_slot)
	  + trailing_wide_ints<MAX_INTS>::extra_size (prec, n));
}

// Return the number of wide ints needed to represent R.

unsigned int
irange_storage_slot::num_wide_ints_needed (const irange &r)
{
  return r.num_pairs () * 2 + 1;
}

// Return TRUE if R fits in the current slot.

bool
irange_storage_slot::fits_p (const irange &r) const
{
  return m_ints.num_elements () >= num_wide_ints_needed (r);
}

// Dump the current slot.

void
irange_storage_slot::dump () const
{
  fprintf (stderr, "raw irange_storage_slot:\n");
  for (unsigned i = 1; i < m_ints.num_elements (); i += 2)
    {
      m_ints[i].dump ();
      m_ints[i + 1].dump ();
    }
  fprintf (stderr, "NONZERO ");
  wide_int nz = get_nonzero_bits ();
  nz.dump ();
}

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

// Implementation of frange_storage_slot.

frange_storage_slot *
frange_storage_slot::alloc_slot (vrange_allocator &allocator, const frange &r)
{
  size_t size = sizeof (frange_storage_slot);
  frange_storage_slot *p
    = static_cast <frange_storage_slot *> (allocator.alloc (size));
  new (p) frange_storage_slot (r);
  return p;
}

void
frange_storage_slot::set_frange (const frange &r)
{
  gcc_checking_assert (fits_p (r));
  gcc_checking_assert (!r.undefined_p ());

  m_kind = r.m_kind;
  m_min = r.m_min;
  m_max = r.m_max;
  m_pos_nan = r.m_pos_nan;
  m_neg_nan = r.m_neg_nan;
}

void
frange_storage_slot::get_frange (frange &r, tree type) const
{
  gcc_checking_assert (r.supports_type_p (type));

  // Handle explicit NANs.
  if (m_kind == VR_NAN)
    {
      if (HONOR_NANS (type))
	{
	  if (m_pos_nan && m_neg_nan)
	    r.set_nan (type);
	  else
	    r.set_nan (type, m_neg_nan);
	}
      else
	r.set_undefined ();
      return;
    }

  // We use the constructor to create the new range instead of writing
  // out the bits into the frange directly, because the global range
  // being read may be being inlined into a function with different
  // restrictions as when it was originally written.  We want to make
  // sure the resulting range is canonicalized correctly for the new
  // consumer.
  r = frange (type, m_min, m_max, m_kind);

  // The constructor will set the NAN bits for HONOR_NANS, but we must
  // make sure to set the NAN sign if known.
  if (HONOR_NANS (type) && (m_pos_nan ^ m_neg_nan) == 1)
    r.update_nan (m_neg_nan);
  else if (!m_pos_nan && !m_neg_nan)
    r.clear_nan ();
}

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