/* A class for building vector rtx 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 . */ #include "config.h" #include "system.h" #include "coretypes.h" #include "tm.h" #include "rtl.h" #include "rtx-vector-builder.h" /* Return a CONST_VECTOR for the current constant. V is an existing rtvec that contains all the elements. */ rtx rtx_vector_builder::build (rtvec v) { finalize (); rtx x = find_cached_value (); if (x) return x; x = gen_rtx_raw_CONST_VECTOR (m_mode, v); CONST_VECTOR_NPATTERNS (x) = npatterns (); CONST_VECTOR_NELTS_PER_PATTERN (x) = nelts_per_pattern (); return x; } /* Return a vector element with the value BASE + FACTOR * STEP. */ rtx rtx_vector_builder::apply_step (rtx base, unsigned int factor, const wide_int &step) const { scalar_int_mode int_mode = as_a (GET_MODE_INNER (m_mode)); return immed_wide_int_const (wi::add (rtx_mode_t (base, int_mode), factor * step), int_mode); } /* Return a CONST_VECTOR for the current constant. */ rtx rtx_vector_builder::build () { finalize (); rtx x = find_cached_value (); if (x) return x; unsigned int nelts; if (!GET_MODE_NUNITS (m_mode).is_constant (&nelts)) nelts = encoded_nelts (); rtvec v = rtvec_alloc (nelts); for (unsigned int i = 0; i < nelts; ++i) RTVEC_ELT (v, i) = elt (i); x = gen_rtx_raw_CONST_VECTOR (m_mode, v); CONST_VECTOR_NPATTERNS (x) = npatterns (); CONST_VECTOR_NELTS_PER_PATTERN (x) = nelts_per_pattern (); return x; } /* Check whether there is a global cached value for the vector. Return it if so, otherwise return null. */ rtx rtx_vector_builder::find_cached_value () { if (encoded_nelts () != 1) return NULL_RTX; rtx elt = (*this)[0]; if (GET_MODE_CLASS (m_mode) == MODE_VECTOR_BOOL) { if (elt == const1_rtx || elt == constm1_rtx) return CONST1_RTX (m_mode); else if (elt == const0_rtx) return CONST0_RTX (m_mode); else gcc_unreachable (); } /* We can be called before the global vector constants are set up, but in that case we'll just return null. */ scalar_mode inner_mode = GET_MODE_INNER (m_mode); if (elt == CONST0_RTX (inner_mode)) return CONST0_RTX (m_mode); else if (elt == CONST1_RTX (inner_mode)) return CONST1_RTX (m_mode); else if (elt == CONSTM1_RTX (inner_mode)) return CONSTM1_RTX (m_mode); return NULL_RTX; }