Get rid of Lowering::getCastDescription
authorMike Danes <onemihaid@hotmail.com>
Sun, 5 Aug 2018 16:53:50 +0000 (19:53 +0300)
committerMike Danes <onemihaid@hotmail.com>
Thu, 6 Sep 2018 15:53:38 +0000 (18:53 +0300)
src/jit/codegenarmarch.cpp
src/jit/codegenxarch.cpp
src/jit/gentree.cpp
src/jit/gentree.h
src/jit/lower.cpp
src/jit/lower.h

index c59edda..b3a2ee2 100644 (file)
@@ -2858,6 +2858,8 @@ void CodeGen::genJmpMethod(GenTree* jmp)
 //
 void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, regNumber reg)
 {
+    assert(cast->IsOverflowCheckRequired());
+
     const var_types srcType      = genActualType(cast->gtGetOp1()->TypeGet());
     const bool      srcUnsigned  = cast->IsUnsigned();
     const unsigned  srcSize      = genTypeSize(srcType);
@@ -2984,9 +2986,7 @@ void CodeGen::genIntToIntCast(GenTreeCast* cast)
     instruction ins = INS_none;
     emitAttr    insSize;
 
-    Lowering::CastInfo castInfo;
-    Lowering::getCastDescription(cast, &castInfo);
-    if (castInfo.requiresOverflowCheck)
+    if (cast->IsOverflowCheckRequired())
     {
         genIntCastOverflowCheck(cast, srcReg);
 
index 352f27b..555c550 100644 (file)
@@ -6353,6 +6353,8 @@ void CodeGen::genLongToIntCast(GenTree* cast)
 //
 void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, regNumber reg)
 {
+    assert(cast->IsOverflowCheckRequired());
+
     const var_types srcType      = genActualType(cast->gtGetOp1()->TypeGet());
     const bool      srcUnsigned  = cast->IsUnsigned();
     const unsigned  srcSize      = genTypeSize(srcType);
@@ -6441,7 +6443,6 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, regNumber reg)
 //    On x86 casts to (U)BYTE require that the source be in a byte register.
 //
 // TODO-XArch-CQ: Allow castOp to be a contained node without an assigned register.
-// TODO: refactor to use getCastDescription
 //
 void CodeGen::genIntToIntCast(GenTreeCast* cast)
 {
@@ -6469,9 +6470,7 @@ void CodeGen::genIntToIntCast(GenTreeCast* cast)
     instruction ins = INS_none;
     emitAttr    insSize;
 
-    Lowering::CastInfo castInfo;
-    Lowering::getCastDescription(cast, &castInfo);
-    if (castInfo.requiresOverflowCheck)
+    if (cast->IsOverflowCheckRequired())
     {
         genIntCastOverflowCheck(cast, srcReg);
 
index 94152ea..3504aee 100644 (file)
@@ -17940,3 +17940,43 @@ regNumber GenTree::ExtractTempReg(regMaskTP mask /* = (regMaskTP)-1 */)
     gtRsvdRegs &= ~tempRegMask;
     return genRegNumFromMask(tempRegMask);
 }
+
+//------------------------------------------------------------------------
+// IsOverflowCheckRequired: Check if this cast node requires an overflow check.
+//
+// Notes:
+//     Unlike gtOverflow, this function returns true only for casts that actually
+//     require an overflow check:
+//       - narrowing casts (e.g. TYP_INT -> TYP_SHORT, TYP_LONG -> TYP_INT)
+//       - sign changing casts (e.g. TYP_INT -> TYP_UINT, TYP_ULONG -> TYP_LONG)
+//       - widening from signed to unsigned casts (only TYP_INT -> TYP_ULONG)
+//
+bool GenTreeCast::IsOverflowCheckRequired() const
+{
+    if (!gtOverflow())
+    {
+        return false;
+    }
+
+    const var_types srcType      = genActualType(gtGetOp1()->TypeGet());
+    const bool      srcUnsigned  = IsUnsigned();
+    const unsigned  srcSize      = genTypeSize(srcType);
+    const var_types castType     = gtCastType;
+    const bool      castUnsigned = varTypeIsUnsigned(castType);
+    const unsigned  castSize     = genTypeSize(castType);
+
+    if (castSize > srcSize)
+    {
+        // Overflow check required for widening from signed to unsigned.
+        return !srcUnsigned && castUnsigned;
+    }
+
+    if (castSize == srcSize)
+    {
+        // Overflow check required for any sign changing cast.
+        return srcUnsigned != castUnsigned;
+    }
+
+    // Overflow check required for any narrowing cast.
+    return true;
+}
index ef86c5d..24f52f4 100644 (file)
@@ -2901,6 +2901,9 @@ struct GenTreeCast : public GenTreeOp
     {
     }
 #endif
+
+    // Returns true for casts that require an overflow check.
+    bool IsOverflowCheckRequired() const;
 };
 
 // GT_BOX nodes are place markers for boxed values.  The "real" tree
index 0d0f480..fb5fab2 100644 (file)
@@ -5519,121 +5519,6 @@ bool Lowering::NodesAreEquivalentLeaves(GenTree* tree1, GenTree* tree2)
     }
 }
 
-/**
- * Get common information required to handle a cast instruction
- */
-void Lowering::getCastDescription(GenTree* treeNode, CastInfo* castInfo)
-{
-    // Intialize castInfo
-    memset(castInfo, 0, sizeof(*castInfo));
-
-    GenTree* castOp = treeNode->gtCast.CastOp();
-
-    var_types dstType = treeNode->CastToType();
-    var_types srcType = genActualType(castOp->TypeGet());
-
-    castInfo->unsignedDest   = varTypeIsUnsigned(dstType);
-    castInfo->unsignedSource = varTypeIsUnsigned(srcType);
-
-    // If necessary, force the srcType to unsigned when the GT_UNSIGNED flag is set.
-    if (!castInfo->unsignedSource && (treeNode->gtFlags & GTF_UNSIGNED) != 0)
-    {
-        srcType                  = genUnsignedType(srcType);
-        castInfo->unsignedSource = true;
-    }
-
-    if (treeNode->gtOverflow() &&
-        (genTypeSize(srcType) >= genTypeSize(dstType) || (srcType == TYP_INT && dstType == TYP_ULONG)))
-    {
-        castInfo->requiresOverflowCheck = true;
-    }
-
-    if (castInfo->requiresOverflowCheck)
-    {
-        ssize_t typeMin       = 0;
-        ssize_t typeMax       = 0;
-        ssize_t typeMask      = 0;
-        bool    signCheckOnly = false;
-
-        // Do we need to compare the value, or just check masks
-        switch (dstType)
-        {
-            default:
-                assert(!"unreachable: getCastDescription");
-                break;
-
-            case TYP_BYTE:
-                typeMask = ssize_t((int)0xFFFFFF80);
-                typeMin  = SCHAR_MIN;
-                typeMax  = SCHAR_MAX;
-                break;
-
-            case TYP_UBYTE:
-                typeMask = ssize_t((int)0xFFFFFF00L);
-                break;
-
-            case TYP_SHORT:
-                typeMask = ssize_t((int)0xFFFF8000);
-                typeMin  = SHRT_MIN;
-                typeMax  = SHRT_MAX;
-                break;
-
-            case TYP_USHORT:
-                typeMask = ssize_t((int)0xFFFF0000L);
-                break;
-
-            case TYP_INT:
-                if (srcType == TYP_UINT)
-                {
-                    signCheckOnly = true;
-                }
-                else
-                {
-#ifdef _TARGET_64BIT_
-                    typeMask = 0xFFFFFFFF80000000LL;
-#else
-                    typeMask = 0x80000000;
-#endif
-                    typeMin = INT_MIN;
-                    typeMax = INT_MAX;
-                }
-                break;
-
-            case TYP_UINT:
-                if (srcType == TYP_INT)
-                {
-                    signCheckOnly = true;
-                }
-                else
-                {
-#ifdef _TARGET_64BIT_
-                    typeMask = 0xFFFFFFFF00000000LL;
-#else
-                    typeMask = 0x00000000;
-#endif
-                }
-                break;
-
-            case TYP_LONG:
-                signCheckOnly = true;
-                break;
-
-            case TYP_ULONG:
-                signCheckOnly = true;
-                break;
-        }
-
-        if (signCheckOnly)
-        {
-            castInfo->signCheckOnly = true;
-        }
-
-        castInfo->typeMax  = typeMax;
-        castInfo->typeMin  = typeMin;
-        castInfo->typeMask = typeMask;
-    }
-}
-
 //------------------------------------------------------------------------
 // Containment Analysis
 //------------------------------------------------------------------------
index 656e177..c78e26b 100644 (file)
@@ -30,23 +30,6 @@ public:
     }
     virtual void DoPhase() override;
 
-    // If requiresOverflowCheck is false, all other values will be unset
-    struct CastInfo
-    {
-        bool requiresOverflowCheck; // Will the cast require an overflow check
-        bool unsignedSource;        // Is the source unsigned
-        bool unsignedDest;          // is the dest unsigned
-
-        // All other fields are only meaningful if requiresOverflowCheck is set.
-
-        ssize_t typeMin;       // Lowest storable value of the dest type
-        ssize_t typeMax;       // Highest storable value of the dest type
-        ssize_t typeMask;      // For converting from/to unsigned
-        bool    signCheckOnly; // For converting between unsigned/signed int
-    };
-
-    static void getCastDescription(GenTree* treeNode, CastInfo* castInfo);
-
     // This variant of LowerRange is called from outside of the main Lowering pass,
     // so it creates its own instance of Lowering to do so.
     void LowerRange(BasicBlock* block, LIR::ReadOnlyRange& range)