3 * Array bounds check removal
6 * Massimiliano Mantione (massi@ximian.com)
8 * (C) 2004 Ximian, Inc. http://www.ximian.com
14 #include <mono/metadata/debug-helpers.h>
15 #include <mono/metadata/mempool.h>
16 #include <mono/metadata/opcodes.h>
17 #include <mono/metadata/mempool-internals.h>
18 #include <mono/utils/mono-compiler.h>
24 #include "abcremoval.h"
26 #if TARGET_SIZEOF_VOID_P == 8
27 #define OP_PCONST OP_I8CONST
29 #define OP_PCONST OP_ICONST
33 #define TRACE_ABC_REMOVAL (verbose_level > 2)
34 #define REPORT_ABC_REMOVAL (verbose_level > 1)
37 * A little hack for the verbosity level.
38 * The verbosity level is stored in the cfg, but not all functions that must
39 * print something see the cfg, so we store the verbosity level here at the
40 * beginning of the algorithm.
41 * This is not thread safe (does not handle correctly different verbosity
42 * levels in different threads), and is not exact in case of dynamic changes
43 * of the verbosity level...
44 * Anyway, this is not needed, all that can happen is that something more
45 * (or less) is logged, the result is in any case correct.
47 static int verbose_level
;
50 #define RELATION_BETWEEN_VALUES(value,related_value) (\
51 ((value) > (related_value))? MONO_GT_RELATION :\
52 (((value) < (related_value))? MONO_LT_RELATION : MONO_EQ_RELATION))
54 #define MAKE_VALUE_ANY(v) do{\
55 (v).type = MONO_ANY_SUMMARIZED_VALUE;\
58 #define MAKE_VALUE_RELATION_ANY(r) do{\
59 (r)->relation = MONO_ANY_RELATION;\
60 MAKE_VALUE_ANY((r)->related_value);\
63 #define INITIALIZE_VALUE_RELATION(r) do{\
64 MAKE_VALUE_RELATION_ANY((r));\
68 #define MONO_NEGATED_RELATION(r) ((MonoValueRelation)((~(r))&MONO_ANY_RELATION))
69 #define MONO_SYMMETRIC_RELATION(r) ((MonoValueRelation)(((r)&MONO_EQ_RELATION)|(((r)&MONO_LT_RELATION)<<1)|((r&MONO_GT_RELATION)>>1)))
74 print_relation (int relation
) {
77 if (relation
& MONO_LT_RELATION
) {
81 if (relation
& MONO_EQ_RELATION
) {
88 if (relation
& MONO_GT_RELATION
) {
99 print_summarized_value (MonoSummarizedValue
*value
) {
100 switch (value
->type
) {
101 case MONO_ANY_SUMMARIZED_VALUE
:
104 case MONO_CONSTANT_SUMMARIZED_VALUE
:
105 printf ("CONSTANT %d", value
->value
.constant
.value
);
107 case MONO_VARIABLE_SUMMARIZED_VALUE
:
108 printf ("VARIABLE %d, delta %d", value
->value
.variable
.variable
, value
->value
.variable
.delta
);
110 case MONO_PHI_SUMMARIZED_VALUE
: {
113 for (phi
= 0; phi
< value
->value
.phi
.number_of_alternatives
; phi
++) {
114 if (phi
) printf (",");
115 printf ("%d", value
->value
.phi
.phi_alternatives
[phi
]);
121 g_assert_not_reached ();
126 print_summarized_value_relation (MonoSummarizedValueRelation
*relation
) {
127 printf ("Relation ");
128 print_relation (relation
->relation
);
129 printf (" with value ");
130 print_summarized_value (&(relation
->related_value
));
135 print_summarized_value_relation_chain (MonoSummarizedValueRelation
*relation
) {
136 printf ("Relations:\n");
138 print_summarized_value_relation (relation
);
140 relation
= relation
->next
;
146 print_evaluation_context_status (MonoRelationsEvaluationStatus status
) {
147 if (status
== MONO_RELATIONS_EVALUATION_NOT_STARTED
) {
148 printf ("EVALUATION_NOT_STARTED");
150 gboolean print_or
= FALSE
;
153 if (status
& MONO_RELATIONS_EVALUATION_IN_PROGRESS
) {
154 if (print_or
) printf ("|");
155 printf ("EVALUATION_IN_PROGRESS");
158 if (status
& MONO_RELATIONS_EVALUATION_COMPLETED
) {
159 if (print_or
) printf ("|");
160 printf ("EVALUATION_COMPLETED");
163 if (status
& MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_ASCENDING
) {
164 if (print_or
) printf ("|");
165 printf ("RECURSIVELY_ASCENDING");
168 if (status
& MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_DESCENDING
) {
169 if (print_or
) printf ("|");
170 printf ("RECURSIVELY_DESCENDING");
173 if (status
& MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_INDEFINITE
) {
174 if (print_or
) printf ("|");
175 printf ("RECURSIVELY_INDEFINITE");
184 print_evaluation_context_ranges (MonoRelationsEvaluationRanges
*ranges
) {
185 printf ("(ranges: zero [%d,%d], variable [%d,%d])", ranges
->zero
.lower
, ranges
->zero
.upper
, ranges
->variable
.lower
, ranges
->variable
.upper
);
189 print_evaluation_context (MonoRelationsEvaluationContext
*context
, MonoRelationsEvaluationStatus status
) {
190 print_evaluation_context_status (status
);
191 if (status
& (MONO_RELATIONS_EVALUATION_IN_PROGRESS
|MONO_RELATIONS_EVALUATION_COMPLETED
)) {
192 print_evaluation_context_ranges (&(context
->ranges
));
199 print_evaluation_area (MonoVariableRelationsEvaluationArea
*area
) {
201 printf ("Dump of evaluation area (%d variables):\n", area
->cfg
->num_varinfo
);
202 for (i
= 0; i
< area
->cfg
->num_varinfo
; i
++) {
203 printf ("Variable %d: ", i
);
204 print_evaluation_context (&(area
->contexts
[i
]));
205 print_summarized_value_relation_chain (&(area
->relations
[i
]));
210 print_evaluation_area_contexts (MonoVariableRelationsEvaluationArea
*area
) {
212 printf ("Dump of evaluation area contexts (%d variables):\n", area
->cfg
->num_varinfo
);
213 for (i
= 0; i
< area
->cfg
->num_varinfo
; i
++) {
214 printf ("Variable %d: ", i
);
215 print_evaluation_context (&(area
->contexts
[i
]));
221 * Check if the delta of an integer variable value is safe with respect
222 * to the variable size in bytes and its kind (signed or unsigned).
223 * If the delta is not safe, make the value an "any".
225 static G_GNUC_UNUSED
void
226 check_delta_safety (MonoVariableRelationsEvaluationArea
*area
, MonoSummarizedValue
*value
) {
227 if (value
->type
== MONO_VARIABLE_SUMMARIZED_VALUE
) {
228 int variable
= value
->value
.variable
.variable
;
229 int delta
= value
->value
.variable
.delta
;
230 if ((area
->variable_value_kind
[variable
]) & MONO_UNSIGNED_VALUE_FLAG
) {
232 MAKE_VALUE_ANY (*value
);
235 if (((area
->variable_value_kind
[variable
]) & MONO_INTEGER_VALUE_SIZE_BITMASK
) < 4) {
236 MAKE_VALUE_ANY (*value
);
237 } else if (delta
> 16) {
238 MAKE_VALUE_ANY (*value
);
245 * get_relation_from_ins:
247 * Obtain relations from a MonoInst.
249 * result_value_kind: the "expected" kind of result;
250 * result: the "summarized" value
251 * returns the "actual" kind of result, if guessable (otherwise MONO_UNKNOWN_INTEGER_VALUE)
253 static MonoIntegerValueKind
254 get_relation_from_ins (MonoVariableRelationsEvaluationArea
*area
, MonoInst
*ins
, MonoSummarizedValueRelation
*result
, MonoIntegerValueKind result_value_kind
)
256 MonoIntegerValueKind value_kind
;
257 MonoSummarizedValue
*value
= &result
->related_value
;
259 if (ins
->type
== STACK_I8
) {
260 value_kind
= MONO_INTEGER_VALUE_SIZE_8
;
261 } else if (ins
->type
== STACK_I4
) {
262 value_kind
= MONO_INTEGER_VALUE_SIZE_4
;
264 value_kind
= MONO_UNKNOWN_INTEGER_VALUE
;
267 result
->relation
= MONO_EQ_RELATION
;
268 MAKE_VALUE_ANY (*value
);
270 switch (ins
->opcode
) {
272 value
->type
= MONO_CONSTANT_SUMMARIZED_VALUE
;
273 value
->value
.constant
.value
= ins
->inst_c0
;
276 value
->type
= MONO_VARIABLE_SUMMARIZED_VALUE
;
277 value
->value
.variable
.variable
= ins
->sreg1
;
278 value
->value
.variable
.delta
= 0;
281 value
->type
= MONO_VARIABLE_SUMMARIZED_VALUE
;
282 value
->value
.variable
.variable
= ins
->sreg1
;
283 value
->value
.variable
.delta
= 0;
284 value_kind
= MONO_INTEGER_VALUE_SIZE_8
;
287 value
->type
= MONO_PHI_SUMMARIZED_VALUE
;
288 value
->value
.phi
.number_of_alternatives
= *(ins
->inst_phi_args
);
289 value
->value
.phi
.phi_alternatives
= ins
->inst_phi_args
+ 1;
292 value
->type
= MONO_VARIABLE_SUMMARIZED_VALUE
;
293 value
->value
.variable
.variable
= ins
->sreg1
;
294 value
->value
.variable
.delta
= ins
->inst_imm
;
296 //check_delta_safety (area, result);
299 value
->type
= MONO_VARIABLE_SUMMARIZED_VALUE
;
300 value
->value
.variable
.variable
= ins
->sreg1
;
301 value
->value
.variable
.delta
= -ins
->inst_imm
;
303 //check_delta_safety (area, result);
306 /* The result of an unsigned remainder is 0 < x < the divisor */
307 result
->relation
= MONO_LT_RELATION
;
308 value
->type
= MONO_VARIABLE_SUMMARIZED_VALUE
;
309 value
->value
.variable
.variable
= ins
->sreg2
;
310 value
->value
.variable
.delta
= 0;
311 value_kind
= MONO_UNSIGNED_INTEGER_VALUE_SIZE_4
;
315 * We represent arrays by their length, so r1<-ldlen r2 is stored
316 * as r1 == r2 in the evaluation graph.
318 value
->type
= MONO_VARIABLE_SUMMARIZED_VALUE
;
319 value
->value
.variable
.variable
= ins
->sreg1
;
320 value
->value
.variable
.delta
= 0;
321 value_kind
= MONO_UNSIGNED_INTEGER_VALUE_SIZE_4
;
324 value
->type
= MONO_VARIABLE_SUMMARIZED_VALUE
;
325 value
->value
.variable
.variable
= ins
->sreg1
;
326 value
->value
.variable
.delta
= 0;
327 area
->defs
[ins
->dreg
] = ins
;
330 /* The result is non-null */
331 result
->relation
= MONO_GT_RELATION
;
332 value
->type
= MONO_CONSTANT_SUMMARIZED_VALUE
;
333 value
->value
.constant
.value
= 0;
336 /* FIXME: Add more opcodes */
338 /* These opcodes are not currently handled while running SciMark, first
339 * column is the number of times the warning was shown:
371 * 12 outarg_vtretaddr
399 static MonoValueRelation
400 get_relation_from_branch_instruction (MonoInst
*ins
)
402 if (MONO_IS_COND_BRANCH_OP (ins
)) {
403 CompRelation rel
= mono_opcode_to_cond (ins
->opcode
);
407 return MONO_EQ_RELATION
;
409 return MONO_NE_RELATION
;
412 return MONO_LE_RELATION
;
415 return MONO_GE_RELATION
;
418 return MONO_LT_RELATION
;
421 return MONO_GT_RELATION
;
423 g_assert_not_reached ();
424 return MONO_ANY_RELATION
;
427 return MONO_ANY_RELATION
;
432 * Given a BB, find its entry condition and put its relations in a
433 * "MonoAdditionalVariableRelationsForBB" structure.
435 * relations: the resulting relations (entry condition of the given BB)
438 get_relations_from_previous_bb (MonoVariableRelationsEvaluationArea
*area
, MonoBasicBlock
*bb
, MonoAdditionalVariableRelationsForBB
*relations
)
440 MonoBasicBlock
*in_bb
;
441 MonoInst
*ins
, *compare
, *branch
;
442 MonoValueRelation branch_relation
;
443 MonoValueRelation symmetric_relation
;
446 INITIALIZE_VALUE_RELATION (&(relations
->relation1
.relation
));
447 relations
->relation1
.relation
.relation_is_static_definition
= FALSE
;
448 relations
->relation1
.relation
.next
= NULL
;
449 relations
->relation1
.insertion_point
= NULL
;
450 relations
->relation1
.variable
= -1;
451 INITIALIZE_VALUE_RELATION (&(relations
->relation2
.relation
));
452 relations
->relation2
.relation
.relation_is_static_definition
= FALSE
;
453 relations
->relation2
.relation
.next
= NULL
;
454 relations
->relation2
.insertion_point
= NULL
;
455 relations
->relation2
.variable
= -1;
457 if (bb
->in_count
== 1) { /* Should write the code to "sum" conditions... */
458 in_bb
= bb
->in_bb
[0];
460 if ((in_bb
->last_ins
== NULL
) || (in_bb
->code
== in_bb
->last_ins
))
463 for (ins
= in_bb
->code
; ins
->next
!= in_bb
->last_ins
; ins
= ins
->next
)
468 branch_relation
= get_relation_from_branch_instruction (branch
);
470 if (branch_relation
!= MONO_ANY_RELATION
) {
471 if (branch
->inst_true_bb
== bb
) {
473 } else if (branch
->inst_false_bb
== bb
) {
477 g_assert_not_reached ();
480 branch_relation
= MONO_NEGATED_RELATION (branch_relation
);
481 symmetric_relation
= MONO_SYMMETRIC_RELATION (branch_relation
);
483 /* FIXME: Other compare opcodes */
484 if (compare
->opcode
== OP_ICOMPARE
) {
485 relations
->relation1
.variable
= compare
->sreg1
;
486 relations
->relation1
.relation
.relation
= branch_relation
;
487 relations
->relation1
.relation
.related_value
.type
= MONO_VARIABLE_SUMMARIZED_VALUE
;
488 relations
->relation1
.relation
.related_value
.value
.variable
.variable
= compare
->sreg2
;
489 relations
->relation1
.relation
.related_value
.value
.variable
.delta
= 0;
491 relations
->relation2
.variable
= compare
->sreg2
;
492 relations
->relation2
.relation
.relation
= symmetric_relation
;
493 relations
->relation2
.relation
.related_value
.type
= MONO_VARIABLE_SUMMARIZED_VALUE
;
494 relations
->relation2
.relation
.related_value
.value
.variable
.variable
= compare
->sreg1
;
495 relations
->relation2
.relation
.related_value
.value
.variable
.delta
= 0;
496 } else if (compare
->opcode
== OP_ICOMPARE_IMM
) {
497 relations
->relation1
.variable
= compare
->sreg1
;
498 relations
->relation1
.relation
.relation
= branch_relation
;
499 relations
->relation1
.relation
.related_value
.type
= MONO_CONSTANT_SUMMARIZED_VALUE
;
500 relations
->relation1
.relation
.related_value
.value
.constant
.value
= compare
->inst_imm
;
507 * Add the given relations to the evaluation area.
508 * area: the evaluation area
509 * change: the relations that must be added
512 apply_change_to_evaluation_area (MonoVariableRelationsEvaluationArea
*area
, MonoAdditionalVariableRelation
*change
)
514 MonoSummarizedValueRelation
*base_relation
;
516 if (change
->relation
.relation
!= MONO_ANY_RELATION
) {
517 base_relation
= &(area
->relations
[change
->variable
]);
518 while ((base_relation
->next
!= NULL
) && (base_relation
->next
->relation_is_static_definition
)) {
519 base_relation
= base_relation
->next
;
521 change
->insertion_point
= base_relation
;
522 change
->relation
.next
= base_relation
->next
;
523 base_relation
->next
= &(change
->relation
);
528 * Remove the given relation from the evaluation area.
529 * change: the relation that must be removed
532 remove_change_from_evaluation_area (MonoAdditionalVariableRelation
*change
)
534 if (change
->insertion_point
!= NULL
) {
535 change
->insertion_point
->next
= change
->relation
.next
;
536 change
->relation
.next
= NULL
;
542 clean_contexts (MonoVariableRelationsEvaluationArea
*area
, int number
)
544 memset(area
->statuses
, MONO_RELATIONS_EVALUATION_NOT_STARTED
, number
* sizeof(MonoRelationsEvaluationStatus
));
549 * Perform the intersection of a range and a constant value (taking into
550 * account the relation that the value has with the range).
551 * range: the range that will be intersected with the value
552 * value: the value that will be intersected with the range
553 * relation: the relation between the range and the value
556 intersect_value( MonoRelationsEvaluationRange
*range
, int value
, MonoValueRelation relation
)
559 case MONO_NO_RELATION
:
560 MONO_MAKE_RELATIONS_EVALUATION_RANGE_IMPOSSIBLE (*range
);
562 case MONO_ANY_RELATION
:
564 case MONO_EQ_RELATION
:
565 MONO_UPPER_EVALUATION_RANGE_INTERSECTION (range
->upper
, value
);
566 MONO_LOWER_EVALUATION_RANGE_INTERSECTION (range
->lower
, value
);
568 case MONO_NE_RELATION
: {
569 /* IMPROVEMENT Figure this out! (ignoring it is safe anyway) */
572 case MONO_LT_RELATION
:
573 MONO_UPPER_EVALUATION_RANGE_INTERSECTION (range
->upper
, MONO_UPPER_EVALUATION_RANGE_NOT_EQUAL (value
));
575 case MONO_LE_RELATION
:
576 MONO_UPPER_EVALUATION_RANGE_INTERSECTION (range
->upper
, value
);
578 case MONO_GT_RELATION
:
579 MONO_LOWER_EVALUATION_RANGE_INTERSECTION (range
->lower
, MONO_LOWER_EVALUATION_RANGE_NOT_EQUAL (value
));
581 case MONO_GE_RELATION
:
582 MONO_LOWER_EVALUATION_RANGE_INTERSECTION (range
->lower
, value
);
585 g_assert_not_reached();
591 * Perform the intersection of two pairs of ranges (taking into account the
592 * relation between the ranges and a given delta).
593 * ranges: the ranges that will be intersected
594 * other_ranges the other ranges that will be intersected
595 * delta: the delta between the pairs of ranges
596 * relation: the relation between the pairs of ranges
599 intersect_ranges( MonoRelationsEvaluationRanges
*ranges
, MonoRelationsEvaluationRanges
*other_ranges
, int delta
, MonoValueRelation relation
)
603 case MONO_NO_RELATION
:
604 MONO_MAKE_RELATIONS_EVALUATION_RANGES_IMPOSSIBLE (*ranges
);
606 case MONO_ANY_RELATION
:
608 case MONO_EQ_RELATION
:
609 MONO_RELATIONS_EVALUATION_RANGES_INTERSECTION (*ranges
, *other_ranges
);
611 case MONO_NE_RELATION
: {
612 /* FIXME Figure this out! (ignoring it is safe anyway) */
615 case MONO_LT_RELATION
:
616 MONO_UPPER_EVALUATION_RANGE_INTERSECTION (ranges
->zero
.upper
, MONO_UPPER_EVALUATION_RANGE_NOT_EQUAL (other_ranges
->zero
.upper
));
617 MONO_UPPER_EVALUATION_RANGE_INTERSECTION (ranges
->variable
.upper
, MONO_UPPER_EVALUATION_RANGE_NOT_EQUAL (other_ranges
->variable
.upper
));
619 case MONO_LE_RELATION
:
620 MONO_UPPER_EVALUATION_RANGE_INTERSECTION (ranges
->zero
.upper
, other_ranges
->zero
.upper
);
621 MONO_UPPER_EVALUATION_RANGE_INTERSECTION (ranges
->variable
.upper
, other_ranges
->variable
.upper
);
623 case MONO_GT_RELATION
:
624 MONO_LOWER_EVALUATION_RANGE_INTERSECTION (ranges
->zero
.lower
, MONO_LOWER_EVALUATION_RANGE_NOT_EQUAL (other_ranges
->zero
.lower
));
625 MONO_LOWER_EVALUATION_RANGE_INTERSECTION (ranges
->variable
.lower
, MONO_LOWER_EVALUATION_RANGE_NOT_EQUAL (other_ranges
->variable
.lower
));
627 case MONO_GE_RELATION
:
628 MONO_LOWER_EVALUATION_RANGE_INTERSECTION (ranges
->zero
.lower
, other_ranges
->zero
.lower
);
629 MONO_LOWER_EVALUATION_RANGE_INTERSECTION (ranges
->variable
.lower
, other_ranges
->variable
.lower
);
632 g_assert_not_reached();
635 MonoRelationsEvaluationRanges translated_ranges
= *other_ranges
;
636 MONO_ADD_DELTA_SAFELY_TO_RANGES (translated_ranges
, delta
);
637 intersect_ranges( ranges
, &translated_ranges
, FALSE
, relation
);
642 * Recursive method that traverses the relation graph to evaluate the
643 * relation between two variables.
644 * At the end of the execution, the resulting ranges are in the context of
645 * the "starting" variable.
646 * area: the current evaluation area (it contains the relation graph and
647 * memory for all the evaluation contexts is already allocated)
648 * variable: starting variable (the value ranges in its context are the result
649 * of the execution of this procedure)
650 * target_variable: the variable with respect to which the starting variable
651 * is evaluated (tipically the starting variable is the index
652 * and the target one is the array (which means its length))
653 * father_context: the previous evaluation context in recursive invocations
654 * (or NULL for the first invocation)
657 evaluate_relation_with_target_variable (MonoVariableRelationsEvaluationArea
*area
, const int variable
, const int target_variable
, MonoRelationsEvaluationContext
*father_context
)
659 MonoRelationsEvaluationContext
* const context
= &(area
->contexts
[variable
]);
660 MonoRelationsEvaluationStatus
* const status
= &(area
->statuses
[variable
]);
662 // First of all, we check the evaluation status
663 // (what must be done is *very* different in each case)
665 case MONO_RELATIONS_EVALUATION_NOT_STARTED
: {
666 MonoSummarizedValueRelation
*relation
= &(area
->relations
[variable
]);
668 if (TRACE_ABC_REMOVAL
) {
669 printf ("Evaluating variable %d (target variable %d)\n", variable
, target_variable
);
670 print_summarized_value_relation (relation
);
674 // We properly inizialize the context
675 *status
= MONO_RELATIONS_EVALUATION_IN_PROGRESS
;
676 context
->father
= father_context
;
677 MONO_MAKE_RELATIONS_EVALUATION_RANGES_WEAK (context
->ranges
);
679 // If we have found the target variable, we can set the range
680 // related to it in the context to "equal" (which is [0,0])
681 if (variable
== target_variable
) {
682 if (TRACE_ABC_REMOVAL
) {
683 printf ("Target variable reached (%d), continuing to evaluate relations with constants\n", variable
);
685 context
->ranges
.variable
.lower
= 0;
686 context
->ranges
.variable
.upper
= 0;
689 // Examine all relations for this variable (scan the list)
690 // The contribute of each relation will be intersected (logical and)
691 while (relation
!= NULL
) {
692 context
->current_relation
= relation
;
694 if (TRACE_ABC_REMOVAL
) {
695 printf ("Processing (%d): ", variable
);
696 print_summarized_value_relation (relation
);
700 // We decie what to do according the the type of the related value
701 switch (relation
->related_value
.type
) {
702 case MONO_ANY_SUMMARIZED_VALUE
:
703 // No added information, skip it
705 case MONO_CONSTANT_SUMMARIZED_VALUE
:
706 // Intersect range with constant (taking into account the relation)
707 intersect_value (&(context
->ranges
.zero
), relation
->related_value
.value
.constant
.value
, relation
->relation
);
709 case MONO_VARIABLE_SUMMARIZED_VALUE
:
710 // Generally, evaluate related variable and intersect ranges.
711 // However, some check is necessary...
713 // If the relation is "ANY", nothing to do (no added information)
714 if (relation
->relation
!= MONO_ANY_RELATION
) {
715 int related_variable
= relation
->related_value
.value
.variable
.variable
;
716 MonoRelationsEvaluationContext
*related_context
= &(area
->contexts
[related_variable
]);
717 MonoRelationsEvaluationStatus related_status
= area
->statuses
[related_variable
];
719 // The second condition in the "or" avoids messing with "back edges" in the graph traversal
720 // (they are simply ignored instead of triggering the handling of recursion)
721 if ( (related_status
== MONO_RELATIONS_EVALUATION_NOT_STARTED
) || !
722 ((related_context
->current_relation
->related_value
.type
== MONO_VARIABLE_SUMMARIZED_VALUE
) &&
723 (related_context
->current_relation
->related_value
.value
.variable
.variable
== variable
))) {
724 // Evaluate the related variable
725 evaluate_relation_with_target_variable (area
, related_variable
, target_variable
, context
);
727 // Check if we are part of a recursive loop
728 if (*status
& MONO_RELATIONS_EVALUATION_IS_RECURSIVE
) {
729 if (TRACE_ABC_REMOVAL
) {
730 printf ("Recursivity detected for variable %d (target variable %d), status ", variable
, target_variable
);
731 print_evaluation_context_status (*status
);
734 // If we are, check if the evaluation of the related variable is complete
735 if (related_status
== MONO_RELATIONS_EVALUATION_COMPLETED
) {
736 // If it is complete, we are part of a recursive definition.
737 // Since it is a *definition* (and definitions are evaluated *before*
738 // conditions because they are first in the list), intersection is not
739 // strictly necessary, we simply copy the ranges and apply the delta
740 context
->ranges
= related_context
->ranges
;
741 /* Delta has already been checked for over/under-flow when evaluating values */
742 MONO_ADD_DELTA_SAFELY_TO_RANGES (context
->ranges
, relation
->related_value
.value
.variable
.delta
);
743 *status
= MONO_RELATIONS_EVALUATION_COMPLETED
;
744 if (TRACE_ABC_REMOVAL
) {
745 printf (", ranges already computed, result: \n");
746 print_evaluation_context_ranges (&(context
->ranges
));
747 printf (" (delta is %d)\n", relation
->related_value
.value
.variable
.delta
);
750 // If it is not complete, do nothing (we do not have enough information)
751 if (TRACE_ABC_REMOVAL
) {
752 printf (", ranges not computed\n");
756 // If we are not (the common case) intersect the result
757 intersect_ranges( &(context
->ranges
), &(related_context
->ranges
), relation
->related_value
.value
.variable
.delta
, relation
->relation
);
760 if (TRACE_ABC_REMOVAL
) {
761 printf ("Relation is a back-edge in this traversal, skipping\n");
766 case MONO_PHI_SUMMARIZED_VALUE
: {
767 // We must compute all PHI alternatives, combining the results (with a union, which is a logical "or"),
768 // and intersect this result with the ranges in the context; we must also take into account recursions
769 // (with loops that can be ascending, descending, or indefinite)
770 MonoRelationsEvaluationRanges phi_ranges
;
772 gboolean is_ascending
= FALSE
;
773 gboolean is_descending
= FALSE
;
775 MONO_MAKE_RELATIONS_EVALUATION_RANGES_IMPOSSIBLE (phi_ranges
);
776 for (phi
= 0; phi
< relation
->related_value
.value
.phi
.number_of_alternatives
; phi
++) {
777 int phi_alternative
= relation
->related_value
.value
.phi
.phi_alternatives
[phi
];
778 evaluate_relation_with_target_variable (area
, phi_alternative
, target_variable
, context
);
780 // This means we are part of a recursive loop
781 if (*status
& MONO_RELATIONS_EVALUATION_IS_RECURSIVE
) {
782 if (TRACE_ABC_REMOVAL
) {
783 printf ("Recursivity detected for variable %d (target variable %d), status ", variable
, target_variable
);
784 print_evaluation_context_status (*status
);
787 if (*status
& MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_ASCENDING
) {
790 if (*status
& MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_DESCENDING
) {
791 is_descending
= TRUE
;
793 if (*status
& MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_INDEFINITE
) {
795 is_descending
= TRUE
;
798 // Clear "recursivity" bits in the status (recursion has been handled)
799 *status
= MONO_RELATIONS_EVALUATION_IN_PROGRESS
;
801 MONO_RELATIONS_EVALUATION_RANGES_UNION (phi_ranges
, area
->contexts
[phi_alternative
].ranges
);
805 // Apply the effects of all recursive loops
807 phi_ranges
.zero
.upper
= INT_MAX
;
808 phi_ranges
.variable
.upper
= INT_MAX
;
811 phi_ranges
.zero
.lower
= INT_MIN
;
812 phi_ranges
.variable
.lower
= INT_MIN
;
815 // Intersect final result
816 MONO_RELATIONS_EVALUATION_RANGES_INTERSECTION (context
->ranges
, phi_ranges
);
820 g_assert_not_reached();
823 // Pass to next relation
824 relation
= relation
->next
;
827 // Check if any recursivity bits are still in the status, and in any case clear them
828 if (*status
& MONO_RELATIONS_EVALUATION_IS_RECURSIVE
) {
829 if (TRACE_ABC_REMOVAL
) {
830 printf ("Recursivity for variable %d (target variable %d) discards computation, status ", variable
, target_variable
);
831 print_evaluation_context_status (*status
);
834 // If yes, we did not have enough information (most likely we were evaluated inside a PHI, but we also
835 // depended on the same PHI, which was still in evaluation...), so clear the status to "NOT_STARTED"
836 // (if we will be evaluated again, the PHI will be already done, so our evaluation will succeed)
837 *status
= MONO_RELATIONS_EVALUATION_NOT_STARTED
;
839 if (TRACE_ABC_REMOVAL
) {
840 printf ("Ranges for variable %d (target variable %d) computed: ", variable
, target_variable
);
841 print_evaluation_context_ranges (&(context
->ranges
));
844 // If not (the common case) the evaluation is complete, and the result is in the context
845 *status
= MONO_RELATIONS_EVALUATION_COMPLETED
;
849 case MONO_RELATIONS_EVALUATION_IN_PROGRESS
: {
850 // This means we are in a recursive loop
851 MonoRelationsEvaluationContext
*current_context
= father_context
;
852 MonoRelationsEvaluationContext
*last_context
= context
->father
;
853 gboolean evaluation_can_be_recursive
= TRUE
;
854 gboolean evaluation_is_definition
= TRUE
;
857 if (TRACE_ABC_REMOVAL
) {
858 printf ("Evaluation of variable %d (target variable %d) already in progress\n", variable
, target_variable
);
859 print_evaluation_context (context
, *status
);
860 print_summarized_value_relation (context
->current_relation
);
864 // We must check if the loop can be a recursive definition (we scan the whole loop)
865 while (current_context
!= last_context
) {
866 if (current_context
== NULL
) {
867 printf ("Broken recursive ring in ABC removal\n");
868 g_assert_not_reached ();
871 if (current_context
->current_relation
->relation_is_static_definition
) {
872 if (current_context
->current_relation
->related_value
.type
== MONO_VARIABLE_SUMMARIZED_VALUE
) {
873 /* No need to check path_value for over/under-flow, since delta should be safe */
874 path_value
+= current_context
->current_relation
->related_value
.value
.variable
.delta
;
875 } else if (current_context
->current_relation
->related_value
.type
!= MONO_PHI_SUMMARIZED_VALUE
) {
876 evaluation_can_be_recursive
= FALSE
;
879 evaluation_is_definition
= FALSE
;
880 evaluation_can_be_recursive
= FALSE
;
883 current_context
= current_context
->father
;
886 // If this is a recursive definition, we properly flag the status in all the involved contexts
887 if (evaluation_is_definition
) {
888 MonoRelationsEvaluationStatus recursive_status
;
889 if (evaluation_can_be_recursive
) {
890 if (path_value
> 0) {
891 recursive_status
= MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_ASCENDING
;
892 } else if (path_value
< 0) {
893 recursive_status
= MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_DESCENDING
;
895 recursive_status
= MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_INDEFINITE
;
898 recursive_status
= MONO_RELATIONS_EVALUATION_IS_RECURSIVELY_INDEFINITE
;
901 if (TRACE_ABC_REMOVAL
) {
902 printf ("Recursivity accepted (");
903 print_evaluation_context_status (recursive_status
);
907 current_context
= father_context
;
908 while (current_context
!= last_context
) {
909 int index
= current_context
- area
->contexts
;
910 MonoRelationsEvaluationStatus
*current_status
= &(area
->statuses
[index
]);
911 *current_status
= (MonoRelationsEvaluationStatus
)(*current_status
| recursive_status
);
912 current_context
= current_context
->father
;
915 if (TRACE_ABC_REMOVAL
) {
916 printf ("Recursivity rejected (some relation in the cycle is not a defintion)\n");
921 case MONO_RELATIONS_EVALUATION_COMPLETED
: {
925 if (TRACE_ABC_REMOVAL
) {
926 printf ("Variable %d (target variable %d) already in a recursive ring, skipping\n", variable
, target_variable
);
927 print_evaluation_context (context
, *status
);
928 print_summarized_value_relation (context
->current_relation
);
937 * Apply the given value kind to the given range
940 apply_value_kind_to_range (MonoRelationsEvaluationRange
*range
, MonoIntegerValueKind value_kind
)
942 if (value_kind
!= MONO_UNKNOWN_INTEGER_VALUE
) {
943 if (value_kind
& MONO_UNSIGNED_VALUE_FLAG
) {
944 if (range
->lower
< 0) {
947 if ((value_kind
& MONO_INTEGER_VALUE_SIZE_BITMASK
) == 1) {
948 if (range
->upper
> 0xff) {
951 } else if ((value_kind
& MONO_INTEGER_VALUE_SIZE_BITMASK
) == 2) {
952 if (range
->upper
> 0xffff) {
953 range
->upper
= 0xffff;
957 if ((value_kind
& MONO_INTEGER_VALUE_SIZE_BITMASK
) == 1) {
958 if (range
->lower
< -0x80) {
959 range
->lower
= -0x80;
961 if (range
->upper
> 0x7f) {
964 } else if ((value_kind
& MONO_INTEGER_VALUE_SIZE_BITMASK
) == 2) {
965 if (range
->lower
< -0x8000) {
966 range
->lower
= -0x8000;
968 if (range
->upper
> 0x7fff) {
969 range
->upper
= 0x7fff;
977 * Attempt the removal of bounds checks from a MonoInst.
979 * area: the current evaluation area (it contains the relation graph and
980 * memory for all the evaluation contexts is already allocated)
983 remove_abc_from_inst (MonoInst
*ins
, MonoVariableRelationsEvaluationArea
*area
)
985 /* FIXME: Add support for 'constant' arrays and constant indexes */
987 int array_variable
= ins
->sreg1
;
988 int index_variable
= ins
->sreg2
;
989 MonoRelationsEvaluationContext
*array_context
= &(area
->contexts
[array_variable
]);
990 MonoRelationsEvaluationContext
*index_context
= &(area
->contexts
[index_variable
]);
992 clean_contexts (area
, area
->cfg
->next_vreg
);
994 evaluate_relation_with_target_variable (area
, index_variable
, array_variable
, NULL
);
995 evaluate_relation_with_target_variable (area
, array_variable
, array_variable
, NULL
);
997 if ((index_context
->ranges
.zero
.lower
>=0) && ((index_context
->ranges
.variable
.upper
< 0)||(index_context
->ranges
.zero
.upper
< array_context
->ranges
.zero
.lower
))) {
998 if (REPORT_ABC_REMOVAL
) {
999 printf ("ARRAY-ACCESS: removed bounds check on array %d with index %d\n",
1000 array_variable
, index_variable
);
1004 if (TRACE_ABC_REMOVAL
) {
1005 if (index_context
->ranges
.zero
.lower
>= 0) {
1006 printf ("ARRAY-ACCESS: Removed lower bound check on array %d with index %d\n", array_variable
, index_variable
);
1008 if (index_context
->ranges
.variable
.upper
< 0) {
1009 printf ("ARRAY-ACCESS: Removed upper bound check (through variable) on array %d with index %d\n", array_variable
, index_variable
);
1011 if (index_context
->ranges
.zero
.upper
< array_context
->ranges
.zero
.lower
) {
1012 printf ("ARRAY-ACCESS: Removed upper bound check (through constant) on array %d with index %d\n", array_variable
, index_variable
);
1019 eval_non_null (MonoVariableRelationsEvaluationArea
*area
, int reg
)
1021 MonoRelationsEvaluationContext
*context
= &(area
->contexts
[reg
]);
1023 clean_contexts (area
, area
->cfg
->next_vreg
);
1024 evaluate_relation_with_target_variable (area
, reg
, reg
, NULL
);
1026 return context
->ranges
.zero
.lower
> 0;
1030 add_non_null (MonoVariableRelationsEvaluationArea
*area
, MonoCompile
*cfg
, int reg
,
1031 GSList
**check_relations
)
1033 MonoAdditionalVariableRelation
*rel
;
1035 rel
= (MonoAdditionalVariableRelation
*)mono_mempool_alloc0 (cfg
->mempool
, sizeof (MonoAdditionalVariableRelation
));
1036 rel
->variable
= reg
;
1037 rel
->relation
.relation
= MONO_GT_RELATION
;
1038 rel
->relation
.related_value
.type
= MONO_CONSTANT_SUMMARIZED_VALUE
;
1039 rel
->relation
.related_value
.value
.constant
.value
= 0;
1041 apply_change_to_evaluation_area (area
, rel
);
1043 *check_relations
= g_slist_append_mempool (cfg
->mempool
, *check_relations
, rel
);
1047 * Process a BB removing bounds checks from array accesses.
1048 * It does the following (in sequence):
1049 * - Get the BB entry condition
1050 * - Add its relations to the relation graph in the evaluation area
1051 * - Process all the MonoInst trees in the BB
1052 * - Recursively process all the children BBs in the dominator tree
1053 * - Remove the relations previously added to the relation graph
1055 * bb: the BB that must be processed
1056 * area: the current evaluation area (it contains the relation graph and
1057 * memory for all the evaluation contexts is already allocated)
1060 process_block (MonoCompile
*cfg
, MonoBasicBlock
*bb
, MonoVariableRelationsEvaluationArea
*area
) {
1062 MonoAdditionalVariableRelationsForBB additional_relations
;
1063 GSList
*dominated_bb
, *l
;
1064 GSList
*check_relations
= NULL
;
1066 if (TRACE_ABC_REMOVAL
) {
1067 printf ("\nABCREM BLOCK/2 %d [dfn %d]...\n", bb
->block_num
, bb
->dfn
);
1070 if (bb
->region
!= -1)
1073 get_relations_from_previous_bb (area
, bb
, &additional_relations
);
1074 if (TRACE_ABC_REMOVAL
) {
1075 if (additional_relations
.relation1
.relation
.relation
!= MONO_ANY_RELATION
) {
1076 printf ("Adding relation 1 on variable %d: ", additional_relations
.relation1
.variable
);
1077 print_summarized_value_relation (&(additional_relations
.relation1
.relation
));
1080 if (additional_relations
.relation2
.relation
.relation
!= MONO_ANY_RELATION
) {
1081 printf ("Adding relation 2 on variable %d: ", additional_relations
.relation2
.variable
);
1082 print_summarized_value_relation (&(additional_relations
.relation2
.relation
));
1086 apply_change_to_evaluation_area (area
, &(additional_relations
.relation1
));
1087 apply_change_to_evaluation_area (area
, &(additional_relations
.relation2
));
1089 for (ins
= bb
->code
; ins
; ins
= ins
->next
) {
1090 MonoAdditionalVariableRelation
*rel
;
1091 int array_var
, index_var
;
1093 if (TRACE_ABC_REMOVAL
)
1094 mono_print_ins (ins
);
1096 if (ins
->opcode
== OP_BOUNDS_CHECK
) { /* Handle OP_LDELEMA2D, too */
1097 array_var
= ins
->sreg1
;
1098 index_var
= ins
->sreg2
;
1100 remove_abc_from_inst (ins
, area
);
1102 /* We can derive additional relations from the bounds check */
1103 if (ins
->opcode
!= OP_NOP
) {
1104 rel
= (MonoAdditionalVariableRelation
*)mono_mempool_alloc0 (cfg
->mempool
, sizeof (MonoAdditionalVariableRelation
));
1105 rel
->variable
= index_var
;
1106 rel
->relation
.relation
= MONO_LT_RELATION
;
1107 rel
->relation
.related_value
.type
= MONO_VARIABLE_SUMMARIZED_VALUE
;
1108 rel
->relation
.related_value
.value
.variable
.variable
= array_var
;
1109 rel
->relation
.related_value
.value
.variable
.delta
= 0;
1111 apply_change_to_evaluation_area (area
, rel
);
1113 check_relations
= g_slist_append_mempool (cfg
->mempool
, check_relations
, rel
);
1115 rel
= (MonoAdditionalVariableRelation
*)mono_mempool_alloc0 (cfg
->mempool
, sizeof (MonoAdditionalVariableRelation
));
1116 rel
->variable
= index_var
;
1117 rel
->relation
.relation
= MONO_GE_RELATION
;
1118 rel
->relation
.related_value
.type
= MONO_CONSTANT_SUMMARIZED_VALUE
;
1119 rel
->relation
.related_value
.value
.constant
.value
= 0;
1121 apply_change_to_evaluation_area (area
, rel
);
1123 check_relations
= g_slist_append_mempool (cfg
->mempool
, check_relations
, rel
);
1127 if (ins
->opcode
== OP_CHECK_THIS
) {
1128 if (eval_non_null (area
, ins
->sreg1
)) {
1129 if (REPORT_ABC_REMOVAL
)
1130 printf ("ARRAY-ACCESS: removed check_this instruction.\n");
1135 if (ins
->opcode
== OP_NOT_NULL
)
1136 add_non_null (area
, cfg
, ins
->sreg1
, &check_relations
);
1138 if (ins
->opcode
== OP_COMPARE_IMM
&& ins
->inst_imm
== 0 && ins
->next
&& ins
->next
->opcode
== OP_COND_EXC_EQ
) {
1139 if (eval_non_null (area
, ins
->sreg1
)) {
1140 if (REPORT_ABC_REMOVAL
)
1141 printf ("ARRAY-ACCESS: Removed null check.\n");
1142 NULLIFY_INS (ins
->next
);
1148 * FIXME: abcrem equates an array with its length,
1149 * so a = new int [100] implies a != null, but a = new int [0] doesn't.
1152 * Eliminate MONO_INST_FAULT flags if possible.
1154 if (COMPILE_LLVM (cfg
) && (ins
->opcode
== OP_LDLEN
||
1155 ins
->opcode
== OP_BOUNDS_CHECK
||
1156 ins
->opcode
== OP_STRLEN
||
1157 (MONO_IS_LOAD_MEMBASE (ins
) && (ins
->flags
& MONO_INST_FAULT
)) ||
1158 (MONO_IS_STORE_MEMBASE (ins
) && (ins
->flags
& MONO_INST_FAULT
)))) {
1161 if (MONO_IS_STORE_MEMBASE (ins
))
1162 reg
= ins
->inst_destbasereg
;
1163 else if (MONO_IS_LOAD_MEMBASE (ins
))
1164 reg
= ins
->inst_basereg
;
1169 * This doesn't work because LLVM can move the non-faulting loads before the faulting
1170 * ones (test_0_llvm_moving_faulting_loads ()).
1171 * So only do it if we know the load cannot be moved before the instruction which ensures it is not
1172 * null (i.e. the def of its sreg).
1174 if (area
->defs
[reg
] && area
->defs
[reg
]->opcode
== OP_NEWARR
) {
1175 if (REPORT_ABC_REMOVAL
)
1176 printf ("ARRAY-ACCESS: removed MONO_INST_FAULT flag.\n");
1177 ins
->flags
&= ~MONO_INST_FAULT
;
1180 if (eval_non_null (area, reg)) {
1181 if (REPORT_ABC_REMOVAL)
1182 printf ("ARRAY-ACCESS: removed MONO_INST_FAULT flag.\n");
1183 ins->flags &= ~MONO_INST_FAULT;
1185 add_non_null (area, cfg, reg, &check_relations);
1191 for (dominated_bb
= bb
->dominated
; dominated_bb
!= NULL
; dominated_bb
= dominated_bb
->next
) {
1192 process_block (cfg
, (MonoBasicBlock
*) (dominated_bb
->data
), area
);
1195 for (l
= check_relations
; l
; l
= l
->next
)
1196 remove_change_from_evaluation_area ((MonoAdditionalVariableRelation
*)l
->data
);
1198 remove_change_from_evaluation_area (&(additional_relations
.relation1
));
1199 remove_change_from_evaluation_area (&(additional_relations
.relation2
));
1202 static MonoIntegerValueKind
1203 type_to_value_kind (MonoType
*type
)
1206 return MONO_UNKNOWN_INTEGER_VALUE
;
1207 switch (type
->type
) {
1209 return MONO_INTEGER_VALUE_SIZE_1
;
1212 return MONO_UNSIGNED_INTEGER_VALUE_SIZE_1
;
1215 return MONO_INTEGER_VALUE_SIZE_2
;
1218 return MONO_UNSIGNED_INTEGER_VALUE_SIZE_2
;
1221 return MONO_INTEGER_VALUE_SIZE_4
;
1224 return MONO_UNSIGNED_INTEGER_VALUE_SIZE_4
;
1227 return (MonoIntegerValueKind
)TARGET_SIZEOF_VOID_P
;
1230 return (MonoIntegerValueKind
)(MONO_UNSIGNED_VALUE_FLAG
| TARGET_SIZEOF_VOID_P
);
1233 return MONO_INTEGER_VALUE_SIZE_8
;
1236 return MONO_UNSIGNED_INTEGER_VALUE_SIZE_8
;
1238 return MONO_UNKNOWN_INTEGER_VALUE
;
1243 * mono_perform_abc_removal:
1244 * \param cfg Control Flow Graph
1246 * Performs the ABC removal from a cfg in SSA form.
1247 * It does the following:
1248 * - Prepare the evaluation area
1249 * - Allocate memory for the relation graph in the evaluation area
1250 * (of course, only for variable definitions) and summarize there all
1251 * variable definitions
1252 * - Allocate memory for the evaluation contexts in the evaluation area
1253 * - Recursively process all the BBs in the dominator tree (it is enough
1254 * to invoke the processing on the entry BB)
1256 * cfg: the method code
1259 mono_perform_abc_removal (MonoCompile
*cfg
)
1261 MonoVariableRelationsEvaluationArea area
;
1265 verbose_level
= cfg
->verbose_level
;
1268 area
.relations
= (MonoSummarizedValueRelation
*)
1269 mono_mempool_alloc (cfg
->mempool
, sizeof (MonoSummarizedValueRelation
) * (cfg
->next_vreg
) * 2);
1271 area
.contexts
= (MonoRelationsEvaluationContext
*)
1272 mono_mempool_alloc0 (cfg
->mempool
, sizeof (MonoRelationsEvaluationContext
) * (cfg
->next_vreg
));
1274 area
.statuses
= (MonoRelationsEvaluationStatus
*)
1275 mono_mempool_alloc0 (cfg
->mempool
, sizeof (MonoRelationsEvaluationStatus
) * (cfg
->next_vreg
));
1277 area
.variable_value_kind
= (MonoIntegerValueKind
*)
1278 mono_mempool_alloc (cfg
->mempool
, sizeof (MonoIntegerValueKind
) * (cfg
->next_vreg
));
1279 area
.defs
= (MonoInst
**)mono_mempool_alloc (cfg
->mempool
, sizeof (MonoInst
*) * cfg
->next_vreg
);
1280 for (i
= 0; i
< cfg
->next_vreg
; i
++) {
1281 area
.variable_value_kind
[i
] = MONO_UNKNOWN_INTEGER_VALUE
;
1282 area
.relations
[i
].relation
= MONO_EQ_RELATION
;
1283 area
.relations
[i
].relation_is_static_definition
= TRUE
;
1284 MAKE_VALUE_ANY (area
.relations
[i
].related_value
);
1285 area
.relations
[i
].next
= NULL
;
1286 area
.defs
[i
] = NULL
;
1289 for (bb
= cfg
->bb_entry
; bb
; bb
= bb
->next_bb
) {
1292 if (TRACE_ABC_REMOVAL
)
1293 printf ("\nABCREM BLOCK %d:\n", bb
->block_num
);
1295 for (ins
= bb
->code
; ins
; ins
= ins
->next
) {
1296 const char *spec
= INS_INFO (ins
->opcode
);
1299 if (spec
[MONO_INST_DEST
] == ' ' || MONO_IS_STORE_MEMBASE (ins
))
1302 MONO_INS_FOR_EACH_REG (ins
, idx
, reg
) {
1303 MonoInst
*var
= get_vreg_to_inst (cfg
, *reg
);
1304 if (var
&& (var
->flags
& (MONO_INST_VOLATILE
|MONO_INST_INDIRECT
)))
1307 if (idx
< MONO_INST_LEN
) {
1308 if (TRACE_ABC_REMOVAL
)
1309 printf ("Global register %d is not in the SSA form, skipping.\n", *reg
);
1313 if (spec
[MONO_INST_DEST
] == 'i') {
1314 MonoIntegerValueKind effective_value_kind
;
1315 MonoRelationsEvaluationRange range
;
1316 MonoSummarizedValueRelation
*type_relation
;
1319 if (TRACE_ABC_REMOVAL
)
1320 mono_print_ins (ins
);
1322 var
= get_vreg_to_inst (cfg
, ins
->dreg
);
1324 area
.variable_value_kind
[ins
->dreg
] = type_to_value_kind (var
->inst_vtype
);
1326 effective_value_kind
= get_relation_from_ins (&area
, ins
, &area
.relations
[ins
->dreg
], area
.variable_value_kind
[ins
->dreg
]);
1328 MONO_MAKE_RELATIONS_EVALUATION_RANGE_WEAK (range
);
1329 apply_value_kind_to_range (&range
, area
.variable_value_kind
[ins
->dreg
]);
1330 apply_value_kind_to_range (&range
, effective_value_kind
);
1332 if (range
.upper
< INT_MAX
) {
1333 type_relation
= (MonoSummarizedValueRelation
*) mono_mempool_alloc (cfg
->mempool
, sizeof (MonoSummarizedValueRelation
));
1334 type_relation
->relation
= MONO_LE_RELATION
;
1335 type_relation
->related_value
.type
= MONO_CONSTANT_SUMMARIZED_VALUE
;
1336 type_relation
->related_value
.value
.constant
.value
= range
.upper
;
1337 type_relation
->relation_is_static_definition
= TRUE
;
1338 type_relation
->next
= area
.relations
[ins
->dreg
].next
;
1339 area
.relations
[ins
->dreg
].next
= type_relation
;
1340 if (TRACE_ABC_REMOVAL
) {
1341 printf ("[var%d <= %d]", ins
->dreg
, range
.upper
);
1344 if (range
.lower
> INT_MIN
) {
1345 type_relation
= (MonoSummarizedValueRelation
*) mono_mempool_alloc (cfg
->mempool
, sizeof (MonoSummarizedValueRelation
));
1346 type_relation
->relation
= MONO_GE_RELATION
;
1347 type_relation
->related_value
.type
= MONO_CONSTANT_SUMMARIZED_VALUE
;
1348 type_relation
->related_value
.value
.constant
.value
= range
.lower
;
1349 type_relation
->relation_is_static_definition
= TRUE
;
1350 type_relation
->next
= area
.relations
[ins
->dreg
].next
;
1351 area
.relations
[ins
->dreg
].next
= type_relation
;
1352 if (TRACE_ABC_REMOVAL
) {
1353 printf ("[var%d >= %d]", ins
->dreg
, range
.lower
);
1356 if (TRACE_ABC_REMOVAL
) {
1357 printf ("Summarized variable %d: ", ins
->dreg
);
1358 print_summarized_value (&(area
.relations
[ins
->dreg
].related_value
));
1365 /* Add symmetric relations */
1366 for (i
= 0; i
< cfg
->next_vreg
; i
++) {
1367 if (area
.relations
[i
].related_value
.type
== MONO_VARIABLE_SUMMARIZED_VALUE
) {
1368 int related_index
= cfg
->next_vreg
+ i
;
1369 int related_variable
= area
.relations
[i
].related_value
.value
.variable
.variable
;
1371 area
.relations
[related_index
].relation
= MONO_EQ_RELATION
;
1372 area
.relations
[related_index
].relation_is_static_definition
= TRUE
;
1373 area
.relations
[related_index
].related_value
.type
= MONO_VARIABLE_SUMMARIZED_VALUE
;
1374 area
.relations
[related_index
].related_value
.value
.variable
.variable
= i
;
1375 area
.relations
[related_index
].related_value
.value
.variable
.delta
= - area
.relations
[i
].related_value
.value
.variable
.delta
;
1377 area
.relations
[related_index
].next
= area
.relations
[related_variable
].next
;
1378 area
.relations
[related_variable
].next
= &(area
.relations
[related_index
]);
1380 if (TRACE_ABC_REMOVAL
) {
1381 printf ("Added symmetric summarized value for variable variable %d (to %d): ", i
, related_variable
);
1382 print_summarized_value (&(area
.relations
[related_index
].related_value
));
1388 process_block (cfg
, cfg
->bblocks
[0], &area
);
1391 #else /* !DISABLE_JIT */
1393 MONO_EMPTY_SOURCE_FILE (abcremoval
);
1395 #endif /* !DISABLE_JIT */