| // Basic-block-related classes for RTL SSA -*- C++ -*- |
| // Copyright (C) 2020-2021 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/>. |
| |
| namespace rtl_ssa { |
| |
| // SSA-related information about a basic block. Each block contains |
| // the following, which are conceptually executed in order: |
| // |
| // - an artificial "head" insn_info that holds artificial uses and definitions |
| // for the start of the block. |
| // |
| // - one insn_info for each "real" instruction in the block |
| // (i.e. those that have an RTL pattern). |
| // |
| // - an artificial "end" insn_info that holds artificial uses and definitions |
| // for the end of the block. |
| // |
| // Blocks are grouped together into extended basic blocks. In cases where |
| // multiple EBBs exist (such as in a full diamond), we try to pick the one |
| // that's most frequently executed. |
| // |
| // Blocks are chained together in reverse postorder. (Rather than use a |
| // list, we could instead have stored the index of the block in the overall |
| // postorder. However, using lists should make it cheaper to update the |
| // information after trivial CFG manipulations.) |
| class bb_info |
| { |
| // Size: 6 LP64 words. |
| friend class function_info; |
| |
| public: |
| // Return the previous basic block in reverse postorder, or null if this |
| // is the entry block. |
| bb_info *prev_bb () const { return m_prev_bb; } |
| |
| // Return the next basic block in reverse postorder, or null if this |
| // is the exit block. |
| bb_info *next_bb () const { return m_next_bb; } |
| |
| // Return true if this block is the function's entry block. |
| bool is_entry_block () const { return !m_prev_bb; } |
| |
| // Return true if this block is the function's exit block. |
| bool is_exit_block () const { return !m_next_bb; } |
| |
| // Return the underlying basic_block structure. |
| basic_block cfg_bb () const { return m_cfg_bb; } |
| |
| // Return the unique identifier of the underlying basic_block. These uids |
| // do not follow any particular order. |
| unsigned int index () const { return m_cfg_bb->index; } |
| |
| // Return the EBB that contains this block. |
| ebb_info *ebb () const { return m_ebb; } |
| |
| // Return a list of all the instructions in the block, in execution order. |
| // The list includes the head and end instructions described above. |
| // |
| // Iterations over the list will pick up any new instructions that are |
| // inserted after the iterator's current instruction. |
| iterator_range<any_insn_iterator> all_insns () const; |
| |
| // Like all_insns (), except that the instructions are in reverse order. |
| // |
| // Iterations over the list will pick up any new instructions that are |
| // inserted before the iterator's current instruction. |
| iterator_range<reverse_any_insn_iterator> reverse_all_insns () const; |
| |
| // Like all_insns (), but without the debug instructions. |
| iterator_range<nondebug_insn_iterator> nondebug_insns () const; |
| |
| // Like reverse_all_insns (), but without the debug instructions. |
| iterator_range<reverse_nondebug_insn_iterator> |
| reverse_nondebug_insns () const; |
| |
| // Like all_insns (), but without the artificial instructions. |
| iterator_range<any_insn_iterator> real_insns () const; |
| |
| // Like reverse_all_insns (), but without the artificial instructions. |
| iterator_range<reverse_any_insn_iterator> reverse_real_insns () const; |
| |
| // Like real_insns (), but without the debug instructions. |
| iterator_range<nondebug_insn_iterator> real_nondebug_insns () const; |
| |
| // Like reverse_real_insns (), but without the debug instructions. |
| iterator_range<reverse_nondebug_insn_iterator> |
| reverse_real_nondebug_insns () const; |
| |
| // Return the instruction that holds the artificial uses and |
| // definitions at the head of the block. The associated RTL insn |
| // is the block head note. |
| // |
| // This instruction always exists, even if it has no uses and definitions. |
| insn_info *head_insn () const { return m_head_insn; } |
| |
| // Return the instruction that holds the artificial uses and definitions |
| // at the end of the block. There is no associated RTL insn. |
| // |
| // This instruction always exists, even if it has no uses and definitions. |
| insn_info *end_insn () const { return m_end_insn; } |
| |
| // Print "bb" + index () to PP. |
| void print_identifier (pretty_printer *pp) const; |
| |
| // Print a full description of the block to PP. |
| void print_full (pretty_printer *) const; |
| |
| private: |
| bb_info (basic_block); |
| |
| void set_prev_bb (bb_info *bb) { m_prev_bb = bb; } |
| void set_next_bb (bb_info *bb) { m_next_bb = bb; } |
| void set_cfg_bb (basic_block cfg_bb) { m_cfg_bb = cfg_bb; } |
| void set_ebb (ebb_info *ebb) { m_ebb = ebb; } |
| void set_head_insn (insn_info *insn) { m_head_insn = insn; } |
| void set_end_insn (insn_info *insn) { m_end_insn = insn; } |
| |
| // The values returned by the functions above. |
| bb_info *m_prev_bb; |
| bb_info *m_next_bb; |
| basic_block m_cfg_bb; |
| ebb_info *m_ebb; |
| insn_info *m_head_insn; |
| insn_info *m_end_insn; |
| }; |
| |
| // Iterators for lists of basic blocks. |
| using bb_iterator = list_iterator<bb_info, &bb_info::next_bb>; |
| using reverse_bb_iterator = list_iterator<bb_info, &bb_info::prev_bb>; |
| |
| // This class collects together instructions for which has_call_clobbers () |
| // is true, storing them in a splay tree that follows reverse postorder. |
| // Instances of the class form a singly-linked list, with one instance |
| // per predefined_function_abi. |
| class ebb_call_clobbers_info : public insn_call_clobbers_tree |
| { |
| // Size 3 LP64 words. |
| friend class function_info; |
| |
| public: |
| // Return the next group in the list. |
| ebb_call_clobbers_info *next () const { return m_next; } |
| |
| // Return the function abi used by all the calls in the group. |
| const predefined_function_abi *abi () const { return m_abi; } |
| |
| // Return true if at least one call in the group should conservatively |
| // be assumed to clobber RESOURCE. |
| bool clobbers (resource_info) const; |
| |
| // Print a summary of what the class describes to PP, without printing |
| // the actual instructions. |
| void print_summary (pretty_printer *pp) const; |
| |
| // Print a full description of the object to PP, including the |
| // instructions it contains. |
| void print_full (pretty_printer *) const; |
| |
| private: |
| ebb_call_clobbers_info (const predefined_function_abi *); |
| |
| // The values returned by the accessors above. |
| ebb_call_clobbers_info *m_next; |
| const predefined_function_abi *m_abi; |
| }; |
| |
| // A list of ebb_call_clobbers_infos. |
| using ebb_call_clobbers_iterator |
| = list_iterator<ebb_call_clobbers_info, &ebb_call_clobbers_info::next>; |
| |
| // Information about an extended basic block. |
| // |
| // Each EBB has a list of phi nodes and starts with an artificial phi |
| // instruction that conceptually "executes" the phi nodes. The phi |
| // nodes are independent of one another and so can be executed in any |
| // order. The order of the phi nodes in the list is not significant. |
| // |
| // Each EBB also maintains a list of ebb_call_clobbers_info structures |
| // that describe all instructions for which has_call_clobbers () is true. |
| // See the comment above that class for details. |
| class ebb_info |
| { |
| // Size: 5 LP64 words. |
| friend class function_info; |
| |
| public: |
| // Return the previous EBB in reverse postorder, or null if this EBB |
| // contains the entry block. |
| ebb_info *prev_ebb () const; |
| |
| // Return the next EBB in reverse postorder, or null if this EBB contains |
| // the exit block. |
| ebb_info *next_ebb () const; |
| |
| // Return the instruction that holds the EBB's phi nodes (and does |
| // nothing else). There is no associated RTL insn. |
| // |
| // This instruction always exists, even if the EBB does not currently |
| // need any phi nodes. |
| insn_info *phi_insn () const { return m_phi_insn; } |
| |
| // Return the first and last blocks in the EBB. |
| bb_info *first_bb () const { return m_first_bb; } |
| bb_info *last_bb () const { return m_last_bb; } |
| |
| // Return the first of the EBB's phi nodes. |
| phi_info *first_phi () const { return m_first_phi; } |
| |
| // Return the head of the list of ebb_call_clobbers_infos. |
| ebb_call_clobbers_info *first_call_clobbers () const; |
| |
| // Return the list of ebb_call_clobbers_infos. |
| iterator_range<ebb_call_clobbers_iterator> call_clobbers () const; |
| |
| // Return a list of the EBB's phi nodes, in arbitrary order. |
| iterator_range<phi_iterator> phis () const; |
| |
| // Return a list of the blocks in the EBB, in execution order. |
| iterator_range<bb_iterator> bbs () const; |
| |
| // Return a list of the blocks in the EBB, in reverse execution order. |
| iterator_range<reverse_bb_iterator> reverse_bbs () const; |
| |
| // Return a list of all the instructions in the EBB, in execution order. |
| // The list includes phi_insn (), the head and end of each block, |
| // and the real instructions in each block. |
| // |
| // Iterations over the list will pick up any new instructions that are |
| // inserted after the iterator's current instruction. |
| iterator_range<any_insn_iterator> all_insns () const; |
| |
| // Like all_insns (), except that the instructions are in reverse order. |
| // |
| // Iterations over the list will pick up any new instructions that are |
| // inserted before the iterator's current instruction. |
| iterator_range<reverse_any_insn_iterator> reverse_all_insns () const; |
| |
| // Like all_insns (), but without the debug instructions. |
| iterator_range<nondebug_insn_iterator> nondebug_insns () const; |
| |
| // Like reverse_all_insns (), but without the debug instructions. |
| iterator_range<reverse_nondebug_insn_iterator> |
| reverse_nondebug_insns () const; |
| |
| // Return an insn_range that covers the same instructions as all_insns (). |
| insn_range_info insn_range () const; |
| |
| // Print "ebb" + first_bb ()->index () to PP. |
| void print_identifier (pretty_printer *pp) const; |
| |
| // Print a full description of the EBB to PP. |
| void print_full (pretty_printer *pp) const; |
| |
| private: |
| ebb_info (bb_info *, bb_info *); |
| |
| void set_first_phi (phi_info *phi) { m_first_phi = phi; } |
| void set_phi_insn (insn_info *insn) { m_phi_insn = insn; } |
| void set_first_call_clobbers (ebb_call_clobbers_info *); |
| |
| // The values returned by the functions above. |
| phi_info *m_first_phi; |
| insn_info *m_phi_insn; |
| bb_info *m_first_bb; |
| bb_info *m_last_bb; |
| ebb_call_clobbers_info *m_first_call_clobbers; |
| }; |
| |
| // Iterators for lists of extended basic blocks. |
| using ebb_iterator = list_iterator<ebb_info, &ebb_info::next_ebb>; |
| using reverse_ebb_iterator = list_iterator<ebb_info, &ebb_info::prev_ebb>; |
| |
| void pp_bb (pretty_printer *, const bb_info *); |
| void pp_ebb_call_clobbers (pretty_printer *, const ebb_call_clobbers_info *); |
| void pp_ebb (pretty_printer *, const ebb_info *); |
| |
| } |
| |
| void dump (FILE *, const rtl_ssa::bb_info *); |
| void dump (FILE *, const rtl_ssa::ebb_call_clobbers_info *); |
| void dump (FILE *, const rtl_ssa::ebb_info *); |
| |
| void DEBUG_FUNCTION debug (const rtl_ssa::bb_info *); |
| void DEBUG_FUNCTION debug (const rtl_ssa::ebb_call_clobbers_info *); |
| void DEBUG_FUNCTION debug (const rtl_ssa::ebb_info *); |