logic.cs \
switch.cs \
ctor-bench.cs \
+ readonly.cs \
bulkcpy.il \
math.cs
--- /dev/null
+using System;
+
+public class Test {
+
+ static readonly int a = 5;
+ static readonly int b = 6;
+
+ public static int Main (string[] args) {
+ int repeat = 1;
+
+ if (args.Length == 1)
+ repeat = Convert.ToInt32 (args [0]);
+
+ Console.WriteLine ("Repeat = " + repeat);
+
+ for (int i = 0; i < repeat*3; i++) {
+ for (int j = 0; j < 100000000; j++) {
+ if ((a != 5) || (b != 6))
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+}
+
+
+2003-06-06 Dietmar Maurer <dietmar@ximian.com>
+
+ * mini.c (mono_method_to_ir): inline static readonly fields
+
+ * ssa.c (fold_tree): start cfold support for long (very simple
+ cases only)
+
+ * cfold.c (mono_constant_fold_inst): opt. CEE_CONV_I8 (OP_ICONST)
Fri Jun 6 11:41:18 CEST 2003 Paolo Molaro <lupus@ximian.com>
#define FOLD_UNOP(name,op) \
case name: \
- if (inst->inst_i0->opcode != OP_ICONST) \
- return; \
- inst->opcode = OP_ICONST; \
- inst->inst_c0 = op inst->inst_i0->inst_c0; \
- return;
+ if (inst->inst_i0->opcode == OP_ICONST) { \
+ inst->opcode = OP_ICONST; \
+ inst->inst_c0 = op inst->inst_i0->inst_c0; \
+ } else if (inst->inst_i0->opcode == OP_I8CONST) { \
+ inst->opcode = OP_I8CONST; \
+ inst->inst_l = op inst->inst_i0->inst_l; \
+ } return;
#define FOLD_BRBINOP(name,op,cast) \
case name: \
FOLD_CXX (OP_CGT_UN,>,guint32)
FOLD_CXX (OP_CLT,<,gint32)
FOLD_CXX (OP_CLT_UN,<,guint32)
+ case CEE_CONV_I8:
+ if (inst->inst_i0->opcode == OP_ICONST) {
+ inst->opcode = OP_I8CONST;
+ inst->inst_l = inst->inst_i0->inst_c0;
+ }
+ return;
/* we should be able to handle isinst and castclass as well */
case CEE_ISINST:
case CEE_CASTCLASS:
case CEE_CONV_I1:
case CEE_CONV_I2:
case CEE_CONV_I4:
- case CEE_CONV_I8:
case CEE_CONV_R4:
case CEE_CONV_R8:
case CEE_CONV_U4:
+ case CEE_CONV_I8:
case CEE_CONV_U8:
case CEE_CONV_OVF_I8:
case CEE_CONV_OVF_U8:
case CEE_CONV_R_UN:
CHECK_STACK (1);
ADD_UNOP (*ip);
- ip++;
+ ip++;
break;
case CEE_CONV_OVF_I4:
case CEE_CONV_OVF_I1:
} else
MONO_ADD_INS (bblock, store);
} else {
- MonoInst *load;
- CHECK_STACK_OVF (1);
- MONO_INST_NEW (cfg, load, mono_type_to_ldind (field->type));
- type_to_eval_stack_type (field->type, load);
- load->cil_code = ip;
- load->inst_left = ins;
- *sp++ = load;
- load->flags |= ins_flag;
- ins_flag = 0;
- /* fixme: dont see the problem why this does not work */
- //cfg->disable_aot = TRUE;
+ gboolean is_const = FALSE;
+ MonoVTable *vtable = mono_class_vtable (cfg->domain, klass);
+ if (!((cfg->opt & MONO_OPT_SHARED) || mono_compile_aot) &&
+ vtable->initialized && (field->type->attrs & FIELD_ATTRIBUTE_INIT_ONLY)) {
+ gpointer addr = (char*)vtable->data + field->offset;
+ /* g_print ("RO-FIELD %s.%s:%s\n", klass->name_space, klass->name, field->name);*/
+ is_const = TRUE;
+ switch (field->type->type) {
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_U1:
+ NEW_ICONST (cfg, *sp, *((guint8 *)addr));
+ sp++;
+ break;
+ case MONO_TYPE_I1:
+ NEW_ICONST (cfg, *sp, *((gint8 *)addr));
+ sp++;
+ break;
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_U2:
+ NEW_ICONST (cfg, *sp, *((guint16 *)addr));
+ sp++;
+ break;
+ case MONO_TYPE_I2:
+ NEW_ICONST (cfg, *sp, *((gint16 *)addr));
+ sp++;
+ break;
+ break;
+ case MONO_TYPE_I4:
+ NEW_ICONST (cfg, *sp, *((gint32 *)addr));
+ sp++;
+ break;
+ case MONO_TYPE_U4:
+ NEW_ICONST (cfg, *sp, *((guint32 *)addr));
+ sp++;
+ break;
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_FNPTR:
+ case MONO_TYPE_ARRAY:
+ NEW_PCONST (cfg, *sp, *((gpointer *)addr));
+ type_to_eval_stack_type (field->type, *sp);
+ sp++;
+ break;
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ MONO_INST_NEW (cfg, *sp, OP_I8CONST);
+ sp [0]->type = STACK_I8;
+ sp [0]->inst_l = *((gint64 *)addr);
+ sp++;
+ break;
+ case MONO_TYPE_R4:
+ case MONO_TYPE_R8:
+ case MONO_TYPE_VALUETYPE:
+ default:
+ is_const = FALSE;
+ break;
+ }
+ }
+
+ if (!is_const) {
+ MonoInst *load;
+ CHECK_STACK_OVF (1);
+ MONO_INST_NEW (cfg, load, mono_type_to_ldind (field->type));
+ type_to_eval_stack_type (field->type, load);
+ load->cil_code = ip;
+ load->inst_left = ins;
+ *sp++ = load;
+ load->flags |= ins_flag;
+ ins_flag = 0;
+ /* fixme: dont see the problem why this does not work */
+ //cfg->disable_aot = TRUE;
+ }
}
ip += 5;
break;
return 0;
}
+static int
+simulate_long_compare (int opcode, gint64 a, gint64 b)
+{
+ switch (opcode) {
+ case CEE_BEQ:
+ return a == b;
+ case CEE_BGE:
+ return a >= b;
+ case CEE_BGT:
+ return a > b;
+ case CEE_BLE:
+ return a <= b;
+ case CEE_BLT:
+ return a < b;
+ case CEE_BNE_UN:
+ return a != b;
+ case CEE_BGE_UN:
+ return (unsigned)a >= (unsigned)b;
+ case CEE_BGT_UN:
+ return (unsigned)a > (unsigned)b;
+ case CEE_BLE_UN:
+ return (unsigned)a <= (unsigned)b;
+ case CEE_BLT_UN:
+ return (unsigned)a < (unsigned)b;
+ default:
+ g_assert_not_reached ();
+ }
+
+ return 0;
+}
+
#define EVAL_CXX(name,op,cast) \
case name: \
if (inst->inst_i0->opcode == OP_COMPARE) { \
break;
+/* fixme: this only works for interger constants, but not for other types (long, float) */
static int
evaluate_const_tree (MonoCompile *cfg, MonoInst *inst, int *res, MonoInst **carray)
{
inst->inst_i0->opcode == OP_COMPARE) {
MonoInst *v0 = inst->inst_i0->inst_i0;
MonoInst *v1 = inst->inst_i0->inst_i1;
+ MonoBasicBlock *target = NULL;
- if (evaluate_const_tree (cfg, v0, &a, carray) == 1 &&
- evaluate_const_tree (cfg, v1, &b, carray) == 1) {
- MonoBasicBlock *target;
-
+ /* hack for longs to optimize the simply cases */
+ if (v0->opcode == OP_I8CONST && v1->opcode == OP_I8CONST) {
+ if (simulate_long_compare (inst->opcode, v0->inst_l, v1->inst_l)) {
+ //unlink_target (bb, inst->inst_false_bb);
+ target = inst->inst_true_bb;
+ } else {
+ //unlink_target (bb, inst->inst_true_bb);
+ target = inst->inst_false_bb;
+ }
+ } else if (evaluate_const_tree (cfg, v0, &a, carray) == 1 &&
+ evaluate_const_tree (cfg, v1, &b, carray) == 1) {
if (simulate_compare (inst->opcode, a, b)) {
//unlink_target (bb, inst->inst_false_bb);
target = inst->inst_true_bb;
//unlink_target (bb, inst->inst_true_bb);
target = inst->inst_false_bb;
}
-
+ }
+
+ if (target) {
bb->out_bb [0] = target;
bb->out_count = 1;
inst->opcode = CEE_BR;