svn path=/trunk/mono/; revision=53658
[mono.git] / mono / mini / cfold.c
index 092c7d7ba13ffd093598045f8981de0f18630605..c9daabdb7f6c5d4c781fafb13ba90adec44ec3c3 100644 (file)
@@ -254,3 +254,67 @@ mono_constant_fold (MonoCompile *cfg)
        }
 }
 
+/*
+ * If the arguments to the cond branch are constants, eval and
+ * return BRANCH_NOT_TAKEN for not taken, BRANCH_TAKEN for taken,
+ * BRANCH_UNDEF otherwise.
+ * If this code is changed to handle also non-const values, make sure
+ * side effects are handled in optimize_branches() in mini.c, by
+ * inserting pop instructions.
+ */
+int
+mono_eval_cond_branch (MonoInst *ins)
+{
+       MonoInst *left, *right;
+       /* FIXME: handle also 64 bit ints */
+       left = ins->inst_left->inst_left;
+       if (left->opcode != OP_ICONST && left->opcode != OP_PCONST)
+               return BRANCH_UNDEF;
+       right = ins->inst_left->inst_right;
+       if (right->opcode != OP_ICONST && right->opcode != OP_PCONST)
+               return BRANCH_UNDEF;
+       switch (ins->opcode) {
+       case CEE_BEQ:
+               if (left->inst_c0 == right->inst_c0)
+                       return BRANCH_TAKEN;
+               return BRANCH_NOT_TAKEN;
+       case CEE_BGE:
+               if (left->inst_c0 >= right->inst_c0)
+                       return BRANCH_TAKEN;
+               return BRANCH_NOT_TAKEN;
+       case CEE_BGT:
+               if (left->inst_c0 > right->inst_c0)
+                       return BRANCH_TAKEN;
+               return BRANCH_NOT_TAKEN;
+       case CEE_BLE:
+               if (left->inst_c0 <= right->inst_c0)
+                       return BRANCH_TAKEN;
+               return BRANCH_NOT_TAKEN;
+       case CEE_BLT:
+               if (left->inst_c0 < right->inst_c0)
+                       return BRANCH_TAKEN;
+               return BRANCH_NOT_TAKEN;
+       case CEE_BNE_UN:
+               if ((gsize)left->inst_c0 != (gsize)right->inst_c0)
+                       return BRANCH_TAKEN;
+               return BRANCH_NOT_TAKEN;
+       case CEE_BGE_UN:
+               if ((gsize)left->inst_c0 >= (gsize)right->inst_c0)
+                       return BRANCH_TAKEN;
+               return BRANCH_NOT_TAKEN;
+       case CEE_BGT_UN:
+               if ((gsize)left->inst_c0 > (gsize)right->inst_c0)
+                       return BRANCH_TAKEN;
+               return BRANCH_NOT_TAKEN;
+       case CEE_BLE_UN:
+               if ((gsize)left->inst_c0 <= (gsize)right->inst_c0)
+                       return BRANCH_TAKEN;
+               return BRANCH_NOT_TAKEN;
+       case CEE_BLT_UN:
+               if ((gsize)left->inst_c0 < (gsize)right->inst_c0)
+                       return BRANCH_TAKEN;
+               return BRANCH_NOT_TAKEN;
+       }
+       return BRANCH_UNDEF;
+}
+