2003-06-06 Dietmar Maurer <dietmar@ximian.com>
authorDietmar Maurer <dietmar@mono-cvs.ximian.com>
Fri, 6 Jun 2003 13:05:31 +0000 (13:05 -0000)
committerDietmar Maurer <dietmar@mono-cvs.ximian.com>
Fri, 6 Jun 2003 13:05:31 +0000 (13:05 -0000)
* 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)

svn path=/trunk/mono/; revision=15157

mono/benchmark/Makefile.am
mono/benchmark/readonly.cs [new file with mode: 0755]
mono/mini/ChangeLog
mono/mini/cfold.c
mono/mini/mini.c
mono/mini/ssa.c

index 4db8e150a63a8bfd428831c1b3c7323d36cc1791..68c057bd476b513398f3c9372e14e48951502786 100644 (file)
@@ -21,6 +21,7 @@ TESTSRC=                      \
        logic.cs                \
        switch.cs               \
        ctor-bench.cs           \
+       readonly.cs             \
        bulkcpy.il              \
        math.cs
 
diff --git a/mono/benchmark/readonly.cs b/mono/benchmark/readonly.cs
new file mode 100755 (executable)
index 0000000..11ed40d
--- /dev/null
@@ -0,0 +1,27 @@
+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;
+       }
+}
+
+
index a0cffc5dd541b4a0eac6aec8534a2a606f2bced8..785628cfb2ae1fc5bcd949b44caf45dc05b03e50 100644 (file)
@@ -1,3 +1,11 @@
+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>
 
index 86471e810e970aa91d4379c2e872b8433759ef95..ce794d1c7dac24c4210397cfb20cbac147fee91a 100644 (file)
@@ -118,11 +118,13 @@ is_power_of_two (guint32 val)
 
 #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:      \
@@ -188,6 +190,12 @@ mono_constant_fold_inst (MonoInst *inst, gpointer data)
        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:
index fe23d1734b3f4744c15340fd19cfd7c25dad5d97..f4c73c69e70e74e8df20cb005f28e5b7944506e0 100644 (file)
@@ -3345,17 +3345,17 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                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:
@@ -3864,17 +3864,83 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                } 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;
index 1d0b68f66843c20a16dbff6921d88199ed83a45d..2b9bb373b048bba59cff46f10a0edbef61e602c3 100644 (file)
@@ -729,6 +729,37 @@ simulate_compare (int opcode, int a, int b)
        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) { \
@@ -756,6 +787,7 @@ simulate_compare (int opcode, int a, int b)
                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)
 {
@@ -834,11 +866,19 @@ fold_tree (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, MonoInst **carr
            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;
@@ -846,7 +886,9 @@ fold_tree (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *inst, MonoInst **carr
                                //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;