/* A class for building vector rtx constants.
   Copyright (C) 2017-2021 Free Software Foundation, Inc.

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/>.  */

#ifndef GCC_RTX_VECTOR_BUILDER_H
#define GCC_RTX_VECTOR_BUILDER_H

#include "vector-builder.h"

/* This class is used to build VECTOR_CSTs from a sequence of elements.
   See vector_builder for more details.  */
class rtx_vector_builder : public vector_builder<rtx, machine_mode,
						 rtx_vector_builder>
{
  typedef vector_builder<rtx, machine_mode, rtx_vector_builder> parent;
  friend class vector_builder<rtx, machine_mode, rtx_vector_builder>;

public:
  rtx_vector_builder () : m_mode (VOIDmode) {}
  rtx_vector_builder (machine_mode, unsigned int, unsigned int);
  rtx build (rtvec);
  rtx build ();

  machine_mode mode () const { return m_mode; }

  void new_vector (machine_mode, unsigned int, unsigned int);

private:
  bool equal_p (rtx, rtx) const;
  bool allow_steps_p () const;
  bool integral_p (rtx) const;
  poly_wide_int step (rtx, rtx) const;
  rtx apply_step (rtx, unsigned int, const poly_wide_int &) const;
  bool can_elide_p (rtx) const { return true; }
  void note_representative (rtx *, rtx) {}

  static poly_uint64 shape_nelts (machine_mode mode)
    { return GET_MODE_NUNITS (mode); }
  static poly_uint64 nelts_of (const_rtx x)
    { return CONST_VECTOR_NUNITS (x); }
  static unsigned int npatterns_of (const_rtx x)
    { return CONST_VECTOR_NPATTERNS (x); }
  static unsigned int nelts_per_pattern_of (const_rtx x)
    { return CONST_VECTOR_NELTS_PER_PATTERN (x); }

  rtx find_cached_value ();

  machine_mode m_mode;
};

/* Create a new builder for a vector of mode MODE.  Initially encode the
   value as NPATTERNS interleaved patterns with NELTS_PER_PATTERN elements
   each.  */

inline
rtx_vector_builder::rtx_vector_builder (machine_mode mode,
					unsigned int npatterns,
					unsigned int nelts_per_pattern)
{
  new_vector (mode, npatterns, nelts_per_pattern);
}

/* Start building a new vector of mode MODE.  Initially encode the value
   as NPATTERNS interleaved patterns with NELTS_PER_PATTERN elements each.  */

inline void
rtx_vector_builder::new_vector (machine_mode mode, unsigned int npatterns,
				unsigned int nelts_per_pattern)
{
  m_mode = mode;
  parent::new_vector (GET_MODE_NUNITS (mode), npatterns, nelts_per_pattern);
}

/* Return true if elements ELT1 and ELT2 are equal.  */

inline bool
rtx_vector_builder::equal_p (rtx elt1, rtx elt2) const
{
  return rtx_equal_p (elt1, elt2);
}

/* Return true if a stepped representation is OK.  We don't allow
   linear series for anything other than integers, to avoid problems
   with rounding.  */

inline bool
rtx_vector_builder::allow_steps_p () const
{
  return is_a <scalar_int_mode> (GET_MODE_INNER (m_mode));
}

/* Return true if element ELT can be interpreted as an integer.  */

inline bool
rtx_vector_builder::integral_p (rtx elt) const
{
  return CONST_SCALAR_INT_P (elt);
}

/* Return the value of element ELT2 minus the value of element ELT1.
   Both elements are known to be CONST_SCALAR_INT_Ps.  */

inline poly_wide_int
rtx_vector_builder::step (rtx elt1, rtx elt2) const
{
  return (wi::to_poly_wide (elt2, GET_MODE_INNER (m_mode))
	  - wi::to_poly_wide (elt1, GET_MODE_INNER (m_mode)));
}

#endif
