aboutsummaryrefslogtreecommitdiff
path: root/gcc/rtl-ssa/blocks.h
blob: 9cb0f521111389e86542fd69239f60ffed346421 (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
// Basic-block-related classes for RTL SSA                          -*- C++ -*-
// Copyright (C) 2020-2022 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 *);