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)])
53 static void print_relation(int relation){
56 if (relation & MONO_LT_RELATION){
60 if (relation & MONO_EQ_RELATION){
67 if (relation & MONO_GT_RELATION){
77 static void print_summarized_value(MonoSummarizedValue *value){
78 printf("relation_with_zero: ");
79 print_relation(value->relation_with_zero);
81 printf("relation_with_one: ");
82 print_relation(value->relation_with_one);
84 printf("relation_with_value: ");
85 print_relation(value->relation_with_value);
87 switch (value->value_type){
88 case MONO_CONSTANT_SUMMARIZED_VALUE:
89 printf("Constant value: %d\n", value->value.constant);
91 case MONO_VARIABLE_SUMMARIZED_VALUE:
92 printf("Variable value: %d\n", value->value.variable);
94 case MONO_PHI_SUMMARIZED_VALUE: {
96 printf("PHI value: (");
97 for (i = 0; i < *(value->value.phi_variables); i++){
99 printf("%d", *(value->value.phi_variables + i + 1));
105 printf("Unknown value type: %d\n", value->value_type);
109 static void print_branch_condition(MonoBranchCondition *condition, int n){
110 printf("Branch condition %d, on variable %d\n", n, condition->variable);
111 print_summarized_value(&(condition->value));
114 static void print_branch_data(MonoBranchData *branch, int n){
116 printf("Branch %d, destination BB %d [dfn %d], conditions %d\n",
117 n, branch->destination_block->block_num, branch->destination_block->dfn, branch->number_of_conditions);
118 for(i = 0; i < branch->number_of_conditions; i++){
119 print_branch_condition(&(branch->conditions [i]), i);
123 static void print_summarized_block(MonoSummarizedBasicBlock *block){
125 printf("Summarization of BB %d [dfn %d] (has array accesses: %d), branches: %d\n",
126 block->block->block_num, block->block->dfn, block->has_array_access_instructions, block->number_of_branches);
127 for(i = 0; i < block->number_of_branches; i++){
128 print_branch_data(&(block->branches [i]), i);
132 static void print_variable_relations(MonoVariableRelations *relations, gssize variable, int n){
134 int significantRelations = 0;
135 for (i = 0; i < n; i++){
136 if (relations->relations_with_variables [i] != MONO_ANY_RELATION){
137 significantRelations++;
140 if ((relations->relation_with_zero != MONO_ANY_RELATION) ||
141 (relations->relation_with_one != MONO_ANY_RELATION) ||
142 (significantRelations > 0)){
143 printf("Relations for variable %d:\n", variable);
144 if (relations->relation_with_zero != MONO_ANY_RELATION){
145 printf("relation_with_zero: ");
146 print_relation(relations->relation_with_zero);
149 if (relations->relation_with_one != MONO_ANY_RELATION){
150 printf("relation_with_one: ");
151 print_relation(relations->relation_with_one);
154 if (significantRelations > 0){
155 printf("relations_with_variables (%d significant)\n", significantRelations);
156 for (i = 0; i < n; i++){
157 if (relations->relations_with_variables [i] != MONO_ANY_RELATION){
158 printf("relation with variable %d: ", i);
159 print_relation(relations->relations_with_variables [i]);
167 static void print_all_variable_relations(MonoVariableRelationsEvaluationArea *evaluation_area){
169 printf("relations in evaluation area:\n");
170 for (i = 0; i < evaluation_area->cfg->num_varinfo; i++){
171 print_variable_relations(&(evaluation_area->variable_relations [i]), i, evaluation_area->cfg->num_varinfo);
176 static MonoValueRelation relation_for_sum_of_variable_and_constant(
177 MonoValueRelation variable_relation, MonoValueRelation constant_relation_with_zero){
178 switch (variable_relation){
179 case MONO_EQ_RELATION:
180 return constant_relation_with_zero;
181 case MONO_GE_RELATION:
182 if (constant_relation_with_zero & MONO_LT_RELATION){
183 return MONO_ANY_RELATION;
185 return constant_relation_with_zero;
187 case MONO_LE_RELATION:
188 if (constant_relation_with_zero & MONO_GT_RELATION){
189 return MONO_ANY_RELATION;
191 return constant_relation_with_zero;
193 case MONO_GT_RELATION:
194 if (constant_relation_with_zero & MONO_LT_RELATION){
195 return MONO_ANY_RELATION;
197 return MONO_GT_RELATION;
199 case MONO_LT_RELATION:
200 if (constant_relation_with_zero & MONO_GT_RELATION){
201 return MONO_ANY_RELATION;
203 return MONO_LE_RELATION;
206 g_assert_not_reached();
207 return MONO_ANY_RELATION;
211 static MonoInst *get_variable_value_from_ssa_store(MonoInst *store, int expected_variable_index)
213 switch (store->opcode){
222 if (TRACE_ABC_REMOVAL) {
223 printf("Store instruction found...\n");
225 if (store->inst_left->opcode == OP_LOCAL){
226 int variable_index = store->inst_left->inst_c0;
227 if (TRACE_ABC_REMOVAL) {
228 printf("Value put in local %d (expected %d)\n", variable_index, expected_variable_index);
230 if (variable_index == expected_variable_index)
232 return store->inst_right;
250 static void summarize_value(MonoInst *value, MonoSummarizedValue *result){
251 switch (value->opcode){
253 result->relation_with_zero = RELATION_BETWEEN_VALUES(value->inst_c0, 0);
254 result->relation_with_one = RELATION_BETWEEN_VALUES(abs(value->inst_c0), 1);
255 result->relation_with_value = MONO_EQ_RELATION;
256 result->value_type = MONO_CONSTANT_SUMMARIZED_VALUE;
257 result->value.constant = value->inst_c0;
262 result->relation_with_zero = MONO_ANY_RELATION;
263 result->relation_with_one = MONO_ANY_RELATION;
264 result->relation_with_value = MONO_EQ_RELATION;
265 result->value_type = MONO_VARIABLE_SUMMARIZED_VALUE;
266 result->value.variable = value->inst_c0;
270 if ((value->inst_left->opcode == OP_LOCAL) || (value->inst_left->opcode == OP_ARG)){
271 summarize_value(value->inst_left, result);
273 MAKE_VALUE_ANY(result);
277 case CEE_LDIND_REF: {
278 if ((value->inst_left->opcode == OP_LOCAL) || (value->inst_left->opcode == OP_ARG)){
279 summarize_value(value->inst_left, result);
281 MAKE_VALUE_ANY(result);
287 MonoSummarizedValue left_value;
288 MonoSummarizedValue right_value;
289 summarize_value(value->inst_left, &left_value);
290 summarize_value(value->inst_right, &right_value);
292 if (IS_SUMMARIZED_VALUE_VARIABLE(left_value)) {
293 if (IS_SUMMARIZED_VALUE_CONSTANT(right_value)&& (right_value.value.constant == 1)){
294 MonoValueRelation constant_relation_with_zero = right_value.relation_with_zero;
295 if (value->opcode == CEE_SUB) {
296 constant_relation_with_zero = MONO_SYMMETRIC_RELATION(constant_relation_with_zero);
298 result->relation_with_value = relation_for_sum_of_variable_and_constant(
299 left_value.relation_with_value, constant_relation_with_zero);
300 if (result->relation_with_value != MONO_ANY_RELATION){
301 result->relation_with_zero = MONO_ANY_RELATION;
302 result->relation_with_one = MONO_ANY_RELATION;
303 result->value_type = MONO_VARIABLE_SUMMARIZED_VALUE;
304 result->value.variable = left_value.value.variable;
306 MAKE_VALUE_ANY(result);
309 MAKE_VALUE_ANY(result);
311 } else if (IS_SUMMARIZED_VALUE_VARIABLE(right_value)) {
312 if (IS_SUMMARIZED_VALUE_CONSTANT(left_value)&& (left_value.value.constant == 1)){
313 MonoValueRelation constant_relation_with_zero = left_value.relation_with_zero;
314 if (value->opcode == CEE_SUB) {
315 constant_relation_with_zero = MONO_SYMMETRIC_RELATION(constant_relation_with_zero);
317 result->relation_with_value = relation_for_sum_of_variable_and_constant(
318 right_value.relation_with_value, constant_relation_with_zero);
319 if (result->relation_with_value != MONO_ANY_RELATION){
320 result->relation_with_zero = MONO_ANY_RELATION;
321 result->relation_with_one = MONO_ANY_RELATION;
322 result->value_type = MONO_VARIABLE_SUMMARIZED_VALUE;
323 result->value.variable = right_value.value.variable;
325 MAKE_VALUE_ANY(result);
328 MAKE_VALUE_ANY(result);
330 } else if (IS_SUMMARIZED_VALUE_CONSTANT(right_value)&& IS_SUMMARIZED_VALUE_CONSTANT(left_value)) {
331 /* This should not happen if constant folding has been done */
332 if (right_value.relation_with_value == MONO_EQ_RELATION && left_value.relation_with_value == MONO_EQ_RELATION){
334 if (value->opcode == CEE_ADD) {
335 constant = right_value.value.constant + left_value.value.constant;
338 constant = right_value.value.constant - left_value.value.constant;
340 result->relation_with_zero = RELATION_BETWEEN_VALUES(constant, 0);
341 result->relation_with_one = RELATION_BETWEEN_VALUES(abs(constant), 1);
342 result->relation_with_value = MONO_EQ_RELATION;
343 result->value_type = MONO_CONSTANT_SUMMARIZED_VALUE;
344 result->value.constant = constant;
346 MAKE_VALUE_ANY(result);
349 MAKE_VALUE_ANY(result);
354 summarize_value(value->inst_newa_len, result);
358 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;
370 MAKE_VALUE_ANY(result);
375 static MonoValueRelation get_relation_from_branch_instruction(int opcode){
378 return MONO_EQ_RELATION;
381 return MONO_LT_RELATION;
384 return MONO_LE_RELATION;
387 return MONO_GT_RELATION;
390 return MONO_GE_RELATION;
392 return MONO_NE_RELATION;
394 g_assert_not_reached();
395 return MONO_ANY_RELATION;
399 static int 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);
415 static void analyze_block(MonoBasicBlock *bb, MonoVariableRelationsEvaluationArea *evaluation_area){
416 MonoSummarizedBasicBlock *b = &(evaluation_area->blocks [bb->dfn]);
417 MonoInst *current_inst = bb->code;
418 MonoInst *last_inst = NULL;
421 if (TRACE_ABC_REMOVAL) {
422 printf("Analyzing block %d [dfn %d]\n", bb->block_num, bb->dfn);
425 g_assert(bb->dfn < evaluation_area->cfg->num_bblocks);
426 b->has_array_access_instructions = 0;
429 while (current_inst != NULL){
430 if (TRACE_ABC_REMOVAL) {
431 printf("Analyzing instruction %d\n", inst_index);
435 if (contains_array_access(current_inst)) {
436 b->has_array_access_instructions = 1;
439 if (current_inst->next == NULL){
440 last_inst = current_inst;
442 current_inst = current_inst->next;
445 if (last_inst != NULL){
446 switch (last_inst->opcode){
457 if (last_inst->inst_left->opcode == OP_COMPARE){
458 int number_of_variables;
459 int current_variable;
461 MonoSummarizedValue left_value;
462 MonoSummarizedValue right_value;
463 MonoValueRelation relation = get_relation_from_branch_instruction(last_inst->opcode);
464 MonoValueRelation symmetric_relation = MONO_SYMMETRIC_RELATION(relation);
465 summarize_value(last_inst->inst_left->inst_left, &left_value);
466 summarize_value(last_inst->inst_left->inst_right, &right_value);
467 number_of_variables = 0;
468 current_variable = 0;
469 /* It is actually possible to handle some more case... */
470 if ((left_value.relation_with_value == MONO_EQ_RELATION) &&
471 (right_value.relation_with_value == MONO_EQ_RELATION)){
472 if (left_value.value_type == MONO_VARIABLE_SUMMARIZED_VALUE)number_of_variables++;
473 if (right_value.value_type == MONO_VARIABLE_SUMMARIZED_VALUE)number_of_variables++;
474 if (number_of_variables > 0){
475 MonoBranchData *branch_true;
476 MonoBranchData *branch_false;
478 b->number_of_branches = 2;
479 b->branches = (MonoBranchData*) mono_mempool_alloc(
480 evaluation_area->pool, sizeof(MonoBranchData) * 2);
481 branch_true = &(b->branches [0]);
482 branch_true->destination_block = last_inst->inst_true_bb;
483 branch_true->number_of_conditions = number_of_variables;
484 branch_true->conditions = (MonoBranchCondition*)
485 mono_mempool_alloc(evaluation_area->pool, sizeof(MonoBranchCondition) * number_of_variables);
486 branch_false = &(b->branches [1]);
487 branch_false->destination_block = last_inst->inst_false_bb;
488 branch_false->number_of_conditions = number_of_variables;
489 branch_false->conditions = (MonoBranchCondition*)
490 mono_mempool_alloc(evaluation_area->pool, sizeof(MonoBranchCondition) * number_of_variables);
491 if (left_value.value_type == MONO_VARIABLE_SUMMARIZED_VALUE){
492 MonoBranchCondition *condition_true = &(branch_true->conditions [current_variable]);
493 MonoBranchCondition *condition_false;
495 condition_true->variable = left_value.value.variable;
496 condition_true->value = right_value;
497 condition_true->value.relation_with_zero = MONO_ANY_RELATION;
498 condition_true->value.relation_with_one = MONO_ANY_RELATION;
499 condition_true->value.relation_with_value = relation;
500 condition_false = &(branch_false->conditions [current_variable]);
501 condition_false->variable = left_value.value.variable;
502 condition_false->value = right_value;
503 condition_false->value.relation_with_zero = MONO_ANY_RELATION;
504 condition_false->value.relation_with_one = MONO_ANY_RELATION;
505 condition_false->value.relation_with_value = MONO_NEGATED_RELATION(relation);
508 if (right_value.value_type == MONO_VARIABLE_SUMMARIZED_VALUE){
509 MonoBranchCondition *condition_true = &(branch_true->conditions [current_variable]);
510 MonoBranchCondition *condition_false;
512 condition_true->variable = right_value.value.variable;
513 condition_true->value = left_value;
514 condition_true->value.relation_with_zero = MONO_ANY_RELATION;
515 condition_true->value.relation_with_one = MONO_ANY_RELATION;
516 condition_true->value.relation_with_value = symmetric_relation;
517 condition_false = &(branch_false->conditions [current_variable]);
518 condition_false->variable = right_value.value.variable;
519 condition_false->value = left_value;
520 condition_false->value.relation_with_zero = MONO_ANY_RELATION;
521 condition_false->value.relation_with_one = MONO_ANY_RELATION;
522 condition_false->value.relation_with_value = MONO_NEGATED_RELATION(symmetric_relation);
526 b->number_of_branches = 0;
530 b->number_of_branches = 0;
534 b->number_of_branches = 0;
540 /* Should handle switches... */
541 /* switch_operand = last_inst->inst_right; */
542 /* number_of_cases = GPOINTER_TO_INT (last_inst->klass); */
543 /* cases = last_inst->inst_many_bb; */
544 b->number_of_branches = 0;
548 b->number_of_branches = 0;
552 b->number_of_branches = 0;
556 if (TRACE_ABC_REMOVAL) {
557 print_summarized_block(b);
561 #define SET_VARIABLE_RELATIONS(vr, relation, n)do {\
562 (vr)->relation_with_zero = (relation);\
563 (vr)->relation_with_one = (relation);\
564 memset((vr)->relations_with_variables,(relation),(n));\
567 #define COMBINE_VARIABLE_RELATIONS(operator, vr, related_vr, n)do {\
569 operator((vr)->relation_with_zero, (related_vr)->relation_with_zero);\
570 operator((vr)->relation_with_one, (related_vr)->relation_with_one);\
571 for (i = 0; i < (n); i++){\
572 operator((vr)->relations_with_variables [i], (related_vr)->relations_with_variables [i]);\
576 #define RELATION_ASSIGNMENT(destination,source) (destination)=(source)
577 #define RELATION_UNION(destination,source) (destination)|=(source)
578 #define RELATION_INTERSECTION(destination,source) (destination)&=(source)
582 static void evaluate_variable_relations(gssize variable, MonoVariableRelationsEvaluationArea *evaluation_area, MonoRelationsEvaluationContext *father_context){
583 MonoVariableRelations *relations;
584 MonoRelationsEvaluationContext context;
586 if (TRACE_ABC_REMOVAL) {
587 printf("Applying definition of variable %d\n", variable);
589 relations = &(evaluation_area->variable_relations [variable]);
590 context.father_context = father_context;
591 context.variable = variable;
592 switch (relations->evaluation_step) {
593 case MONO_RELATIONS_EVALUATION_NOT_STARTED: {
594 MonoSummarizedValue *value = &(evaluation_area->variable_definitions [variable]);
595 relations->evaluation_step = MONO_RELATIONS_EVALUATION_IN_PROGRESS;
596 if (TRACE_ABC_REMOVAL) {
597 printf("Current step is MONO_RELATIONS_EVALUATION_NOT_STARTED, summarized value is:\n");
598 print_summarized_value(value);
600 switch (value->value_type){
601 case MONO_CONSTANT_SUMMARIZED_VALUE: {
602 if (value->relation_with_value == MONO_EQ_RELATION){
603 relations->relation_with_zero &= RELATION_BETWEEN_VALUES(value->value.constant, 0);
604 relations->relation_with_one &= RELATION_BETWEEN_VALUES(abs(value->value.constant), 1);
606 /* Other cases should not happen... */
609 case MONO_VARIABLE_SUMMARIZED_VALUE: {
610 gssize related_variable = value->value.variable;
611 relations->relations_with_variables [related_variable] = value->relation_with_value;
612 evaluate_variable_relations(related_variable, evaluation_area, &context);
613 if (value->relation_with_value == MONO_EQ_RELATION){
614 COMBINE_VARIABLE_RELATIONS(RELATION_INTERSECTION, relations,
615 &(evaluation_area->variable_relations [related_variable]), evaluation_area->cfg->num_varinfo);
617 /* Other cases should be handled... */
620 case MONO_PHI_SUMMARIZED_VALUE: {
621 if (value->relation_with_value == MONO_EQ_RELATION){
623 MonoVariableRelations *phi_union = (MonoVariableRelations*) alloca(sizeof(MonoVariableRelations));
624 phi_union->relations_with_variables = (unsigned char*) alloca(evaluation_area->cfg->num_varinfo);
625 SET_VARIABLE_RELATIONS(phi_union, MONO_NO_RELATION, evaluation_area->cfg->num_varinfo);
626 for (phi = 0; phi < *(value->value.phi_variables); phi++){
627 gssize related_variable = value->value.phi_variables [phi+1];
628 evaluate_variable_relations(related_variable, evaluation_area, &context);
629 COMBINE_VARIABLE_RELATIONS(RELATION_UNION, phi_union,
630 &(evaluation_area->variable_relations [related_variable]), evaluation_area->cfg->num_varinfo);
632 if (TRACE_ABC_REMOVAL) {
633 printf("Resulting phi_union is:\n");
634 print_variable_relations(phi_union, variable, evaluation_area->cfg->num_varinfo);
636 COMBINE_VARIABLE_RELATIONS(RELATION_INTERSECTION, relations,
637 phi_union, evaluation_area->cfg->num_varinfo);
639 /* Other cases should not happen... */
643 g_assert_not_reached();
648 case MONO_RELATIONS_EVALUATION_IN_PROGRESS: {
649 MonoVariableRelations *recursive_value_relations = NULL;
650 unsigned char recursive_relation = MONO_ANY_RELATION;
651 MonoRelationsEvaluationContext *current_context = context.father_context;
653 if (TRACE_ABC_REMOVAL) {
654 printf("Current step is MONO_RELATIONS_EVALUATION_IN_PROGRESS\n");
656 relations->definition_is_recursive = 1;
657 while (current_context != NULL && current_context->variable != variable){
658 MonoVariableRelations *context_relations = &(evaluation_area->variable_relations [current_context->variable]);
659 MonoSummarizedValue *context_value = &(evaluation_area->variable_definitions [current_context->variable]);
660 if (TRACE_ABC_REMOVAL) {
661 printf("Backtracing to context %d\n", current_context->variable);
663 if (recursive_value_relations == NULL){
664 if (context_value->relation_with_value != MONO_EQ_RELATION){
665 recursive_value_relations = context_relations;
666 recursive_relation = context_value->relation_with_value;
667 if (TRACE_ABC_REMOVAL) {
668 printf("Accepted recursive definition, relation is ");
669 print_relation(recursive_relation);
674 if (context_value->relation_with_value != MONO_EQ_RELATION){
675 recursive_relation = MONO_NO_RELATION;
676 if (TRACE_ABC_REMOVAL) {
677 printf("Rejected recursive definition, bad relation is ");
678 print_relation(context_value->relation_with_value);
683 current_context = current_context->father_context;
685 if (recursive_value_relations != NULL && recursive_relation != MONO_NO_RELATION){
687 /* This should handle "grows" and "decreases" cases */
688 recursive_value_relations->relation_with_zero &= recursive_relation;
689 for (i = 0; i < evaluation_area->cfg->num_varinfo; i++){
690 recursive_value_relations->relations_with_variables [i] &= recursive_relation;
695 case MONO_RELATIONS_EVALUATION_COMPLETED: {
696 if (TRACE_ABC_REMOVAL) {
697 printf("Current step is MONO_RELATIONS_EVALUATION_COMPLETED\n");
702 g_assert_not_reached();
706 relations->evaluation_step = MONO_RELATIONS_EVALUATION_COMPLETED;
709 static int propagate_relations(MonoVariableRelationsEvaluationArea *evaluation_area){
712 for (variable = 0; variable < evaluation_area->cfg->num_varinfo; variable++){
713 MonoVariableRelations *relations = &(evaluation_area->variable_relations [variable]);
714 gssize related_variable;
715 for (related_variable = 0; related_variable < evaluation_area->cfg->num_varinfo; related_variable++){
716 unsigned char relation_with_variable = relations->relations_with_variables [related_variable];
717 if (relation_with_variable != MONO_ANY_RELATION){
718 MonoVariableRelations *related_relations = &(evaluation_area->variable_relations [related_variable]);
719 gssize variable_related_to_related_variable;
720 unsigned char new_relation_with_zero = PROPAGATED_RELATION(relation_with_variable, related_relations->relation_with_zero);
721 if (RELATION_ADDS_INFORMATION(relations->relation_with_zero, new_relation_with_zero)) {
722 if (TRACE_ABC_REMOVAL) {
723 printf("RELATION_ADDS_INFORMATION variable %d, related_variable %d, relation_with_zero ",
724 variable, related_variable);
725 print_relation(relations->relation_with_zero);
727 print_relation(new_relation_with_zero);
730 relations->relation_with_zero &= new_relation_with_zero;
731 if (TRACE_ABC_REMOVAL) {
732 print_relation(relations->relation_with_zero);
737 for (variable_related_to_related_variable = 0; variable_related_to_related_variable < evaluation_area->cfg->num_varinfo; variable_related_to_related_variable++){
738 unsigned char relation_of_variable = related_relations->relations_with_variables [variable_related_to_related_variable];
739 unsigned char relation_with_other_variable = relations->relations_with_variables [variable_related_to_related_variable];
740 unsigned char new_relation_with_other_variable = PROPAGATED_RELATION(relation_with_variable, relation_of_variable);
741 if (RELATION_ADDS_INFORMATION(relation_with_other_variable, new_relation_with_other_variable)) {
742 if (TRACE_ABC_REMOVAL) {
743 printf("RELATION_ADDS_INFORMATION variable %d, related_variable %d, variable_related_to_related_variable %d, ",
744 variable, related_variable, variable_related_to_related_variable);
745 print_relation(relation_with_variable);
747 print_relation(new_relation_with_other_variable);
750 relations->relations_with_variables [variable_related_to_related_variable] &= new_relation_with_other_variable;
751 if (TRACE_ABC_REMOVAL) {
752 print_relation(relations->relations_with_variables [variable_related_to_related_variable]);
764 static void remove_abc_from_inst(MonoInst *inst, MonoVariableRelationsEvaluationArea *evaluation_area){
765 if (inst->opcode == CEE_LDELEMA){
766 MonoInst *array_inst = inst->inst_left;
767 MonoInst *index_inst = inst->inst_right;
768 /* Both the array and the index must be local variables */
769 if ((array_inst->opcode == CEE_LDIND_REF) &&
770 ((array_inst->inst_left->opcode == OP_LOCAL)||(array_inst->inst_left->opcode == OP_ARG)) &&
771 ((index_inst->opcode == CEE_LDIND_I1) ||
772 (index_inst->opcode == CEE_LDIND_U1) ||
773 (index_inst->opcode == CEE_LDIND_I2) ||
774 (index_inst->opcode == CEE_LDIND_U2) ||
775 (index_inst->opcode == CEE_LDIND_I4) ||
776 (index_inst->opcode == CEE_LDIND_U4))&&
777 ((index_inst->inst_left->opcode == OP_LOCAL)||(index_inst->inst_left->opcode == OP_ARG))){
778 gssize array_variable = array_inst->inst_left->inst_c0;
779 gssize index_variable = index_inst->inst_left->inst_c0;
780 MonoVariableRelations *index_relations = &(evaluation_area->variable_relations [index_variable]);
781 if ( (! (index_relations->relation_with_zero & ~MONO_GE_RELATION)) &&
782 (! (index_relations->relations_with_variables [array_variable] & ~MONO_LT_RELATION)) ) {
783 inst->flags |= (MONO_INST_NORANGECHECK);
785 if (TRACE_ABC_REMOVAL) {
786 if (! (index_relations->relation_with_zero & ~MONO_GE_RELATION)){
787 printf ("ARRAY-ACCESS: Removed lower bound check on array %d with index %d\n", array_variable, index_variable);
790 printf ("ARRAY-ACCESS: Left lower bound check on array %d with index %d\n", array_variable, index_variable);
792 if (! (index_relations->relations_with_variables [array_variable] & ~MONO_LT_RELATION)){
793 printf ("ARRAY-ACCESS: Removed upper bound check on array %d with index %d\n", array_variable, index_variable);
796 printf ("ARRAY-ACCESS: Left upper bound check on array %d with index %d\n", array_variable, index_variable);
799 if (REPORT_ABC_REMOVAL) {
800 if (inst->flags & (MONO_INST_NORANGECHECK)){
801 printf ("ARRAY-ACCESS: removed bounds check on array %d with index %d in method %s\n",
802 array_variable, index_variable, mono_method_full_name(evaluation_area->cfg->method, TRUE));
808 if (mono_burg_arity [inst->opcode]){
809 remove_abc_from_inst(inst->inst_left, evaluation_area);
810 if (mono_burg_arity [inst->opcode] > 1){
811 remove_abc_from_inst(inst->inst_right, evaluation_area);
816 static void remove_abc_from_block(MonoSummarizedBasicBlock *b, MonoVariableRelationsEvaluationArea *evaluation_area){
820 MonoInst *current_inst = b->block->code;
822 if (TRACE_ABC_REMOVAL) {
823 printf("Working on block %d [dfn %d], has_array_access_instructions is %d\n",
824 b->block->block_num, b->block->dfn, b->has_array_access_instructions);
827 if (b->has_array_access_instructions){
828 for (i = 0; i < evaluation_area->cfg->num_varinfo; i++){
829 evaluation_area->variable_relations [i].evaluation_step = MONO_RELATIONS_EVALUATION_NOT_STARTED;
830 evaluation_area->variable_relations [i].definition_is_recursive = 0;
831 SET_VARIABLE_RELATIONS(&(evaluation_area->variable_relations [i]), MONO_ANY_RELATION, evaluation_area->cfg->num_varinfo);
836 /* Walk up dominators tree to put conditions in area */
838 /* for (in_index = 0; in_index < bb->in_count; in_index++){ */
839 if (bb->in_count == 1){ /* Should write the code to "sum" conditions... */
841 MonoBasicBlock *in_bb = bb->in_bb [in_index];
842 MonoSummarizedBasicBlock *in_b = &(evaluation_area->blocks [in_bb->dfn]);
843 for (out_index = 0; out_index < in_b->number_of_branches; out_index++){
844 if (in_b->branches [out_index].destination_block == bb){
845 MonoBranchData *branch;
848 if (TRACE_ABC_REMOVAL) {
849 printf("Applying conditions of branch %d -> %d\n", in_b->block->block_num, bb->block_num);
851 branch = &(in_b->branches [out_index]);
852 for (condition_index = 0; condition_index < branch->number_of_conditions; condition_index++) {
853 MonoBranchCondition *condition = &(branch->conditions [condition_index]);
854 MonoVariableRelations *relations = &(evaluation_area->variable_relations [condition->variable]);
855 switch (condition->value.value_type){
856 case MONO_CONSTANT_SUMMARIZED_VALUE: {
857 if (condition->value.relation_with_value == MONO_EQ_RELATION){
858 relations->relation_with_zero &= RELATION_BETWEEN_VALUES(condition->value.value.constant, 0);
859 relations->relation_with_one &= RELATION_BETWEEN_VALUES(abs(condition->value.value.constant), 1);
860 if (TRACE_ABC_REMOVAL) {
861 printf("Applied equality condition with constant to variable %d; relatrion with 0: ", condition->variable);
862 print_relation(relations->relation_with_zero);
865 } else if (condition->value.value.constant == 0){
866 relations->relation_with_zero &= condition->value.relation_with_value;
867 if (TRACE_ABC_REMOVAL) {
868 printf("Applied relation with 0 to variable %d: ", condition->variable);
869 print_relation(relations->relation_with_zero);
873 /* Other cases should be handled */
876 case MONO_VARIABLE_SUMMARIZED_VALUE: {
877 relations->relations_with_variables [condition->value.value.variable] &= condition->value.relation_with_value;
878 if (TRACE_ABC_REMOVAL) {
879 printf("Applied relation between variables %d and %d: ", condition->variable, condition->value.value.variable);
880 print_relation(relations->relations_with_variables [condition->value.value.variable]);
886 g_assert_not_reached(); /* PHIs are not OK here */
895 if (TRACE_ABC_REMOVAL) {
896 printf("Branch conditions applied... ");
897 print_all_variable_relations(evaluation_area);
900 for (i = 0; i < evaluation_area->cfg->num_varinfo; i++){
901 evaluate_variable_relations(i, evaluation_area, NULL);
904 if (TRACE_ABC_REMOVAL) {
905 printf("Variable definitions applied... ");
906 print_all_variable_relations(evaluation_area);
911 changes = propagate_relations(evaluation_area);
913 if (TRACE_ABC_REMOVAL) {
914 printf("Propagated %d changes\n", changes);
916 } while ((changes > 0) && (i < evaluation_area->cfg->num_varinfo));
918 if (TRACE_ABC_REMOVAL) {
919 printf("Relations fully propagated... ");
920 print_all_variable_relations(evaluation_area);
923 /* Area is ready, look for array access instructions */
924 if (TRACE_ABC_REMOVAL) {
925 printf("Going after array accesses...\n");
927 while (current_inst != NULL){
928 remove_abc_from_inst(current_inst, evaluation_area);
929 current_inst = current_inst->next;
935 mono_perform_abc_removal (MonoCompile *cfg)
937 MonoVariableRelationsEvaluationArea evaluation_area;
939 verbose_level = cfg->verbose_level;
942 if (TRACE_ABC_REMOVAL) {
943 printf("Removing array bound checks in %s\n", mono_method_full_name (cfg->method, TRUE));
946 if (cfg->num_varinfo > 250) {
947 if (TRACE_ABC_REMOVAL) {
948 printf("Too many variables (%d), giving up...\n", cfg->num_varinfo);
953 evaluation_area.pool = mono_mempool_new();
954 evaluation_area.cfg = cfg;
955 evaluation_area.variable_relations = (MonoVariableRelations *)
956 mono_mempool_alloc(evaluation_area.pool, sizeof(MonoVariableRelations) * (cfg->num_varinfo));
957 //printf("Allocated %d bytes for %d variable relations at pointer %p\n",
958 // sizeof(MonoVariableRelations) * (cfg->num_varinfo), (cfg->num_varinfo), evaluation_area.variable_relations);
959 for (i = 0; i < cfg->num_varinfo; i++){
960 evaluation_area.variable_relations [i].relations_with_variables = (unsigned char *)
961 mono_mempool_alloc(evaluation_area.pool, (cfg->num_varinfo));
962 //printf("Allocated %d bytes [%d] at pointer %p\n",
963 // cfg->num_varinfo, i, evaluation_area.variable_relations [i].relations_with_variables);
965 evaluation_area.variable_definitions = (MonoSummarizedValue *)
966 mono_mempool_alloc(evaluation_area.pool, sizeof(MonoSummarizedValue) * (cfg->num_varinfo));
967 //printf("Allocated %d bytes for %d variable definitions at pointer %p\n",
968 // sizeof(MonoSummarizedValue) * (cfg->num_varinfo), (cfg->num_varinfo), evaluation_area.variable_definitions);
969 if (TRACE_ABC_REMOVAL) {
970 printf("Method contains %d variables\n", i);
972 for (i = 0; i < cfg->num_varinfo; i++){
973 if (cfg->vars [i]->def != NULL)
975 MonoInst *value = get_variable_value_from_ssa_store(cfg->vars [i]->def, i);
978 summarize_value(value, evaluation_area.variable_definitions + i);
979 if (TRACE_ABC_REMOVAL) {
980 printf("Summarized variable %d\n", i);
981 print_summarized_value(evaluation_area.variable_definitions + i);
986 MAKE_VALUE_ANY(evaluation_area.variable_definitions + i);
987 if (TRACE_ABC_REMOVAL) {
988 printf("Definition of variable %d is not a proper store\n", i);
994 MAKE_VALUE_ANY(evaluation_area.variable_definitions + i);
995 if (TRACE_ABC_REMOVAL) {
996 printf("Variable %d has no definition, probably it is an argument\n", i);
997 print_summarized_value(evaluation_area.variable_definitions + i);
1002 evaluation_area.blocks = (MonoSummarizedBasicBlock *)
1003 mono_mempool_alloc(evaluation_area.pool, sizeof(MonoSummarizedBasicBlock) * (cfg->num_bblocks));
1004 //printf("Allocated %d bytes for %d blocks at pointer %p\n",
1005 // sizeof(MonoSummarizedBasicBlock) * (cfg->num_bblocks), (cfg->num_bblocks), evaluation_area.blocks);
1007 for (i = 0; i < cfg->num_bblocks; i++){
1008 analyze_block(cfg->bblocks [i], &evaluation_area);
1011 for (i = 0; i < cfg->num_bblocks; i++){
1012 remove_abc_from_block(&(evaluation_area.blocks [i]), &evaluation_area);
1015 mono_mempool_destroy(evaluation_area.pool);
1019 static void remove_abc(MonoInst *inst){
1020 if (inst->opcode == CEE_LDELEMA){
1021 if (TRACE_ABC_REMOVAL||REPORT_ABC_REMOVAL) {
1022 printf("Performing removal...\n");
1024 inst->flags |= (MONO_INST_NORANGECHECK);
1027 if (mono_burg_arity [inst->opcode]){
1028 remove_abc(inst->inst_left);
1029 if (mono_burg_arity [inst->opcode] > 1){
1030 remove_abc(inst->inst_right);
1036 mono_perform_abc_removal (MonoCompile *cfg) {
1037 verbose_level = cfg->verbose_level;
1040 #if (TRACE_ABC_REMOVAL)
1041 printf("Removing array bound checks in %s\n", mono_method_full_name (cfg->method, TRUE));
1044 for (i = 0; i < cfg->num_bblocks; i++){
1045 #if (TRACE_ABC_REMOVAL)
1046 printf(" Working on block %d [dfn %d]\n", cfg->bblocks [i]->block_num, i);
1049 MonoBasicBlock *bb = cfg->bblocks [i];
1050 MonoInst *inst = bb->code;
1051 while (inst != NULL){