From 0613e9cbfd66daf98432076c5b9ac164308d3e4a Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Sun, 6 Feb 2022 20:37:47 +0100 Subject: [PATCH] Normalize returns after optimizing returned indirs This ensures we normalize returned indirs of locals, even when we fold it into an access of a promoted local's field. This may change a signed indir into access of an unsigned field, which may need a sign-extending cast to be inserted. It is not ideal that fgMorphRetInd can 'lose' this information, but given that it is a specialized optimization it seems the simplest solution is to just rely on the follow-up normalization. Fix #61359 --- src/coreclr/jit/morph.cpp | 35 ++++++++++--------- .../JitBlue/Runtime_61359/Runtime_61359.cs | 19 ++++++++++ .../Runtime_61359/Runtime_61359.csproj | 13 +++++++ 3 files changed, 50 insertions(+), 17 deletions(-) create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_61359/Runtime_61359.cs create mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_61359/Runtime_61359.csproj diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 27300cd32d63b7..bfacb1624e2441 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -11421,23 +11421,6 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) return fgMorphIntoHelperCall(tree, helper, gtNewCallArgs(op1, op2)); case GT_RETURN: - // normalize small integer return values - if (fgGlobalMorph && varTypeIsSmall(info.compRetType) && (op1 != nullptr) && !op1->TypeIs(TYP_VOID) && - fgCastNeeded(op1, info.compRetType)) - { - // Small-typed return values are normalized by the callee - op1 = gtNewCastNode(TYP_INT, op1, false, info.compRetType); - - // Propagate GTF_COLON_COND - op1->gtFlags |= (tree->gtFlags & GTF_COLON_COND); - - tree->AsOp()->gtOp1 = fgMorphTree(op1); - - // Propagate side effect flags - tree->SetAllEffectsFlags(tree->AsOp()->gtGetOp1()); - - return tree; - } if (!tree->TypeIs(TYP_VOID)) { if (op1->OperIs(GT_OBJ, GT_BLK, GT_IND)) @@ -11471,6 +11454,24 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) } } } + + // normalize small integer return values + if (fgGlobalMorph && varTypeIsSmall(info.compRetType) && (op1 != nullptr) && !op1->TypeIs(TYP_VOID) && + fgCastNeeded(op1, info.compRetType)) + { + // Small-typed return values are normalized by the callee + op1 = gtNewCastNode(TYP_INT, op1, false, info.compRetType); + + // Propagate GTF_COLON_COND + op1->gtFlags |= (tree->gtFlags & GTF_COLON_COND); + + tree->AsOp()->gtOp1 = fgMorphTree(op1); + + // Propagate side effect flags + tree->SetAllEffectsFlags(tree->AsOp()->gtGetOp1()); + + return tree; + } break; case GT_EQ: diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_61359/Runtime_61359.cs b/src/tests/JIT/Regression/JitBlue/Runtime_61359/Runtime_61359.cs new file mode 100644 index 00000000000000..6a38a4cf157de6 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_61359/Runtime_61359.cs @@ -0,0 +1,19 @@ +// 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; + +public unsafe class Runtime_61359 +{ + public static int Main() + { + return HalfToInt16Bits((Half)(-1)) == -17408 ? 100 : -1; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + static short HalfToInt16Bits(Half h) + { + return *(short*)&h; + } +} \ No newline at end of file diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_61359/Runtime_61359.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_61359/Runtime_61359.csproj new file mode 100644 index 00000000000000..1a1d3eadae5ce4 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_61359/Runtime_61359.csproj @@ -0,0 +1,13 @@ + + + Exe + + + None + True + True + + + + + \ No newline at end of file