0d00454a9da7304b4425afd9eea2ff14c40c1cc5
[mono.git] / mono / mini / abcremoval.h
1 /*
2  * abcremoval.h: Array bounds check removal
3  *
4  * Author:
5  *   Massimiliano Mantione (massi@ximian.com)
6  *
7  * (C) 2004 Ximian, Inc.  http://www.ximian.com
8  */
9
10 #ifndef __MONO_ABCREMOVAL_H__
11 #define __MONO_ABCREMOVAL_H__
12
13 #include <limits.h>
14
15 #include "mini.h"
16
17
18 /**
19  * All handled value types (expressions) in variable definitions and branch
20  * contitions:
21  * ANY: not handled
22  * CONSTANT: an integer constant
23  * VARIABLE: a reference to a variable, with an optional delta (can be zero)
24  * PHI: a PHI definition of the SSA representation
25  */
26 typedef enum {
27         MONO_ANY_SUMMARIZED_VALUE,
28         MONO_CONSTANT_SUMMARIZED_VALUE,
29         MONO_VARIABLE_SUMMARIZED_VALUE,
30         MONO_PHI_SUMMARIZED_VALUE
31 } MonoSummarizedValueType;
32
33 /**
34  * A MONO_CONSTANT_SUMMARIZED_VALUE value.
35  * value: the value
36  */
37 typedef struct MonoSummarizedConstantValue {
38         int value;
39 } MonoSummarizedConstantValue;
40
41 /**
42  * A MONO_VARIABLE_SUMMARIZED_VALUE value
43  * variable: the variable index in the cfg
44  * delta: the delta (can be zero)
45  */
46 typedef struct MonoSummarizedVariableValue {
47         int variable;
48         int delta;
49 } MonoSummarizedVariableValue;
50
51 /**
52  * A MONO_PHI_SUMMARIZED_VALUE value.
53  * number_of_alternatives: the number of alternatives in the PHI definition
54  * phi_alternatives: an array of integers with the indexes of the variables
55  *                   which are the alternatives in this PHI definition
56  */
57 typedef struct MonoSummarizedPhiValue {
58         int number_of_alternatives;
59         int *phi_alternatives;
60 } MonoSummarizedPhiValue;
61
62 /**
63  * A summarized value.
64  * In practice it is a "tagged union".
65  */
66 typedef struct MonoSummarizedValue {
67         MonoSummarizedValueType type;
68         union {
69                 MonoSummarizedConstantValue constant;
70                 MonoSummarizedVariableValue variable;
71                 MonoSummarizedPhiValue phi;
72         } value;
73 } MonoSummarizedValue;
74
75 /**
76  * A "relation" between two values.
77  * The enumeration is used as a bit field, with three significant bits.
78  * The degenerated cases are meaningful:
79  * MONO_ANY_RELATION: we know nothing of this relation
80  * MONO_NO_RELATION: no relation is possible (this code is unreachable)
81  */
82 typedef enum {
83         MONO_EQ_RELATION = 1,
84         MONO_LT_RELATION = 2,
85         MONO_GT_RELATION = 4,
86         MONO_NE_RELATION = (MONO_LT_RELATION|MONO_GT_RELATION),
87         MONO_LE_RELATION = (MONO_LT_RELATION|MONO_EQ_RELATION),
88         MONO_GE_RELATION = (MONO_GT_RELATION|MONO_EQ_RELATION),
89         MONO_ANY_RELATION = (MONO_EQ_RELATION|MONO_LT_RELATION|MONO_GT_RELATION),
90         MONO_NO_RELATION = 0
91 } MonoValueRelation;
92
93 /**
94  * A "kind" of integer value.
95  * The enumeration is used as a bit field, with two fields.
96  * The first, four bits wide, is the "sizeof" in bytes.
97  * The second is a flag that is true if the value is unsigned.
98  */
99 typedef enum {
100         MONO_INTEGER_VALUE_SIZE_1 = 1,
101         MONO_INTEGER_VALUE_SIZE_2 = 2,
102         MONO_INTEGER_VALUE_SIZE_4 = 4,
103         MONO_INTEGER_VALUE_SIZE_8 = 8,
104         MONO_INTEGER_VALUE_SIZE_BITMASK = 15,
105         MONO_UNSIGNED_VALUE_FLAG = 16,
106         MONO_UNSIGNED_INTEGER_VALUE_SIZE_1 = MONO_UNSIGNED_VALUE_FLAG|MONO_INTEGER_VALUE_SIZE_1,
107         MONO_UNSIGNED_INTEGER_VALUE_SIZE_2 = MONO_UNSIGNED_VALUE_FLAG|MONO_INTEGER_VALUE_SIZE_2,
108         MONO_UNSIGNED_INTEGER_VALUE_SIZE_4 = MONO_UNSIGNED_VALUE_FLAG|MONO_INTEGER_VALUE_SIZE_4,
109         MONO_UNSIGNED_INTEGER_VALUE_SIZE_8 = MONO_UNSIGNED_VALUE_FLAG|MONO_INTEGER_VALUE_SIZE_8,
110         MONO_UNKNOWN_INTEGER_VALUE = 0
111 } MonoIntegerValueKind;
112
113 /**
114  * A relation between variables (or a variable and a constant).
115  * The first variable (the one "on the left of the expression") is implicit.
116  * relation: the relation between the variable and the value
117  * related_value: the related value
118  * relation_is_static_definition: TRUE if the relation comes from a veriable
119  *                                definition, FALSE if it comes from a branch
120  *                                condition
121  * next: pointer to the next relation of this variable in the evaluation area
122  *       (relations are always kept in the evaluation area, one list for each
123  *       variable)
124  */
125 typedef struct MonoSummarizedValueRelation {
126         MonoValueRelation relation;
127         MonoSummarizedValue related_value;
128         gboolean relation_is_static_definition;
129         struct MonoSummarizedValueRelation *next;
130 } MonoSummarizedValueRelation;
131
132 /**
133  * The evaluation status for one variable.
134  * The enumeration is used as a bit field, because the status has two
135  * distinct sections.
136  * The first is the "main" one (bits 0, 1 and 2), which is actually a proper
137  * enumeration (the bits are mutually exclusive, and their meaning is obvious).
138  * The other section (the bits in the MONO_RELATIONS_EVALUATION_IS_RECURSIVE
139  * set) is used to mark an evaluation as recursive (while backtracking through
140  * the evaluation contexts), to state if the graph loop gives a value that is
141  * ascending, descending or indefinite.
142  * The bits are handled separately because the same evaluation context could
143  * belong to more than one loop, so that each loop would set its bits.
144  * After the backtracking, the bits are examined and a decision is taken.
145  * 
146  */
147 typedef enum {
148         MONO_RELATIONS_EVALUATION_NOT_STARTED = 0,
149         MONO_RELATIONS_EVALUATION_IN_PROGRESS = 1,
150         MONO_RELATIONS_EVALUATION_COMPLETED = 2,
151         MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_ASCENDING = 4,
152         MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_DESCENDING = 8,
153         MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_INDEFINITE = 16,
154         MONO_RELATIONS_EVALUATION_IS_RECURSIVE = (MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_ASCENDING|MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_DESCENDING|MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_INDEFINITE)
155 } MonoRelationsEvaluationStatus;
156
157 /**
158  * A range of values (ranges include their limits).
159  * A range from MIN_INT to MAX_INT is "indefinite" (any value).
160  * A range where upper < lower means unreachable code (some of the relations
161  * that generated the range is incompatible, like x = 0 and x > 0).
162  * lower: the lower limit
163  * upper: the upper limit
164  */
165 typedef struct MonoRelationsEvaluationRange {
166         int lower;
167         int upper;
168 } MonoRelationsEvaluationRange;
169
170 /**
171  * The two ranges that contain the result of a variable evaluation.
172  * zero: the range with respect to zero
173  * variable: the range with respect to the target variable in this evaluation
174  */
175 typedef struct MonoRelationsEvaluationRanges {
176         MonoRelationsEvaluationRange zero;
177         MonoRelationsEvaluationRange variable;
178 } MonoRelationsEvaluationRanges;
179
180 /**
181  * The context of a variable evaluation.
182  * current_relation: the relation that is currently evaluated.
183  * ranges: the result of the evaluation.
184  * father: the context of the evaluation that invoked this one (used to
185  *         perform the backtracking when loops are detected.
186  */
187 typedef struct MonoRelationsEvaluationContext {
188         MonoSummarizedValueRelation *current_relation;
189         MonoRelationsEvaluationRanges ranges;
190         struct MonoRelationsEvaluationContext *father;
191 } MonoRelationsEvaluationContext;
192
193 /*
194  * Basic macros to initialize and check ranges.
195  */
196 #define MONO_MAKE_RELATIONS_EVALUATION_RANGE_WEAK(r) do{\
197                 (r).lower = INT_MIN;\
198                 (r).upper = INT_MAX;\
199         } while (0)
200 #define MONO_MAKE_RELATIONS_EVALUATION_RANGES_WEAK(rs) do{\
201                 MONO_MAKE_RELATIONS_EVALUATION_RANGE_WEAK ((rs).zero); \
202                 MONO_MAKE_RELATIONS_EVALUATION_RANGE_WEAK ((rs).variable); \
203         } while (0)
204 #define MONO_MAKE_RELATIONS_EVALUATION_RANGE_IMPOSSIBLE(r) do{\
205                 (r).lower = INT_MAX;\
206                 (r).upper = INT_MIN;\
207         } while (0)
208 #define MONO_MAKE_RELATIONS_EVALUATION_RANGES_IMPOSSIBLE(rs) do{\
209                 MONO_MAKE_RELATIONS_EVALUATION_RANGE_IMPOSSIBLE ((rs).zero); \
210                 MONO_MAKE_RELATIONS_EVALUATION_RANGE_IMPOSSIBLE ((rs).variable); \
211         } while (0)
212 #define MONO_RELATIONS_EVALUATION_RANGE_IS_WEAK(r) (((r).lower==INT_MIN)&&((r).upper==INT_MAX))
213 #define MONO_RELATIONS_EVALUATION_RANGES_ARE_WEAK(rs) \
214         (MONO_RELATIONS_EVALUATION_RANGE_IS_WEAK((rs).zero) && \
215         MONO_RELATIONS_EVALUATION_RANGE_IS_WEAK((rs).variable))
216 #define MONO_RELATIONS_EVALUATION_RANGE_IS_IMPOSSIBLE(r) (((r).lower)>((r).upper))
217 #define MONO_RELATIONS_EVALUATION_RANGES_ARE_IMPOSSIBLE(rs) \
218         (MONO_RELATIONS_EVALUATION_RANGE_IS_IMPOSSIBLE((rs).zero) || \
219         MONO_RELATIONS_EVALUATION_RANGE_IS_IMPOSSIBLE((rs).variable))
220
221 /*
222  * The following macros are needed because ranges include theit limits, but
223  * some relations explicitly exclude them (GT and LT).
224  */
225 #define MONO_UPPER_EVALUATION_RANGE_NOT_EQUAL(ur) ((((ur)==INT_MIN)||((ur)==INT_MAX))?(ur):((ur)-1))
226 #define MONO_LOWER_EVALUATION_RANGE_NOT_EQUAL(lr) ((((lr)==INT_MIN)||((lr)==INT_MAX))?(lr):((lr)+1))
227 #define MONO_APPLY_INEQUALITY_TO_EVALUATION_RANGE(r) do{\
228                 (r).lower = MONO_LOWER_EVALUATION_RANGE_NOT_EQUAL ((r).lower);\
229                 (r).upper = MONO_UPPER_EVALUATION_RANGE_NOT_EQUAL ((r).upper);\
230         } while (0)
231 #define MONO_APPLY_INEQUALITY_TO_EVALUATION_RANGES(rs) do{\
232                 MONO_APPLY_INEQUALITY_TO_EVALUATION_RANGE ((rs).zero); \
233                 MONO_APPLY_INEQUALITY_TO_EVALUATION_RANGE ((rs).variable); \
234         } while (0)
235
236 /*
237  * The following macros perform union and intersection operations on ranges.
238  */
239 #define MONO_LOWER_EVALUATION_RANGE_UNION(lr,other_lr) ((lr)=MIN(lr,other_lr))
240 #define MONO_UPPER_EVALUATION_RANGE_UNION(ur,other_ur) ((ur)=MAX(ur,other_ur))
241 #define MONO_LOWER_EVALUATION_RANGE_INTERSECTION(lr,other_lr) ((lr)=MAX(lr,other_lr))
242 #define MONO_UPPER_EVALUATION_RANGE_INTERSECTION(ur,other_ur) ((ur)=MIN(ur,other_ur))
243 #define MONO_RELATIONS_EVALUATION_RANGE_UNION(r,other_r) do{\
244                 MONO_LOWER_EVALUATION_RANGE_UNION((r).lower,(other_r).lower);\
245                 MONO_UPPER_EVALUATION_RANGE_UNION((r).upper,(other_r).upper);\
246         } while (0)
247 #define MONO_RELATIONS_EVALUATION_RANGE_INTERSECTION(r,other_r) do{\
248                 MONO_LOWER_EVALUATION_RANGE_INTERSECTION((r).lower,(other_r).lower);\
249                 MONO_UPPER_EVALUATION_RANGE_INTERSECTION((r).upper,(other_r).upper);\
250         } while (0)
251 #define MONO_RELATIONS_EVALUATION_RANGES_UNION(rs,other_rs) do{\
252                 MONO_RELATIONS_EVALUATION_RANGE_UNION ((rs).zero,(other_rs).zero); \
253                 MONO_RELATIONS_EVALUATION_RANGE_UNION ((rs).variable,(other_rs).variable); \
254         } while (0)
255 #define MONO_RELATIONS_EVALUATION_RANGES_INTERSECTION(rs,other_rs) do{\
256                 MONO_RELATIONS_EVALUATION_RANGE_INTERSECTION ((rs).zero,(other_rs).zero); \
257                 MONO_RELATIONS_EVALUATION_RANGE_INTERSECTION ((rs).variable,(other_rs).variable); \
258         } while (0)
259
260 /*
261  * The following macros add or subtract "safely" (without over/under-flow) a
262  * delta (constant) value to a range.
263  */
264 #define MONO_ADD_DELTA_SAFELY(v,d) do{\
265                 if (((d) > 0) && ((v) != INT_MIN)) {\
266                         (v) = (((v)+(d))>(v))?((v)+(d)):INT_MAX;\
267                 } else if (((d) < 0) && ((v) != INT_MAX)) {\
268                         (v) = (((v)+(d))<(v))?((v)+(d)):INT_MIN;\
269                 }\
270         } while (0)
271 #define MONO_SUB_DELTA_SAFELY(v,d) do{\
272                 if (((d) < 0) && ((v) != INT_MIN)) {\
273                         (v) = (((v)-(d))>(v))?((v)-(d)):INT_MAX;\
274                 } else if (((d) > 0) && ((v) != INT_MAX)) {\
275                         (v) = (((v)-(d))<(v))?((v)-(d)):INT_MIN;\
276                 }\
277         } while (0)
278 #define MONO_ADD_DELTA_SAFELY_TO_RANGE(r,d) do{\
279                 MONO_ADD_DELTA_SAFELY((r).lower,(d));\
280                 MONO_ADD_DELTA_SAFELY((r).upper,(d));\
281         } while (0)
282 #define MONO_SUB_DELTA_SAFELY_FROM_RANGE(r,d) do{\
283                 MONO_SUB_DELTA_SAFELY((r).lower,(d));\
284                 MONO_SUB_DELTA_SAFELY((r).upper,(d));\
285         } while (0)
286 #define MONO_ADD_DELTA_SAFELY_TO_RANGES(rs,d) do{\
287                 MONO_ADD_DELTA_SAFELY_TO_RANGE((rs).zero,(d));\
288                 MONO_ADD_DELTA_SAFELY_TO_RANGE((rs).variable,(d));\
289         } while (0)
290 #define MONO_SUB_DELTA_SAFELY_FROM_RANGES(rs,d) do{\
291                 MONO_SUB_DELTA_SAFELY_FROM_RANGE((rs).zero,(d));\
292                 MONO_SUB_DELTA_SAFELY_FROM_RANGE((rs).variable,(d));\
293         } while (0)
294
295
296 /**
297  * The main evaluation area.
298  * cfg: the cfg of the method that is being examined.
299  * relations: and array of relations, one for each method variable (each
300  *            relation is the head of a list); this is the evaluation graph
301  * contexts: an array of evaluation contexts (one for each method variable)
302  * variable_value_kind: an array of MonoIntegerValueKind, one for each local
303  *                      variable (or argument)
304  * defs: maps vregs to the instruction which defines it.
305  */
306 typedef struct MonoVariableRelationsEvaluationArea {
307         MonoCompile *cfg;
308         MonoSummarizedValueRelation *relations;
309
310 /**
311  * statuses and contexts are parallel arrays. A given index into each refers to
312  * the same context. This is a performance optimization. Clean_context was
313  * coming to dominate the running time of abcremoval. By
314  * storing the statuses together, we can memset the entire
315  * region.
316  */ 
317         MonoRelationsEvaluationStatus *statuses;
318         MonoRelationsEvaluationContext *contexts;
319
320         MonoIntegerValueKind *variable_value_kind;
321         MonoInst **defs;
322 } MonoVariableRelationsEvaluationArea;
323
324 /**
325  * Convenience structure to define an "additional" relation for the main
326  * evaluation graph.
327  * variable: the variable to which the relation is applied
328  * relation: the relation
329  * insertion_point: the point in the graph where the relation is inserted
330  *                  (useful for removing it from the list when backtracking
331  *                  in the traversal of the dominator tree)
332  */
333 typedef struct MonoAdditionalVariableRelation {
334         int variable;
335         MonoSummarizedValueRelation relation;
336         MonoSummarizedValueRelation *insertion_point;
337 } MonoAdditionalVariableRelation;
338
339 /**
340  * Convenience structure that stores two additional relations.
341  * In the current code, each BB can add at most two relations to the main
342  * evaluation graph, so one of these structures is enough to hold all the
343  * modifications to the graph made examining one BB.
344  */
345 typedef struct MonoAdditionalVariableRelationsForBB {
346         MonoAdditionalVariableRelation relation1;
347         MonoAdditionalVariableRelation relation2;
348 } MonoAdditionalVariableRelationsForBB;
349
350
351 #endif /* __MONO_ABCREMOVAL_H__ */