[Arm64] genSIMDIntrinsicNarrow/Widen
authorSteve MacLean <sdmaclea.qdt@qualcommdatacenter.com>
Fri, 3 Nov 2017 21:41:59 +0000 (17:41 -0400)
committerSteve MacLean <sdmaclea.qdt@qualcommdatacenter.com>
Mon, 6 Nov 2017 20:41:22 +0000 (15:41 -0500)
src/jit/codegenarm64.cpp
src/jit/emitarm64.cpp

index 74ef06d..6c21c9b 100644 (file)
@@ -4219,11 +4219,17 @@ void CodeGen::genSIMDIntrinsicWiden(GenTreeSIMD* simdNode)
 
     instruction ins = getOpForSIMDIntrinsic(simdNode->gtSIMDIntrinsicID, baseType);
 
-    bool     is16B = (simdNode->gtSIMDIntrinsicID == SIMDIntrinsicWidenHi);
-    emitAttr attr  = is16B ? EA_16BYTE : EA_8BYTE;
-    insOpts  opt   = genGetSimdInsOpt(is16B, baseType);
+    if (varTypeIsFloating(baseType))
+    {
+        getEmitter()->emitIns_R_R(ins, EA_8BYTE, targetReg, op1Reg);
+    }
+    else
+    {
+        bool    is16B = (simdNode->gtSIMDIntrinsicID == SIMDIntrinsicWidenHi);
+        insOpts opt   = genGetSimdInsOpt(is16B, baseType);
 
-    getEmitter()->emitIns_R_R(ins, attr, targetReg, op1Reg, opt);
+        getEmitter()->emitIns_R_R(ins, is16B ? EA_16BYTE : EA_8BYTE, targetReg, op1Reg, opt);
+    }
 
     genProduceReg(simdNode);
 }
@@ -4258,19 +4264,48 @@ void CodeGen::genSIMDIntrinsicNarrow(GenTreeSIMD* simdNode)
     assert(genIsValidFloatReg(op2Reg));
     assert(genIsValidFloatReg(targetReg));
     assert(op2Reg != targetReg);
+    assert(simdNode->gtSIMDSize == 16);
 
     instruction ins = getOpForSIMDIntrinsic(simdNode->gtSIMDIntrinsicID, baseType);
-
     assert((ins == INS_fcvtn) || (ins == INS_xtn));
 
-    instruction ins2 = ins == INS_fcvtn ? INS_fcvtn2 : INS_xtn2;
-
-    bool     is16B = (simdNode->gtSIMDSize > 8);
-    emitAttr attr  = is16B ? EA_16BYTE : EA_8BYTE;
-    insOpts  opt   = genGetSimdInsOpt(is16B, baseType);
+    if (ins == INS_fcvtn)
+    {
+        getEmitter()->emitIns_R_R(INS_fcvtn, EA_8BYTE, targetReg, op1Reg);
+        getEmitter()->emitIns_R_R(INS_fcvtn2, EA_8BYTE, targetReg, op2Reg);
+    }
+    else
+    {
+        insOpts opt  = INS_OPTS_NONE;
+        insOpts opt2 = INS_OPTS_NONE;
 
-    getEmitter()->emitIns_R_R(ins, attr, targetReg, op1Reg, opt);
-    getEmitter()->emitIns_R_R(ins2, attr, targetReg, op2Reg, opt);
+        // This is not the same as genGetSimdInsOpt()
+        // Basetype is the soure operand type
+        // However encoding is based on the destination operand type which is 1/2 the basetype.
+        switch (baseType)
+        {
+            case TYP_ULONG:
+            case TYP_LONG:
+                opt  = INS_OPTS_2S;
+                opt2 = INS_OPTS_4S;
+                break;
+            case TYP_UINT:
+            case TYP_INT:
+                opt  = INS_OPTS_4H;
+                opt2 = INS_OPTS_8H;
+                break;
+            case TYP_CHAR:
+            case TYP_SHORT:
+                opt  = INS_OPTS_8B;
+                opt2 = INS_OPTS_16B;
+                break;
+            default:
+                assert(!"Unsupported narrowing element type");
+                unreached();
+        }
+        getEmitter()->emitIns_R_R(INS_xtn, EA_8BYTE, targetReg, op1Reg, opt);
+        getEmitter()->emitIns_R_R(INS_xtn2, EA_16BYTE, targetReg, op2Reg, opt2);
+    }
 
     genProduceReg(simdNode);
 }
index 56df042..161597e 100644 (file)
@@ -3985,8 +3985,8 @@ void emitter::emitIns_R_R(
             assert(isValidVectorDatasize(size));
             assert(isValidArrangement(size, opt));
             elemsize = optGetElemsize(opt);
-            assert(size != EA_16BYTE);    // Narrowing must start with wide format
-            assert(elemsize != EA_1BYTE); // Narrowing must start with more than one byte src
+            assert(size == (ins == INS_xtn) ? EA_8BYTE : EA_16BYTE); // Size is determined by instruction
+            assert(elemsize != EA_8BYTE);                            // Narrowing must not end with 8 byte data
             fmt = IF_DV_2M;
             break;
 
@@ -4132,23 +4132,13 @@ void emitter::emitIns_R_R(
 
         case INS_fcvtl:
         case INS_fcvtl2:
-            assert(isVectorRegister(reg1));
-            assert(isVectorRegister(reg2));
-            assert(isValidVectorDatasize(size));
-            assert(isValidArrangement(size, opt));
-            elemsize = optGetElemsize(opt);
-            assert(elemsize == EA_4BYTE); // Widening from Float to Double, opt should correspond to src layout
-            fmt = IF_DV_2G;
-            break;
-
         case INS_fcvtn:
         case INS_fcvtn2:
             assert(isVectorRegister(reg1));
             assert(isVectorRegister(reg2));
             assert(isValidVectorDatasize(size));
-            assert(isValidArrangement(size, opt));
-            elemsize = optGetElemsize(opt);
-            assert(elemsize == EA_8BYTE); // Narrowing from Double to Float, opt should correspond to src layout
+            assert(insOptsNone(opt));
+            assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
             fmt = IF_DV_2G;
             break;