Fix VSO 462269.
authorPat Gavlin <pagavlin@microsoft.com>
Thu, 13 Jul 2017 19:59:29 +0000 (12:59 -0700)
committerPat Gavlin <pagavlin@microsoft.com>
Wed, 9 Aug 2017 15:12:39 +0000 (08:12 -0700)
When decomposing a long compare on 32-bit platforms, the operands to the
decomposed compare must be sign- or zero-extended appropriately.

src/jit/decomposelongs.cpp
src/jit/decomposelongs.h
tests/src/JIT/Regression/JitBlue/DevDiv_462269/DevDiv_462269.il [new file with mode: 0644]
tests/src/JIT/Regression/JitBlue/DevDiv_462269/DevDiv_462269.ilproj [new file with mode: 0644]

index 96d3b0b..7cf1049 100644 (file)
@@ -607,7 +607,8 @@ GenTree* DecomposeLongs::DecomposeCast(LIR::Use& use)
             // check provided by codegen.
             //
 
-            loResult = loSrcOp;
+            const bool signExtend = (cast->gtFlags & GTF_UNSIGNED) == 0;
+            loResult              = EnsureIntSized(loSrcOp, signExtend);
 
             hiResult                       = cast;
             hiResult->gtType               = TYP_INT;
@@ -657,7 +658,9 @@ GenTree* DecomposeLongs::DecomposeCast(LIR::Use& use)
             }
             else if (varTypeIsUnsigned(srcType))
             {
-                loResult = cast->gtGetOp1();
+                const bool signExtend = (cast->gtFlags & GTF_UNSIGNED) == 0;
+                loResult              = EnsureIntSized(cast->gtGetOp1(), signExtend);
+
                 hiResult = m_compiler->gtNewZeroConNode(TYP_INT);
 
                 Range().InsertAfter(cast, hiResult);
@@ -1918,6 +1921,43 @@ GenTree* DecomposeLongs::RepresentOpAsLocalVar(GenTree* op, GenTree* user, GenTr
 }
 
 //------------------------------------------------------------------------
+// DecomposeLongs::EnsureIntSized:
+//    Checks to see if the given node produces an int-sized value and
+//    performs the appropriate widening if it does not.
+//
+// Arguments:
+//    node       - The node that may need to be widened.
+//    signExtend - True if the value should be sign-extended; false if it
+//                 should be zero-extended.
+//
+// Return Value:
+//    The node that produces the widened value.
+GenTree* DecomposeLongs::EnsureIntSized(GenTree* node, bool signExtend)
+{
+    assert(node != nullptr);
+    if (!varTypeIsSmall(node))
+    {
+        assert(genTypeSize(node) == genTypeSize(TYP_INT));
+        return node;
+    }
+
+    if (node->OperIs(GT_LCL_VAR) && !m_compiler->lvaTable[node->AsLclVarCommon()->gtLclNum].lvNormalizeOnLoad())
+    {
+        node->gtType = TYP_INT;
+        return node;
+    }
+
+    GenTree* const cast = m_compiler->gtNewCastNode(TYP_INT, node, node->TypeGet());
+    if (!signExtend)
+    {
+        cast->gtFlags |= GTF_UNSIGNED;
+    }
+
+    Range().InsertAfter(node, cast);
+    return cast;
+}
+
+//------------------------------------------------------------------------
 // GetHiOper: Convert arithmetic operator to "high half" operator of decomposed node.
 //
 // Arguments:
index ff4f4ac..7a0d6ff 100644 (file)
@@ -61,6 +61,7 @@ private:
     // Helper functions
     GenTree* FinalizeDecomposition(LIR::Use& use, GenTree* loResult, GenTree* hiResult, GenTree* insertResultAfter);
     GenTree* RepresentOpAsLocalVar(GenTree* op, GenTree* user, GenTree** edge);
+    GenTree* EnsureIntSized(GenTree* node, bool signExtend);
 
     GenTree* StoreNodeToVar(LIR::Use& use);
     static genTreeOps GetHiOper(genTreeOps oper);
diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_462269/DevDiv_462269.il b/tests/src/JIT/Regression/JitBlue/DevDiv_462269/DevDiv_462269.il
new file mode 100644 (file)
index 0000000..344879c
--- /dev/null
@@ -0,0 +1,142 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.assembly extern mscorlib{}
+.assembly ILGEN_MODULE{}
+.class ILGEN_CLASS
+{
+    .method static int64 ILGEN_METHOD(unsigned int32, float32, unsigned int8, char, int64, float64)
+    {
+        .maxstack  65535
+        .locals init (float64, unsigned int32, int64, int32, unsigned int16, unsigned int64, char, int8, unsigned int32, bool, bool)
+
+        ldloc.s 0x02
+        ldloc.s 0x02
+        add
+        conv.ovf.u2
+        not
+        ldarg 0x0004
+        ldloc 0x0005
+        conv.ovf.i8.un
+        conv.ovf.i2
+        shl
+        ldarg.s 0x02
+        conv.ovf.u4
+        ldarg 0x0004
+        conv.ovf.u1.un
+        rem.un
+        shr.un
+        not
+        ldarg.s 0x04
+        not
+        div
+        ldloc 0x0005
+        add
+        conv.ovf.u8.un
+        ldloc.s 0x05
+        ldloc 0x0002
+        ldarg.s 0x04
+        div.un
+        neg
+        ldarg 0x0004
+        ldloc.s 0x06
+        conv.ovf.i8
+        conv.ovf.u1.un
+        conv.ovf.i8.un
+        sub
+        sub.ovf
+        and
+        ldarg 0x0005
+        ldarg.s 0x05
+        ceq
+        starg.s 0x03
+        ldarg 0x0003
+        conv.ovf.i8
+        ldarg.s 0x03
+        conv.ovf.u8
+        ldloc.s 0x04
+        shl
+        cgt
+        ldarg.s 0x03
+        neg
+        cgt
+        not
+        shr
+        ldarg.s 0x01
+        pop
+        and
+        conv.ovf.u4
+        ceq
+        pop
+        ldloc 0x0000
+        ldloc 0x0007
+        conv.r.un
+        neg
+        mul
+        ckfinite
+        ldloc 0x0000
+        ckfinite
+        neg
+        mul
+        pop
+        ldloc.s 0x05
+        ldloc 0x0005
+        and
+        ldc.r8 float64(0xc4a68d93e8d67cec)
+        conv.ovf.i8.un
+        dup
+        and
+        and
+        ldarg 0x0004
+        ldarg 0x0000
+        ldarg 0x0003
+        clt
+        shl
+        conv.ovf.u4
+        ldarg.s 0x00
+        shr.un
+        conv.ovf.u8
+        ldloc 0x0006
+        pop
+        xor
+        conv.ovf.i8.un
+        conv.i8
+        neg
+        ldarg.s 0x01
+        conv.i1
+        conv.u8
+        nop
+        add.ovf.un
+        ldloc.s 0x02
+        conv.u8
+        mul.ovf
+        ret
+    }
+
+    .method static int32 Main()
+    {
+        .entrypoint
+
+        .try
+        {
+            ldc.i4 0
+            ldc.r4 0
+            ldc.i4 0
+            dup
+            ldc.i8 0
+            ldc.r8 0
+            call int64 ILGEN_CLASS::ILGEN_METHOD(unsigned int32, float32, unsigned int8, char, int64, float64)
+            pop
+            leave.s done
+        }
+        catch [mscorlib]System.Exception
+        {
+            leave.s done
+        }
+
+    done:
+        ldc.i4 100
+        ret
+    }
+}
diff --git a/tests/src/JIT/Regression/JitBlue/DevDiv_462269/DevDiv_462269.ilproj b/tests/src/JIT/Regression/JitBlue/DevDiv_462269/DevDiv_462269.ilproj
new file mode 100644 (file)
index 0000000..113e6e5
--- /dev/null
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <AssemblyName>$(MSBuildProjectName)</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  </PropertyGroup>
+  <ItemGroup>
+    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+      <Visible>False</Visible>
+    </CodeAnalysisDependentAssemblyPaths>
+  </ItemGroup>
+  <PropertyGroup>
+    <DebugType>None</DebugType>
+    <Optimize>True</Optimize>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="DevDiv_462269.il" />
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+  <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
+  </PropertyGroup> 
+</Project>