From: Will Smith Date: Thu, 9 Feb 2023 17:45:54 +0000 (-0800) Subject: [JIT] X64 - Peephole optimization to skip emitting `movsxd` (#81721) X-Git-Tag: accepted/tizen/unified/riscv/20231226.055536~4131 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4d515393816a0e0a2e9ad6103ebcd78a561085f0;p=platform%2Fupstream%2Fdotnet%2Fruntime.git [JIT] X64 - Peephole optimization to skip emitting `movsxd` (#81721) * Allow GT_CAST for long to small types on 64bit * Check unsigned * Minor cleanup * Added AreUpper32BitsSigned for peephole optimization * Renamed to AreUpper32BitsFFFF. Simplified check. * comments * Formatting:: * Feedback. Added disasm test. --- diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 5c30a83..a468033 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -7008,6 +7008,7 @@ void CodeGen::genIntToIntCast(GenTreeCast* cast) case GenIntCastDesc::LOAD_SIGN_EXTEND_INT: ins = INS_movsxd; insSize = 4; + canSkip = compiler->opts.OptimizationEnabled() && emit->AreUpper32BitsSignExtended(srcReg); break; #endif case GenIntCastDesc::COPY: diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 90c681d..86ad832 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -619,6 +619,54 @@ bool emitter::AreUpper32BitsZero(regNumber reg) } //------------------------------------------------------------------------ +// AreUpper32BitsSignExtended: check if some previously emitted +// instruction sign-extended the upper 32 bits. +// +// Arguments: +// reg - register of interest +// +// Return Value: +// true if previous instruction upper 32 bits are sign-extended. +// false if it did not, or if we can't safely determine. +bool emitter::AreUpper32BitsSignExtended(regNumber reg) +{ + // Only allow GPRs. + // If not a valid register, then return false. + if (!genIsValidIntReg(reg)) + return false; + + // Only consider if safe + // + if (!emitCanPeepholeLastIns()) + { + return false; + } + + instrDesc* id = emitLastIns; + + if (id->idReg1() != reg) + { + return false; + } + + // movsx always sign extends to 8 bytes. W-bit is set. + if (id->idIns() == INS_movsx) + { + return true; + } + +#ifdef TARGET_AMD64 + // movsxd is always an 8 byte operation. W-bit is set. + if (id->idIns() == INS_movsxd) + { + return true; + } +#endif + + return false; +} + +//------------------------------------------------------------------------ // AreFlagsSetToZeroCmp: Checks if the previous instruction set the SZ, and optionally OC, flags to // the same values as if there were a compare to 0 // diff --git a/src/coreclr/jit/emitxarch.h b/src/coreclr/jit/emitxarch.h index 6741676..64c7147 100644 --- a/src/coreclr/jit/emitxarch.h +++ b/src/coreclr/jit/emitxarch.h @@ -128,6 +128,7 @@ static bool IsJccInstruction(instruction ins); static bool IsJmpInstruction(instruction ins); bool AreUpper32BitsZero(regNumber reg); +bool AreUpper32BitsSignExtended(regNumber reg); bool AreFlagsSetToZeroCmp(regNumber reg, emitAttr opSize, genTreeOps treeOps); bool AreFlagsSetForSignJumpOpt(regNumber reg, emitAttr opSize, GenTree* tree); diff --git a/src/tests/JIT/opt/Casts/IntCast.cs b/src/tests/JIT/opt/Casts/IntCast.cs new file mode 100644 index 0000000..1b360f0 --- /dev/null +++ b/src/tests/JIT/opt/Casts/IntCast.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; + +namespace CodeGenTests +{ + class IntCast + { + [MethodImpl(MethodImplOptions.NoInlining)] + static long Cast_Short_To_Long(short value) + { + // X64-NOT: cdqe + return (long)value; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static long Cast_Short_To_Long_Add(short value1, short value2) + { + // X64: movsx + // X64-NOT: cdqe + // X64: movsx + // X64-NOT: movsxd + + return (long)value1 + (long)value2; + } + + static int Main() + { + if (Cast_Short_To_Long(Int16.MaxValue) != 32767) + return 0; + + if (Cast_Short_To_Long_Add(Int16.MaxValue, Int16.MaxValue) != 65534) + return 0; + + return 100; + } + } +} \ No newline at end of file diff --git a/src/tests/JIT/opt/Casts/IntCast.csproj b/src/tests/JIT/opt/Casts/IntCast.csproj new file mode 100644 index 0000000..42a89c8 --- /dev/null +++ b/src/tests/JIT/opt/Casts/IntCast.csproj @@ -0,0 +1,17 @@ + + + Exe + + + None + True + + + + true + + + + + +