From 7e00ee6be9590670d060117fd3932808bd7a86e6 Mon Sep 17 00:00:00 2001 From: Pat Gavlin Date: Thu, 17 Nov 2016 22:37:17 -0800 Subject: Fix codegen for `(umod (gt_long) (const int))`. When targeting x86, we opt not to use a helper call to implement the 64-bit unsigned modulus operator if we have a tree of either of the following forms: - `(umod ulong (x ulong) (cast ulong (const int const_val)))` - `(umod ulong (x ulong) (const ulong const_val))` where `const_val` falls in the range `[2, 0x3fffffff]`. We eventually decompose this into `(umod uint (gt_long lo hi) (const int const_val))`. This was then emitted as: mov eax, lo mov edx, hi mov reg, const_val div edx:eax reg Unfortunately, this generated code does not take into account the fact that the result of the modulus may not fit into 32 bits. This can cause an overflow exception at runtime despite the fact that the modulus originally produced a 64-bit result. This change fixes the code generation to check for overflow before performing the modulus and perform a 64-bit division if the result would overflow. This results in generated code like the following: mov eax, lo mov edx, hi mov reg, const_val cmp edx, reg jb noOverflow mov temp, eax mov edx, eax xor edx, edx div edx:eax, const_val mov eax, temp noOverflow: div edx:eax, const_val Which is identical to the code produced by JIT32 and the legacy backend. --- .../Regression/JitBlue/GitHub_8170/GitHub_8170.cs | 23 +++++++++++ .../JitBlue/GitHub_8170/GitHub_8170.csproj | 46 ++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.cs create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.csproj (limited to 'tests') diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.cs b/tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.cs new file mode 100644 index 0000000000..d3fe8d9cf3 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.cs @@ -0,0 +1,23 @@ +// 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. + +using System.Runtime.CompilerServices; + +// This test checks for proper behavior w.r.t. overflow for expressions of the form `val % constant` where `val` is an +// unsigned long and `constant` is a 32- or 64-bit integer constant in the range [2,0x3fffffff]. These expressions +// should never produce an overflow exception. + +static class C +{ + [MethodImpl(MethodImplOptions.NoInlining)] + static uint M(ulong l) + { + return (uint)(l % 10000000); + } + + static int Main() + { + return M(ulong.MaxValue) == 9551615 ? 100 : 101; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.csproj new file mode 100644 index 0000000000..81aa7299d0 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_8170/GitHub_8170.csproj @@ -0,0 +1,46 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + Properties + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages + ..\..\ + + 7a9bfb7d + + + + + + + + + False + + + + None + True + + + + + + + + + $(JitPackagesConfigFileDirectory)minimal\project.json + $(JitPackagesConfigFileDirectory)minimal\project.lock.json + + + + + -- cgit v1.2.3