[netcore] Enable Vector<T>.get_Item () intrinsics for floats/doubles.
authorZoltan Varga <vargaz@gmail.com>
Tue, 3 Sep 2019 21:14:50 +0000 (17:14 -0400)
committerLarry Ewing <lewing@microsoft.com>
Wed, 4 Sep 2019 03:05:15 +0000 (22:05 -0500)
Commit migrated from https://github.com/mono/mono/commit/e1b568b5293a5f85c0f0c6b3c68255c810c085df

src/mono/mono/mini/mini-llvm.c
src/mono/mono/mini/mini-ops.h
src/mono/mono/mini/simd-intrinsics-netcore.c

index 227e3e8..61eeb11 100644 (file)
@@ -7304,7 +7304,9 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        break;
                }
                case OP_XEXTRACT_I32:
-               case OP_XEXTRACT_I64: {
+               case OP_XEXTRACT_I64:
+               case OP_XEXTRACT_R8:
+               case OP_XEXTRACT_R4: {
                        LLVMBasicBlockRef bbs [64];
                        LLVMValueRef switch_ins;
                        LLVMValueRef phi_values [64];
index 1718976..8204b94 100644 (file)
@@ -1379,6 +1379,9 @@ MINI_OP(OP_XCAST, "xcast", XREG, XREG, NONE)
 /* The index is assumed to be in range */
 MINI_OP(OP_XEXTRACT_I32, "xextract_i32", IREG, XREG, IREG)
 MINI_OP(OP_XEXTRACT_I64, "xextract_i64", LREG, XREG, IREG)
+MINI_OP(OP_XEXTRACT_R8, "xextract_r8", FREG, XREG, IREG)
+/* Return an R4 */
+MINI_OP(OP_XEXTRACT_R4, "xextract_r4", FREG, XREG, IREG)
 
 MINI_OP(OP_LZCNT32, "lzcnt32", IREG, IREG, NONE)
 MINI_OP(OP_LZCNT64, "lzcnt64", LREG, LREG, NONE)
index f1df047..841c1da 100644 (file)
@@ -313,16 +313,35 @@ emit_sys_numerics_vector_t (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
        case SN_get_Item:
                MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, args [1]->dreg, len);
                MONO_EMIT_NEW_COND_EXC (cfg, GE_UN, "IndexOutOfRangeException");
-               if (etype->type == MONO_TYPE_R4 || etype->type == MONO_TYPE_R8)
-                       // FIXME:
-                       return NULL;
-               // FIXME: Optimize constant case
-               gboolean is64 = etype->type == MONO_TYPE_I8 || etype->type == MONO_TYPE_U8;
-               MONO_INST_NEW (cfg, ins, is64 ? OP_XEXTRACT_I64 : OP_XEXTRACT_I32);
-               ins->dreg = is64 ? alloc_lreg (cfg) : alloc_ireg (cfg);
+               int opcode = -1;
+               int dreg;
+               gboolean is64 = FALSE;
+               switch (etype->type) {
+               case MONO_TYPE_I8:
+               case MONO_TYPE_U8:
+                       opcode = OP_XEXTRACT_I64;
+                       is64 = TRUE;
+                       dreg = alloc_lreg (cfg);
+                       break;
+               case MONO_TYPE_R8:
+                       opcode = OP_XEXTRACT_R8;
+                       dreg = alloc_freg (cfg);
+                       break;
+               case MONO_TYPE_R4:
+                       g_assert (cfg->r4fp);
+                       opcode = OP_XEXTRACT_R4;
+                       dreg = alloc_freg (cfg);
+                       break;
+               default:
+                       opcode = OP_XEXTRACT_I32;
+                       dreg = alloc_ireg (cfg);
+                       break;
+               }
+               MONO_INST_NEW (cfg, ins, opcode);
+               ins->dreg = dreg;
                ins->sreg1 = load_simd_vreg (cfg, cmethod, args [0], NULL);
                ins->sreg2 = args [1]->dreg;
-               ins->type = is64 ? STACK_I8 : STACK_I4;
+               mini_type_to_eval_stack_type (cfg, etype, ins);
                MONO_ADD_INS (cfg->cbb, ins);
                return ins;
        case SN_ctor: