123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- /* RTL iterators
- Copyright (C) 2014-2019 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/>. */
- /* This structure describes the subrtxes of an rtx as follows:
- - if the rtx has no subrtxes, START and COUNT are both 0.
- - if all the subrtxes of an rtx are stored in a contiguous block
- of XEXPs ("e"s), START is the index of the first XEXP and COUNT
- is the number of them.
- - otherwise START is arbitrary and COUNT is UCHAR_MAX.
- rtx_all_subrtx_bounds applies to all codes. rtx_nonconst_subrtx_bounds
- is like rtx_all_subrtx_bounds except that all constant rtxes are treated
- as having no subrtxes. */
- struct rtx_subrtx_bound_info {
- unsigned char start;
- unsigned char count;
- };
- extern rtx_subrtx_bound_info rtx_all_subrtx_bounds[];
- extern rtx_subrtx_bound_info rtx_nonconst_subrtx_bounds[];
- /* Return true if CODE has no subrtxes. */
- static inline bool
- leaf_code_p (enum rtx_code code)
- {
- return rtx_all_subrtx_bounds[code].count == 0;
- }
- /* Used to iterate over subrtxes of an rtx. T abstracts the type of
- access. */
- template <typename T>
- class generic_subrtx_iterator
- {
- static const size_t LOCAL_ELEMS = 16;
- typedef typename T::value_type value_type;
- typedef typename T::rtx_type rtx_type;
- typedef typename T::rtunion_type rtunion_type;
- public:
- struct array_type
- {
- array_type ();
- ~array_type ();
- value_type stack[LOCAL_ELEMS];
- vec <value_type, va_heap, vl_embed> *heap;
- };
- generic_subrtx_iterator (array_type &, value_type,
- const rtx_subrtx_bound_info *);
- value_type operator * () const;
- bool at_end () const;
- void next ();
- void skip_subrtxes ();
- void substitute (value_type);
- private:
- /* The bounds to use for iterating over subrtxes. */
- const rtx_subrtx_bound_info *m_bounds;
- /* The storage used for the worklist. */
- array_type &m_array;
- /* The current rtx. */
- value_type m_current;
- /* The base of the current worklist. */
- value_type *m_base;
- /* The number of subrtxes in M_BASE. */
- size_t m_end;
- /* The following booleans shouldn't end up in registers or memory
- but just direct control flow. */
- /* True if the iteration is over. */
- bool m_done;
- /* True if we should skip the subrtxes of M_CURRENT. */
- bool m_skip;
- /* True if M_CURRENT has been replaced with a different rtx. */
- bool m_substitute;
- static void free_array (array_type &);
- static size_t add_subrtxes_to_queue (array_type &, value_type *, size_t,
- rtx_type);
- static value_type *add_single_to_queue (array_type &, value_type *, size_t,
- value_type);
- };
- template <typename T>
- inline generic_subrtx_iterator <T>::array_type::array_type () : heap (0) {}
- template <typename T>
- inline generic_subrtx_iterator <T>::array_type::~array_type ()
- {
- if (__builtin_expect (heap != 0, false))
- free_array (*this);
- }
- /* Iterate over X and its subrtxes, in arbitrary order. Use ARRAY to
- store the worklist. We use an external array in order to avoid
- capturing the fields of this structure when taking the address of
- the array. Use BOUNDS to find the bounds of simple "e"-string codes. */
- template <typename T>
- inline generic_subrtx_iterator <T>::
- generic_subrtx_iterator (array_type &array, value_type x,
- const rtx_subrtx_bound_info *bounds)
- : m_bounds (bounds),
- m_array (array),
- m_current (x),
- m_base (m_array.stack),
- m_end (0),
- m_done (false),
- m_skip (false),
- m_substitute (false)
- {
- }
- /* Return the current subrtx. */
- template <typename T>
- inline typename T::value_type
- generic_subrtx_iterator <T>::operator * () const
- {
- return m_current;
- }
- /* Return true if the iteration has finished. */
- template <typename T>
- inline bool
- generic_subrtx_iterator <T>::at_end () const
- {
- return m_done;
- }
- /* Move on to the next subrtx. */
- template <typename T>
- inline void
- generic_subrtx_iterator <T>::next ()
- {
- if (m_substitute)
- {
- m_substitute = false;
- m_skip = false;
- return;
- }
- if (!m_skip)
- {
- /* Add the subrtxes of M_CURRENT. */
- rtx_type x = T::get_rtx (m_current);
- if (__builtin_expect (x != 0, true))
- {
- enum rtx_code code = GET_CODE (x);
- ssize_t count = m_bounds[code].count;
- if (count > 0)
- {
- /* Handle the simple case of a single "e" block that is known
- to fit into the current array. */
- if (__builtin_expect (m_end + count <= LOCAL_ELEMS + 1, true))
- {
- /* Set M_CURRENT to the first subrtx and queue the rest. */
- ssize_t start = m_bounds[code].start;
- rtunion_type *src = &x->u.fld[start];
- if (__builtin_expect (count > 2, false))
- m_base[m_end++] = T::get_value (src[2].rt_rtx);
- if (count > 1)
- m_base[m_end++] = T::get_value (src[1].rt_rtx);
- m_current = T::get_value (src[0].rt_rtx);
- return;
- }
- /* Handle cases which aren't simple "e" sequences or where
- the sequence might overrun M_BASE. */
- count = add_subrtxes_to_queue (m_array, m_base, m_end, x);
- if (count > 0)
- {
- m_end += count;
- if (m_end > LOCAL_ELEMS)
- m_base = m_array.heap->address ();
- m_current = m_base[--m_end];
- return;
- }
- }
- }
- }
- else
- m_skip = false;
- if (m_end == 0)
- m_done = true;
- else
- m_current = m_base[--m_end];
- }
- /* Skip the subrtxes of the current rtx. */
- template <typename T>
- inline void
- generic_subrtx_iterator <T>::skip_subrtxes ()
- {
- m_skip = true;
- }
- /* Ignore the subrtxes of the current rtx and look at X instead. */
- template <typename T>
- inline void
- generic_subrtx_iterator <T>::substitute (value_type x)
- {
- m_substitute = true;
- m_current = x;
- }
- /* Iterators for const_rtx. */
- struct const_rtx_accessor
- {
- typedef const_rtx value_type;
- typedef const_rtx rtx_type;
- typedef const rtunion rtunion_type;
- static rtx_type get_rtx (value_type x) { return x; }
- static value_type get_value (rtx_type x) { return x; }
- };
- typedef generic_subrtx_iterator <const_rtx_accessor> subrtx_iterator;
- /* Iterators for non-constant rtx. */
- struct rtx_var_accessor
- {
- typedef rtx value_type;
- typedef rtx rtx_type;
- typedef rtunion rtunion_type;
- static rtx_type get_rtx (value_type x) { return x; }
- static value_type get_value (rtx_type x) { return x; }
- };
- typedef generic_subrtx_iterator <rtx_var_accessor> subrtx_var_iterator;
- /* Iterators for rtx *. */
- struct rtx_ptr_accessor
- {
- typedef rtx *value_type;
- typedef rtx rtx_type;
- typedef rtunion rtunion_type;
- static rtx_type get_rtx (value_type ptr) { return *ptr; }
- static value_type get_value (rtx_type &x) { return &x; }
- };
- typedef generic_subrtx_iterator <rtx_ptr_accessor> subrtx_ptr_iterator;
- #define ALL_BOUNDS rtx_all_subrtx_bounds
- #define NONCONST_BOUNDS rtx_nonconst_subrtx_bounds
- /* Use ITER to iterate over const_rtx X and its recursive subrtxes,
- using subrtx_iterator::array ARRAY as the storage for the worklist.
- ARRAY can be reused for multiple consecutive iterations but shouldn't
- be shared by two concurrent iterations. TYPE is ALL if all subrtxes
- are of interest or NONCONST if it is safe to ignore subrtxes of
- constants. */
- #define FOR_EACH_SUBRTX(ITER, ARRAY, X, TYPE) \
- for (subrtx_iterator ITER (ARRAY, X, TYPE##_BOUNDS); !ITER.at_end (); \
- ITER.next ())
- /* Like FOR_EACH_SUBRTX, but iterate over subrtxes of an rtx X. */
- #define FOR_EACH_SUBRTX_VAR(ITER, ARRAY, X, TYPE) \
- for (subrtx_var_iterator ITER (ARRAY, X, TYPE##_BOUNDS); !ITER.at_end (); \
- ITER.next ())
- /* Like FOR_EACH_SUBRTX, but iterate over subrtx pointers of rtx pointer X.
- For example, if X is &PATTERN (insn) and the pattern is a SET, iterate
- over &PATTERN (insn), &SET_DEST (PATTERN (insn)), etc. */
- #define FOR_EACH_SUBRTX_PTR(ITER, ARRAY, X, TYPE) \
- for (subrtx_ptr_iterator ITER (ARRAY, X, TYPE##_BOUNDS); !ITER.at_end (); \
- ITER.next ())
|