[xbuild] Vbc task - make error column check a little non-specific.
[mono.git] / mono / mini / simd-intrinsics.c
index aaf6a1935df772c8d327bbe61f6b49cd49f27d1b..d77d23df6bf2b52e6ea1e6cef420c9aa57f16110 100644 (file)
@@ -138,6 +138,9 @@ static const SimdIntrinsc vector4f_intrinsics[] = {
        { SN_CompareNotLessThan, OP_COMPPS, SIMD_VERSION_SSE1, SIMD_EMIT_BINARY, SIMD_COMP_NLT },
        { SN_CompareOrdered, OP_COMPPS, SIMD_VERSION_SSE1, SIMD_EMIT_BINARY, SIMD_COMP_ORD },
        { SN_CompareUnordered, OP_COMPPS, SIMD_VERSION_SSE1, SIMD_EMIT_BINARY, SIMD_COMP_UNORD },
+       { SN_ConvertToDouble, OP_CVTPS2PD, SIMD_VERSION_SSE2, SIMD_EMIT_UNARY },
+       { SN_ConvertToInt, OP_CVTPS2DQ, SIMD_VERSION_SSE2, SIMD_EMIT_UNARY },
+       { SN_ConvertToIntTruncated, OP_CVTTPS2DQ, SIMD_VERSION_SSE2, SIMD_EMIT_UNARY },
        { SN_DuplicateHigh, OP_DUPPS_HIGH, SIMD_VERSION_SSE3, SIMD_EMIT_UNARY },
        { SN_DuplicateLow, OP_DUPPS_LOW, SIMD_VERSION_SSE3, SIMD_EMIT_UNARY },
        { SN_HorizontalAdd, OP_HADDPS, SIMD_VERSION_SSE3, SIMD_EMIT_BINARY },
@@ -189,6 +192,9 @@ static const SimdIntrinsc vector2d_intrinsics[] = {
        { SN_CompareNotLessThan, OP_COMPPD, SIMD_VERSION_SSE1, SIMD_EMIT_BINARY, SIMD_COMP_NLT },
        { SN_CompareOrdered, OP_COMPPD, SIMD_VERSION_SSE1, SIMD_EMIT_BINARY, SIMD_COMP_ORD },
        { SN_CompareUnordered, OP_COMPPD, SIMD_VERSION_SSE1, SIMD_EMIT_BINARY, SIMD_COMP_UNORD },
+       { SN_ConvertToFloat, OP_CVTPD2PS, SIMD_VERSION_SSE2, SIMD_EMIT_UNARY },
+       { SN_ConvertToInt, OP_CVTPD2DQ, SIMD_VERSION_SSE2, SIMD_EMIT_UNARY },
+       { SN_ConvertToIntTruncated, OP_CVTTPD2DQ, SIMD_VERSION_SSE2, SIMD_EMIT_UNARY },
        { SN_Duplicate, OP_DUPPD, SIMD_VERSION_SSE3, SIMD_EMIT_UNARY },
        { SN_HorizontalAdd, OP_HADDPD, SIMD_VERSION_SSE3, SIMD_EMIT_BINARY },
        { SN_HorizontalSub, OP_HSUBPD, SIMD_VERSION_SSE3, SIMD_EMIT_BINARY },   
@@ -201,6 +207,7 @@ static const SimdIntrinsc vector2d_intrinsics[] = {
        { SN_PrefetchTemporal1stLevelCache, 0, SIMD_VERSION_SSE1, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_1 },
        { SN_PrefetchTemporal2ndLevelCache, 0, SIMD_VERSION_SSE1, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_2 },
        { SN_PrefetchNonTemporal, 0, SIMD_VERSION_SSE1, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_NTA },
+       { SN_Shuffle, OP_SHUFPD, SIMD_VERSION_SSE1, SIMD_EMIT_SHUFFLE },
        { SN_Sqrt, OP_SQRTPD, SIMD_VERSION_SSE1, SIMD_EMIT_UNARY },
        { SN_StoreAligned, OP_STOREX_ALIGNED_MEMBASE_REG, SIMD_VERSION_SSE1, SIMD_EMIT_STORE },
        { SN_get_X, 0, SIMD_VERSION_SSE1, SIMD_EMIT_GETTER_QWORD },
@@ -225,6 +232,7 @@ static const SimdIntrinsc vector2ul_intrinsics[] = {
        { SN_PrefetchTemporal1stLevelCache, 0, SIMD_VERSION_SSE1, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_1 },
        { SN_PrefetchTemporal2ndLevelCache, 0, SIMD_VERSION_SSE1, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_2 },
        { SN_PrefetchNonTemporal, 0, SIMD_VERSION_SSE1, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_NTA },
+       { SN_Shuffle, OP_SHUFPD, SIMD_VERSION_SSE1, SIMD_EMIT_SHUFFLE },
        { SN_StoreAligned, OP_STOREX_ALIGNED_MEMBASE_REG, SIMD_VERSION_SSE1, SIMD_EMIT_STORE },
        { SN_UnpackHigh, OP_UNPACK_HIGHQ, SIMD_VERSION_SSE1, SIMD_EMIT_BINARY },
        { SN_UnpackLow, OP_UNPACK_LOWQ, SIMD_VERSION_SSE1, SIMD_EMIT_BINARY },
@@ -253,6 +261,7 @@ static const SimdIntrinsc vector2l_intrinsics[] = {
        { SN_PrefetchTemporal1stLevelCache, 0, SIMD_VERSION_SSE1, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_1 },
        { SN_PrefetchTemporal2ndLevelCache, 0, SIMD_VERSION_SSE1, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_2 },
        { SN_PrefetchNonTemporal, 0, SIMD_VERSION_SSE1, SIMD_EMIT_PREFETCH, SIMD_PREFETCH_MODE_NTA },
+       { SN_Shuffle, OP_SHUFPD, SIMD_VERSION_SSE1, SIMD_EMIT_SHUFFLE },
        { SN_StoreAligned, OP_STOREX_ALIGNED_MEMBASE_REG, SIMD_VERSION_SSE1, SIMD_EMIT_STORE },
        { SN_UnpackHigh, OP_UNPACK_HIGHQ, SIMD_VERSION_SSE1, SIMD_EMIT_BINARY },
        { SN_UnpackLow, OP_UNPACK_LOWQ, SIMD_VERSION_SSE1, SIMD_EMIT_BINARY },
@@ -312,6 +321,8 @@ static const SimdIntrinsc vector4i_intrinsics[] = {
        { SN_ctor, OP_EXPAND_I4, SIMD_VERSION_SSE1, SIMD_EMIT_CTOR },
        { SN_CompareEqual, OP_PCMPEQD, SIMD_VERSION_SSE1, SIMD_EMIT_BINARY },
        { SN_CompareGreaterThan, OP_PCMPGTD, SIMD_VERSION_SSE1, SIMD_EMIT_BINARY },
+       { SN_ConvertToDouble, OP_CVTDQ2PD, SIMD_VERSION_SSE2, SIMD_EMIT_UNARY },
+       { SN_ConvertToFloat, OP_CVTDQ2PS, SIMD_VERSION_SSE2, SIMD_EMIT_UNARY },
        { SN_LoadAligned, 0, SIMD_VERSION_SSE1, SIMD_EMIT_LOAD_ALIGNED },
        { SN_LogicalRightShift, OP_PSHRD, SIMD_VERSION_SSE1, SIMD_EMIT_SHIFT },
        { SN_Max, OP_PMAXD, SIMD_VERSION_SSE41, SIMD_EMIT_BINARY },
@@ -996,6 +1007,30 @@ mono_type_elements_shift_bits (MonoType *type)
        g_assert_not_reached ();
 }
 
+static G_GNUC_UNUSED int
+mono_type_to_insert_op (MonoType *type)
+{
+       switch (type->type) {
+       case MONO_TYPE_I1:
+       case MONO_TYPE_U1:
+               return OP_INSERT_I1;
+       case MONO_TYPE_I2:
+       case MONO_TYPE_U2:
+               return OP_INSERT_I2;
+       case MONO_TYPE_I4:
+       case MONO_TYPE_U4:
+               return OP_INSERT_I4;
+       case MONO_TYPE_I8:
+       case MONO_TYPE_U8:
+               return OP_INSERT_I8;
+       case MONO_TYPE_R4:
+               return OP_INSERT_R4;
+       case MONO_TYPE_R8:
+               return OP_INSERT_R8;
+       }
+       g_assert_not_reached ();
+}
+
 static int
 mono_type_to_slow_insert_op (MonoType *type)
 {
@@ -1031,7 +1066,14 @@ simd_intrinsic_emit_setter (const SimdIntrinsc *intrinsic, MonoCompile *cfg, Mon
 
        size = mono_type_size (sig->params [0], &align); 
 
-       if (size == 2 || size == 4 || size == 8) {
+       if (COMPILE_LLVM (cfg)) {
+               MONO_INST_NEW (cfg, ins, mono_type_to_insert_op (sig->params [0]));
+               ins->klass = cmethod->klass;
+               ins->dreg = ins->sreg1 = dreg = load_simd_vreg (cfg, cmethod, args [0], &indirect);
+               ins->sreg2 = args [1]->dreg;
+               ins->inst_c0 = intrinsic->opcode;
+               MONO_ADD_INS (cfg->cbb, ins);
+       } else if (size == 2 || size == 4 || size == 8) {
                MONO_INST_NEW (cfg, ins, mono_type_to_slow_insert_op (sig->params [0]));
                ins->klass = cmethod->klass;
                /*This is a partial load so we encode the dependency on the previous value by setting dreg and sreg1 to the same value.*/
@@ -1314,24 +1356,32 @@ static MonoInst*
 simd_intrinsic_emit_shuffle (const SimdIntrinsc *intrinsic, MonoCompile *cfg, MonoMethod *cmethod, MonoInst **args)
 {
        MonoInst *ins;
-       int vreg;
+       int vreg, vreg2 = -1;
+       int param_count = mono_method_signature (cmethod)->param_count;
 
-       /*TODO Exposing shuffle is not a good thing as it's non obvious. We should come up with better abstractions*/
-
-       if (args [1]->opcode != OP_ICONST) {
+       if (args [param_count - 1]->opcode != OP_ICONST) {
                /*TODO Shuffle with non literals is not yet supported */
                return NULL;
        }
+
        vreg = get_simd_vreg (cfg, cmethod, args [0]);
-       NULLIFY_INS (args [1]);
+       if (param_count == 3)
+               vreg2 = get_simd_vreg (cfg, cmethod, args [1]);
+
+       NULLIFY_INS (args [param_count - 1]);
+
 
        MONO_INST_NEW (cfg, ins, intrinsic->opcode);
        ins->klass = cmethod->klass;
        ins->sreg1 = vreg;
-       ins->inst_c0 = args [1]->inst_c0;
+       ins->sreg2 = vreg2;
+       ins->inst_c0 = args [param_count - 1]->inst_c0;
        ins->type = STACK_VTYPE;
        ins->dreg = alloc_ireg (cfg);
        MONO_ADD_INS (cfg->cbb, ins);
+
+       if (param_count == 3 && ins->opcode == OP_PSHUFLED)
+               ins->opcode = OP_SHUFPS;
        return ins;
 }