1 /* A class for building vector rtx constants. 2 Copyright (C) 2017-2018 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free 8 Software Foundation; either version 3, or (at your option) any later 9 version. 10 11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20 #include "config.h" 21 #include "system.h" 22 #include "coretypes.h" 23 #include "tm.h" 24 #include "rtl.h" 25 #include "rtx-vector-builder.h" 26 27 /* Return a CONST_VECTOR for the current constant. V is an existing 28 rtvec that contains all the elements. */ 29 30 rtx 31 rtx_vector_builder::build (rtvec v) 32 { 33 finalize (); 34 35 rtx x = find_cached_value (); 36 if (x) 37 return x; 38 39 x = gen_rtx_raw_CONST_VECTOR (m_mode, v); 40 CONST_VECTOR_NPATTERNS (x) = npatterns (); 41 CONST_VECTOR_NELTS_PER_PATTERN (x) = nelts_per_pattern (); 42 return x; 43 } 44 45 /* Return a vector element with the value BASE + FACTOR * STEP. */ 46 47 rtx 48 rtx_vector_builder::apply_step (rtx base, unsigned int factor, 49 const wide_int &step) const 50 { 51 scalar_int_mode int_mode = as_a <scalar_int_mode> (GET_MODE_INNER (m_mode)); 52 return immed_wide_int_const (wi::add (rtx_mode_t (base, int_mode), 53 factor * step), 54 int_mode); 55 } 56 57 /* Return a CONST_VECTOR for the current constant. */ 58 59 rtx 60 rtx_vector_builder::build () 61 { 62 finalize (); 63 64 rtx x = find_cached_value (); 65 if (x) 66 return x; 67 68 unsigned int nelts; 69 if (!GET_MODE_NUNITS (m_mode).is_constant (&nelts)) 70 nelts = encoded_nelts (); 71 rtvec v = rtvec_alloc (nelts); 72 for (unsigned int i = 0; i < nelts; ++i) 73 RTVEC_ELT (v, i) = elt (i); 74 x = gen_rtx_raw_CONST_VECTOR (m_mode, v); 75 CONST_VECTOR_NPATTERNS (x) = npatterns (); 76 CONST_VECTOR_NELTS_PER_PATTERN (x) = nelts_per_pattern (); 77 return x; 78 } 79 80 /* Check whether there is a global cached value for the vector. 81 Return it if so, otherwise return null. */ 82 83 rtx 84 rtx_vector_builder::find_cached_value () 85 { 86 if (encoded_nelts () != 1) 87 return NULL_RTX; 88 89 rtx elt = (*this)[0]; 90 91 if (GET_MODE_CLASS (m_mode) == MODE_VECTOR_BOOL) 92 { 93 if (elt == const1_rtx || elt == constm1_rtx) 94 return CONST1_RTX (m_mode); 95 else if (elt == const0_rtx) 96 return CONST0_RTX (m_mode); 97 else 98 gcc_unreachable (); 99 } 100 101 /* We can be called before the global vector constants are set up, 102 but in that case we'll just return null. */ 103 scalar_mode inner_mode = GET_MODE_INNER (m_mode); 104 if (elt == CONST0_RTX (inner_mode)) 105 return CONST0_RTX (m_mode); 106 else if (elt == CONST1_RTX (inner_mode)) 107 return CONST1_RTX (m_mode); 108 else if (elt == CONSTM1_RTX (inner_mode)) 109 return CONSTM1_RTX (m_mode); 110 111 return NULL_RTX; 112 } 113