5 #include <mono/metadata/debug-helpers.h>
6 #include <mono/metadata/mempool.h>
7 #include <mono/metadata/opcodes.h>
12 #include "abcremoval.h"
14 extern guint8 mono_burg_arity [];
16 #define TRACE_ABC_REMOVAL (verbose_level > 2)
17 #define REPORT_ABC_REMOVAL (verbose_level > 0)
19 #define CHEAT_AND_REMOVE_ALL_CHECKS 0
21 static int verbose_level;
23 #if (!CHEAT_AND_REMOVE_ALL_CHECKS)
26 #define IS_SUMMARIZED_VALUE_CONSTANT(value) ((value).value_type==MONO_CONSTANT_SUMMARIZED_VALUE)
27 #define IS_SUMMARIZED_VALUE_VARIABLE(value) ((value).value_type==MONO_VARIABLE_SUMMARIZED_VALUE)
29 #define RELATION_BETWEEN_VALUES(value,related_value) (\
30 ((value) > (related_value))? MONO_GT_RELATION :\
31 (((value) < (related_value))? MONO_LT_RELATION : MONO_EQ_RELATION))
33 #define MAKE_VALUE_ANY(v) do{\
34 (v)->relation_with_zero = MONO_ANY_RELATION;\
35 (v)->relation_with_one = MONO_ANY_RELATION;\
36 (v)->relation_with_value = MONO_ANY_RELATION;\
37 (v)->value_type = MONO_CONSTANT_SUMMARIZED_VALUE;\
38 (v)->value.constant = 0;\
41 #define MONO_NEGATED_RELATION(r) ((~(r))&MONO_ANY_RELATION)
42 #define MONO_SYMMETRIC_RELATION(r) (((r)&MONO_EQ_RELATION)|(((r)&MONO_LT_RELATION)<<1)|((r&MONO_GT_RELATION)>>1))
44 #define RELATION_ADDS_INFORMATION(r,r_maybe_adds_information) ((r)&(~(r_maybe_adds_information)))
46 unsigned char propagated_relations_table [] = {
47 #include "propagated_relations_table.def"
50 #define PROPAGATED_RELATION(r,r_to_propagate) (propagated_relations_table [((r)<<3)|(r_to_propagate)])
54 print_relation (int relation) {
57 if (relation & MONO_LT_RELATION) {
61 if (relation & MONO_EQ_RELATION) {
68 if (relation & MONO_GT_RELATION) {
79 print_summarized_value (MonoSummarizedValue *value) {
80 printf ("relation_with_zero: ");
81 print_relation (value->relation_with_zero);
83 printf ("relation_with_one: ");
84 print_relation (value->relation_with_one);
86 printf ("relation_with_value: ");
87 print_relation (value->relation_with_value);
89 switch (value->value_type) {
90 case MONO_CONSTANT_SUMMARIZED_VALUE:
91 printf ("Constant value: %d\n", value->value.constant);
93 case MONO_VARIABLE_SUMMARIZED_VALUE:
94 printf ("Variable value: %d\n", value->value.variable);
96 case MONO_PHI_SUMMARIZED_VALUE: {
98 printf ("PHI value: (");
99 for (i = 0; i < *(value->value.phi_variables); i++) {
101 printf ("%d", *(value->value.phi_variables + i + 1));
107 printf ("Unknown value type: %d\n", value->value_type);
112 print_branch_condition (MonoBranchCondition *condition, int n) {
113 printf ("Branch condition %d, on variable %d\n", n, condition->variable);
114 print_summarized_value (&(condition->value));
118 print_branch_data (MonoBranchData *branch, int n) {
120 printf ("Branch %d, destination BB %d [dfn %d], conditions %d\n",
121 n, branch->destination_block->block_num, branch->destination_block->dfn, branch->number_of_conditions);
122 for (i = 0; i < branch->number_of_conditions; i++) {
123 print_branch_condition (&(branch->conditions [i]), i);
128 print_summarized_block (MonoSummarizedBasicBlock *block) {
130 printf ("Summarization of BB %d [dfn %d] (has array accesses: %d), branches: %d\n",
131 block->block->block_num, block->block->dfn, block->has_array_access_instructions, block->number_of_branches);
132 for (i = 0; i < block->number_of_branches; i++) {
133 print_branch_data (&(block->branches [i]), i);
138 print_variable_relations (MonoVariableRelations *relations, gssize variable, int n) {
140 int significantRelations = 0;
141 for (i = 0; i < n; i++) {
142 if (relations->relations_with_variables [i] != MONO_ANY_RELATION) {
143 significantRelations++;
146 if ((relations->relation_with_zero != MONO_ANY_RELATION) ||
147 (relations->relation_with_one != MONO_ANY_RELATION) ||
148 (significantRelations > 0)) {
149 printf ("Relations for variable %d:\n", variable);
150 if (relations->relation_with_zero != MONO_ANY_RELATION) {
151 printf ("relation_with_zero: ");
152 print_relation (relations->relation_with_zero);
155 if (relations->relation_with_one != MONO_ANY_RELATION) {
156 printf ("relation_with_one: ");
157 print_relation (relations->relation_with_one);
160 if (significantRelations > 0) {
161 printf ("relations_with_variables (%d significant)\n", significantRelations);
162 for (i = 0; i < n; i++) {
163 if (relations->relations_with_variables [i] != MONO_ANY_RELATION) {
164 printf ("relation with variable %d: ", i);
165 print_relation (relations->relations_with_variables [i]);
174 print_all_variable_relations (MonoVariableRelationsEvaluationArea *evaluation_area) {
176 printf ("relations in evaluation area:\n");
177 for (i = 0; i < evaluation_area->cfg->num_varinfo; i++) {
178 print_variable_relations (&(evaluation_area->variable_relations [i]), i, evaluation_area->cfg->num_varinfo);
183 static MonoValueRelation
184 relation_for_sum_of_variable_and_constant (
185 MonoValueRelation variable_relation, MonoValueRelation constant_relation_with_zero) {
186 switch (variable_relation) {
187 case MONO_EQ_RELATION:
188 return constant_relation_with_zero;
189 case MONO_GE_RELATION:
190 if (constant_relation_with_zero & MONO_LT_RELATION) {
191 return MONO_ANY_RELATION;
193 return constant_relation_with_zero;
195 case MONO_LE_RELATION:
196 if (constant_relation_with_zero & MONO_GT_RELATION) {
197 return MONO_ANY_RELATION;
199 return constant_relation_with_zero;
201 case MONO_GT_RELATION:
202 if (constant_relation_with_zero & MONO_LT_RELATION) {
203 return MONO_ANY_RELATION;
205 return MONO_GT_RELATION;
207 case MONO_LT_RELATION:
208 if (constant_relation_with_zero & MONO_GT_RELATION) {
209 return MONO_ANY_RELATION;
211 return MONO_LE_RELATION;
214 g_assert_not_reached ();
215 return MONO_ANY_RELATION;
220 get_variable_value_from_ssa_store (MonoInst *store, int expected_variable_index) {
221 switch (store->opcode) {
230 if (TRACE_ABC_REMOVAL) {
231 printf ("Store instruction found...\n");
233 if (store->inst_left->opcode == OP_LOCAL) {
234 int variable_index = store->inst_left->inst_c0;
235 if (TRACE_ABC_REMOVAL) {
236 printf ("Value put in local %d (expected %d)\n", variable_index, expected_variable_index);
238 if (variable_index == expected_variable_index) {
239 return store->inst_right;
255 summarize_value (MonoInst *value, MonoSummarizedValue *result) {
256 switch (value->opcode) {
258 result->relation_with_zero = RELATION_BETWEEN_VALUES (value->inst_c0, 0);
259 result->relation_with_one = RELATION_BETWEEN_VALUES (abs (value->inst_c0), 1);
260 result->relation_with_value = MONO_EQ_RELATION;
261 result->value_type = MONO_CONSTANT_SUMMARIZED_VALUE;
262 result->value.constant = value->inst_c0;
266 result->relation_with_zero = MONO_ANY_RELATION;
267 result->relation_with_one = MONO_ANY_RELATION;
268 result->relation_with_value = MONO_EQ_RELATION;
269 result->value_type = MONO_VARIABLE_SUMMARIZED_VALUE;
270 result->value.variable = value->inst_c0;
273 if ((value->inst_left->opcode == OP_LOCAL) || (value->inst_left->opcode == OP_ARG)) {
274 summarize_value (value->inst_left, result);
276 MAKE_VALUE_ANY (result);
281 if ((value->inst_left->opcode == OP_LOCAL) || (value->inst_left->opcode == OP_ARG)) {
282 summarize_value (value->inst_left, result);
284 MAKE_VALUE_ANY (result);
289 MonoSummarizedValue left_value;
290 MonoSummarizedValue right_value;
291 summarize_value (value->inst_left, &left_value);
292 summarize_value (value->inst_right, &right_value);
294 if (IS_SUMMARIZED_VALUE_VARIABLE (left_value)) {
295 if (IS_SUMMARIZED_VALUE_CONSTANT (right_value)&& (right_value.value.constant = 1)) {
296 MonoValueRelation constant_relation_with_zero = right_value.relation_with_zero;
297 if (value->opcode == CEE_SUB) {
298 constant_relation_with_zero = MONO_SYMMETRIC_RELATION (constant_relation_with_zero);
300 result->relation_with_value = relation_for_sum_of_variable_and_constant (
301 left_value.relation_with_value, constant_relation_with_zero);
302 if (result->relation_with_value != MONO_ANY_RELATION) {
303 result->relation_with_zero = MONO_ANY_RELATION;
304 result->relation_with_one = MONO_ANY_RELATION;
305 result->value_type = MONO_VARIABLE_SUMMARIZED_VALUE;
306 result->value.variable = left_value.value.variable;
308 MAKE_VALUE_ANY (result);
311 MAKE_VALUE_ANY (result);
313 } else if (IS_SUMMARIZED_VALUE_VARIABLE (right_value)) {
314 if (IS_SUMMARIZED_VALUE_CONSTANT (left_value)&& (left_value.value.constant == 1)) {
315 MonoValueRelation constant_relation_with_zero = left_value.relation_with_zero;
316 if (value->opcode == CEE_SUB) {
317 constant_relation_with_zero = MONO_SYMMETRIC_RELATION (constant_relation_with_zero);
319 result->relation_with_value = relation_for_sum_of_variable_and_constant (
320 right_value.relation_with_value, constant_relation_with_zero);
321 if (result->relation_with_value != MONO_ANY_RELATION) {
322 result->relation_with_zero = MONO_ANY_RELATION;
323 result->relation_with_one = MONO_ANY_RELATION;
324 result->value_type = MONO_VARIABLE_SUMMARIZED_VALUE;
325 result->value.variable = right_value.value.variable;
327 MAKE_VALUE_ANY (result);
330 MAKE_VALUE_ANY (result);
332 } else if (IS_SUMMARIZED_VALUE_CONSTANT (right_value)&& IS_SUMMARIZED_VALUE_CONSTANT (left_value)) {
333 /* This should not happen if constant folding has been done */
334 if (right_value.relation_with_value == MONO_EQ_RELATION && left_value.relation_with_value == MONO_EQ_RELATION) {
336 if (value->opcode == CEE_ADD) {
337 constant = right_value.value.constant + left_value.value.constant;
340 constant = right_value.value.constant - left_value.value.constant;
342 result->relation_with_zero = RELATION_BETWEEN_VALUES (constant, 0);
343 result->relation_with_one = RELATION_BETWEEN_VALUES (abs (constant), 1);
344 result->relation_with_value = MONO_EQ_RELATION;
345 result->value_type = MONO_CONSTANT_SUMMARIZED_VALUE;
346 result->value.constant = constant;
348 MAKE_VALUE_ANY (result);
351 MAKE_VALUE_ANY (result);
356 summarize_value (value->inst_newa_len, result);
359 summarize_value (value->inst_left, result);
362 result->relation_with_zero = MONO_ANY_RELATION;
363 result->relation_with_one = MONO_ANY_RELATION;
364 result->relation_with_value = MONO_EQ_RELATION;
365 result->value_type = MONO_PHI_SUMMARIZED_VALUE;
366 result->value.phi_variables = value->inst_phi_args;
369 MAKE_VALUE_ANY (result);
373 static MonoValueRelation
374 get_relation_from_branch_instruction (int opcode) {
377 return MONO_EQ_RELATION;
380 return MONO_LT_RELATION;
383 return MONO_LE_RELATION;
386 return MONO_GT_RELATION;
389 return MONO_GE_RELATION;
391 return MONO_NE_RELATION;
393 g_assert_not_reached ();
394 return MONO_ANY_RELATION;
399 contains_array_access (MonoInst *inst) {
400 if (inst->opcode == CEE_LDELEMA) { /* Handle OP_LDELEMA2D, too */
404 if (mono_burg_arity [inst->opcode]) {
405 if (contains_array_access (inst->inst_left)) {
408 if (mono_burg_arity [inst->opcode] > 1) {
409 return contains_array_access (inst->inst_right);
416 analyze_block (MonoBasicBlock *bb, MonoVariableRelationsEvaluationArea *evaluation_area) {
417 MonoSummarizedBasicBlock *b = &(evaluation_area->blocks [bb->dfn]);
418 MonoInst *current_inst = bb->code;
419 MonoInst *last_inst = NULL;
422 if (TRACE_ABC_REMOVAL) {
423 printf ("Analyzing block %d [dfn %d]\n", bb->block_num, bb->dfn);
426 g_assert (bb->dfn < evaluation_area->cfg->num_bblocks);
427 b->has_array_access_instructions = 0;
430 while (current_inst != NULL) {
431 if (TRACE_ABC_REMOVAL) {
432 printf ("Analyzing instruction %d\n", inst_index);
436 if (contains_array_access (current_inst)) {
437 b->has_array_access_instructions = 1;
440 if (current_inst->next == NULL) {
441 last_inst = current_inst;
443 current_inst = current_inst->next;
446 if (last_inst != NULL) {
447 switch (last_inst->opcode) {
458 if (last_inst->inst_left->opcode == OP_COMPARE) {
459 int number_of_variables = 0;
460 int current_variable = 0;
462 MonoSummarizedValue left_value;
463 MonoSummarizedValue right_value;
464 MonoValueRelation relation = get_relation_from_branch_instruction (last_inst->opcode);
465 MonoValueRelation symmetric_relation = MONO_SYMMETRIC_RELATION (relation);
466 summarize_value (last_inst->inst_left->inst_left, &left_value);
467 summarize_value (last_inst->inst_left->inst_right, &right_value);
468 /* It is actually possible to handle some more case... */
469 if ((left_value.relation_with_value == MONO_EQ_RELATION) &&
470 (right_value.relation_with_value == MONO_EQ_RELATION)) {
471 if (left_value.value_type == MONO_VARIABLE_SUMMARIZED_VALUE)number_of_variables++;
472 if (right_value.value_type == MONO_VARIABLE_SUMMARIZED_VALUE)number_of_variables++;
473 if (number_of_variables > 0) {
474 b->number_of_branches = 2;
475 b->branches = (MonoBranchData*) mono_mempool_alloc (
476 evaluation_area->pool, sizeof (MonoBranchData) * 2);
477 MonoBranchData *branch_true = &(b->branches [0]);
478 branch_true->destination_block = last_inst->inst_true_bb;
479 branch_true->number_of_conditions = number_of_variables;
480 branch_true->conditions = (MonoBranchCondition*)
481 mono_mempool_alloc (evaluation_area->pool, sizeof (MonoBranchCondition) * number_of_variables);
482 MonoBranchData *branch_false = &(b->branches [1]);
483 branch_false->destination_block = last_inst->inst_false_bb;
484 branch_false->number_of_conditions = number_of_variables;
485 branch_false->conditions = (MonoBranchCondition*)
486 mono_mempool_alloc (evaluation_area->pool, sizeof (MonoBranchCondition) * number_of_variables);
487 if (left_value.value_type == MONO_VARIABLE_SUMMARIZED_VALUE) {
488 MonoBranchCondition *condition_true = &(branch_true->conditions [current_variable]);
489 condition_true->variable = left_value.value.variable;
490 condition_true->value = right_value;
491 condition_true->value.relation_with_zero = MONO_ANY_RELATION;
492 condition_true->value.relation_with_one = MONO_ANY_RELATION;
493 condition_true->value.relation_with_value = relation;
494 MonoBranchCondition *condition_false = &(branch_false->conditions [current_variable]);
495 condition_false->variable = left_value.value.variable;
496 condition_false->value = right_value;
497 condition_false->value.relation_with_zero = MONO_ANY_RELATION;
498 condition_false->value.relation_with_one = MONO_ANY_RELATION;
499 condition_false->value.relation_with_value = MONO_NEGATED_RELATION (relation);
502 if (right_value.value_type == MONO_VARIABLE_SUMMARIZED_VALUE) {
503 MonoBranchCondition *condition_true = &(branch_true->conditions [current_variable]);
504 condition_true->variable = right_value.value.variable;
505 condition_true->value = left_value;
506 condition_true->value.relation_with_zero = MONO_ANY_RELATION;
507 condition_true->value.relation_with_one = MONO_ANY_RELATION;
508 condition_true->value.relation_with_value = symmetric_relation;
509 MonoBranchCondition *condition_false = &(branch_false->conditions [current_variable]);
510 condition_false->variable = right_value.value.variable;
511 condition_false->value = left_value;
512 condition_false->value.relation_with_zero = MONO_ANY_RELATION;
513 condition_false->value.relation_with_one = MONO_ANY_RELATION;
514 condition_false->value.relation_with_value = MONO_NEGATED_RELATION (symmetric_relation);
517 b->number_of_branches = 0;
521 b->number_of_branches = 0;
525 b->number_of_branches = 0;
530 /* Should handle switches... */
531 /* switch_operand = last_inst->inst_right; */
532 /* number_of_cases = GPOINTER_TO_INT (last_inst->klass); */
533 /* cases = last_inst->inst_many_bb; */
534 b->number_of_branches = 0;
538 b->number_of_branches = 0;
542 b->number_of_branches = 0;
546 if (TRACE_ABC_REMOVAL) {
547 print_summarized_block (b);
551 #define SET_VARIABLE_RELATIONS(vr, relation, n)do {\
552 (vr)->relation_with_zero = (relation);\
553 (vr)->relation_with_one = (relation);\
554 memset ((vr)->relations_with_variables,(relation),(n));\
557 #define COMBINE_VARIABLE_RELATIONS(operator, vr, related_vr, n)do {\
559 operator ((vr)->relation_with_zero, (related_vr)->relation_with_zero);\
560 operator ((vr)->relation_with_one, (related_vr)->relation_with_one);\
561 for (i = 0; i < (n); i++) {\
562 operator ((vr)->relations_with_variables [i], (related_vr)->relations_with_variables [i]);\
566 #define RELATION_ASSIGNMENT(destination,source) (destination)=(source)
567 #define RELATION_UNION(destination,source) (destination)|=(source)
568 #define RELATION_INTERSECTION(destination,source) (destination)&=(source)
573 evaluate_variable_relations (gssize variable, MonoVariableRelationsEvaluationArea *evaluation_area, MonoRelationsEvaluationContext *father_context) {
574 MonoVariableRelations *relations = &(evaluation_area->variable_relations [variable]);
575 MonoRelationsEvaluationContext context;
576 if (TRACE_ABC_REMOVAL) {
577 printf ("Applying definition of variable %d\n", variable);
579 context.father_context = father_context;
580 context.variable = variable;
581 switch (relations->evaluation_step) {
582 case MONO_RELATIONS_EVALUATION_NOT_STARTED: {
583 MonoSummarizedValue *value = &(evaluation_area->variable_definitions [variable]);
584 relations->evaluation_step = MONO_RELATIONS_EVALUATION_IN_PROGRESS;
585 if (TRACE_ABC_REMOVAL) {
586 printf ("Current step is MONO_RELATIONS_EVALUATION_NOT_STARTED, summarized value is:\n");
587 print_summarized_value (value);
589 switch (value->value_type) {
590 case MONO_CONSTANT_SUMMARIZED_VALUE:
591 if (value->relation_with_value == MONO_EQ_RELATION) {
592 relations->relation_with_zero &= RELATION_BETWEEN_VALUES (value->value.constant, 0);
593 relations->relation_with_one &= RELATION_BETWEEN_VALUES (abs (value->value.constant), 1);
595 /* Other cases should not happen... */
597 case MONO_VARIABLE_SUMMARIZED_VALUE: {
598 gssize related_variable = value->value.variable;
599 relations->relations_with_variables [related_variable] = value->relation_with_value;
600 evaluate_variable_relations (related_variable, evaluation_area, &context);
601 if (value->relation_with_value == MONO_EQ_RELATION) {
602 COMBINE_VARIABLE_RELATIONS (RELATION_INTERSECTION, relations,
603 &(evaluation_area->variable_relations [related_variable]), evaluation_area->cfg->num_varinfo);
605 /* Other cases should be handled... */
608 case MONO_PHI_SUMMARIZED_VALUE:
609 if (value->relation_with_value == MONO_EQ_RELATION) {
611 MonoVariableRelations *phi_union = (MonoVariableRelations*) alloca (sizeof (MonoVariableRelations));
612 phi_union->relations_with_variables = (unsigned char*) alloca (evaluation_area->cfg->num_varinfo);
613 SET_VARIABLE_RELATIONS (phi_union, MONO_NO_RELATION, evaluation_area->cfg->num_varinfo);
614 for (phi = 0; phi < *(value->value.phi_variables); phi++) {
615 gssize related_variable = value->value.phi_variables [phi+1];
616 evaluate_variable_relations (related_variable, evaluation_area, &context);
617 COMBINE_VARIABLE_RELATIONS (RELATION_UNION, phi_union,
618 &(evaluation_area->variable_relations [related_variable]), evaluation_area->cfg->num_varinfo);
620 if (TRACE_ABC_REMOVAL) {
621 printf ("Resulting phi_union is:\n");
622 print_variable_relations (phi_union, variable, evaluation_area->cfg->num_varinfo);
624 COMBINE_VARIABLE_RELATIONS (RELATION_INTERSECTION, relations,
625 phi_union, evaluation_area->cfg->num_varinfo);
627 /* Other cases should not happen... */
630 g_assert_not_reached ();
634 case MONO_RELATIONS_EVALUATION_IN_PROGRESS: {
635 MonoVariableRelations *recursive_value_relations = NULL;
636 unsigned char recursive_relation = MONO_ANY_RELATION;
637 MonoRelationsEvaluationContext *current_context = context.father_context;
638 if (TRACE_ABC_REMOVAL) {
639 printf ("Current step is MONO_RELATIONS_EVALUATION_IN_PROGRESS\n");
641 relations->definition_is_recursive = 1;
642 while (current_context != NULL && current_context->variable != variable) {
643 MonoVariableRelations *context_relations = &(evaluation_area->variable_relations [current_context->variable]);
644 MonoSummarizedValue *context_value = &(evaluation_area->variable_definitions [current_context->variable]);
645 if (TRACE_ABC_REMOVAL) {
646 printf ("Backtracing to context %d\n", current_context->variable);
648 if (recursive_value_relations == NULL) {
649 if (context_value->relation_with_value != MONO_EQ_RELATION) {
650 recursive_value_relations = context_relations;
651 recursive_relation = context_value->relation_with_value;
652 if (TRACE_ABC_REMOVAL) {
653 printf ("Accepted recursive definition, relation is ");
654 print_relation (recursive_relation);
659 if (context_value->relation_with_value != MONO_EQ_RELATION) {
660 recursive_relation = MONO_NO_RELATION;
661 if (TRACE_ABC_REMOVAL) {
662 printf ("Rejected recursive definition, bad relation is ");
663 print_relation (context_value->relation_with_value);
668 current_context = current_context->father_context;
670 if (recursive_value_relations != NULL && recursive_relation != MONO_NO_RELATION) {
672 /* This should handle "grows" and "decreases" cases */
673 recursive_value_relations->relation_with_zero &= recursive_relation;
674 for (i = 0; i < evaluation_area->cfg->num_varinfo; i++) {
675 recursive_value_relations->relations_with_variables [i] &= recursive_relation;
680 case MONO_RELATIONS_EVALUATION_COMPLETED:
681 if (TRACE_ABC_REMOVAL) {
682 printf ("Current step is MONO_RELATIONS_EVALUATION_COMPLETED\n");
686 g_assert_not_reached ();
689 relations->evaluation_step = MONO_RELATIONS_EVALUATION_COMPLETED;
693 propagate_relations (MonoVariableRelationsEvaluationArea *evaluation_area) {
696 for (variable = 0; variable < evaluation_area->cfg->num_varinfo; variable++) {
697 MonoVariableRelations *relations = &(evaluation_area->variable_relations [variable]);
698 gssize related_variable;
699 for (related_variable = 0; related_variable < evaluation_area->cfg->num_varinfo; related_variable++) {
700 unsigned char relation_with_variable = relations->relations_with_variables [related_variable];
701 if (relation_with_variable != MONO_ANY_RELATION) {
702 MonoVariableRelations *related_relations = &(evaluation_area->variable_relations [related_variable]);
703 gssize variable_related_to_related_variable;
704 unsigned char new_relation_with_zero = PROPAGATED_RELATION (relation_with_variable, related_relations->relation_with_zero);
705 if (RELATION_ADDS_INFORMATION (relations->relation_with_zero, new_relation_with_zero)) {
706 if (TRACE_ABC_REMOVAL) {
707 printf ("RELATION_ADDS_INFORMATION variable %d, related_variable %d, relation_with_zero ",
708 variable, related_variable);
709 print_relation (relations->relation_with_zero);
711 print_relation (new_relation_with_zero);
714 relations->relation_with_zero &= new_relation_with_zero;
715 if (TRACE_ABC_REMOVAL) {
716 print_relation (relations->relation_with_zero);
721 for (variable_related_to_related_variable = 0; variable_related_to_related_variable < evaluation_area->cfg->num_varinfo; variable_related_to_related_variable++) {
722 unsigned char relation_of_variable = related_relations->relations_with_variables [variable_related_to_related_variable];
723 unsigned char relation_with_other_variable = relations->relations_with_variables [variable_related_to_related_variable];
724 unsigned char new_relation_with_other_variable = PROPAGATED_RELATION (relation_with_variable, relation_of_variable);
725 if (RELATION_ADDS_INFORMATION (relation_with_other_variable, new_relation_with_other_variable)) {
726 if (TRACE_ABC_REMOVAL) {
727 printf ("RELATION_ADDS_INFORMATION variable %d, related_variable %d, variable_related_to_related_variable %d, ",
728 variable, related_variable, variable_related_to_related_variable);
729 print_relation (relation_with_variable);
731 print_relation (new_relation_with_other_variable);
734 relations->relations_with_variables [variable_related_to_related_variable] &= new_relation_with_other_variable;
735 if (TRACE_ABC_REMOVAL) {
736 print_relation (relations->relations_with_variables [variable_related_to_related_variable]);
749 remove_abc_from_inst (MonoInst *inst, MonoVariableRelationsEvaluationArea *evaluation_area) {
750 if (inst->opcode == CEE_LDELEMA) {
751 MonoInst *array_inst = inst->inst_left;
752 MonoInst *index_inst = inst->inst_right;
753 /* Both the array and the index must be local variables */
754 if ((array_inst->opcode == CEE_LDIND_REF) &&
755 ((array_inst->inst_left->opcode == OP_LOCAL)||(array_inst->inst_left->opcode == OP_ARG)) &&
756 ((index_inst->opcode == CEE_LDIND_I1) ||
757 (index_inst->opcode == CEE_LDIND_U1) ||
758 (index_inst->opcode == CEE_LDIND_I2) ||
759 (index_inst->opcode == CEE_LDIND_U2) ||
760 (index_inst->opcode == CEE_LDIND_I4) ||
761 (index_inst->opcode == CEE_LDIND_U4))&&
762 ((index_inst->inst_left->opcode == OP_LOCAL)||(index_inst->inst_left->opcode == OP_ARG))) {
763 gssize array_variable = array_inst->inst_left->inst_c0;
764 gssize index_variable = index_inst->inst_left->inst_c0;
765 MonoVariableRelations *index_relations = &(evaluation_area->variable_relations [index_variable]);
766 if ( (! (index_relations->relation_with_zero & ~MONO_GE_RELATION)) &&
767 (! (index_relations->relations_with_variables [array_variable] & ~MONO_LT_RELATION)) ) {
768 inst->flags |= (MONO_INST_NORANGECHECK);
770 if (TRACE_ABC_REMOVAL) {
771 if (! (index_relations->relation_with_zero & ~MONO_GE_RELATION)) {
772 printf ("ARRAY-ACCESS: Removed lower bound check on array %d with index %d\n", array_variable, index_variable);
774 printf ("ARRAY-ACCESS: Left lower bound check on array %d with index %d\n", array_variable, index_variable);
776 if (! (index_relations->relations_with_variables [array_variable] & ~MONO_LT_RELATION)) {
777 printf ("ARRAY-ACCESS: Removed upper bound check on array %d with index %d\n", array_variable, index_variable);
779 printf ("ARRAY-ACCESS: Left upper bound check on array %d with index %d\n", array_variable, index_variable);
782 if (REPORT_ABC_REMOVAL) {
783 if (inst->flags & (MONO_INST_NORANGECHECK)) {
784 printf ("ARRAY-ACCESS: removed bounds check on array %d with index %d in method %s\n",
785 array_variable, index_variable, mono_method_full_name (evaluation_area->cfg->method, TRUE));
791 if (mono_burg_arity [inst->opcode]) {
792 remove_abc_from_inst (inst->inst_left, evaluation_area);
793 if (mono_burg_arity [inst->opcode] > 1) {
794 remove_abc_from_inst (inst->inst_right, evaluation_area);
800 remove_abc_from_block (MonoSummarizedBasicBlock *b, MonoVariableRelationsEvaluationArea *evaluation_area) {
804 MonoInst *current_inst = b->block->code;
806 if (TRACE_ABC_REMOVAL) {
807 printf ("Working on block %d [dfn %d], has_array_access_instructions is %d\n",
808 b->block->block_num, b->block->dfn, b->has_array_access_instructions);
811 if (b->has_array_access_instructions) {
812 for (i = 0; i < evaluation_area->cfg->num_varinfo; i++) {
813 evaluation_area->variable_relations [i].evaluation_step = MONO_RELATIONS_EVALUATION_NOT_STARTED;
814 evaluation_area->variable_relations [i].definition_is_recursive = 0;
815 SET_VARIABLE_RELATIONS (&(evaluation_area->variable_relations [i]), MONO_ANY_RELATION, evaluation_area->cfg->num_varinfo);
820 /* Walk up dominators tree to put conditions in area */
822 /* for (in_index = 0; in_index < bb->in_count; in_index++) { */
823 if (bb->in_count == 1) { /* Should write the code to "sum" conditions... */
825 MonoBasicBlock *in_bb = bb->in_bb [in_index];
826 MonoSummarizedBasicBlock *in_b = &(evaluation_area->blocks [in_bb->dfn]);
827 for (out_index = 0; out_index < in_b->number_of_branches; out_index++) {
828 if (in_b->branches [out_index].destination_block == bb) {
829 MonoBranchData *branch;
831 if (TRACE_ABC_REMOVAL) {
832 printf ("Applying conditions of branch %d -> %d\n", in_b->block->block_num, bb->block_num);
834 branch = &(in_b->branches [out_index]);
835 for (condition_index = 0; condition_index < branch->number_of_conditions; condition_index++) {
836 MonoBranchCondition *condition = &(branch->conditions [condition_index]);
837 MonoVariableRelations *relations = &(evaluation_area->variable_relations [condition->variable]);
838 switch (condition->value.value_type) {
839 case MONO_CONSTANT_SUMMARIZED_VALUE: {
840 if (condition->value.relation_with_value == MONO_EQ_RELATION) {
841 relations->relation_with_zero &= RELATION_BETWEEN_VALUES (condition->value.value.constant, 0);
842 relations->relation_with_one &= RELATION_BETWEEN_VALUES (abs (condition->value.value.constant), 1);
843 if (TRACE_ABC_REMOVAL) {
844 printf ("Applied equality condition with constant to variable %d; relatrion with 0: ", condition->variable);
845 print_relation (relations->relation_with_zero);
848 } else if (condition->value.value.constant == 0) {
849 relations->relation_with_zero &= condition->value.relation_with_value;
850 if (TRACE_ABC_REMOVAL) {
851 printf ("Applied relation with 0 to variable %d: ", condition->variable);
852 print_relation (relations->relation_with_zero);
856 /* Other cases should be handled */
859 case MONO_VARIABLE_SUMMARIZED_VALUE: {
860 relations->relations_with_variables [condition->value.value.variable] &= condition->value.relation_with_value;
861 if (TRACE_ABC_REMOVAL) {
862 printf ("Applied relation between variables %d and %d: ", condition->variable, condition->value.value.variable);
863 print_relation (relations->relations_with_variables [condition->value.value.variable]);
869 g_assert_not_reached (); /* PHIs are not OK here */
878 if (TRACE_ABC_REMOVAL) {
879 printf ("Branch conditions applied... ");
880 print_all_variable_relations (evaluation_area);
883 for (i = 0; i < evaluation_area->cfg->num_varinfo; i++) {
884 evaluate_variable_relations (i, evaluation_area, NULL);
887 if (TRACE_ABC_REMOVAL) {
888 printf ("Variable definitions applied... ");
889 print_all_variable_relations (evaluation_area);
894 changes = propagate_relations (evaluation_area);
896 if (TRACE_ABC_REMOVAL) {
897 printf ("Propagated %d changes\n", changes);
899 } while ((changes > 0) && (i < evaluation_area->cfg->num_varinfo));
901 if (TRACE_ABC_REMOVAL) {
902 printf ("Relations fully propagated... ");
903 print_all_variable_relations (evaluation_area);
906 /* Area is ready, look for array access instructions */
907 if (TRACE_ABC_REMOVAL) {
908 printf ("Going after array accesses...\n");
910 while (current_inst != NULL) {
911 remove_abc_from_inst (current_inst, evaluation_area);
912 current_inst = current_inst->next;
918 mono_perform_abc_removal (MonoCompile *cfg)
920 MonoVariableRelationsEvaluationArea evaluation_area;
922 verbose_level = cfg->verbose_level;
925 if (TRACE_ABC_REMOVAL) {
926 printf ("Removing array bound checks in %s\n", mono_method_full_name (cfg->method, TRUE));
929 if (cfg->num_varinfo > 250) {
930 if (TRACE_ABC_REMOVAL) {
931 printf ("Too many variables (%d), giving up...\n", cfg->num_varinfo);
936 evaluation_area.pool = mono_mempool_new ();
937 evaluation_area.cfg = cfg;
938 evaluation_area.variable_relations = (MonoVariableRelations *)
939 mono_mempool_alloc (evaluation_area.pool, sizeof (MonoVariableRelations) * (cfg->num_varinfo));
940 //printf ("Allocated %d bytes for %d variable relations at pointer %p\n",
941 // sizeof (MonoVariableRelations) * (cfg->num_varinfo), (cfg->num_varinfo), evaluation_area.variable_relations);
942 for (i = 0; i < cfg->num_varinfo; i++ ) {
943 evaluation_area.variable_relations [i].relations_with_variables = (unsigned char *)
944 mono_mempool_alloc (evaluation_area.pool, (cfg->num_varinfo));
945 //printf ("Allocated %d bytes [%d] at pointer %p\n",
946 // cfg->num_varinfo, i, evaluation_area.variable_relations [i].relations_with_variables);
948 evaluation_area.variable_definitions = (MonoSummarizedValue *)
949 mono_mempool_alloc (evaluation_area.pool, sizeof (MonoSummarizedValue) * (cfg->num_varinfo));
950 //printf ("Allocated %d bytes for %d variable definitions at pointer %p\n",
951 // sizeof (MonoSummarizedValue) * (cfg->num_varinfo), (cfg->num_varinfo), evaluation_area.variable_definitions);
952 if (TRACE_ABC_REMOVAL) {
953 printf ("Method contains %d variables\n", i);
955 for (i = 0; i < cfg->num_varinfo; i++) {
956 if (cfg->vars [i]->def != NULL) {
957 MonoInst *value = get_variable_value_from_ssa_store (cfg->vars [i]->def, i);
959 summarize_value (value, evaluation_area.variable_definitions + i);
960 if (TRACE_ABC_REMOVAL) {
961 printf ("Summarized variable %d\n", i);
962 print_summarized_value (evaluation_area.variable_definitions + i);
965 MAKE_VALUE_ANY (evaluation_area.variable_definitions + i);
966 if (TRACE_ABC_REMOVAL) {
967 printf ("Definition of variable %d is not a proper store\n", i);
971 MAKE_VALUE_ANY (evaluation_area.variable_definitions + i);
972 if (TRACE_ABC_REMOVAL) {
973 printf ("Variable %d has no definition, probably it is an argument\n", i);
974 print_summarized_value (evaluation_area.variable_definitions + i);
979 evaluation_area.blocks = (MonoSummarizedBasicBlock *)
980 mono_mempool_alloc (evaluation_area.pool, sizeof (MonoSummarizedBasicBlock) * (cfg->num_bblocks));
981 //printf ("Allocated %d bytes for %d blocks at pointer %p\n",
982 // sizeof (MonoSummarizedBasicBlock) * (cfg->num_bblocks), (cfg->num_bblocks), evaluation_area.blocks);
984 for (i = 0; i < cfg->num_bblocks; i++) {
985 analyze_block (cfg->bblocks [i], &evaluation_area);
988 for (i = 0; i < cfg->num_bblocks; i++) {
989 remove_abc_from_block (&(evaluation_area.blocks [i]), &evaluation_area);
992 mono_mempool_destroy (evaluation_area.pool);
996 static void remove_abc (MonoInst *inst) {
997 if (inst->opcode == CEE_LDELEMA) {
998 if (TRACE_ABC_REMOVAL||REPORT_ABC_REMOVAL) {
999 printf ("Performing removal...\n");
1001 inst->flags |= (MONO_INST_NORANGECHECK);
1004 if (mono_burg_arity [inst->opcode]) {
1005 remove_abc (inst->inst_left);
1006 if (mono_burg_arity [inst->opcode] > 1) {
1007 remove_abc (inst->inst_right);
1013 mono_perform_abc_removal (MonoCompile *cfg) {
1014 verbose_level = cfg->verbose_level;
1017 #if (TRACE_ABC_REMOVAL)
1018 printf ("Removing array bound checks in %s\n", mono_method_full_name (cfg->method, TRUE));
1021 for (i = 0; i < cfg->num_bblocks; i++) {
1022 #if (TRACE_ABC_REMOVAL)
1023 printf (" Working on block %d [dfn %d]\n", cfg->bblocks [i]->block_num, i);
1026 MonoBasicBlock *bb = cfg->bblocks [i];
1027 MonoInst *inst = bb->code;
1028 while (inst != NULL) {