Author: zoltan
Date: 2007-11-21 11:52:58 -0500 (Wed, 21 Nov 2007)
New Revision: 90092

Modified:
   branches/vargaz/mini-linear-il/mono/mono/mini/ChangeLog
   branches/vargaz/mini-linear-il/mono/mono/mini/basic.cs
   branches/vargaz/mini-linear-il/mono/mono/mini/local-propagation.c
   branches/vargaz/mini-linear-il/mono/mono/mini/mini-codegen.c
   branches/vargaz/mini-linear-il/mono/mono/mini/mini.c
   branches/vargaz/mini-linear-il/mono/mono/mini/mini.h
Log:
2007-11-21  Zoltan Varga  <[EMAIL PROTECTED]>

        * local-propagation.c (mono_branch_to_cmov): Implement another form
        of branch->cmov conversion.

        * mini.c (mini_method_compile): Reorder order of optimizations a bit.

        * mini.c: Export some bblock related functions.

        * basic.cs: Add more branch->cmov tests.


Modified: branches/vargaz/mini-linear-il/mono/mono/mini/ChangeLog
===================================================================
--- branches/vargaz/mini-linear-il/mono/mono/mini/ChangeLog     2007-11-21 
16:25:26 UTC (rev 90091)
+++ branches/vargaz/mini-linear-il/mono/mono/mini/ChangeLog     2007-11-21 
16:52:58 UTC (rev 90092)
@@ -1,5 +1,14 @@
 2007-11-21  Zoltan Varga  <[EMAIL PROTECTED]>
 
+       * local-propagation.c (mono_branch_to_cmov): Implement another form
+       of branch->cmov conversion.
+
+       * mini.c (mini_method_compile): Reorder order of optimizations a bit.
+
+       * mini.c: Export some bblock related functions.
+
+       * basic.cs: Add more branch->cmov tests.
+
        * mini-ops.h: Add CMOV opcodes.
 
        * cpu-amd64.md mini-amd64.c: Implement CMOV opcodes.

Modified: branches/vargaz/mini-linear-il/mono/mono/mini/basic.cs
===================================================================
--- branches/vargaz/mini-linear-il/mono/mono/mini/basic.cs      2007-11-21 
16:25:26 UTC (rev 90091)
+++ branches/vargaz/mini-linear-il/mono/mono/mini/basic.cs      2007-11-21 
16:52:58 UTC (rev 90092)
@@ -1274,4 +1274,36 @@
 
                return 0;
        }
+
+       public static int cmov (int i) {
+               int j = 0;
+
+               if (i > 0)
+                       j = 1;
+
+               return j;
+       }
+
+       public static int cmov2 (int i) {
+               int j = 0;
+
+               if (i <= 0)
+                       ;
+               else
+                       j = 1;
+
+               return j;
+       }
+               
+       public static int test_0_branch_to_cmov_opt () {
+               if (cmov (0) != 0)
+                       return 1;
+               if (cmov (1) != 1)
+                       return 2;
+               if (cmov2 (0) != 0)
+                       return 1;
+               if (cmov2 (1) != 1)
+                       return 2;
+               return 0;
+       }
 }

Modified: branches/vargaz/mini-linear-il/mono/mono/mini/local-propagation.c
===================================================================
--- branches/vargaz/mini-linear-il/mono/mono/mini/local-propagation.c   
2007-11-21 16:25:26 UTC (rev 90091)
+++ branches/vargaz/mini-linear-il/mono/mono/mini/local-propagation.c   
2007-11-21 16:52:58 UTC (rev 90092)
@@ -1763,7 +1763,8 @@
 
        /* 
         * This pass requires somewhat optimized IR code so it should be run 
after
-        * local cprop/deadce.
+        * local cprop/deadce. Also, it should be run before dominator 
computation, since
+        * it changes control flow.
         */
        for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
                MonoBasicBlock *bb1, *bb2;
@@ -1931,17 +1932,163 @@
                        mono_unlink_bblock (cfg, bb, bb2);
                        mono_unlink_bblock (cfg, bb1, bb1->out_bb [0]);
                        mono_unlink_bblock (cfg, bb2, bb2->out_bb [0]);
+                       mono_remove_bblock (cfg, bb1);
+                       mono_remove_bblock (cfg, bb2);
 
-                       /* Merge bb1 and its successor if possible */
+                       /* Merge bb and its successor if possible */
                        if ((bb->out_bb [0]->in_count == 1) && (bb->out_bb [0] 
!= cfg->bb_exit) &&
                                (bb->region == bb->out_bb [0]->region)) {
                                // FIXME:
-                               //mono_merge_basic_blocks (bb, bb->out_bb [0]);
+                               mono_merge_basic_blocks (bb, bb->out_bb [0]);
                        }
                }
+
+               /* Look for the IR code generated from if (cond) <var> <- <a>
+                * which is:
+                * BB:
+                * b<cond> [BB1BB2]
+                * BB1:
+                * <var> <- <a>
+                * br BB2
+                */
+
+               if ((bb2->in_count == 1 && bb2->out_count == 1 && bb2->out_bb 
[0] == bb1) ||
+                       (bb1->in_count == 1 && bb1->out_count == 1 && 
bb1->out_bb [0] == bb2)) {
+                       MonoInst *prev, *compare, *branch, *ins1, *cmov, *tmp;
+                       gboolean simple;
+                       int dreg, tmp_reg;
+                       CompType comp_type;
+                       CompRelation cond;
+                       MonoBasicBlock *next_bb, *code_bb;
+
+                       /* code_bb is the bblock containing code, next_bb is 
the successor bblock */
+                       if (bb2->in_count == 1 && bb2->out_count == 1 && 
bb2->out_bb [0] == bb1) {
+                               code_bb = bb2;
+                               next_bb = bb1;
+                       } else {
+                               code_bb = bb1;
+                               next_bb = bb2;
+                       }
+
+                       ins1 = code_bb->code;
+
+                       /* Check that code_bb is simple */
+                       simple = TRUE;
+                       for (tmp = ins1->next; tmp; tmp = tmp->next)
+                               if (!((tmp->opcode == OP_NOP) || (tmp->opcode 
== OP_BR)))
+                                       simple = FALSE;
+
+                       if (!simple)
+                               continue;
+
+                       /* We move ins1 before the compare so it should have no 
side effect */
+                       if (!INS_HAS_NO_SIDE_EFFECT (ins1))
+                               continue;
+
+                       if (bb->last_ins && bb->last_ins->opcode == OP_BR_REG)
+                               continue;
+
+                       /* Find the compare instruction */
+                       prev = NULL;
+                       compare = bb->code;
+                       g_assert (compare);
+                       while (compare->next && !MONO_IS_COND_BRANCH_OP 
(compare->next)) {
+                               prev = compare;
+                               compare = compare->next;
+                       }
+                       g_assert (compare->next && MONO_IS_COND_BRANCH_OP 
(compare->next));
+                       branch = compare->next;
+
+                       /* Moving ins1 could change the comparison */
+                       /* FIXME: */
+                       if (!((compare->sreg1 != ins1->dreg) && (compare->sreg2 
!= ins1->dreg)))
+                               continue;
+
+                       /* FIXME: */
+                       comp_type = mono_opcode_to_type (branch->opcode, 
compare->opcode);
+                       if (!((comp_type == CMP_TYPE_I) || (comp_type == 
CMP_TYPE_L)))
+                               continue;
+
+                       /* FIXME: */
+                       /* ins->type might not be set */
+                       if (INS_INFO (ins1->opcode) [MONO_INST_DEST] != 'i')
+                               continue;
+
+                       /* FIXME: */
+                       if (cfg->ret && ins1->dreg == cfg->ret->dreg)
+                               continue;
+
+                       if (cfg->verbose_level > 2) {
+                               printf ("\tBranch -> CMove optimization (2) in 
BB%d on\n", bb->block_num);
+                               printf ("\t\t"); mono_print_ins (compare);
+                               printf ("\t\t"); mono_print_ins (compare->next);
+                               printf ("\t\t"); mono_print_ins (ins1);
+                       }
+
+                       changed = TRUE;
+
+                       //printf ("HIT!\n");
+
+                       tmp_reg = mono_alloc_dreg (cfg, STACK_I4);
+                       dreg = ins1->dreg;
+
+                       /* Rewrite ins1 to emit to tmp_reg */
+                       ins1->dreg = tmp_reg;
+
+                       /* Remove ins1 from code_bb */
+                       code_bb->code = code_bb->last_ins = NULL;
+
+                       /* Move ins1 before the comparison */
+                       /* FIXME: Move this to a helper function */
+                       if (prev == NULL) {
+                               bb->code = ins1;
+                       } else {
+                               prev->next = ins1;
+                       }
+                       ins1->next = compare;
+
+                       /* Add cmov instruction */
+                       MONO_INST_NEW (cfg, cmov, OP_NOP);
+                       cmov->dreg = dreg;
+                       cmov->sreg1 = dreg;
+                       cmov->sreg2 = tmp_reg;
+                       cond = mono_opcode_to_cond (branch->opcode);
+                       if (code_bb == bb2)
+                               cond = mono_negate_cond (cond);
+                       switch (mono_opcode_to_type (branch->opcode, 
compare->opcode)) {
+                       case CMP_TYPE_I:
+                               cmov->opcode = int_cmov_opcodes [cond];
+                               break;
+                       case CMP_TYPE_L:
+                               cmov->opcode = long_cmov_opcodes [cond];
+                               break;
+                       default:
+                               g_assert_not_reached ();
+                       }
+                       compare->next = cmov;
+                       cmov->next = branch;
+
+                       /* Rewrite the branch */
+                       branch->opcode = OP_BR;
+                       branch->inst_target_bb = next_bb;
+                       mono_link_bblock (cfg, bb, branch->inst_target_bb);
+
+                       /* Reorder bblocks */
+                       mono_unlink_bblock (cfg, bb, code_bb);
+                       mono_unlink_bblock (cfg, code_bb, next_bb);
+
+                       /* Merge bb and its successor if possible */
+                       if ((bb->out_bb [0]->in_count == 1) && (bb->out_bb [0] 
!= cfg->bb_exit) &&
+                               (bb->region == bb->out_bb [0]->region)) {
+                               mono_merge_basic_blocks (bb, bb->out_bb [0]);
+                       }
+               }
        }
 
-       if (changed)
+       if (changed) {
+               if (cfg->opt & MONO_OPT_BRANCH)
+                       mono_optimize_branches (cfg);
                /* Merging bblocks could make some variables local */
                mono_handle_global_vregs (cfg);
+       }
 }

Modified: branches/vargaz/mini-linear-il/mono/mono/mini/mini-codegen.c
===================================================================
--- branches/vargaz/mini-linear-il/mono/mono/mini/mini-codegen.c        
2007-11-21 16:25:26 UTC (rev 90091)
+++ branches/vargaz/mini-linear-il/mono/mono/mini/mini-codegen.c        
2007-11-21 16:52:58 UTC (rev 90092)
@@ -2020,6 +2020,35 @@
        }
 }
 
+CompRelation
+mono_negate_cond (CompRelation cond)
+{
+       switch (cond) {
+       case CMP_EQ:
+               return CMP_NE;
+       case CMP_NE:
+               return CMP_EQ;
+       case CMP_LE:
+               return CMP_GT;
+       case CMP_GE:
+               return CMP_LT;
+       case CMP_LT:
+               return CMP_GE;
+       case CMP_GT:
+               return CMP_LE;
+       case CMP_LE_UN:
+               return CMP_GT_UN;
+       case CMP_GE_UN:
+               return CMP_LT_UN;
+       case CMP_LT_UN:
+               return CMP_GE_UN;
+       case CMP_GT_UN:
+               return CMP_LE_UN;
+       default:
+               g_assert_not_reached ();
+       }
+}
+
 CompType
 mono_opcode_to_type (int opcode, int cmp_opcode)
 {

Modified: branches/vargaz/mini-linear-il/mono/mono/mini/mini.c
===================================================================
--- branches/vargaz/mini-linear-il/mono/mono/mini/mini.c        2007-11-21 
16:25:26 UTC (rev 90091)
+++ branches/vargaz/mini-linear-il/mono/mono/mini/mini.c        2007-11-21 
16:52:58 UTC (rev 90092)
@@ -10802,6 +10802,23 @@
        }               
 }
 
+/*
+ * mono_remove_block:
+ *
+ *   Remove BB from the control flow graph
+ */
+void
+mono_remove_bblock (MonoCompile *cfg, MonoBasicBlock *bb) 
+{
+       MonoBasicBlock *tmp_bb;
+
+       for (tmp_bb = cfg->bb_entry; tmp_bb && tmp_bb->next_bb != bb; tmp_bb = 
tmp_bb->next_bb)
+               ;
+
+       g_assert (tmp_bb);
+       tmp_bb->next_bb = bb->next_bb;
+}
+
 /* checks that a and b represent the same instructions, conservatively,
  * it can return FALSE also for two trees that are equal.
  * FIXME: also make sure there are no side effects.
@@ -10909,8 +10926,8 @@
  * Optimizes the branches on the Control Flow Graph
  *
  */
-static void
-optimize_branches (MonoCompile *cfg)
+void
+mono_optimize_branches (MonoCompile *cfg)
 {
        int i, changed = FALSE;
        MonoBasicBlock *bb, *bbn;
@@ -11871,12 +11888,19 @@
        }
 
        if (cfg->opt & MONO_OPT_BRANCH)
-               optimize_branches (cfg);
+               mono_optimize_branches (cfg);
 
        if (cfg->opt & MONO_OPT_SSAPRE) {
                remove_critical_edges (cfg);
        }
 
+       if (cfg->new_ir) {
+               /* This must be done _before_ global reg alloc and _after_ 
decompose */
+               mono_handle_global_vregs (cfg);
+               mono_local_deadce (cfg);
+               mono_branch_to_cmov (cfg);
+       }
+
        /* Depth-first ordering on basic blocks */
        cfg->bblocks = mono_mempool_alloc (cfg->mempool, sizeof 
(MonoBasicBlock*) * (cfg->num_bblocks + 1));
 
@@ -11913,14 +11937,6 @@
                mono_compute_natural_loops (cfg);
        }
 
-
-       if (cfg->new_ir) {
-               /* This must be done _before_ global reg alloc and _after_ 
decompose */
-               mono_handle_global_vregs (cfg);
-               mono_local_deadce (cfg);
-               mono_branch_to_cmov (cfg);
-       }
-
        /* after method_to_ir */
        if (parts == 1)
                return cfg;
@@ -12013,7 +12029,7 @@
                        mono_ssa_remove (cfg);
 
                if (cfg->opt & MONO_OPT_BRANCH)
-                       optimize_branches (cfg);
+                       mono_optimize_branches (cfg);
        }
 #endif
 

Modified: branches/vargaz/mini-linear-il/mono/mono/mini/mini.h
===================================================================
--- branches/vargaz/mini-linear-il/mono/mono/mini/mini.h        2007-11-21 
16:25:26 UTC (rev 90091)
+++ branches/vargaz/mini-linear-il/mono/mono/mini/mini.h        2007-11-21 
16:52:58 UTC (rev 90092)
@@ -1013,7 +1013,9 @@
 guint32   mono_alloc_dreg                   (MonoCompile *cfg, MonoStackType 
stack_type) MONO_INTERNAL;
 void      mono_link_bblock                  (MonoCompile *cfg, MonoBasicBlock 
*from, MonoBasicBlock* to) MONO_INTERNAL;
 void      mono_unlink_bblock                (MonoCompile *cfg, MonoBasicBlock 
*from, MonoBasicBlock* to) MONO_INTERNAL;
+void      mono_remove_bblock                (MonoCompile *cfg, MonoBasicBlock 
*bb) MONO_INTERNAL;
 void      mono_merge_basic_blocks           (MonoBasicBlock *bb, 
MonoBasicBlock *bbn) MONO_INTERNAL;
+void      mono_optimize_branches            (MonoCompile *cfg) MONO_INTERNAL;
 void      mono_blockset_print               (MonoCompile *cfg, MonoBitSet 
*set, const char *name, guint idom) MONO_INTERNAL;
 void      mono_print_tree                   (MonoInst *tree) MONO_INTERNAL;
 void      mono_print_tree_nl                (MonoInst *tree) MONO_INTERNAL;
@@ -1142,6 +1144,7 @@
 void              mini_emit_memcpy2 (MonoCompile *cfg, int destreg, int 
doffset, int srcreg, int soffset, int size, int align) MONO_INTERNAL;
 CompRelation      mono_opcode_to_cond (int opcode) MONO_INTERNAL;
 CompType          mono_opcode_to_type (int opcode, int cmp_opcode) 
MONO_INTERNAL;
+CompRelation      mono_negate_cond (CompRelation cond) MONO_INTERNAL;
 
 void              mono_decompose_long_opts (MonoCompile *cfg) MONO_INTERNAL;
 void              mono_decompose_vtype_opts (MonoCompile *cfg) MONO_INTERNAL;

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to