From d0baa73f54eb0f7eba1364e207c02afa984760cb Mon Sep 17 00:00:00 2001 From: mikedn Date: Thu, 5 Oct 2017 08:04:26 +0300 Subject: [PATCH] Fix condition flags reuse optimization (#14323) This optimization is not valid for unsigned LT/LE/GT/GE relops. Using the Carry flag this way indicates that the operation overflowed, not that the result is less than 0, that's impossible for unsigned integers. This is also not valid for signed LT/LE/GT/GE relops due to integer overflow. --- src/jit/codegenxarch.cpp | 3 +- src/jit/lower.cpp | 4 +- .../JitBlue/GitHub_14321/GitHub_14321.il | 56 ++++++++++++++++++++++ .../JitBlue/GitHub_14321/GitHub_14321.ilproj | 24 ++++++++++ 4 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_14321/GitHub_14321.il create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_14321/GitHub_14321.ilproj diff --git a/src/jit/codegenxarch.cpp b/src/jit/codegenxarch.cpp index adfb575..bbac381 100644 --- a/src/jit/codegenxarch.cpp +++ b/src/jit/codegenxarch.cpp @@ -887,8 +887,7 @@ void CodeGen::genCodeForBinary(GenTree* treeNode) } // try to use an inc or dec - if (oper == GT_ADD && !varTypeIsFloating(treeNode) && src->isContainedIntOrIImmed() && !treeNode->gtOverflowEx() && - !treeNode->gtSetFlags()) + if (oper == GT_ADD && !varTypeIsFloating(treeNode) && src->isContainedIntOrIImmed() && !treeNode->gtOverflowEx()) { if (src->IsIntegralConst(1)) { diff --git a/src/jit/lower.cpp b/src/jit/lower.cpp index c2c405f..18cf09a 100644 --- a/src/jit/lower.cpp +++ b/src/jit/lower.cpp @@ -2616,10 +2616,8 @@ GenTree* Lowering::LowerCompare(GenTree* cmp) } #endif // _TARGET_XARCH_ } - else + else if (cmp->OperIs(GT_EQ, GT_NE)) { - assert(cmp->OperIs(GT_EQ, GT_NE, GT_LE, GT_LT, GT_GE, GT_GT)); - GenTree* op1 = cmp->gtGetOp1(); GenTree* op2 = cmp->gtGetOp2(); diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_14321/GitHub_14321.il b/tests/src/JIT/Regression/JitBlue/GitHub_14321/GitHub_14321.il new file mode 100644 index 0000000..4dc1b41 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_14321/GitHub_14321.il @@ -0,0 +1,56 @@ +// 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 {auto} +.assembly extern System.Console {auto} +.assembly GitHub_14321 {} + +.class Program +{ + .method static bool TestUnsigned(int32) noinlining + { + .maxstack 2 + + ldarg.0 + ldc.i4 42 + sub + ldc.i4 0 + clt.un + ret + } + + .method static bool TestSignedOverflow(int32) noinlining + { + .maxstack 2 + + ldarg.0 + ldc.i4 42 + add + ldc.i4 0 + cgt + ret + } + + .method static int32 Main() + { + .entrypoint + .maxstack 1 + + ldc.i4 42 + call bool Program::TestUnsigned(int32) + brtrue FAIL + ldc.i4 0x7fffffff + call bool Program::TestSignedOverflow(int32) + brtrue FAIL + ldstr "PASS" + call void [System.Console]System.Console::WriteLine(string) + ldc.i4 100 + ret + FAIL: + ldstr "FAIL" + call void [System.Console]System.Console::WriteLine(string) + ldc.i4 1 + ret + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_14321/GitHub_14321.ilproj b/tests/src/JIT/Regression/JitBlue/GitHub_14321/GitHub_14321.ilproj new file mode 100644 index 0000000..2c8dc0b --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_14321/GitHub_14321.ilproj @@ -0,0 +1,24 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + ..\..\ + 1 + + + + + None + True + + + + + + + \ No newline at end of file -- 2.7.4