Remove most ARM NYI (#17365)
authorBruce Forstall <brucefo@microsoft.com>
Tue, 3 Apr 2018 21:32:19 +0000 (14:32 -0700)
committerGitHub <noreply@github.com>
Tue, 3 Apr 2018 21:32:19 +0000 (14:32 -0700)
* Remove most ARM NYI

Convert most existing ARM NYI either to asserts or remove
the code entirely.

A few NYI are left, including:
1. GT_BITCAST from 'int' to 'float'
2. initblk unrolling is unimplemented: https://github.com/dotnet/coreclr/issues/16349
3. SIMD-related NYI (SIMD is currently unimplemented)

src/jit/codegenarm.cpp
src/jit/codegenarmarch.cpp
src/jit/codegenxarch.cpp
src/jit/compiler.h
src/jit/lowerarmarch.cpp
src/jit/lsraarm.cpp

index 639d259..c405e33 100644 (file)
@@ -239,17 +239,6 @@ void CodeGen::genCodeForBinary(GenTree* treeNode)
     genProduceReg(treeNode);
 }
 
-//------------------------------------------------------------------------
-// genLockedInstructions: Generate code for the locked operations.
-//
-// Notes:
-//    Handles GT_LOCKADD, GT_XCHG, GT_XADD nodes.
-//
-void CodeGen::genLockedInstructions(GenTreeOp* treeNode)
-{
-    NYI("genLockedInstructions");
-}
-
 //--------------------------------------------------------------------------------------
 // genLclHeap: Generate code for localloc
 //
@@ -988,17 +977,10 @@ void CodeGen::genCodeForStoreLclFld(GenTreeLclFld* tree)
     GenTree*    data = tree->gtOp1;
     instruction ins  = ins_Store(targetType);
     emitAttr    attr = emitTypeSize(targetType);
-    if (data->isContainedIntOrIImmed())
-    {
-        assert(data->IsIntegralConst(0));
-        NYI_ARM("st.lclFld contained operand");
-    }
-    else
-    {
-        assert(!data->isContained());
-        genConsumeReg(data);
-        emit->emitIns_S_R(ins, attr, data->gtRegNum, varNum, offset);
-    }
+
+    assert(!data->isContained());
+    genConsumeReg(data);
+    emit->emitIns_S_R(ins, attr, data->gtRegNum, varNum, offset);
 
     genUpdateLife(tree);
     varDsc->lvRegNum = REG_STK;
@@ -1039,17 +1021,8 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* tree)
     {
         genConsumeRegs(data);
 
-        regNumber dataReg = REG_NA;
-        if (data->isContainedIntOrIImmed())
-        {
-            assert(data->IsIntegralConst(0));
-            NYI_ARM("st.lclVar contained operand");
-        }
-        else
-        {
-            assert(!data->isContained());
-            dataReg = data->gtRegNum;
-        }
+        assert(!data->isContained());
+        regNumber dataReg = data->gtRegNum;
         assert(dataReg != REG_NA);
 
         if (targetReg == REG_NA) // store into stack based LclVar
@@ -1282,9 +1255,6 @@ void CodeGen::genCodeForStoreInd(GenTreeStoreInd* tree)
         // registers are taken care of.
         genConsumeOperands(tree);
 
-#if NOGC_WRITE_BARRIERS
-        NYI_ARM("NOGC_WRITE_BARRIERS");
-#else
         // At this point, we should not have any interference.
         // That is, 'data' must not be in REG_ARG_0,
         //  as that is where 'addr' must go.
@@ -1301,7 +1271,6 @@ void CodeGen::genCodeForStoreInd(GenTreeStoreInd* tree)
         {
             inst_RV_RV(INS_mov, REG_ARG_1, data->gtRegNum, data->TypeGet());
         }
-#endif // NOGC_WRITE_BARRIERS
 
         genGCWriteBarrier(tree, writeBarrierForm);
     }
@@ -1694,9 +1663,7 @@ void CodeGen::genStoreLongLclVar(GenTree* treeNode)
         GenTree* loVal = op1->gtGetOp1();
         GenTree* hiVal = op1->gtGetOp2();
 
-        // NYI: Contained immediates.
-        NYI_IF((loVal->gtRegNum == REG_NA) || (hiVal->gtRegNum == REG_NA),
-               "Store of long lclVar with contained immediate");
+        noway_assert((loVal->gtRegNum != REG_NA) && (hiVal->gtRegNum != REG_NA));
 
         emit->emitIns_S_R(ins_Store(TYP_INT), EA_4BYTE, loVal->gtRegNum, lclNum, 0);
         emit->emitIns_S_R(ins_Store(TYP_INT), EA_4BYTE, hiVal->gtRegNum, lclNum, genTypeSize(TYP_INT));
index d4f6343..79cea8d 100644 (file)
@@ -160,7 +160,9 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
 #else  // !_TARGET_ARM64_
                 if (varTypeIsFloating(treeNode))
                 {
-                    NYI_ARM("genRegCopy from 'int' to 'float'");
+                    // GT_BITCAST on ARM is only used to cast floating-point arguments to integer
+                    // registers. Nobody generates GT_BITCAST from int to float currently.
+                    NYI_ARM("GT_BITCAST from 'int' to 'float'");
                 }
                 else
                 {
@@ -172,7 +174,8 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
                     }
                     else
                     {
-                        regNumber otherReg = (regNumber)treeNode->AsMultiRegOp()->gtOtherReg;
+                        assert(op1->TypeGet() == TYP_DOUBLE);
+                        regNumber otherReg = treeNode->AsMultiRegOp()->gtOtherReg;
                         assert(otherReg != REG_NA);
                         inst_RV_RV_RV(INS_vmov_d2i, targetReg, otherReg, genConsumeReg(op1), EA_8BYTE);
                     }
@@ -328,28 +331,27 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
         case GT_PUTARG_SPLIT:
             genPutArgSplit(treeNode->AsPutArgSplit());
             break;
-#endif
+#endif // _TARGET_ARM_
 
         case GT_CALL:
             genCallInstruction(treeNode->AsCall());
             break;
 
+        case GT_MEMORYBARRIER:
+            instGen_MemoryBarrier();
+            break;
+
+#ifdef _TARGET_ARM64_
         case GT_LOCKADD:
         case GT_XCHG:
         case GT_XADD:
             genLockedInstructions(treeNode->AsOp());
             break;
 
-        case GT_MEMORYBARRIER:
-            instGen_MemoryBarrier();
-            break;
-
         case GT_CMPXCHG:
-            NYI_ARM("GT_CMPXCHG");
-#ifdef _TARGET_ARM64_
             genCodeForCmpXchg(treeNode->AsCmpXchg());
-#endif
             break;
+#endif // _TARGET_ARM64_
 
         case GT_RELOAD:
             // do nothing - reload is just a marker.
@@ -511,12 +513,12 @@ void CodeGen::genIntrinsic(GenTree* treeNode)
             genConsumeOperands(treeNode->AsOp());
             getEmitter()->emitInsBinary(INS_frintm, emitActualTypeSize(treeNode), treeNode, srcNode);
             break;
-#endif
+
         case CORINFO_INTRINSIC_Round:
-            NYI_ARM("genIntrinsic for round - not implemented yet");
             genConsumeOperands(treeNode->AsOp());
-            getEmitter()->emitInsBinary(INS_ROUND, emitActualTypeSize(treeNode), treeNode, srcNode);
+            getEmitter()->emitInsBinary(INS_frintn, emitActualTypeSize(treeNode), treeNode, srcNode);
             break;
+#endif // _TARGET_ARM64_
 
         case CORINFO_INTRINSIC_Sqrt:
             genConsumeOperands(treeNode->AsOp());
@@ -2116,6 +2118,8 @@ void CodeGen::genRegCopy(GenTree* treeNode)
 #else  // !_TARGET_ARM64_
         if (varTypeIsFloating(treeNode))
         {
+            // GT_COPY from 'int' to 'float' currently can't happen. Maybe if ARM SIMD is implemented
+            // it will happen, according to the comment above?
             NYI_ARM("genRegCopy from 'int' to 'float'");
         }
         else
index 9f7f38d..a6dc3b5 100644 (file)
@@ -3576,7 +3576,7 @@ void CodeGen::genLockedInstructions(GenTreeOp* treeNode)
 }
 
 //------------------------------------------------------------------------
-// genCodeForSwap: Produce code for a GT_CMPXCHG node.
+// genCodeForCmpXchg: Produce code for a GT_CMPXCHG node.
 //
 // Arguments:
 //    tree - the GT_CMPXCHG node
@@ -8640,9 +8640,7 @@ void CodeGen::genStoreLongLclVar(GenTree* treeNode)
         GenTree* loVal = op1->gtGetOp1();
         GenTree* hiVal = op1->gtGetOp2();
 
-        // NYI: Contained immediates.
-        NYI_IF((loVal->gtRegNum == REG_NA) || (hiVal->gtRegNum == REG_NA),
-               "Store of long lclVar with contained immediate");
+        noway_assert((loVal->gtRegNum != REG_NA) && (hiVal->gtRegNum != REG_NA));
 
         emit->emitIns_S_R(ins_Store(TYP_INT), EA_4BYTE, loVal->gtRegNum, lclNum, 0);
         emit->emitIns_S_R(ins_Store(TYP_INT), EA_4BYTE, hiVal->gtRegNum, lclNum, genTypeSize(TYP_INT));
index 80c90e8..a39f714 100644 (file)
@@ -10528,7 +10528,7 @@ const instruction INS_ADDC            = INS_adc;
 const instruction INS_SUBC            = INS_sbb;
 const instruction INS_NOT             = INS_not;
 
-#endif
+#endif // _TARGET_XARCH_
 
 #ifdef _TARGET_ARM_
 
@@ -10550,22 +10550,20 @@ const instruction INS_ADDC            = INS_adc;
 const instruction INS_SUBC            = INS_sbc;
 const instruction INS_NOT             = INS_mvn;
 
-const instruction INS_ABS   = INS_vabs;
-const instruction INS_ROUND = INS_invalid;
-const instruction INS_SQRT  = INS_vsqrt;
+const instruction INS_ABS  = INS_vabs;
+const instruction INS_SQRT = INS_vsqrt;
 
-#endif
+#endif // _TARGET_ARM_
 
 #ifdef _TARGET_ARM64_
 
 const instruction INS_MULADD     = INS_madd;
 const instruction INS_BREAKPOINT = INS_bkpt;
 
-const instruction INS_ABS   = INS_fabs;
-const instruction INS_ROUND = INS_frintn;
-const instruction INS_SQRT  = INS_fsqrt;
+const instruction INS_ABS  = INS_fabs;
+const instruction INS_SQRT = INS_fsqrt;
 
-#endif
+#endif // _TARGET_ARM64_
 
 /*****************************************************************************/
 
index 0d755fe..f18793d 100644 (file)
@@ -409,17 +409,12 @@ void Lowering::LowerCast(GenTree* tree)
     if (varTypeIsFloating(srcType))
     {
         noway_assert(!tree->gtOverflow());
+        assert(!varTypeIsSmall(dstType)); // fgMorphCast creates intermediate casts when converting from float to small
+                                          // int.
     }
 
     assert(!varTypeIsSmall(srcType));
 
-    // case of src is a floating point type and dst is a small type.
-    if (varTypeIsFloating(srcType) && varTypeIsSmall(dstType))
-    {
-        NYI_ARM("Lowering for cast from float to small type"); // Not tested yet.
-        tmpType = TYP_INT;
-    }
-
     if (tmpType != TYP_UNDEF)
     {
         GenTree* tmp = comp->gtNewCastNode(tmpType, op1, tree->IsUnsigned(), tmpType);
index 63e93fa..05a0238 100644 (file)
@@ -237,7 +237,7 @@ void LinearScan::BuildNode(GenTree* tree)
                     assert(info->dstCount == 1);
                     break;
                 default:
-                    NYI_ARM("LinearScan::Build for GT_INTRINSIC");
+                    unreached();
                     break;
             }
         }
@@ -756,15 +756,6 @@ void LinearScan::BuildNode(GenTree* tree)
         }
         break;
 
-        default:
-#ifdef DEBUG
-            char message[256];
-            _snprintf_s(message, _countof(message), _TRUNCATE, "NYI: Unimplemented node type %s",
-                        GenTree::OpName(tree->OperGet()));
-            NYIRAW(message);
-#else
-            NYI_ARM("BuildNode default case");
-#endif
         case GT_LCL_FLD:
         case GT_LCL_FLD_ADDR:
         case GT_LCL_VAR:
@@ -788,6 +779,15 @@ void LinearScan::BuildNode(GenTree* tree)
             info->srcCount         = appendBinaryLocationInfoToList(tree->AsOp());
             assert(info->srcCount == 2);
             break;
+
+        default:
+#ifdef DEBUG
+            char message[256];
+            _snprintf_s(message, _countof(message), _TRUNCATE, "NYI: Unimplemented node type %s",
+                        GenTree::OpName(tree->OperGet()));
+            NYIRAW(message);
+#endif
+            unreached();
     } // end switch (tree->OperGet())
 
     if (tree->IsUnusedValue() && (info->dstCount != 0))