summaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-threadedge.h
blob: 3d67a127996c9de68ebf9921827881fd1e100915 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* Header file for SSA jump threading.
   Copyright (C) 2013-2023 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/>.  */

#ifndef GCC_TREE_SSA_THREADEDGE_H
#define GCC_TREE_SSA_THREADEDGE_H

// Class used to maintain path state in the jump threader and pass it
// to the jump threader simplifier.

class jt_state
{
public:
  virtual ~jt_state () { }
  virtual void push (edge);
  virtual void pop ();
  virtual void register_equiv (tree dest, tree src, bool update_range);
  virtual void register_equivs_edge (edge e);
  virtual void register_equivs_stmt (gimple *, basic_block,
				     class jt_simplifier *);
  virtual void record_ranges_from_stmt (gimple *stmt, bool temporary);
  void get_path (vec<basic_block> &);
  void append_path (basic_block);
  void dump (FILE *);
  void debug ();

private:
  auto_vec<basic_block> m_blocks;
  static const basic_block BB_MARKER;
};

// Statement simplifier callback for the jump threader.

class jt_simplifier
{
public:
  virtual ~jt_simplifier () { }
  virtual tree simplify (gimple *, gimple *, basic_block, jt_state *) = 0;
};

class hybrid_jt_state : public jt_state
{
private:
  void register_equivs_stmt (gimple *, basic_block, jt_simplifier *) override
  {
    // Ranger has no need to simplify anything.
  }
};

class hybrid_jt_simplifier : public jt_simplifier
{
public:
  hybrid_jt_simplifier (class gimple_ranger *r, class path_range_query *q);
  tree simplify (gimple *stmt, gimple *, basic_block, jt_state *) override;

private:
  void compute_exit_dependencies (bitmap dependencies,
				  const vec<basic_block> &path,
				  gimple *stmt);

  gimple_ranger *m_ranger;
  path_range_query *m_query;
};

// This is the high level threader.  The entry point is
// thread_outgoing_edges(), which calculates and registers paths to be
// threaded.  When all candidates have been registered,
// thread_through_all_blocks() is called to actually change the CFG.

class jump_threader
{
public:
  jump_threader (jt_simplifier *, class jt_state *);
  ~jump_threader ();
  void thread_outgoing_edges (basic_block);
  void remove_jump_threads_including (edge_def *);
  bool thread_through_all_blocks (bool may_peel_loop_headers);

private:
  tree simplify_control_stmt_condition (edge, gimple *);
  tree simplify_control_stmt_condition_1 (edge,
					  gimple *,
					  tree op0,
					  tree_code cond_code,
					  tree op1,
					  unsigned limit);

  bool thread_around_empty_blocks (vec<class jump_thread_edge *> *path,
				   edge, bitmap visited);
  int thread_through_normal_block (vec<jump_thread_edge *> *path,
				   edge, bitmap visited);
  void thread_across_edge (edge);
  bool record_temporary_equivalences_from_phis (edge);
  gimple *record_temporary_equivalences_from_stmts_at_dest (edge);

  // Dummy condition to avoid creating lots of throw away statements.
  gcond *dummy_cond;

  class fwd_jt_path_registry *m_registry;
  jt_simplifier *m_simplifier;
  jt_state *m_state;
};

extern void propagate_threaded_block_debug_into (basic_block, basic_block);
extern bool single_succ_to_potentially_threadable_block (basic_block);

// ?? All this ssa_name_values stuff is the store of values for
// avail_exprs_stack and const_and_copies, so it really belongs in the
// jump_threader class.  However, it's probably not worth touching
// this, since all this windable state is slated to go with the
// ranger.
extern vec<tree> ssa_name_values;
#define SSA_NAME_VALUE(x) \
    (SSA_NAME_VERSION (x) < ssa_name_values.length () \
     ? ssa_name_values[SSA_NAME_VERSION (x)] \
     : NULL_TREE)
extern void set_ssa_name_value (tree, tree);

#endif /* GCC_TREE_SSA_THREADEDGE_H */