inst->inst_i1 = tmp; \
} \
} \
+ if (inst->inst_i1->opcode == OP_ICONST && inst->opcode == CEE_ADD) { \
+ if (inst->inst_i1->inst_c0 == 0) { \
+ *inst = *(inst->inst_i0); \
+ return; \
+ } \
+ } \
if (inst->inst_i1->opcode == OP_ICONST && inst->opcode == CEE_MUL) { \
int power2; \
if (inst->inst_i1->inst_c0 == 1) { \
} \
return;
+#ifndef G_MININT32
+#define MYGINT32_MAX 2147483647
+#define G_MININT32 (-MYGINT32_MAX -1)
+#endif
+
+/*
+ * We can't let this cause a division by zero exception since the division
+ * might not be executed during runtime.
+ */
#define FOLD_BINOPZ(name,op,cast) \
case name: \
if (inst->inst_i1->opcode == OP_ICONST && inst->opcode == CEE_REM_UN && inst->inst_i1->inst_c0 == 2) { \
return; \
} \
if (inst->inst_i1->opcode == OP_ICONST) { \
- /* let the runtime throw the exception. */ \
if (!inst->inst_i1->inst_c0) return; \
if (inst->inst_i0->opcode == OP_ICONST) { \
+ if ((inst->inst_i0->inst_c0 == G_MININT32) && (inst->inst_i1->inst_c0 == -1)) \
+ return; \
inst->inst_c0 = (cast)inst->inst_i0->inst_c0 op (cast)inst->inst_i1->inst_c0; \
inst->opcode = OP_ICONST; \
} else { \
*/
#if SIZEOF_VOID_P == 4
case CEE_CONV_I4:
- if ((inst->inst_left->type == STACK_I4)||(inst->inst_left->type == STACK_PTR)) {
+ if ((inst->inst_left->type == STACK_I4) || (inst->inst_left->type == STACK_PTR)) {
*inst = *inst->inst_left;
}
break;
}
}
+/*
+ * 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;
+}
+