/* A class for building vector tree 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_TREE_VECTOR_BUILDER_H
#define GCC_TREE_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 tree_vector_builder : public vector_builder<tree, tree,
						  tree_vector_builder>
{
  typedef vector_builder<tree, tree, tree_vector_builder> parent;
  friend class vector_builder<tree, tree, tree_vector_builder>;

public:
  tree_vector_builder () : m_type (0) {}
  tree_vector_builder (tree, unsigned int, unsigned int);
  tree build ();

  tree type () const { return m_type; }

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

private:
  bool equal_p (const_tree, const_tree) const;
  bool allow_steps_p () const;
  bool integral_p (const_tree) const;
  wide_int step (const_tree, const_tree) const;
  tree apply_step (tree, unsigned int, const wide_int &) const;
  bool can_elide_p (const_tree) const;
  void note_representative (tree *, tree);

  static poly_uint64 shape_nelts (const_tree t)
    { return TYPE_VECTOR_SUBPARTS (t); }
  static poly_uint64 nelts_of (const_tree t)
    { return VECTOR_CST_NELTS (t); }
  static unsigned int npatterns_of (const_tree t)
    { return VECTOR_CST_NPATTERNS (t); }
  static unsigned int nelts_per_pattern_of (const_tree t)
    { return VECTOR_CST_NELTS_PER_PATTERN (t); }

  tree m_type;
};

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

inline
tree_vector_builder::tree_vector_builder (tree type, unsigned int npatterns,
					  unsigned int nelts_per_pattern)
{
  new_vector (type, npatterns, nelts_per_pattern);
}

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

inline void
tree_vector_builder::new_vector (tree type, unsigned int npatterns,
				 unsigned int nelts_per_pattern)
{
  m_type = type;
  parent::new_vector (TYPE_VECTOR_SUBPARTS (type), npatterns,
		      nelts_per_pattern);
}

/* Return true if elements I1 and I2 are equal.  */

inline bool
tree_vector_builder::equal_p (const_tree elt1, const_tree elt2) const
{
  return operand_equal_p (elt1, elt2, OEP_BITWISE);
}

/* 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
tree_vector_builder::allow_steps_p () const
{
  return INTEGRAL_TYPE_P (TREE_TYPE (m_type));
}

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

inline bool
tree_vector_builder::integral_p (const_tree elt) const
{
  return TREE_CODE (elt) == INTEGER_CST;
}

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

inline wide_int
tree_vector_builder::step (const_tree elt1, const_tree elt2) const
{
  return wi::to_wide (elt2) - wi::to_wide (elt1);
}

/* Return true if we can drop element ELT, even if the retained elements
   are different.  Return false if this would mean losing overflow
   information.  */

inline bool
tree_vector_builder::can_elide_p (const_tree elt) const
{
  return !CONSTANT_CLASS_P (elt) || !TREE_OVERFLOW (elt);
}

/* Record that ELT2 is being elided, given that ELT1_PTR points to the last
   encoded element for the containing pattern.  */

inline void
tree_vector_builder::note_representative (tree *elt1_ptr, tree elt2)
{
  if (CONSTANT_CLASS_P (elt2) && TREE_OVERFLOW (elt2))
    {
      gcc_assert (operand_equal_p (*elt1_ptr, elt2, 0));
      if (!TREE_OVERFLOW (elt2))
	*elt1_ptr = elt2;
    }
}

#endif
