mirror of
https://github.com/autc04/Retro68.git
synced 2024-09-29 10:55:00 +00:00
147 lines
4.9 KiB
C
147 lines
4.9 KiB
C
/* 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;
|
|
}
|