Merge pull request #11713 from mskvortsov/Ckfinite
authorBruce Forstall <brucefo@microsoft.com>
Fri, 19 May 2017 22:48:46 +0000 (15:48 -0700)
committerGitHub <noreply@github.com>
Fri, 19 May 2017 22:48:46 +0000 (15:48 -0700)
[RyuJIT/ARM32] Ckfinite codegen

src/jit/codegenarm.cpp
src/jit/codegenarmarch.cpp
src/jit/lsraarm.cpp

index 7102279..380cf26 100644 (file)
@@ -1230,6 +1230,53 @@ void CodeGen::genCodeForDivMod(GenTreeOp* tree)
 }
 
 //------------------------------------------------------------------------
+// genCkfinite: Generate code for ckfinite opcode.
+//
+// Arguments:
+//    treeNode - The GT_CKFINITE node
+//
+// Return Value:
+//    None.
+//
+// Assumptions:
+//    GT_CKFINITE node has reserved an internal register.
+//
+void CodeGen::genCkfinite(GenTreePtr treeNode)
+{
+    assert(treeNode->OperGet() == GT_CKFINITE);
+
+    emitter*  emit       = getEmitter();
+    var_types targetType = treeNode->TypeGet();
+    regNumber intReg     = treeNode->GetSingleTempReg();
+    regNumber fpReg      = genConsumeReg(treeNode->gtOp.gtOp1);
+    regNumber targetReg  = treeNode->gtRegNum;
+
+    // Extract and sign-extend the exponent into an integer register
+    if (targetType == TYP_FLOAT)
+    {
+        emit->emitIns_R_R(INS_vmov_f2i, EA_4BYTE, intReg, fpReg);
+        emit->emitIns_R_R_I_I(INS_sbfx, EA_4BYTE, intReg, intReg, 23, 8);
+    }
+    else
+    {
+        assert(targetType == TYP_DOUBLE);
+        emit->emitIns_R_R(INS_vmov_f2i, EA_4BYTE, intReg, REG_NEXT(fpReg));
+        emit->emitIns_R_R_I_I(INS_sbfx, EA_4BYTE, intReg, intReg, 20, 11);
+    }
+
+    // If exponent is all 1's, throw ArithmeticException
+    emit->emitIns_R_I(INS_add, EA_4BYTE, intReg, 1, INS_FLAGS_SET);
+    genJumpToThrowHlpBlk(EJ_eq, SCK_ARITH_EXCPN);
+
+    // If it's a finite value, copy it to targetReg
+    if (targetReg != fpReg)
+    {
+        emit->emitIns_R_R(ins_Copy(targetType), emitTypeSize(treeNode), targetReg, fpReg);
+    }
+    genProduceReg(treeNode);
+}
+
+//------------------------------------------------------------------------
 // genCodeForCompare: Produce code for a GT_EQ/GT_NE/GT_LT/GT_LE/GT_GE/GT_GT node.
 //
 // Arguments:
index e85ea6a..590c67e 100644 (file)
@@ -195,10 +195,6 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode)
             genCodeForMulHi(treeNode->AsOp());
             break;
 
-        case GT_CKFINITE:
-            genCkfinite(treeNode);
-            break;
-
         case GT_SWAP:
             genCodeForSwap(treeNode->AsOp());
             break;
@@ -209,6 +205,10 @@ void CodeGen::genCodeForTreeNode(GenTreePtr treeNode)
 
 #endif // _TARGET_ARM64_
 
+        case GT_CKFINITE:
+            genCkfinite(treeNode);
+            break;
+
         case GT_INTRINSIC:
             genIntrinsic(treeNode);
             break;
index 0d1cfe6..2c13954 100644 (file)
@@ -629,6 +629,12 @@ void Lowering::TreeNodeInfoInit(GenTree* tree)
             TreeNodeInfoInitCmp(tree);
             break;
 
+        case GT_CKFINITE:
+            info->srcCount         = 1;
+            info->dstCount         = 1;
+            info->internalIntCount = 1;
+            break;
+
         case GT_CALL:
             TreeNodeInfoInitCall(tree->AsCall());
             break;