From 94de26a3d610b5c8499f102205bdc39c67f2d624 Mon Sep 17 00:00:00 2001 From: SingleAccretion Date: Thu, 3 Jun 2021 12:12:13 +0300 Subject: [PATCH] Do not eliminate casts from FP types An optimization in morph was deleting casts on the RHS of a narrow store if the cast-to-type was wider than the type being stored. This is only valid for casts from integral types, as the backend does not handle "STOREIND(byte*, double)", nor is there an instruction to go from an XMM register to a narrow memory location on x86/x64. The issue is not reproducible right now because fgMorphCast wraps the casts in question, but it is an invalid IR transformation nonetheless, and similar code in fgMorphSmpOpOptional guards against non-integral sources. --- src/coreclr/jit/morph.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index b6e1f808ea909..a1a12d597e307 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -13378,10 +13378,11 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) tree->AsOp()->gtOp1 = op1; } - /* If we are storing a small type, we might be able to omit a cast */ - if ((effectiveOp1->gtOper == GT_IND) && varTypeIsSmall(effectiveOp1->TypeGet())) + // If we are storing a small type, we might be able to omit a cast. + if (effectiveOp1->OperIs(GT_IND) && varTypeIsSmall(effectiveOp1)) { - if (!gtIsActiveCSE_Candidate(op2) && (op2->gtOper == GT_CAST) && !op2->gtOverflow()) + if (!gtIsActiveCSE_Candidate(op2) && op2->OperIs(GT_CAST) && + varTypeIsIntegral(op2->AsCast()->CastOp()) && !op2->gtOverflow()) { var_types castType = op2->CastToType(); @@ -13389,7 +13390,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) // castType is larger or the same as op1's type // then we can discard the cast. - if (varTypeIsSmall(castType) && (genTypeSize(castType) >= genTypeSize(effectiveOp1->TypeGet()))) + if (varTypeIsSmall(castType) && (genTypeSize(castType) >= genTypeSize(effectiveOp1))) { tree->AsOp()->gtOp2 = op2 = op2->AsCast()->CastOp(); }