1  /* Header file for SSA jump threading.
       2     Copyright (C) 2013-2023 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  #ifndef GCC_TREE_SSA_THREADEDGE_H
      21  #define GCC_TREE_SSA_THREADEDGE_H
      22  
      23  // Class used to maintain path state in the jump threader and pass it
      24  // to the jump threader simplifier.
      25  
      26  class jt_state
      27  {
      28  public:
      29    virtual ~jt_state () { }
      30    virtual void push (edge);
      31    virtual void pop ();
      32    virtual void register_equiv (tree dest, tree src, bool update_range);
      33    virtual void register_equivs_edge (edge e);
      34    virtual void register_equivs_stmt (gimple *, basic_block,
      35  				     class jt_simplifier *);
      36    virtual void record_ranges_from_stmt (gimple *stmt, bool temporary);
      37    void get_path (vec<basic_block> &);
      38    void append_path (basic_block);
      39    void dump (FILE *);
      40    void debug ();
      41  
      42  private:
      43    auto_vec<basic_block> m_blocks;
      44    static const basic_block BB_MARKER;
      45  };
      46  
      47  // Statement simplifier callback for the jump threader.
      48  
      49  class jt_simplifier
      50  {
      51  public:
      52    virtual ~jt_simplifier () { }
      53    virtual tree simplify (gimple *, gimple *, basic_block, jt_state *) = 0;
      54  };
      55  
      56  class hybrid_jt_state : public jt_state
      57  {
      58  private:
      59    void register_equivs_stmt (gimple *, basic_block, jt_simplifier *) override
      60    {
      61      // Ranger has no need to simplify anything.
      62    }
      63  };
      64  
      65  class hybrid_jt_simplifier : public jt_simplifier
      66  {
      67  public:
      68    hybrid_jt_simplifier (class gimple_ranger *r, class path_range_query *q);
      69    tree simplify (gimple *stmt, gimple *, basic_block, jt_state *) override;
      70  
      71  private:
      72    void compute_exit_dependencies (bitmap dependencies,
      73  				  const vec<basic_block> &path,
      74  				  gimple *stmt);
      75  
      76    gimple_ranger *m_ranger;
      77    path_range_query *m_query;
      78  };
      79  
      80  // This is the high level threader.  The entry point is
      81  // thread_outgoing_edges(), which calculates and registers paths to be
      82  // threaded.  When all candidates have been registered,
      83  // thread_through_all_blocks() is called to actually change the CFG.
      84  
      85  class jump_threader
      86  {
      87  public:
      88    jump_threader (jt_simplifier *, class jt_state *);
      89    ~jump_threader ();
      90    void thread_outgoing_edges (basic_block);
      91    void remove_jump_threads_including (edge_def *);
      92    bool thread_through_all_blocks (bool may_peel_loop_headers);
      93  
      94  private:
      95    tree simplify_control_stmt_condition (edge, gimple *);
      96    tree simplify_control_stmt_condition_1 (edge,
      97  					  gimple *,
      98  					  tree op0,
      99  					  tree_code cond_code,
     100  					  tree op1,
     101  					  unsigned limit);
     102  
     103    bool thread_around_empty_blocks (vec<class jump_thread_edge *> *path,
     104  				   edge, bitmap visited);
     105    int thread_through_normal_block (vec<jump_thread_edge *> *path,
     106  				   edge, bitmap visited);
     107    void thread_across_edge (edge);
     108    bool record_temporary_equivalences_from_phis (edge);
     109    gimple *record_temporary_equivalences_from_stmts_at_dest (edge);
     110  
     111    // Dummy condition to avoid creating lots of throw away statements.
     112    gcond *dummy_cond;
     113  
     114    class fwd_jt_path_registry *m_registry;
     115    jt_simplifier *m_simplifier;
     116    jt_state *m_state;
     117  };
     118  
     119  extern void propagate_threaded_block_debug_into (basic_block, basic_block);
     120  extern bool single_succ_to_potentially_threadable_block (basic_block);
     121  
     122  // ?? All this ssa_name_values stuff is the store of values for
     123  // avail_exprs_stack and const_and_copies, so it really belongs in the
     124  // jump_threader class.  However, it's probably not worth touching
     125  // this, since all this windable state is slated to go with the
     126  // ranger.
     127  extern vec<tree> ssa_name_values;
     128  #define SSA_NAME_VALUE(x) \
     129      (SSA_NAME_VERSION (x) < ssa_name_values.length () \
     130       ? ssa_name_values[SSA_NAME_VERSION (x)] \
     131       : NULL_TREE)
     132  extern void set_ssa_name_value (tree, tree);
     133  
     134  #endif /* GCC_TREE_SSA_THREADEDGE_H */