Add mixed r4/r8 opcodes to binary opcodes.
authorZoltan Varga <vargaz@gmail.com>
Fri, 6 Feb 2015 16:56:10 +0000 (11:56 -0500)
committerZoltan Varga <vargaz@gmail.com>
Fri, 6 Feb 2015 18:32:03 +0000 (13:32 -0500)
mono/mini/iltests.il.in
mono/mini/method-to-ir.c

index b64792863d8b768a2f6c47a09182edbe68d0a5f9..8510917341b87d747bd61318c19552789f330cf5 100644 (file)
@@ -2718,4 +2718,67 @@ END:
           ldc.i4.0
        ret
   }
+
+  .method public hidebysig static int32  test_5_r4_fadd_mixed() cil managed
+  {
+    // Code size       17 (0x11)
+    .maxstack  2
+    .locals init (float32 V_0,
+             float64 V_1)
+    IL_0000:  ldc.r4     3
+    IL_0005:  stloc.0
+    IL_0006:  ldc.r8     2
+    IL_000b:  stloc.1
+    IL_000c:  ldloc.0
+    IL_000d:  ldloc.1
+    IL_000e:  add
+    IL_000f:  conv.i4
+    IL_0010:  ret
+  }
+
+ .method public hidebysig static int32  test_0_fcmp_eq_r4_mixed() cil managed
+  {
+    // Code size       32 (0x20)
+    .maxstack  2
+    .locals init (float32 V_0,
+             float64 V_1)
+    IL_0000:  ldc.r4     1
+    IL_0005:  stloc.0
+    IL_0006:  ldc.r8     1
+    IL_000f:  stloc.1
+    IL_0010:  ldloc.0
+    IL_0012:  ldloc.1
+    IL_0013:  bne.un     IL_001e
+
+    IL_0018:  ldc.i4.0
+    IL_0019:  br         IL_001f
+
+    IL_001e:  ldc.i4.1
+    IL_001f:  ret
+  } // end of method Tests::test_0_fcmp_eq_r4_mixed
+
+  .method public hidebysig static int32  test_0_fceq_r4_mixed() cil managed
+  {
+    // Code size       31 (0x1f)
+    .maxstack  2
+    .locals init (float32 V_0,
+             float64 V_1,
+             bool V_2)
+    IL_0000:  ldc.r4     1
+    IL_0005:  stloc.0
+    IL_0006:  ldc.r8     1
+    IL_000b:  stloc.1
+    IL_000c:  ldloc.0
+    IL_000d:  ldloc.1
+    IL_000e:  ceq
+    IL_0010:  stloc.2
+    IL_0011:  ldloc.2
+    IL_0012:  brfalse    IL_001d
+
+    IL_0017:  ldc.i4.0
+    IL_0018:  br         IL_001e
+
+    IL_001d:  ldc.i4.1
+    IL_001e:  ret
+  } // end of method Tests::test_0_fceq_r4
 }
index b61559e31eb707641f76a534e67a6f2d8d28ae94..f4552d4b942478db91607867aa3808621a9e28fd 100755 (executable)
@@ -459,19 +459,48 @@ gsharedvt_failure (MonoCompile *cfg, int opcode, const char *file, int line)
        } while (0)
 #endif
 
+/* Emit conversions so both operands of a binary opcode are of the same type */
+static void
+add_widen_op (MonoCompile *cfg, MonoInst *ins, MonoInst **arg1_ref, MonoInst **arg2_ref)
+{
+       MonoInst *arg1 = *arg1_ref;
+       MonoInst *arg2 = *arg2_ref;
+
+       if (cfg->r4fp &&
+               ((arg1->type == STACK_R4 && arg2->type == STACK_R8) ||
+                (arg1->type == STACK_R8 && arg2->type == STACK_R4))) {
+               MonoInst *conv;
+
+               /* Mixing r4/r8 is allowed by the spec */
+               if (arg1->type == STACK_R4) {
+                       int dreg = alloc_freg (cfg);
+
+                       EMIT_NEW_UNALU (cfg, conv, OP_RCONV_TO_R8, dreg, arg1->dreg);
+                       conv->type = STACK_R8;
+                       ins->sreg1 = dreg;
+                       *arg1_ref = conv;
+               }
+               if (arg2->type == STACK_R4) {
+                       int dreg = alloc_freg (cfg);
+
+                       EMIT_NEW_UNALU (cfg, conv, OP_RCONV_TO_R8, dreg, arg2->dreg);
+                       conv->type = STACK_R8;
+                       ins->sreg2 = dreg;
+                       *arg2_ref = conv;
+               }
+       }
+
 #if SIZEOF_REGISTER == 8
-#define ADD_WIDEN_OP(ins, arg1, arg2) do { \
-               /* FIXME: Need to add many more cases */ \
-               if ((arg1)->type == STACK_PTR && (arg2)->type == STACK_I4) {    \
-                       MonoInst *widen; \
-                       int dr = alloc_preg (cfg); \
-                       EMIT_NEW_UNALU (cfg, widen, OP_SEXT_I4, dr, (arg2)->dreg); \
-                       (ins)->sreg2 = widen->dreg; \
-               } \
-       } while (0)
-#else
-#define ADD_WIDEN_OP(ins, arg1, arg2)
+       /* FIXME: Need to add many more cases */
+       if ((arg1)->type == STACK_PTR && (arg2)->type == STACK_I4) {
+               MonoInst *widen;
+
+               int dr = alloc_preg (cfg);
+               EMIT_NEW_UNALU (cfg, widen, OP_SEXT_I4, dr, (arg2)->dreg);
+               (ins)->sreg2 = widen->dreg;
+       }
 #endif
+}
 
 #define ADD_BINOP(op) do {     \
                MONO_INST_NEW (cfg, ins, (op)); \
@@ -481,7 +510,7 @@ gsharedvt_failure (MonoCompile *cfg, int opcode, const char *file, int line)
                type_from_op (cfg, ins, sp [0], sp [1]);        \
                CHECK_TYPE (ins);       \
                /* Have to insert a widening op */               \
-        ADD_WIDEN_OP (ins, sp [0], sp [1]); \
+        add_widen_op (cfg, ins, &sp [0], &sp [1]);              \
         ins->dreg = alloc_dreg ((cfg), (ins)->type); \
         MONO_ADD_INS ((cfg)->cbb, (ins)); \
         *sp++ = mono_decompose_opcode ((cfg), (ins)); \
@@ -506,6 +535,7 @@ gsharedvt_failure (MonoCompile *cfg, int opcode, const char *file, int line)
                cmp->sreg2 = sp [1]->dreg;      \
                type_from_op (cfg, cmp, sp [0], sp [1]);        \
                CHECK_TYPE (cmp);       \
+               add_widen_op (cfg, cmp, &sp [0], &sp [1]);                                              \
                type_from_op (cfg, ins, sp [0], sp [1]);                                                        \
                ins->inst_many_bb = mono_mempool_alloc (cfg->mempool, sizeof(gpointer)*2);      \
                GET_BBLOCK (cfg, tblock, target);               \
@@ -793,11 +823,11 @@ bin_num_table [STACK_MAX] [STACK_MAX] = {
        {STACK_INV, STACK_I4,  STACK_INV, STACK_PTR, STACK_INV, STACK_MP,  STACK_INV, STACK_INV},
        {STACK_INV, STACK_INV, STACK_I8,  STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
        {STACK_INV, STACK_PTR, STACK_INV, STACK_PTR, STACK_INV, STACK_MP,  STACK_INV, STACK_INV},
-       {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_R8,  STACK_INV, STACK_INV, STACK_INV},
+       {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_R8,  STACK_INV, STACK_INV, STACK_INV, STACK_R8},
        {STACK_INV, STACK_MP,  STACK_INV, STACK_MP,  STACK_INV, STACK_PTR, STACK_INV, STACK_INV},
        {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
        {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
-       {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_R4}
+       {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_R8, STACK_INV, STACK_INV, STACK_INV, STACK_R4}
 };
 
 static const char 
@@ -825,11 +855,11 @@ bin_comp_table [STACK_MAX] [STACK_MAX] = {
        {0, 1, 0, 1, 0, 0, 0, 0}, /* i, int32 */
        {0, 0, 1, 0, 0, 0, 0, 0}, /* L, int64 */
        {0, 1, 0, 1, 0, 2, 4, 0}, /* p, ptr */
-       {0, 0, 0, 0, 1, 0, 0, 0}, /* F, R8 */
+       {0, 0, 0, 0, 1, 0, 0, 0, 1}, /* F, R8 */
        {0, 0, 0, 2, 0, 1, 0, 0}, /* &, managed pointer */
        {0, 0, 0, 4, 0, 0, 3, 0}, /* O, reference */
        {0, 0, 0, 0, 0, 0, 0, 0}, /* vt value type */
-       {0, 0, 0, 0, 0, 0, 0, 0, 1}, /* r, r4 */
+       {0, 0, 0, 0, 1, 0, 0, 0, 1}, /* r, r4 */
 };
 
 /* reduce the size of this table */
@@ -9858,7 +9888,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ins->sreg2 = sp [1]->dreg;
                        type_from_op (cfg, ins, sp [0], sp [1]);
                        CHECK_TYPE (ins);
-                       ADD_WIDEN_OP (ins, sp [0], sp [1]);
+                       add_widen_op (cfg, ins, &sp [0], &sp [1]);
                        ins->dreg = alloc_dreg ((cfg), (ins)->type);
 
                        /* FIXME: Pass opcode to is_inst_imm */
@@ -9888,7 +9918,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                ins->inst_imm = (gssize)(sp [1]->inst_c0);
                                        ins->sreg2 = -1;
 
-                                       /* Might be followed by an instruction added by ADD_WIDEN_OP */
+                                       /* Might be followed by an instruction added by add_widen_op */
                                        if (sp [1]->next == NULL)
                                                NULLIFY_INS (sp [1]);
                                }
@@ -12225,8 +12255,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        case CEE_CGT_UN:
                        case CEE_CLT:
                        case CEE_CLT_UN: {
-                               MonoInst *cmp;
+                               MonoInst *cmp, *arg1, *arg2;
+
                                CHECK_STACK (2);
+                               sp -= 2;
+                               arg1 = sp [0];
+                               arg2 = sp [1];
+
                                /*
                                 * The following transforms:
                                 *    CEE_CEQ    into OP_CEQ
@@ -12236,25 +12271,25 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                 *    CEE_CLT_UN into OP_CLT_UN
                                 */
                                MONO_INST_NEW (cfg, cmp, (OP_CEQ - CEE_CEQ) + ip [1]);
-                               
+
                                MONO_INST_NEW (cfg, ins, cmp->opcode);
-                               sp -= 2;
-                               cmp->sreg1 = sp [0]->dreg;
-                               cmp->sreg2 = sp [1]->dreg;
-                               type_from_op (cfg, cmp, sp [0], sp [1]);
+                               cmp->sreg1 = arg1->dreg;
+                               cmp->sreg2 = arg2->dreg;
+                               type_from_op (cfg, cmp, arg1, arg2);
                                CHECK_TYPE (cmp);
-                               if ((sp [0]->type == STACK_I8) || ((SIZEOF_VOID_P == 8) && ((sp [0]->type == STACK_PTR) || (sp [0]->type == STACK_OBJ) || (sp [0]->type == STACK_MP))))
+                               add_widen_op (cfg, cmp, &arg1, &arg2);
+                               if ((arg1->type == STACK_I8) || ((SIZEOF_VOID_P == 8) && ((arg1->type == STACK_PTR) || (arg1->type == STACK_OBJ) || (arg1->type == STACK_MP))))
                                        cmp->opcode = OP_LCOMPARE;
-                               else if (sp [0]->type == STACK_R4)
+                               else if (arg1->type == STACK_R4)
                                        cmp->opcode = OP_RCOMPARE;
-                               else if (sp [0]->type == STACK_R8)
+                               else if (arg1->type == STACK_R8)
                                        cmp->opcode = OP_FCOMPARE;
                                else
                                        cmp->opcode = OP_ICOMPARE;
                                MONO_ADD_INS (bblock, cmp);
                                ins->type = STACK_I4;
                                ins->dreg = alloc_dreg (cfg, ins->type);
-                               type_from_op (cfg, ins, sp [0], sp [1]);
+                               type_from_op (cfg, ins, arg1, arg2);
 
                                if (cmp->opcode == OP_FCOMPARE || cmp->opcode == OP_RCOMPARE) {
                                        /*