2 * abcremoval.c: Array bounds check removal
5 * Massimiliano Mantione (massi@ximian.com)
7 * (C) 2004 Ximian, Inc. http://www.ximian.com
13 #include <mono/metadata/debug-helpers.h>
14 #include <mono/metadata/mempool.h>
15 #include <mono/metadata/opcodes.h>
25 #include "abcremoval.h"
27 #if SIZEOF_VOID_P == 8
28 #define OP_PCONST OP_I8CONST
30 #define OP_PCONST OP_ICONST
34 #define TRACE_ABC_REMOVAL (verbose_level > 2)
35 #define REPORT_ABC_REMOVAL (verbose_level > 0)
38 * A little hack for the verbosity level.
39 * The verbosity level is stored in the cfg, but not all functions that must
40 * print something see the cfg, so we store the verbosity level here at the
41 * beginning of the algorithm.
42 * This is not thread safe (does not handle correctly different verbosity
43 * levels in different threads), and is not exact in case of dynamic changes
44 * of the verbosity level...
45 * Anyway, this is not needed, all that can happen is that something more
46 * (or less) is logged, the result is in any case correct.
48 static int verbose_level;
51 #define RELATION_BETWEEN_VALUES(value,related_value) (\
52 ((value) > (related_value))? MONO_GT_RELATION :\
53 (((value) < (related_value))? MONO_LT_RELATION : MONO_EQ_RELATION))
55 #define MAKE_VALUE_ANY(v) do{\
56 (v).type = MONO_ANY_SUMMARIZED_VALUE;\
59 #define MAKE_VALUE_RELATION_ANY(r) do{\
60 (r)->relation = MONO_ANY_RELATION;\
61 MAKE_VALUE_ANY((r)->related_value);\
64 #define INITIALIZE_VALUE_RELATION(r) do{\
65 MAKE_VALUE_RELATION_ANY((r));\
69 #define MONO_NEGATED_RELATION(r) ((~(r))&MONO_ANY_RELATION)
70 #define MONO_SYMMETRIC_RELATION(r) (((r)&MONO_EQ_RELATION)|(((r)&MONO_LT_RELATION)<<1)|((r&MONO_GT_RELATION)>>1))
75 print_relation (int relation) {
78 if (relation & MONO_LT_RELATION) {
82 if (relation & MONO_EQ_RELATION) {
89 if (relation & MONO_GT_RELATION) {
100 print_summarized_value (MonoSummarizedValue *value) {
101 switch (value->type) {
102 case MONO_ANY_SUMMARIZED_VALUE:
105 case MONO_CONSTANT_SUMMARIZED_VALUE:
106 printf ("CONSTANT %d", value->value.constant.value);
108 case MONO_VARIABLE_SUMMARIZED_VALUE:
109 printf ("VARIABLE %d, delta %d", value->value.variable.variable, value->value.variable.delta);
111 case MONO_PHI_SUMMARIZED_VALUE: {
114 for (phi = 0; phi < value->value.phi.number_of_alternatives; phi++) {
115 if (phi) printf (",");
116 printf ("%d", value->value.phi.phi_alternatives [phi]);
122 g_assert_not_reached ();
127 print_summarized_value_relation (MonoSummarizedValueRelation *relation) {
128 printf ("Relation ");
129 print_relation (relation->relation);
130 printf (" with value ");
131 print_summarized_value (&(relation->related_value));
136 print_summarized_value_relation_chain (MonoSummarizedValueRelation *relation) {
137 printf ("Relations:\n");
139 print_summarized_value_relation (relation);
141 relation = relation->next;
147 print_evaluation_context_status (MonoRelationsEvaluationStatus status) {
148 if (status == MONO_RELATIONS_EVALUATION_NOT_STARTED) {
149 printf ("EVALUATION_NOT_STARTED");
151 gboolean print_or = FALSE;
154 if (status & MONO_RELATIONS_EVALUATION_IN_PROGRESS) {
155 if (print_or) printf ("|");
156 printf ("EVALUATION_IN_PROGRESS");
159 if (status & MONO_RELATIONS_EVALUATION_COMPLETED) {
160 if (print_or) printf ("|");
161 printf ("EVALUATION_COMPLETED");
164 if (status & MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_ASCENDING) {
165 if (print_or) printf ("|");
166 printf ("RECURSIVELY_ASCENDING");
169 if (status & MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_DESCENDING) {
170 if (print_or) printf ("|");
171 printf ("RECURSIVELY_DESCENDING");
174 if (status & MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_INDEFINITE) {
175 if (print_or) printf ("|");
176 printf ("RECURSIVELY_INDEFINITE");
185 print_evaluation_context_ranges (MonoRelationsEvaluationRanges *ranges) {
186 printf ("(ranges: zero [%d,%d], variable [%d,%d])", ranges->zero.lower, ranges->zero.upper, ranges->variable.lower, ranges->variable.upper);
190 print_evaluation_context (MonoRelationsEvaluationContext *context) {
191 printf ("Context status: ");
192 print_evaluation_context_status (context->status);
193 if (context->status & (MONO_RELATIONS_EVALUATION_IN_PROGRESS|MONO_RELATIONS_EVALUATION_COMPLETED)) {
194 print_evaluation_context_ranges (&(context->ranges));
201 print_evaluation_area (MonoVariableRelationsEvaluationArea *area) {
203 printf ("Dump of evaluation area (%d variables):\n", area->cfg->num_varinfo);
204 for (i = 0; i < area->cfg->num_varinfo; i++) {
205 printf ("Variable %d: ", i);
206 print_evaluation_context (&(area->contexts [i]));
207 print_summarized_value_relation_chain (&(area->relations [i]));
212 print_evaluation_area_contexts (MonoVariableRelationsEvaluationArea *area) {
214 printf ("Dump of evaluation area contexts (%d variables):\n", area->cfg->num_varinfo);
215 for (i = 0; i < area->cfg->num_varinfo; i++) {
216 printf ("Variable %d: ", i);
217 print_evaluation_context (&(area->contexts [i]));
223 * Given a MonoInst, if it is a store to a variable return the MonoInst that
224 * represents the stored value.
225 * If anything goes wrong, return NULL.
226 * store: the MonoInst that should be a store
227 * expected_variable_index: the variable where the value should be stored
228 * return: either the stored value, or NULL
231 get_variable_value_from_store_instruction (MonoInst *store, int expected_variable_index) {
232 switch (store->opcode) {
241 if (TRACE_ABC_REMOVAL) {
242 printf ("[store instruction found]");
244 if ((store->inst_left->opcode == OP_LOCAL) || (store->inst_left->opcode == OP_ARG)) {
245 int variable_index = store->inst_left->inst_c0;
246 if (TRACE_ABC_REMOVAL) {
247 printf ("[value put in local %d (expected %d)]", variable_index, expected_variable_index);
249 if (variable_index == expected_variable_index) {
250 return store->inst_right;
266 * Check if the delta of an integer variable value is safe with respect
267 * to the variable size in bytes and its kind (signed or unsigned).
268 * If the delta is not safe, make the value an "any".
271 check_delta_safety (MonoVariableRelationsEvaluationArea *area, MonoSummarizedValue *value) {
272 if (value->type == MONO_VARIABLE_SUMMARIZED_VALUE) {
273 int variable = value->value.variable.variable;
274 int delta = value->value.variable.delta;
275 if ((area->variable_value_kind [variable]) & MONO_UNSIGNED_VALUE_FLAG) {
277 MAKE_VALUE_ANY (*value);
280 if (((area->variable_value_kind [variable]) & MONO_INTEGER_VALUE_SIZE_BITMASK) < 4) {
281 MAKE_VALUE_ANY (*value);
282 } else if (delta > 16) {
283 MAKE_VALUE_ANY (*value);
289 /* Prototype, definition comes later */
291 summarize_array_value (MonoVariableRelationsEvaluationArea *area, MonoInst *value, MonoSummarizedValue *result, gboolean is_array_type);
294 * Given a MonoInst representing an integer value, store it in "summarized" form.
295 * result_value_kind: the "expected" kind of result;
296 * result: the "summarized" value
297 * returns the "actual" kind of result, if guessable (otherwise MONO_UNKNOWN_INTEGER_VALUE)
299 static MonoIntegerValueKind
300 summarize_integer_value (MonoVariableRelationsEvaluationArea *area, MonoInst *value, MonoSummarizedValue *result, MonoIntegerValueKind result_value_kind) {
301 MonoIntegerValueKind value_kind;
303 if (value->type == STACK_I8) {
304 value_kind = MONO_INTEGER_VALUE_SIZE_8;
305 } else if (value->type == STACK_I4) {
306 value_kind = MONO_INTEGER_VALUE_SIZE_4;
308 value_kind = MONO_UNKNOWN_INTEGER_VALUE;
311 switch (value->opcode) {
313 result->type = MONO_CONSTANT_SUMMARIZED_VALUE;
314 result->value.constant.value = value->inst_c0;
318 result->type = MONO_VARIABLE_SUMMARIZED_VALUE;
319 result->value.variable.variable = value->inst_c0;
320 result->value.variable.delta = 0;
321 value_kind = area->variable_value_kind [value->inst_c0];
324 value_kind = MONO_INTEGER_VALUE_SIZE_1;
327 value_kind = MONO_UNSIGNED_INTEGER_VALUE_SIZE_1;
330 value_kind = MONO_INTEGER_VALUE_SIZE_2;
333 value_kind = MONO_UNSIGNED_INTEGER_VALUE_SIZE_2;
336 value_kind = MONO_INTEGER_VALUE_SIZE_4;
339 value_kind = MONO_UNSIGNED_INTEGER_VALUE_SIZE_4;
342 value_kind = MONO_INTEGER_VALUE_SIZE_8;
345 value_kind = SIZEOF_VOID_P;
347 if ((value->inst_left->opcode == OP_LOCAL) || (value->inst_left->opcode == OP_ARG)) {
348 value_kind = summarize_integer_value (area, value->inst_left, result, result_value_kind);
350 MAKE_VALUE_ANY (*result);
354 MonoSummarizedValue left_value;
355 MonoSummarizedValue right_value;
356 summarize_integer_value (area, value->inst_left, &left_value, result_value_kind);
357 summarize_integer_value (area, value->inst_right, &right_value, result_value_kind);
359 if (left_value.type == MONO_VARIABLE_SUMMARIZED_VALUE) {
360 if (right_value.type == MONO_CONSTANT_SUMMARIZED_VALUE) {
361 result->type = MONO_VARIABLE_SUMMARIZED_VALUE;
362 result->value.variable.variable = left_value.value.variable.variable;
363 result->value.variable.delta = left_value.value.variable.delta + right_value.value.constant.value;
365 MAKE_VALUE_ANY (*result);
367 } else if (right_value.type == MONO_VARIABLE_SUMMARIZED_VALUE) {
368 if (left_value.type == MONO_CONSTANT_SUMMARIZED_VALUE) {
369 result->type = MONO_VARIABLE_SUMMARIZED_VALUE;
370 result->value.variable.variable = right_value.value.variable.variable;
371 result->value.variable.delta = left_value.value.constant.value + right_value.value.variable.delta;
373 MAKE_VALUE_ANY (*result);
375 } else if ((right_value.type == MONO_CONSTANT_SUMMARIZED_VALUE) && (left_value.type == MONO_CONSTANT_SUMMARIZED_VALUE)) {
376 /* This should not happen if constant folding has been done */
377 result->type = MONO_CONSTANT_SUMMARIZED_VALUE;
378 result->value.constant.value = left_value.value.constant.value + right_value.value.constant.value;
380 MAKE_VALUE_ANY (*result);
382 if (result->type == MONO_VARIABLE_SUMMARIZED_VALUE) {
383 check_delta_safety (area, result);
388 MonoSummarizedValue left_value;
389 MonoSummarizedValue right_value;
390 summarize_integer_value (area, value->inst_left, &left_value, result_value_kind);
391 summarize_integer_value (area, value->inst_right, &right_value, result_value_kind);
393 if (left_value.type == MONO_VARIABLE_SUMMARIZED_VALUE) {
394 if (right_value.type == MONO_CONSTANT_SUMMARIZED_VALUE) {
395 result->type = MONO_VARIABLE_SUMMARIZED_VALUE;
396 result->value.variable.variable = left_value.value.variable.variable;
397 result->value.variable.delta = left_value.value.variable.delta - right_value.value.constant.value;
399 MAKE_VALUE_ANY (*result);
401 } else if ((right_value.type == MONO_CONSTANT_SUMMARIZED_VALUE) && (left_value.type == MONO_CONSTANT_SUMMARIZED_VALUE)) {
402 /* This should not happen if constant folding has been done */
403 result->type = MONO_CONSTANT_SUMMARIZED_VALUE;
404 result->value.constant.value = left_value.value.constant.value - right_value.value.constant.value;
406 MAKE_VALUE_ANY (*result);
408 if (result->type == MONO_VARIABLE_SUMMARIZED_VALUE) {
409 check_delta_safety (area, result);
414 MonoSummarizedValue left_value;
415 MonoSummarizedValue right_value;
416 int constant_operand_value;
418 summarize_integer_value (area, value->inst_left, &left_value, result_value_kind);
419 summarize_integer_value (area, value->inst_right, &right_value, result_value_kind);
421 if (left_value.type == MONO_CONSTANT_SUMMARIZED_VALUE) {
422 constant_operand_value = left_value.value.constant.value;
423 } else if (right_value.type == MONO_CONSTANT_SUMMARIZED_VALUE) {
424 constant_operand_value = right_value.value.constant.value;
426 constant_operand_value = 0;
429 if (constant_operand_value > 0) {
430 if (constant_operand_value <= 0xff) {
431 if ((result_value_kind & MONO_INTEGER_VALUE_SIZE_BITMASK) > 1) {
432 value_kind = MONO_UNSIGNED_INTEGER_VALUE_SIZE_1;
434 } else if (constant_operand_value <= 0xffff) {
435 if ((result_value_kind & MONO_INTEGER_VALUE_SIZE_BITMASK) > 2) {
436 value_kind = MONO_UNSIGNED_INTEGER_VALUE_SIZE_2;
441 MAKE_VALUE_ANY (*result);
445 case CEE_CONV_OVF_I1:
446 case CEE_CONV_OVF_I1_UN:
447 value_kind = MONO_INTEGER_VALUE_SIZE_1;
448 MAKE_VALUE_ANY (*result);
451 case CEE_CONV_OVF_U1:
452 value_kind = MONO_UNSIGNED_INTEGER_VALUE_SIZE_1;
453 MAKE_VALUE_ANY (*result);
456 case CEE_CONV_OVF_I2:
457 case CEE_CONV_OVF_I2_UN:
458 value_kind = MONO_INTEGER_VALUE_SIZE_2;
459 MAKE_VALUE_ANY (*result);
462 case CEE_CONV_OVF_U2:
463 value_kind = MONO_UNSIGNED_INTEGER_VALUE_SIZE_2;
464 MAKE_VALUE_ANY (*result);
467 summarize_array_value (area, value->inst_left, result, TRUE);
468 value_kind = MONO_UNSIGNED_INTEGER_VALUE_SIZE_4;
471 value_kind = summarize_integer_value (area, value->inst_left, result, result_value_kind);
474 result->type = MONO_PHI_SUMMARIZED_VALUE;
475 result->value.phi.number_of_alternatives = *(value->inst_phi_args);
476 result->value.phi.phi_alternatives = value->inst_phi_args + 1;
479 MAKE_VALUE_ANY (*result);
485 * Given a MonoInst representing an array value, store it in "summarized" form.
486 * result: the "summarized" value
487 * is_array_type: TRUE of we are *sure* that an eventual OP_PCONST will point
488 * to a MonoArray (this can happen for already initialized readonly static fields,
489 * in which case we will get the array length directly from the MonoArray)
492 summarize_array_value (MonoVariableRelationsEvaluationArea *area, MonoInst *value, MonoSummarizedValue *result, gboolean is_array_type) {
493 switch (value->opcode) {
496 result->type = MONO_VARIABLE_SUMMARIZED_VALUE;
497 result->value.variable.variable = value->inst_c0;
498 result->value.variable.delta = 0;
501 summarize_array_value (area, value->inst_left, result, FALSE);
504 summarize_integer_value (area, value->inst_newa_len, result, MONO_UNKNOWN_INTEGER_VALUE);
507 if ((is_array_type) && (value->inst_p0 != NULL)) {
508 MonoArray *array = (MonoArray *) (value->inst_p0);
509 result->type = MONO_CONSTANT_SUMMARIZED_VALUE;
510 result->value.constant.value = array->max_length;
512 MAKE_VALUE_ANY (*result);
516 result->type = MONO_PHI_SUMMARIZED_VALUE;
517 result->value.phi.number_of_alternatives = *(value->inst_phi_args);
518 result->value.phi.phi_alternatives = value->inst_phi_args + 1;
521 MAKE_VALUE_ANY (*result);
525 static MonoValueRelation
526 get_relation_from_branch_instruction (int opcode) {
529 return MONO_EQ_RELATION;
532 return MONO_LT_RELATION;
535 return MONO_LE_RELATION;
538 return MONO_GT_RELATION;
541 return MONO_GE_RELATION;
543 return MONO_NE_RELATION;
545 return MONO_ANY_RELATION;
550 * Given a BB, find its entry condition and put its relations in a
551 * "MonoAdditionalVariableRelationsForBB" structure.
553 * relations: the resulting relations (entry condition of the given BB)
556 get_relations_from_previous_bb (MonoVariableRelationsEvaluationArea *area, MonoBasicBlock *bb, MonoAdditionalVariableRelationsForBB *relations) {
557 MonoBasicBlock *in_bb;
559 MonoValueRelation branch_relation;
560 MonoValueRelation symmetric_relation;
562 INITIALIZE_VALUE_RELATION (&(relations->relation1.relation));
563 relations->relation1.relation.relation_is_static_definition = FALSE;
564 relations->relation1.insertion_point = NULL;
565 relations->relation1.variable = -1;
566 INITIALIZE_VALUE_RELATION (&(relations->relation2.relation));
567 relations->relation2.relation.relation_is_static_definition = FALSE;
568 relations->relation2.insertion_point = NULL;
569 relations->relation2.variable = -1;
572 if (bb->in_count == 1) { /* Should write the code to "sum" conditions... */
573 in_bb = bb->in_bb [0];
574 branch = in_bb->last_ins;
575 if (branch == NULL) return;
576 branch_relation = get_relation_from_branch_instruction (branch->opcode);
577 if ((branch_relation != MONO_ANY_RELATION) && (branch->inst_left->opcode == OP_COMPARE)) {
578 MonoSummarizedValue left_value;
579 MonoSummarizedValue right_value;
582 if (branch->inst_true_bb == bb) {
584 } else if (branch->inst_false_bb == bb) {
588 g_assert_not_reached ();
592 branch_relation = MONO_NEGATED_RELATION (branch_relation);
594 symmetric_relation = MONO_SYMMETRIC_RELATION (branch_relation);
596 summarize_integer_value (area, branch->inst_left->inst_left, &left_value, MONO_UNKNOWN_INTEGER_VALUE);
597 summarize_integer_value (area, branch->inst_left->inst_right, &right_value, MONO_UNKNOWN_INTEGER_VALUE);
599 if ((left_value.type == MONO_VARIABLE_SUMMARIZED_VALUE) && ((right_value.type == MONO_VARIABLE_SUMMARIZED_VALUE)||(right_value.type == MONO_CONSTANT_SUMMARIZED_VALUE))) {
600 relations->relation1.variable = left_value.value.variable.variable;
601 relations->relation1.relation.relation = branch_relation;
602 relations->relation1.relation.related_value = right_value;
603 if (right_value.type == MONO_CONSTANT_SUMMARIZED_VALUE) {
604 relations->relation1.relation.related_value.value.constant.value -= left_value.value.variable.delta;
606 relations->relation1.relation.related_value.value.variable.delta -= left_value.value.variable.delta;
609 if ((right_value.type == MONO_VARIABLE_SUMMARIZED_VALUE) && ((left_value.type == MONO_VARIABLE_SUMMARIZED_VALUE)||(left_value.type == MONO_CONSTANT_SUMMARIZED_VALUE))) {
610 relations->relation2.variable = right_value.value.variable.variable;
611 relations->relation2.relation.relation = symmetric_relation;
612 relations->relation2.relation.related_value = left_value;
613 if (left_value.type == MONO_CONSTANT_SUMMARIZED_VALUE) {
614 relations->relation2.relation.related_value.value.constant.value -= right_value.value.variable.delta;
616 relations->relation2.relation.related_value.value.variable.delta -= right_value.value.variable.delta;
625 * Add the given relations to the evaluation area.
626 * area: the evaluation area
627 * change: the relations that must be added
630 apply_change_to_evaluation_area (MonoVariableRelationsEvaluationArea *area, MonoAdditionalVariableRelation *change) {
631 MonoSummarizedValueRelation *base_relation;
633 if (change->relation.relation != MONO_ANY_RELATION) {
634 base_relation = &(area->relations [change->variable]);
635 while ((base_relation->next != NULL) && (base_relation->next->relation_is_static_definition)) {
636 base_relation = base_relation->next;
638 change->insertion_point = base_relation;
639 change->relation.next = base_relation->next;
640 base_relation->next = &(change->relation);
645 * Remove the given relation from the evaluation area.
646 * change: the relation that must be removed
649 remove_change_from_evaluation_area (MonoAdditionalVariableRelation *change) {
650 if (change->insertion_point != NULL) {
651 change->insertion_point->next = change->relation.next;
652 change->relation.next = NULL;
658 clean_contexts (MonoRelationsEvaluationContext *contexts, int number) {
660 for (i = 0; i < number; i++) {
661 contexts [i].status = MONO_RELATIONS_EVALUATION_NOT_STARTED;
667 * Perform the intersection of a range and a constant value (taking into
668 * account the relation that the value has with the range).
669 * range: the range that will be intersected with the value
670 * value: the value that will be intersected with the range
671 * relation: the relation between the range and the value
674 intersect_value( MonoRelationsEvaluationRange *range, int value, MonoValueRelation relation ) {
676 case MONO_NO_RELATION:
677 MONO_MAKE_RELATIONS_EVALUATION_RANGE_IMPOSSIBLE (*range);
679 case MONO_ANY_RELATION:
681 case MONO_EQ_RELATION:
682 MONO_UPPER_EVALUATION_RANGE_INTERSECTION (range->upper, value);
683 MONO_LOWER_EVALUATION_RANGE_INTERSECTION (range->lower, value);
685 case MONO_NE_RELATION: {
686 /* IMPROVEMENT Figure this out! (ignoring it is safe anyway) */
689 case MONO_LT_RELATION:
690 MONO_UPPER_EVALUATION_RANGE_INTERSECTION (range->upper, MONO_UPPER_EVALUATION_RANGE_NOT_EQUAL (value));
692 case MONO_LE_RELATION:
693 MONO_UPPER_EVALUATION_RANGE_INTERSECTION (range->upper, value);
695 case MONO_GT_RELATION:
696 MONO_LOWER_EVALUATION_RANGE_INTERSECTION (range->lower, MONO_LOWER_EVALUATION_RANGE_NOT_EQUAL (value));
698 case MONO_GE_RELATION:
699 MONO_LOWER_EVALUATION_RANGE_INTERSECTION (range->lower, value);
702 g_assert_not_reached();
708 * Perform the intersection of two pairs of ranges (taking into account the
709 * relation between the ranges and a given delta).
710 * ranges: the ranges that will be intersected
711 * other_ranges the other ranges that will be intersected
712 * delta: the delta between the pairs of ranges
713 * relation: the relation between the pairs of ranges
716 intersect_ranges( MonoRelationsEvaluationRanges *ranges, MonoRelationsEvaluationRanges *other_ranges, int delta, MonoValueRelation relation ) {
719 case MONO_NO_RELATION:
720 MONO_MAKE_RELATIONS_EVALUATION_RANGES_IMPOSSIBLE (*ranges);
722 case MONO_ANY_RELATION:
724 case MONO_EQ_RELATION:
725 MONO_RELATIONS_EVALUATION_RANGES_INTERSECTION (*ranges, *other_ranges);
727 case MONO_NE_RELATION: {
728 /* FIXME Figure this out! (ignoring it is safe anyway) */
731 case MONO_LT_RELATION:
732 MONO_UPPER_EVALUATION_RANGE_INTERSECTION (ranges->zero.upper, MONO_UPPER_EVALUATION_RANGE_NOT_EQUAL (other_ranges->zero.upper));
733 MONO_UPPER_EVALUATION_RANGE_INTERSECTION (ranges->variable.upper, MONO_UPPER_EVALUATION_RANGE_NOT_EQUAL (other_ranges->variable.upper));
735 case MONO_LE_RELATION:
736 MONO_UPPER_EVALUATION_RANGE_INTERSECTION (ranges->zero.upper, other_ranges->zero.upper);
737 MONO_UPPER_EVALUATION_RANGE_INTERSECTION (ranges->variable.upper, other_ranges->variable.upper);
739 case MONO_GT_RELATION:
740 MONO_LOWER_EVALUATION_RANGE_INTERSECTION (ranges->zero.lower, MONO_LOWER_EVALUATION_RANGE_NOT_EQUAL (other_ranges->zero.lower));
741 MONO_LOWER_EVALUATION_RANGE_INTERSECTION (ranges->variable.lower, MONO_LOWER_EVALUATION_RANGE_NOT_EQUAL (other_ranges->variable.lower));
743 case MONO_GE_RELATION:
744 MONO_LOWER_EVALUATION_RANGE_INTERSECTION (ranges->zero.lower, other_ranges->zero.lower);
745 MONO_LOWER_EVALUATION_RANGE_INTERSECTION (ranges->variable.lower, other_ranges->variable.lower);
748 g_assert_not_reached();
751 MonoRelationsEvaluationRanges translated_ranges = *other_ranges;
752 MONO_ADD_DELTA_SAFELY_TO_RANGES (translated_ranges, delta);
753 intersect_ranges( ranges, &translated_ranges, FALSE, relation );
758 * Recursive method that traverses the relation graph to evaluate the
759 * relation between two variables.
760 * At the end of the execution, the resulting ranges are in the context of
761 * the "starting" variable.
762 * area: the current evaluation area (it contains the relation graph and
763 * memory for all the evaluation contexts is already allocated)
764 * variable: starting variable (the value ranges in its context are the result
765 * of the execution of this procedure)
766 * target_variable: the variable with respect to which the starting variable
767 * is evaluated (tipically the starting variable is the index
768 * and the target one is the array (which means its length))
769 * father_context: the previous evaluation context in recursive invocations
770 * (or NULL for the first invocation)
773 evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea *area, int variable, int target_variable, MonoRelationsEvaluationContext *father_context) {
774 MonoRelationsEvaluationContext *context = &(area->contexts [variable]);
776 // First of all, we check the evaluation status
777 // (what must be done is *very* different in each case)
778 switch (context->status) {
779 case MONO_RELATIONS_EVALUATION_NOT_STARTED: {
780 MonoSummarizedValueRelation *relation = &(area->relations [variable]);
782 if (TRACE_ABC_REMOVAL) {
783 printf ("Evaluating varible %d (target variable %d)\n", variable, target_variable);
784 print_summarized_value_relation (relation);
788 // We properly inizialize the context
789 context->status = MONO_RELATIONS_EVALUATION_IN_PROGRESS;
790 context->father = father_context;
791 MONO_MAKE_RELATIONS_EVALUATION_RANGES_WEAK (context->ranges);
793 // If we have found the target variable, we can set the range
794 // related to it in the context to "equal" (which is [0,0])
795 if (variable == target_variable) {
796 if (TRACE_ABC_REMOVAL) {
797 printf ("Target variable reached (%d), continuing to evaluate relations with constants\n", variable);
799 context->ranges.variable.lower = 0;
800 context->ranges.variable.upper = 0;
803 // Examine all relations for this variable (scan the list)
804 // The contribute of each relation will be intersected (logical and)
805 while (relation != NULL) {
806 context->current_relation = relation;
808 if (TRACE_ABC_REMOVAL) {
809 printf ("Processing (%d): ", variable);
810 print_summarized_value_relation (relation);
814 // We decie what to do according the the type of the related value
815 switch (relation->related_value.type) {
816 case MONO_ANY_SUMMARIZED_VALUE:
817 // No added information, skip it
819 case MONO_CONSTANT_SUMMARIZED_VALUE:
820 // Intersect range with constant (taking into account the relation)
821 intersect_value (&(context->ranges.zero), relation->related_value.value.constant.value, relation->relation);
823 case MONO_VARIABLE_SUMMARIZED_VALUE:
824 // Generally, evaluate related variable and intersect ranges.
825 // However, some check is necessary...
827 // If the relation is "ANY", nothing to do (no added information)
828 if (relation->relation != MONO_ANY_RELATION) {
829 int related_variable = relation->related_value.value.variable.variable;
830 MonoRelationsEvaluationContext *related_context = &(area->contexts [related_variable]);
832 // The second condition in the "or" avoids messing with "back edges" in the graph traversal
833 // (they are simply ignored instead of triggering the handling of recursion)
834 if ( (related_context->status == MONO_RELATIONS_EVALUATION_NOT_STARTED) || !
835 ((related_context->current_relation->related_value.type == MONO_VARIABLE_SUMMARIZED_VALUE) &&
836 (related_context->current_relation->related_value.value.variable.variable == variable))) {
837 // Evaluate the related variable
838 evaluate_relation_with_target_variable (area, related_variable, target_variable, context);
840 // Check if we are part of a recursive loop
841 if (context->status & MONO_RELATIONS_EVALUATION_IS_RECURSIVE) {
842 if (TRACE_ABC_REMOVAL) {
843 printf ("Recursivity detected for varible %d (target variable %d), status ", variable, target_variable);
844 print_evaluation_context_status (context->status);
847 // If we are, check if the evaluation of the related variable is complete
848 if (related_context->status == MONO_RELATIONS_EVALUATION_COMPLETED) {
849 // If it is complete, we are part of a recursive definition.
850 // Since it is a *definition* (and definitions are evaluated *before*
851 // conditions because they are first in the list), intersection is not
852 // strictly necessary, we simply copy the ranges and apply the delta
853 context->ranges = related_context->ranges;
854 /* Delta has already been checked for over/under-flow when evaluating values */
855 MONO_ADD_DELTA_SAFELY_TO_RANGES (context->ranges, relation->related_value.value.variable.delta);
856 context->status = MONO_RELATIONS_EVALUATION_COMPLETED;
857 if (TRACE_ABC_REMOVAL) {
858 printf (", ranges already computed, result: \n");
859 print_evaluation_context_ranges (&(context->ranges));
860 printf (" (delta is %d)\n", relation->related_value.value.variable.delta);
863 // If it is not complete, do nothing (we do not have enough information)
864 if (TRACE_ABC_REMOVAL) {
865 printf (", ranges not computed\n");
869 // If we are not (the common case) intersect the result
870 intersect_ranges( &(context->ranges), &(related_context->ranges), relation->related_value.value.variable.delta, relation->relation );
873 if (TRACE_ABC_REMOVAL) {
874 printf ("Relation is a back-edge in this traversal, skipping\n");
879 case MONO_PHI_SUMMARIZED_VALUE: {
880 // We must compute all PHI alternatives, combining the results (with a union, which is a logical "or"),
881 // and intersect this result with the ranges in the context; we must also take into account recursions
882 // (with loops that can be ascending, descending, or indefinite)
883 MonoRelationsEvaluationRanges phi_ranges;
885 gboolean is_ascending = FALSE;
886 gboolean is_descending = FALSE;
888 MONO_MAKE_RELATIONS_EVALUATION_RANGES_IMPOSSIBLE (phi_ranges);
889 for (phi = 0; phi < relation->related_value.value.phi.number_of_alternatives; phi++) {
890 int phi_alternative = relation->related_value.value.phi.phi_alternatives [phi];
891 evaluate_relation_with_target_variable (area, phi_alternative, target_variable, context);
893 // This means we are part of a recursive loop
894 if (context->status & MONO_RELATIONS_EVALUATION_IS_RECURSIVE) {
895 if (TRACE_ABC_REMOVAL) {
896 printf ("Recursivity detected for varible %d (target variable %d), status ", variable, target_variable);
897 print_evaluation_context_status (context->status);
900 if (context->status & MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_ASCENDING) {
903 if (context->status & MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_DESCENDING) {
904 is_descending = TRUE;
906 if (context->status & MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_INDEFINITE) {
908 is_descending = TRUE;
911 // Clear "recursivity" bits in the status (recursion has been handled)
912 context->status = MONO_RELATIONS_EVALUATION_IN_PROGRESS;
914 MONO_RELATIONS_EVALUATION_RANGES_UNION (phi_ranges, area->contexts [phi_alternative].ranges);
918 // Apply the effects of all recursive loops
920 phi_ranges.zero.upper = INT_MAX;
921 phi_ranges.variable.upper = INT_MAX;
924 phi_ranges.zero.lower = INT_MIN;
925 phi_ranges.variable.lower = INT_MIN;
928 // Intersect final result
929 MONO_RELATIONS_EVALUATION_RANGES_INTERSECTION (context->ranges, phi_ranges);
933 g_assert_not_reached();
936 // Pass to next relation
937 relation = relation->next;
940 // Check if any recursivity bits are still in the status, and in any case clear them
941 if (context->status & MONO_RELATIONS_EVALUATION_IS_RECURSIVE) {
942 if (TRACE_ABC_REMOVAL) {
943 printf ("Recursivity for varible %d (target variable %d) discards computation, status ", variable, target_variable);
944 print_evaluation_context_status (context->status);
947 // If yes, we did not have enough information (most likely we were evaluated inside a PHI, but we also
948 // depended on the same PHI, which was still in evaluation...), so clear the status to "NOT_STARTED"
949 // (if we will be evaluated again, the PHI will be already done, so our evaluation will succeed)
950 context->status = MONO_RELATIONS_EVALUATION_NOT_STARTED;
952 if (TRACE_ABC_REMOVAL) {
953 printf ("Ranges for varible %d (target variable %d) computed: ", variable, target_variable);
954 print_evaluation_context_ranges (&(context->ranges));
957 // If not (the common case) the evaluation is complete, and the result is in the context
958 context->status = MONO_RELATIONS_EVALUATION_COMPLETED;
962 case MONO_RELATIONS_EVALUATION_IN_PROGRESS: {
963 // This means we are in a recursive loop
964 MonoRelationsEvaluationContext *current_context = father_context;
965 MonoRelationsEvaluationContext *last_context = context->father;
966 gboolean evaluation_can_be_recursive = TRUE;
967 gboolean evaluation_is_definition = TRUE;
970 if (TRACE_ABC_REMOVAL) {
971 printf ("Evaluation of varible %d (target variable %d) already in progress\n", variable, target_variable);
972 print_evaluation_context (context);
973 print_summarized_value_relation (context->current_relation);
977 // We must check if the loop can be a recursive definition (we scan the whole loop)
978 while (current_context != last_context) {
979 if (current_context == NULL) {
980 printf ("Broken recursive ring in ABC removal\n");
981 g_assert_not_reached ();
984 if (current_context->current_relation->relation_is_static_definition) {
985 if (current_context->current_relation->related_value.type == MONO_VARIABLE_SUMMARIZED_VALUE) {
986 /* No need to check path_value for over/under-flow, since delta should be safe */
987 path_value += current_context->current_relation->related_value.value.variable.delta;
988 } else if (current_context->current_relation->related_value.type != MONO_PHI_SUMMARIZED_VALUE) {
989 evaluation_can_be_recursive = FALSE;
992 evaluation_is_definition = FALSE;
993 evaluation_can_be_recursive = FALSE;
996 current_context = current_context->father;
999 // If this is a recursive definition, we properly flag the status in all the involved contexts
1000 if (evaluation_is_definition) {
1001 MonoRelationsEvaluationStatus recursive_status;
1002 if (evaluation_can_be_recursive) {
1003 if (path_value > 0) {
1004 recursive_status = MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_ASCENDING;
1005 } else if (path_value < 0) {
1006 recursive_status = MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_DESCENDING;
1008 recursive_status = MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_INDEFINITE;
1011 recursive_status = MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_INDEFINITE;
1014 if (TRACE_ABC_REMOVAL) {
1015 printf ("Recursivity accepted (");
1016 print_evaluation_context_status (recursive_status);
1020 current_context = father_context;
1021 while (current_context != last_context) {
1022 current_context->status |= recursive_status;
1023 current_context = current_context->father;
1026 if (TRACE_ABC_REMOVAL) {
1027 printf ("Recursivity rejected (some relation in the cycle is not a defintion)\n");
1032 case MONO_RELATIONS_EVALUATION_COMPLETED: {
1036 if (TRACE_ABC_REMOVAL) {
1037 printf ("Varible %d (target variable %d) already in a recursive ring, skipping\n", variable, target_variable);
1038 print_evaluation_context (context);
1039 print_summarized_value_relation (context->current_relation);
1048 * Apply the given value kind to the given range
1050 static void apply_value_kind_to_range (MonoRelationsEvaluationRange *range, MonoIntegerValueKind value_kind) {
1051 if (value_kind != MONO_UNKNOWN_INTEGER_VALUE) {
1052 if (value_kind & MONO_UNSIGNED_VALUE_FLAG) {
1053 if (range->lower < 0) {
1056 if ((value_kind & MONO_INTEGER_VALUE_SIZE_BITMASK) == 1) {
1057 if (range->upper > 0xff) {
1058 range->upper = 0xff;
1060 } else if ((value_kind & MONO_INTEGER_VALUE_SIZE_BITMASK) == 2) {
1061 if (range->upper > 0xffff) {
1062 range->upper = 0xffff;
1066 if ((value_kind & MONO_INTEGER_VALUE_SIZE_BITMASK) == 1) {
1067 if (range->lower < -0x80) {
1068 range->lower = -0x80;
1070 if (range->upper > 0x7f) {
1071 range->upper = 0x7f;
1073 } else if ((value_kind & MONO_INTEGER_VALUE_SIZE_BITMASK) == 2) {
1074 if (range->lower < -0x8000) {
1075 range->lower = -0x8000;
1077 if (range->upper > 0x7fff) {
1078 range->upper = 0x7fff;
1086 * Attempt the removal of bounds checks from a MonoInst.
1087 * inst: the MonoInst
1088 * area: the current evaluation area (it contains the relation graph and
1089 * memory for all the evaluation contexts is already allocated)
1092 remove_abc_from_inst (MonoInst *inst, MonoVariableRelationsEvaluationArea *area) {
1093 if (inst->opcode == CEE_LDELEMA) {
1094 MonoInst *array_inst = inst->inst_left;
1095 MonoInst *index_inst = inst->inst_right;
1096 MonoSummarizedValue array_value;
1097 MonoSummarizedValue index_value;
1098 MonoIntegerValueKind index_value_kind;
1100 /* First of all, examine the CEE_LDELEMA operands */
1101 summarize_array_value (area, array_inst, &array_value, TRUE);
1102 index_value_kind = summarize_integer_value (area, index_inst, &index_value, MONO_UNKNOWN_INTEGER_VALUE);
1104 /* If the array is a local variable... */
1105 if (array_value.type == MONO_VARIABLE_SUMMARIZED_VALUE) {
1106 int array_variable = array_value.value.variable.variable;
1107 MonoRelationsEvaluationContext *array_context = &(area->contexts [array_variable]);
1109 if (index_value.type == MONO_CONSTANT_SUMMARIZED_VALUE) {
1110 // The easiest case: we just evaluate the array length, to see if it has some relation
1111 // with the index constant, and act accordingly
1113 clean_contexts (area->contexts, area->cfg->num_varinfo);
1114 evaluate_relation_with_target_variable (area, array_variable, array_variable, NULL);
1116 if ((index_value.value.constant.value >= 0) && (index_value.value.constant.value < array_context->ranges.zero.lower)) {
1117 if (REPORT_ABC_REMOVAL) {
1118 printf ("ARRAY-ACCESS: removed bounds check on array %d with constant index %d in method %s\n",
1119 array_variable, index_value.value.constant.value, mono_method_full_name (area->cfg->method, TRUE));
1121 inst->flags |= (MONO_INST_NORANGECHECK);
1123 } else if (index_value.type == MONO_VARIABLE_SUMMARIZED_VALUE) {
1124 // The common case: we must evaluate both the index and the array length, and check for relevant
1125 // relations both through variable definitions and as constant definitions
1127 int index_variable = index_value.value.variable.variable;
1128 MonoRelationsEvaluationContext *index_context = &(area->contexts [index_variable]);
1130 clean_contexts (area->contexts, area->cfg->num_varinfo);
1132 evaluate_relation_with_target_variable (area, index_variable, array_variable, NULL);
1133 evaluate_relation_with_target_variable (area, array_variable, array_variable, NULL);
1135 MONO_SUB_DELTA_SAFELY_FROM_RANGES (index_context->ranges, index_value.value.variable.delta);
1136 /* Apply index value kind */
1137 apply_value_kind_to_range (&(index_context->ranges.zero), index_value_kind);
1139 if (index_context->ranges.zero.lower >= 0) {
1140 if (TRACE_ABC_REMOVAL) {
1141 printf ("ARRAY-ACCESS: Removed lower bound check on array %d with index %d\n", array_variable, index_variable);
1143 if ((index_context->ranges.variable.upper < 0)||(index_context->ranges.zero.upper < array_context->ranges.zero.lower)) {
1144 if (REPORT_ABC_REMOVAL) {
1145 printf ("ARRAY-ACCESS: removed bounds check on array %d with index %d in method %s\n",
1146 array_variable, index_variable, mono_method_full_name (area->cfg->method, TRUE));
1148 inst->flags |= (MONO_INST_NORANGECHECK);
1151 if (TRACE_ABC_REMOVAL) {
1152 if (index_context->ranges.variable.upper < 0) {
1153 printf ("ARRAY-ACCESS: Removed upper bound check (through variable) on array %d with index %d\n", array_variable, index_variable);
1155 if (index_context->ranges.zero.upper < array_context->ranges.zero.lower) {
1156 printf ("ARRAY-ACCESS: Removed upper bound check (through constant) on array %d with index %d\n", array_variable, index_variable);
1160 } else if (array_value.type == MONO_CONSTANT_SUMMARIZED_VALUE) {
1161 if (index_value.type == MONO_CONSTANT_SUMMARIZED_VALUE) {
1162 /* The easiest possible case: constant with constant */
1163 if ((index_value.value.constant.value >= 0) && (index_value.value.constant.value < array_value.value.constant.value)) {
1164 if (REPORT_ABC_REMOVAL) {
1165 printf ("ARRAY-ACCESS: removed bounds check on array of constant length %d with constant index %d in method %s\n",
1166 array_value.value.constant.value, index_value.value.constant.value, mono_method_full_name (area->cfg->method, TRUE));
1168 inst->flags |= (MONO_INST_NORANGECHECK);
1170 } else if (index_value.type == MONO_VARIABLE_SUMMARIZED_VALUE) {
1171 /* The index has a variable related value, which must be evaluated */
1172 int index_variable = index_value.value.variable.variable;
1173 MonoRelationsEvaluationContext *index_context = &(area->contexts [index_variable]);
1175 clean_contexts (area->contexts, area->cfg->num_varinfo);
1176 evaluate_relation_with_target_variable (area, index_variable, index_variable, NULL);
1177 /* Apply index value kind */
1178 apply_value_kind_to_range (&(index_context->ranges.zero), index_value_kind);
1180 if ((index_context->ranges.zero.lower >= 0) && (index_context->ranges.zero.upper < array_value.value.constant.value)) {
1181 if (REPORT_ABC_REMOVAL) {
1182 printf ("ARRAY-ACCESS: removed bounds check on array of constant length %d with index %d ranging from %d to %d in method %s\n",
1183 array_value.value.constant.value, index_variable, index_context->ranges.zero.lower, index_context->ranges.zero.upper, mono_method_full_name (area->cfg->method, TRUE));
1185 inst->flags |= (MONO_INST_NORANGECHECK);
1187 } else if (index_value_kind != MONO_UNKNOWN_INTEGER_VALUE) {
1188 /* The index has an unknown but bounded value */
1189 MonoRelationsEvaluationRange range;
1190 MONO_MAKE_RELATIONS_EVALUATION_RANGE_WEAK (range);
1191 apply_value_kind_to_range (&range, index_value_kind);
1193 if ((range.lower >= 0) && (range.upper < array_value.value.constant.value)) {
1194 if (REPORT_ABC_REMOVAL) {
1195 printf ("ARRAY-ACCESS: removed bounds check on array of constant length %d with unknown index ranging from %d to %d in method %s\n",
1196 array_value.value.constant.value, range.lower, range.upper, mono_method_full_name (area->cfg->method, TRUE));
1198 inst->flags |= (MONO_INST_NORANGECHECK);
1206 * Recursively scan a tree of MonoInst looking for array accesses.
1207 * inst: the root of the MonoInst tree
1208 * area: the current evaluation area (it contains the relation graph and
1209 * memory for all the evaluation contexts is already allocated)
1212 process_inst (MonoInst *inst, MonoVariableRelationsEvaluationArea *area) {
1213 if (inst->opcode == CEE_LDELEMA) { /* Handle OP_LDELEMA2D, too */
1214 if (TRACE_ABC_REMOVAL) {
1215 printf ("Attempting check removal...\n");
1218 remove_abc_from_inst (inst, area);
1221 if (mono_burg_arity [inst->opcode]) {
1222 process_inst (inst->inst_left, area);
1223 if (mono_burg_arity [inst->opcode] > 1) {
1224 process_inst (inst->inst_right, area);
1233 * Process a BB removing bounds checks from array accesses.
1234 * It does the following (in sequence):
1235 * - Get the BB entry condition
1236 * - Add its relations to the relation graph in the evaluation area
1237 * - Process all the MonoInst trees in the BB
1238 * - Recursively process all the children BBs in the dominator tree
1239 * - Remove the relations previously added to the relation graph
1241 * bb: the BB that must be processed
1242 * area: the current evaluation area (it contains the relation graph and
1243 * memory for all the evaluation contexts is already allocated)
1246 process_block (MonoBasicBlock *bb, MonoVariableRelationsEvaluationArea *area) {
1248 MonoInst *current_inst;
1249 MonoAdditionalVariableRelationsForBB additional_relations;
1250 GSList *dominated_bb;
1252 if (TRACE_ABC_REMOVAL) {
1253 printf ("Processing block %d [dfn %d]...\n", bb->block_num, bb->dfn);
1256 get_relations_from_previous_bb (area, bb, &additional_relations);
1257 if (TRACE_ABC_REMOVAL) {
1258 if (additional_relations.relation1.relation.relation != MONO_ANY_RELATION) {
1259 printf ("Adding relation 1 on variable %d: ", additional_relations.relation1.variable);
1260 print_summarized_value_relation (&(additional_relations.relation1.relation));
1263 if (additional_relations.relation2.relation.relation != MONO_ANY_RELATION) {
1264 printf ("Adding relation 2 on variable %d: ", additional_relations.relation2.variable);
1265 print_summarized_value_relation (&(additional_relations.relation2.relation));
1269 apply_change_to_evaluation_area (area, &(additional_relations.relation1));
1270 apply_change_to_evaluation_area (area, &(additional_relations.relation2));
1273 MONO_BB_FOR_EACH_INS (bb, current_inst) {
1274 if (TRACE_ABC_REMOVAL) {
1275 printf ("Processing instruction %d\n", inst_index);
1279 process_inst (current_inst, area);
1283 if (TRACE_ABC_REMOVAL) {
1284 printf ("Processing block %d [dfn %d] done.\n", bb->block_num, bb->dfn);
1287 for (dominated_bb = bb->dominated; dominated_bb != NULL; dominated_bb = dominated_bb->next) {
1288 process_block ((MonoBasicBlock*) (dominated_bb->data), area);
1291 remove_change_from_evaluation_area (&(additional_relations.relation1));
1292 remove_change_from_evaluation_area (&(additional_relations.relation2));
1298 * mono_perform_abc_removal:
1299 * @cfg: Control Flow Graph
1301 * Performs the ABC removal from a cfg in SSA form.
1302 * It does the following:
1303 * - Prepare the evaluation area
1304 * - Allocate memory for the relation graph in the evaluation area
1305 * (of course, only for variable definitions) and summarize there all
1306 * variable definitions
1307 * - Allocate memory for the evaluation contexts in the evaluation area
1308 * - Recursively process all the BBs in the dominator tree (it is enough
1309 * to invoke the processing on the entry BB)
1311 * cfg: the method code
1314 mono_perform_abc_removal (MonoCompile *cfg)
1316 MonoVariableRelationsEvaluationArea area;
1319 verbose_level = cfg->verbose_level;
1321 if (TRACE_ABC_REMOVAL) {
1322 printf ("Removing array bound checks in %s\n", mono_method_full_name (cfg->method, TRUE));
1326 area.relations = (MonoSummarizedValueRelation *)
1327 mono_mempool_alloc (cfg->mempool, sizeof (MonoSummarizedValueRelation) * (cfg->num_varinfo) * 2);
1328 area.contexts = (MonoRelationsEvaluationContext *)
1329 mono_mempool_alloc (cfg->mempool, sizeof (MonoRelationsEvaluationContext) * (cfg->num_varinfo));
1330 area.variable_value_kind = (MonoIntegerValueKind *)
1331 mono_mempool_alloc (cfg->mempool, sizeof (MonoIntegerValueKind) * (cfg->num_varinfo));
1332 for (i = 0; i < cfg->num_varinfo; i++) {
1333 area.variable_value_kind [i] = MONO_UNKNOWN_INTEGER_VALUE;
1334 area.relations [i].relation = MONO_EQ_RELATION;
1335 area.relations [i].relation_is_static_definition = TRUE;
1336 area.relations [i].next = NULL;
1337 if (MONO_VARINFO (cfg, i)->def != NULL) {
1338 MonoInst *value = get_variable_value_from_store_instruction (MONO_VARINFO (cfg, i)->def, i);
1339 if (value != NULL) {
1340 gboolean is_array_type;
1341 MonoIntegerValueKind effective_value_kind;
1342 MonoRelationsEvaluationRange range;
1343 MonoSummarizedValueRelation *type_relation;
1345 switch (cfg->varinfo [i]->inst_vtype->type) {
1346 case MONO_TYPE_ARRAY:
1347 case MONO_TYPE_SZARRAY:
1348 is_array_type = TRUE;
1349 goto handle_array_value;
1350 case MONO_TYPE_OBJECT:
1351 is_array_type = FALSE;
1353 summarize_array_value (&area, value, &(area.relations [i].related_value), is_array_type);
1354 if (TRACE_ABC_REMOVAL) {
1355 printf ("Summarized variable %d as array (is_array_type = %s): ", i, (is_array_type?"TRUE":"FALSE"));
1356 print_summarized_value (&(area.relations [i].related_value));
1361 area.variable_value_kind [i] = MONO_INTEGER_VALUE_SIZE_1;
1362 goto handle_integer_value;
1364 area.variable_value_kind [i] = MONO_UNSIGNED_INTEGER_VALUE_SIZE_1;
1365 goto handle_integer_value;
1367 area.variable_value_kind [i] = MONO_INTEGER_VALUE_SIZE_2;
1368 goto handle_integer_value;
1370 area.variable_value_kind [i] = MONO_UNSIGNED_INTEGER_VALUE_SIZE_2;
1371 goto handle_integer_value;
1373 area.variable_value_kind [i] = MONO_INTEGER_VALUE_SIZE_4;
1374 goto handle_integer_value;
1376 area.variable_value_kind [i] = MONO_UNSIGNED_INTEGER_VALUE_SIZE_4;
1377 goto handle_integer_value;
1379 area.variable_value_kind [i] = SIZEOF_VOID_P;
1380 goto handle_integer_value;
1382 area.variable_value_kind [i] = (MONO_UNSIGNED_VALUE_FLAG|SIZEOF_VOID_P);
1383 goto handle_integer_value;
1385 area.variable_value_kind [i] = MONO_INTEGER_VALUE_SIZE_8;
1386 goto handle_integer_value;
1388 area.variable_value_kind [i] = MONO_UNSIGNED_INTEGER_VALUE_SIZE_8;
1389 handle_integer_value:
1390 effective_value_kind = summarize_integer_value (&area, value, &(area.relations [i].related_value), area.variable_value_kind [i]);
1391 MONO_MAKE_RELATIONS_EVALUATION_RANGE_WEAK (range);
1392 apply_value_kind_to_range (&range, area.variable_value_kind [i]);
1393 apply_value_kind_to_range (&range, effective_value_kind);
1395 if (range.upper < INT_MAX) {
1396 type_relation = (MonoSummarizedValueRelation *) mono_mempool_alloc (cfg->mempool, sizeof (MonoSummarizedValueRelation));
1397 type_relation->relation = MONO_LE_RELATION;
1398 type_relation->related_value.type = MONO_CONSTANT_SUMMARIZED_VALUE;
1399 type_relation->related_value.value.constant.value = range.upper;
1400 type_relation->relation_is_static_definition = TRUE;
1401 type_relation->next = area.relations [i].next;
1402 area.relations [i].next = type_relation;
1403 if (TRACE_ABC_REMOVAL) {
1404 printf ("[var%d <= %d]", i, range.upper);
1407 if (range.lower > INT_MIN) {
1408 type_relation = (MonoSummarizedValueRelation *) mono_mempool_alloc (cfg->mempool, sizeof (MonoSummarizedValueRelation));
1409 type_relation->relation = MONO_GE_RELATION;
1410 type_relation->related_value.type = MONO_CONSTANT_SUMMARIZED_VALUE;
1411 type_relation->related_value.value.constant.value = range.lower;
1412 type_relation->relation_is_static_definition = TRUE;
1413 type_relation->next = area.relations [i].next;
1414 area.relations [i].next = type_relation;
1415 if (TRACE_ABC_REMOVAL) {
1416 printf ("[var%d >= %d]", i, range.lower);
1419 if (TRACE_ABC_REMOVAL) {
1420 printf ("Summarized variable %d: ", i);
1421 print_summarized_value (&(area.relations [i].related_value));
1426 MAKE_VALUE_ANY (area.relations [i].related_value);
1427 if (TRACE_ABC_REMOVAL) {
1428 printf ("Variable %d not handled (type %d)\n", i, cfg->varinfo [i]->inst_vtype->type);
1432 MAKE_VALUE_ANY (area.relations [i].related_value);
1433 if (TRACE_ABC_REMOVAL) {
1434 printf ("Definition of variable %d is not a proper store\n", i);
1438 MAKE_VALUE_ANY (area.relations [i].related_value);
1439 if (TRACE_ABC_REMOVAL) {
1440 printf ("Variable %d has no definition, probably it is an argument\n", i);
1444 for (i = 0; i < cfg->num_varinfo; i++) {
1445 if (area.relations [i].related_value.type == MONO_VARIABLE_SUMMARIZED_VALUE) {
1446 int related_index = cfg->num_varinfo + i;
1447 int related_variable = area.relations [i].related_value.value.variable.variable;
1449 area.relations [related_index].relation = MONO_EQ_RELATION;
1450 area.relations [related_index].relation_is_static_definition = TRUE;
1451 area.relations [related_index].related_value.type = MONO_VARIABLE_SUMMARIZED_VALUE;
1452 area.relations [related_index].related_value.value.variable.variable = i;
1453 area.relations [related_index].related_value.value.variable.delta = - area.relations [i].related_value.value.variable.delta;
1455 area.relations [related_index].next = area.relations [related_variable].next;
1456 area.relations [related_variable].next = &(area.relations [related_index]);
1458 if (TRACE_ABC_REMOVAL) {
1459 printf ("Added symmetric summarized value for variable variable %d (to %d): ", i, related_variable);
1460 print_summarized_value (&(area.relations [related_index].related_value));
1466 process_block (cfg->bblocks [0], &area);
1469 #endif /* DISABLE_SSA */
1471 #endif /* DISABLE_JIT */