view gcc/tree-vector-builder.c @ 144:8f4e72ab4e11

fix segmentation fault caused by nothing next cur_op to end
author Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Sun, 23 Dec 2018 21:23:56 +0900
parents 84e7813d76e9
children 1830386684a0
line wrap: on
line source

/* A class for building vector tree constants.
   Copyright (C) 2017-2018 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/>.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
#include "fold-const.h"
#include "tree-vector-builder.h"

/* Try to start building a new vector of type TYPE that holds the result of
   a unary operation on VECTOR_CST T.  ALLOW_STEPPED_P is true if the
   operation can handle stepped encodings directly, without having to
   expand the full sequence.

   Return true if the operation is possible, which it always is when
   ALLOW_STEPPED_P is true.  Leave the builder unchanged otherwise.  */

bool
tree_vector_builder::new_unary_operation (tree type, tree t,
					  bool allow_stepped_p)
{
  poly_uint64 full_nelts = TYPE_VECTOR_SUBPARTS (type);
  gcc_assert (known_eq (full_nelts, TYPE_VECTOR_SUBPARTS (TREE_TYPE (t))));
  unsigned int npatterns = VECTOR_CST_NPATTERNS (t);
  unsigned int nelts_per_pattern = VECTOR_CST_NELTS_PER_PATTERN (t);
  if (!allow_stepped_p && nelts_per_pattern > 2)
    {
      if (!full_nelts.is_constant ())
	return false;
      npatterns = full_nelts.to_constant ();
      nelts_per_pattern = 1;
    }
  new_vector (type, npatterns, nelts_per_pattern);
  return true;
}

/* Try to start building a new vector of type TYPE that holds the result of
   a binary operation on VECTOR_CSTs T1 and T2.  ALLOW_STEPPED_P is true if
   the operation can handle stepped encodings directly, without having to
   expand the full sequence.

   Return true if the operation is possible.  Leave the builder unchanged
   otherwise.  */

bool
tree_vector_builder::new_binary_operation (tree type, tree t1, tree t2,
					   bool allow_stepped_p)
{
  poly_uint64 full_nelts = TYPE_VECTOR_SUBPARTS (type);
  gcc_assert (known_eq (full_nelts, TYPE_VECTOR_SUBPARTS (TREE_TYPE (t1)))
	      && known_eq (full_nelts, TYPE_VECTOR_SUBPARTS (TREE_TYPE (t2))));
  /* Conceptually we split the patterns in T1 and T2 until we have
     an equal number for both.  Each split pattern requires the same
     number of elements per pattern as the original.  E.g. splitting:

       { 1, 2, 3, ... }

     into two gives:

       { 1, 3, 5, ... }
       { 2, 4, 6, ... }

     while splitting:

       { 1, 0, ... }

     into two gives:

       { 1, 0, ... }
       { 0, 0, ... }.  */
  unsigned int npatterns = least_common_multiple (VECTOR_CST_NPATTERNS (t1),
						  VECTOR_CST_NPATTERNS (t2));
  unsigned int nelts_per_pattern = MAX (VECTOR_CST_NELTS_PER_PATTERN (t1),
					VECTOR_CST_NELTS_PER_PATTERN (t2));
  if (!allow_stepped_p && nelts_per_pattern > 2)
    {
      if (!full_nelts.is_constant ())
	return false;
      npatterns = full_nelts.to_constant ();
      nelts_per_pattern = 1;
    }
  new_vector (type, npatterns, nelts_per_pattern);
  return true;
}

/* Return the number of elements that the caller needs to operate on in
   order to handle a binary operation on VECTOR_CSTs T1 and T2.  This static
   function is used instead of new_binary_operation if the result of the
   operation is not a VECTOR_CST.  */

unsigned int
tree_vector_builder::binary_encoded_nelts (tree t1, tree t2)
{
  poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (t1));
  gcc_assert (known_eq (nelts, TYPE_VECTOR_SUBPARTS (TREE_TYPE (t2))));
  /* See new_binary_operation for details.  */
  unsigned int npatterns = least_common_multiple (VECTOR_CST_NPATTERNS (t1),
						  VECTOR_CST_NPATTERNS (t2));
  unsigned int nelts_per_pattern = MAX (VECTOR_CST_NELTS_PER_PATTERN (t1),
					VECTOR_CST_NELTS_PER_PATTERN (t2));
  unsigned HOST_WIDE_INT const_nelts;
  if (nelts.is_constant (&const_nelts))
    return MIN (npatterns * nelts_per_pattern, const_nelts);
  return npatterns * nelts_per_pattern;
}

/* Return a vector element with the value BASE + FACTOR * STEP.  */

tree
tree_vector_builder::apply_step (tree base, unsigned int factor,
				 const wide_int &step) const
{
  return wide_int_to_tree (TREE_TYPE (base),
			   wi::to_wide (base) + factor * step);
}

/* Return a VECTOR_CST for the current constant.  */

tree
tree_vector_builder::build ()
{
  finalize ();
  gcc_assert (pow2p_hwi (npatterns ()));
  tree v = make_vector (exact_log2 (npatterns ()), nelts_per_pattern ());
  TREE_TYPE (v) = m_type;
  memcpy (VECTOR_CST_ENCODED_ELTS (v), address (),
	  encoded_nelts () * sizeof (tree));
  return v;
}