2 * ssapre.h: SSA Partial Redundancy Elimination
5 * Massimiliano Mantione (massi@ximian.com)
7 * (C) 2004 Novell, Inc. http://www.novell.com
10 #ifndef __MONO_SSAPRE_H__
11 #define __MONO_SSAPRE_H__
15 #include <mono/metadata/mempool.h>
18 * Hack to apply SSAPRE only to a given method (invaluable in debugging)
20 #define MONO_APPLY_SSAPRE_TO_SINGLE_METHOD 0
23 * Hack to apply SSAPRE only to a given expression (invaluable in debugging)
25 #define MONO_APPLY_SSAPRE_TO_SINGLE_EXPRESSION 0
28 * All the different kind of arguments we can handle.
29 * "ANY" means the argument is unknown or cannot be handled, and "NOT_PRESENT"
30 * that the expression does not have this argument (has not "enough" arity).
33 MONO_SSAPRE_EXPRESSION_ARGUMENT_ANY
,
34 MONO_SSAPRE_EXPRESSION_ARGUMENT_NOT_PRESENT
,
35 MONO_SSAPRE_EXPRESSION_ARGUMENT_ORIGINAL_VARIABLE
,
36 MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE
,
37 MONO_SSAPRE_EXPRESSION_ARGUMENT_INTEGER_CONSTANT
,
38 MONO_SSAPRE_EXPRESSION_ARGUMENT_LONG_COSTANT
,
39 MONO_SSAPRE_EXPRESSION_ARGUMENT_FLOAT_COSTANT
,
40 MONO_SSAPRE_EXPRESSION_ARGUMENT_DOUBLE_COSTANT
41 } MonoSsapreExpressionArgumentType
;
44 * A struct representing an expression argument (the used branch in the
45 * union depends on the value of the type field).
47 typedef struct MonoSsapreExpressionArgument
{
48 MonoSsapreExpressionArgumentType type
;
50 int original_variable
;
53 gint64
* long_constant
;
54 float* float_constant
;
55 double* double_constant
;
57 } MonoSsapreExpressionArgument
;
60 * Macros used when comparing expression arguments, which return -1,0 or 1.
62 #define MONO_COMPARE_SSAPRE_DIRECT_VALUES(v1,v2) (((v2)>(v1)?(1):((v2)<(v1)?(-1):(0))))
63 #define MONO_COMPARE_SSAPRE_POINTER_VALUES(p1,p2) (((*p2)>(*p1)?(1):((*p2)<(*p1)?(-1):(0))))
65 #define MONO_COMPARE_SSAPRE_EXPRESSION_ARGUMENT_VALUES(t,v1,v2) (\
66 (t)==MONO_SSAPRE_EXPRESSION_ARGUMENT_ORIGINAL_VARIABLE?\
67 MONO_COMPARE_SSAPRE_DIRECT_VALUES ((v1).original_variable,(v2).original_variable):(\
68 (t)==MONO_SSAPRE_EXPRESSION_ARGUMENT_SSA_VARIABLE?\
69 MONO_COMPARE_SSAPRE_DIRECT_VALUES ((v1).ssa_variable,(v2).ssa_variable):(\
70 (t)==MONO_SSAPRE_EXPRESSION_ARGUMENT_INTEGER_CONSTANT?\
71 MONO_COMPARE_SSAPRE_DIRECT_VALUES ((v1).integer_constant,(v2).integer_constant):(\
72 (t)==MONO_SSAPRE_EXPRESSION_ARGUMENT_LONG_COSTANT?\
73 MONO_COMPARE_SSAPRE_POINTER_VALUES ((v1).long_constant,(v2).long_constant):(\
74 (t)==MONO_SSAPRE_EXPRESSION_ARGUMENT_FLOAT_COSTANT?\
75 MONO_COMPARE_SSAPRE_POINTER_VALUES ((v1).float_constant,(v2).float_constant):(\
76 (t)==MONO_SSAPRE_EXPRESSION_ARGUMENT_DOUBLE_COSTANT?\
77 MONO_COMPARE_SSAPRE_POINTER_VALUES ((v1).double_constant,(v2).double_constant):(\
80 #define MONO_COMPARE_SSAPRE_EXPRESSION_ARGUMENTS(a1,a2) (\
81 MONO_COMPARE_SSAPRE_DIRECT_VALUES ((a1).type,(a2).type)!=0?\
82 MONO_COMPARE_SSAPRE_DIRECT_VALUES ((a1).type,(a2).type):\
83 MONO_COMPARE_SSAPRE_EXPRESSION_ARGUMENT_VALUES ((a1).type,(a1).argument,(a2).argument) )
87 * A struct representing an expression, with its opcode and two arguments
88 * (if the opcode has arity 1 right_argument is MONO_SSAPRE_EXPRESSION_ARGUMENT_NOT_PRESENT).
90 typedef struct MonoSsapreExpressionDescription
{
92 MonoSsapreExpressionArgument left_argument
;
93 MonoSsapreExpressionArgument right_argument
;
94 } MonoSsapreExpressionDescription
;
97 * Macro that compares two expression descriptions (returns -1, 0 or 1).
99 #define MONO_COMPARE_SSAPRE_EXPRESSION_DESCRIPTIONS(d1,d2) (\
100 MONO_COMPARE_SSAPRE_DIRECT_VALUES ((d1).opcode,(d2).opcode)!=0?\
101 MONO_COMPARE_SSAPRE_DIRECT_VALUES ((d1).opcode,(d2).opcode):(\
102 MONO_COMPARE_SSAPRE_EXPRESSION_ARGUMENTS ((d1).left_argument,(d2).left_argument)!=0?\
103 MONO_COMPARE_SSAPRE_EXPRESSION_ARGUMENTS ((d1).left_argument,(d2).left_argument):(\
104 MONO_COMPARE_SSAPRE_EXPRESSION_ARGUMENTS ((d1).right_argument,(d2).right_argument)!=0?\
105 MONO_COMPARE_SSAPRE_EXPRESSION_ARGUMENTS ((d1).right_argument,(d2).right_argument):(\
109 * Struct that contains all the information related to a BB.
110 * Some of them are taken from the corresponding MonoBasicBlock, some are
111 * constant during the compilation of the whole method, others must be
112 * recomputed for each expression.
114 typedef struct MonoSsapreBBInfo
{
115 /* Information constant during the compilation of the whole method: */
117 /* Depth First Number relative to a traversal of the dominator tree */
119 /* Depth First Number relative to a traversal of the CFG */
121 /* Number of descendants in the dominator tree (is equal to the number of strictly dominated BBs) */
123 /* In and out count (taken from the corresponding MonoBasicBlock) */
124 gint16 in_count
, out_count
;
125 /* Idominator (taken from the corresponding MonoBasicBlock, but pointing */
126 /* to the MonoSsapreBBInfo for convenience) */
127 struct MonoSsapreBBInfo
*idominator
;
128 /* In and out BBs (taken from the corresponding MonoBasicBlock, but pointing */
129 /* to the MonoSsapreBBInfo for convenience) */
130 struct MonoSsapreBBInfo
**in_bb
;
131 struct MonoSsapreBBInfo
**out_bb
;
132 /* Dominance frontier (taken from the corresponding MonoBasicBlock) */
133 MonoBitSet
*dfrontier
;
135 /* MonoInst where new phi definitions must be added in the BB */
136 /* (the last existing phi definition, or NULL if there is none) */
137 MonoInst
*phi_insertion_point
;
139 /* Information recomputed during the analysis of each expression: */
141 /* True if the whole BB subtree in the dominator tree is "covered" with */
142 /* BBs marked "interesting" (a BB where this is false cannot be down */
143 /* safe, since there would be a path to exit with no occurrence at all). */
144 /* A more formal way of stating this is that on the DT there is no path */
145 /* from this BB to any leaf that does not meet an interesting BB */
146 gboolean dt_covered_by_interesting_BBs
;
148 /* True if this BB has a PHI occurrence */
150 /* True if this PHI defines a real occurrence */
151 gboolean phi_defines_a_real_occurrence
;
152 /* True if this PHI is down safe */
153 gboolean phi_is_down_safe
;
154 /* True if this PHI can be available */
155 gboolean phi_can_be_available
;
156 /* True if this PHI is "later" */
157 gboolean phi_is_later
;
158 /* The PHI class number */
159 int phi_redundancy_class
;
160 /* The index of this PHI in the cfg->vars array */
161 int phi_variable_index
;
162 /* Array of the class numbers of the PHI arguments (has "in_count" elements) */
163 int *phi_arguments_classes
;
165 /* True if this BB has a PHI argument */
166 gboolean has_phi_argument
;
167 /* True if this PHI argument "has real use" */
168 gboolean phi_argument_has_real_use
;
169 /* True if this PHI argument needs the insertion of a new occurrence */
170 gboolean phi_argument_needs_insert
;
171 /* True if this PHI argument has been processed (see "set_save") */
172 gboolean phi_argument_has_been_processed
;
173 /* The PHI argument class number */
174 int phi_argument_class
;
175 /* The index of this PHI argument in the cfg->vars array */
176 int phi_argument_variable_index
;
177 /* Points to the real occurrence defining this PHI argument (NULL otherwise) */
178 struct MonoSsapreExpressionOccurrence
*phi_argument_defined_by_real_occurrence
;
179 /* Points to the BB containing the PHI defining this PHI argument (NULL otherwise) */
180 struct MonoSsapreBBInfo
*phi_argument_defined_by_phi
;
181 /* Variable version of the left argument og the PHI argument "expected" at */
182 /* the PHI (or BOTTOM_REDUNDANCY_CLASS otherwise), see "renaming_pass" */
183 int phi_argument_left_argument_version
;
184 /* As above, but for the right argument */
185 int phi_argument_right_argument_version
;
187 /* The first real occurrence in this BB (NULL if there is none) */
188 struct MonoSsapreExpressionOccurrence
*first_expression_in_bb
;
189 /* Next BB which has either a real occurrence, a PHI or a PHI argument */
190 /* (NULL if there is none, BBs are in dominator tree depth first preorder) */
191 struct MonoSsapreBBInfo
*next_interesting_bb
;
193 /* Used in maintaining the renaming stack */
194 struct MonoSsapreBBInfo
*next_in_renaming_stack
;
195 struct MonoSsapreExpressionOccurrence
*top_of_local_renaming_stack
;
197 /* MonoBasicBlock representing this BB in the CFG (this is obviously constant) */
203 * The father of an occurrence in the tree of MonoInst.
204 * (needed just because a MonoInst cannot point to its father)
206 typedef struct MonoSsapreFatherExpression
{
207 /* The father occurrence */
208 MonoInst
*father_occurrence
;
209 /* The MonoSsapreFatherExpression node of the "grand father" */
210 struct MonoSsapreFatherExpression
*grand_father
;
211 } MonoSsapreFatherExpression
;
214 * A "real" occurrence.
216 typedef struct MonoSsapreExpressionOccurrence
{
217 /* The occurrence in the CFG */
218 MonoInst
*occurrence
;
219 /* The "father" of this occurrence in the inst tree (if the occurrence is */
220 /* part of a compound expression, otherwise it is NULL) */
221 MonoSsapreFatherExpression
*father_in_tree
;
222 /* The tree just before the occurrence in the CFG (if the occurrence must */
223 /* saved into a temporary, the definition will be placed just after that tree) */
224 MonoInst
*previous_tree
;
225 /* The BB where this occurrence is found */
226 MonoSsapreBBInfo
*bb_info
;
227 /* The description of the occurrence */
228 MonoSsapreExpressionDescription description
;
229 /* Next occurrence of this expression */
230 struct MonoSsapreExpressionOccurrence
*next
;
231 /* Previous occurrence of this expression */
232 struct MonoSsapreExpressionOccurrence
*previous
;
233 /* True if this occurrence is the first in its BB */
234 gboolean is_first_in_bb
;
235 /* True if this occurrence is the last in its BB */
236 gboolean is_last_in_bb
;
237 /* "reload" flag (see "finalize") */
239 /* "save" flag (see "finalize") */
242 /* Used in maintaining the renaming stack */
243 struct MonoSsapreExpressionOccurrence
*next_in_renaming_stack
;
245 /* Class number of this occurrence */
246 int redundancy_class
;
247 /* The index of the temporary of this occurrence in the cfg->vars array */
249 /* Points to the real occurrence defining this occurrence (NULL otherwise) */
250 struct MonoSsapreExpressionOccurrence
*defined_by_real_occurrence
;
251 /* Points to the BB containing the PHI defining this occurrence (NULL otherwise) */
252 struct MonoSsapreBBInfo
*defined_by_phi
;
253 } MonoSsapreExpressionOccurrence
;
257 * An expression to be processed (in the worklist).
259 typedef struct MonoSsapreExpression
{
260 /* The description of the expression */
261 MonoSsapreExpressionDescription description
;
262 /* The type to use when creating values of this expression */
264 /* The list of expression occurrences */
265 MonoSsapreExpressionOccurrence
*occurrences
;
266 /* The last expression occurrence in the list */
267 MonoSsapreExpressionOccurrence
*last_occurrence
;
269 /* Used in maintaining the worklist (an autobalancing binary tree) */
270 struct MonoSsapreExpression
*father
;
271 struct MonoSsapreExpression
*previous
;
272 struct MonoSsapreExpression
*next
;
275 /* Next expression to be processed in the worklist */
276 struct MonoSsapreExpression
*next_in_queue
;
277 } MonoSsapreExpression
;
280 * Macros used to maintain the worklist
282 #define MONO_SSAPRE_GOTO_FIRST_EXPRESSION(e) do{\
283 while ((e)->previous != NULL) (e) = (e)->previous;\
285 #define MONO_SSAPRE_REMOVE_FIRST_EXPRESSION(e) do{\
286 if ((e)->father != NULL) {\
287 (e)->father->previous = (e)->next;\
290 #define MONO_SSAPRE_GOTO_LAST_EXPRESSION(e) do{\
291 while ((e)->next != NULL) (e) = (e)->next;\
293 #define MONO_SSAPRE_REMOVE_LAST_EXPRESSION(e) do{\
294 if ((e)->father != NULL) {\
295 (e)->father->next = (e)->previous;\
299 #define MONO_SSAPRE_MAX_TREE_DEPTH(size,depth) do{\
300 unsigned __mask__ = ~1;\
302 while (((size)&__mask__)!=0) {\
308 #define MONO_SSAPRE_ADD_EXPRESSION_OCCURRANCE(e,o) do{\
309 if ((e)->occurrences == NULL) {\
310 (e)->occurrences = (o);\
312 (e)->last_occurrence->next = (o);\
315 (o)->previous = (e)->last_occurrence;\
316 (e)->last_occurrence = (o);\
318 #define MONO_SSAPRE_REMOVE_EXPRESSION_OCCURRANCE(e,o) do{\
319 if ((e)->occurrences == (o)) {\
320 (e)->occurrences = (o)->next;\
322 if ((e)->last_occurrence == (o)) {\
323 (e)->last_occurrence = (o)->previous;\
325 if ((o)->previous != NULL) {\
326 (o)->previous->next = (o)->next;\
328 if ((o)->next != NULL) {\
329 (o)->next->previous = (o)->previous;\
332 (o)->previous = NULL;\
337 * Availability table element (see "finalize"), one for each redundancy class
339 typedef struct MonoSsapreAvailabilityTableElement
{
340 /* Points to the real occurrence defining this redundancy class (NULL otherwise) */
341 struct MonoSsapreExpressionOccurrence
*class_defined_by_real_occurrence
;
342 /* Points to the BB containing the PHI defining this redundancy class (NULL otherwise) */
343 struct MonoSsapreBBInfo
*class_defined_by_phi
;
344 } MonoSsapreAvailabilityTableElement
;
347 * The "main" work area for the algorithm.
349 typedef struct MonoSsapreWorkArea
{
352 /* The SSAPRE specific mempool */
353 MonoMemPool
*mempool
;
355 /* Number of BBs in the CFG (from cfg) */
357 /* BB information, in dominator tree depth first preorder */
358 MonoSsapreBBInfo
*bb_infos
;
359 /* Pointers to BB information, in CFG depth first preorder */
360 MonoSsapreBBInfo
**bb_infos_in_cfg_dfn_order
;
362 /* Number of variables in the CFG */
364 /* Size of bitset for BBs */
365 int sizeof_bb_bitset
;
366 /* Various bitsets used when working with iterated dfrontiers */
367 MonoBitSet
*expression_occurrences_buffer
;
368 MonoBitSet
*bb_iteration_buffer
;
369 MonoBitSet
*iterated_dfrontier_buffer
;
370 MonoBitSet
*left_argument_bb_bitset
;
371 MonoBitSet
*right_argument_bb_bitset
;
373 /* The depth of the dominator tree */
376 /* The expression worklist */
377 MonoSsapreExpression
*worklist
;
379 /* The expression queue head */
380 MonoSsapreExpression
*first_in_queue
;
381 /* The expression queue tail */
382 MonoSsapreExpression
*last_in_queue
;
384 /* The expression being processed */
385 MonoSsapreExpression
*current_expression
;
386 /* The expression being allocated */
387 MonoSsapreExpressionOccurrence
*current_occurrence
;
389 /* The BB on top of the renaming stack (if "top_of_renaming_stack" is NULL */
390 /* but this is not, then the top of the stack is the PHI in this BB) */
391 struct MonoSsapreBBInfo
*bb_on_top_of_renaming_stack
;
392 /* The top of the renaming stack */
393 struct MonoSsapreExpressionOccurrence
*top_of_renaming_stack
;
395 /* The head of the list of "interesting" BBs */
396 struct MonoSsapreBBInfo
*first_interesting_bb
;
398 /* The number of generated class numbers */
399 int number_of_classes
;
401 /* The number of occurrences scheduled for reloading/insertion */
402 /* (used to decide if the redundancy is worth eliminating) */
403 int occurrences_scheduled_for_reloading
;
404 int arguments_scheduled_for_insertion
;
405 int dominating_arguments_scheduled_for_insertion
;
407 /* Statistics fields (per expression) */
408 int saved_occurrences
;
409 int reloaded_occurrences
;
410 int inserted_occurrences
;
411 int unaltered_occurrences
;
414 #if (MONO_APPLY_SSAPRE_TO_SINGLE_EXPRESSION)
415 gboolean expression_is_handled_father
;
417 } MonoSsapreWorkArea
;
420 #endif /* __MONO_SSAPRE_H__ */