update rx (mobile builds).
[mono-project.git] / mono / mini / ssapre.h
blob1a4ca55f7749618bd14a4c320f8139a5b47fc6f0
1 /*
2 * ssapre.h: SSA Partial Redundancy Elimination
4 * Author:
5 * Massimiliano Mantione (massi@ximian.com)
7 * (C) 2004 Novell, Inc. http://www.novell.com
8 */
10 #ifndef __MONO_SSAPRE_H__
11 #define __MONO_SSAPRE_H__
14 #include "mini.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).
32 typedef enum {
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;
49 union {
50 int original_variable;
51 int ssa_variable;
52 int integer_constant;
53 gint64* long_constant;
54 float* float_constant;
55 double* double_constant;
56 } argument;
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):(\
78 0)))))))
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 {
91 guint16 opcode;
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):(\
106 0))))
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 */
118 gint32 dt_dfn;
119 /* Depth First Number relative to a traversal of the CFG */
120 gint32 cfg_dfn;
121 /* Number of descendants in the dominator tree (is equal to the number of strictly dominated BBs) */
122 int dt_descendants;
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 */
149 gboolean has_phi;
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) */
198 MonoBasicBlock *bb;
199 } MonoSsapreBBInfo;
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") */
238 gboolean reload;
239 /* "save" flag (see "finalize") */
240 gboolean save;
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 */
248 int variable_index;
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 */
263 MonoType *type;
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;
273 int tree_size;
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;\
284 } while (0)
285 #define MONO_SSAPRE_REMOVE_FIRST_EXPRESSION(e) do{\
286 if ((e)->father != NULL) {\
287 (e)->father->previous = (e)->next;\
289 } while (0)
290 #define MONO_SSAPRE_GOTO_LAST_EXPRESSION(e) do{\
291 while ((e)->next != NULL) (e) = (e)->next;\
292 } while (0)
293 #define MONO_SSAPRE_REMOVE_LAST_EXPRESSION(e) do{\
294 if ((e)->father != NULL) {\
295 (e)->father->next = (e)->previous;\
297 } while (0)
299 #define MONO_SSAPRE_MAX_TREE_DEPTH(size,depth) do{\
300 unsigned __mask__ = ~1;\
301 (depth) = 1;\
302 while (((size)&__mask__)!=0) {\
303 __mask__ <<= 1;\
304 (depth)++;\
306 } while (0)
308 #define MONO_SSAPRE_ADD_EXPRESSION_OCCURRANCE(e,o) do{\
309 if ((e)->occurrences == NULL) {\
310 (e)->occurrences = (o);\
311 } else {\
312 (e)->last_occurrence->next = (o);\
314 (o)->next = NULL;\
315 (o)->previous = (e)->last_occurrence;\
316 (e)->last_occurrence = (o);\
317 } while (0)
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;\
331 (o)->next = NULL;\
332 (o)->previous = NULL;\
333 } while (0)
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 {
350 /* The CFG */
351 MonoCompile *cfg;
352 /* The SSAPRE specific mempool */
353 MonoMemPool *mempool;
355 /* Number of BBs in the CFG (from cfg) */
356 int num_bblocks;
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 */
363 int num_vars;
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 */
374 int dt_depth;
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;
412 int added_phis;
414 #if (MONO_APPLY_SSAPRE_TO_SINGLE_EXPRESSION)
415 gboolean expression_is_handled_father;
416 #endif
417 } MonoSsapreWorkArea;
420 #endif /* __MONO_SSAPRE_H__ */