未验证 提交 52cced2d 编写于 作者: W Will Smith 提交者: GitHub

Narrow cast fix (#70518)

* Added genActualTypeSize. Remove narrow cast if the actual type sizes are the same

* Trying to fix build

* Fixing build

* Removed genActualTypeSize. Using genActualType instead

* Added helper function

* Comments

* Moving back to morph

* Removing part of the test

* Added fgOptimizeCastOnAssignment

* Fixing build

* Removing extra bits

* Removed fgIsSafeToRemoveIntToIntCastOnAssignment, inlining the implementation, adding extra logic when actual types are not the same
上级 195a0a90
......@@ -5698,6 +5698,7 @@ private:
GenTree* fgMorphForRegisterFP(GenTree* tree);
GenTree* fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac = nullptr);
GenTree* fgOptimizeCast(GenTreeCast* cast);
GenTree* fgOptimizeCastOnAssignment(GenTreeOp* asg);
GenTree* fgOptimizeEqualityComparisonWithConst(GenTreeOp* cmp);
GenTree* fgOptimizeRelationalComparisonWithConst(GenTreeOp* cmp);
#ifdef FEATURE_HW_INTRINSICS
......
......@@ -11248,7 +11248,6 @@ DONE_MORPHING_CHILDREN:
GenTree* temp;
GenTree* lclVarTree;
GenTree* effectiveOp1;
FieldSeqNode* fieldSeq = nullptr;
switch (oper)
......@@ -11268,28 +11267,14 @@ DONE_MORPHING_CHILDREN:
lclVarTree->gtFlags |= GTF_VAR_DEF;
}
effectiveOp1 = op1->gtEffectiveVal();
// If we are storing a small type, we might be able to omit a cast.
if ((effectiveOp1->OperIs(GT_IND) ||
(effectiveOp1->OperIs(GT_LCL_VAR) &&
lvaGetDesc(effectiveOp1->AsLclVarCommon()->GetLclNum())->lvNormalizeOnLoad())) &&
varTypeIsSmall(effectiveOp1))
if (op2->OperIs(GT_CAST))
{
if (!gtIsActiveCSE_Candidate(op2) && op2->OperIs(GT_CAST) &&
varTypeIsIntegral(op2->AsCast()->CastOp()) && !op2->gtOverflow())
{
var_types castType = op2->CastToType();
tree = fgOptimizeCastOnAssignment(tree->AsOp());
// If we are performing a narrowing cast and
// castType is larger or the same as op1's type
// then we can discard the cast.
assert(tree->OperIs(GT_ASG));
if (varTypeIsSmall(castType) && (genTypeSize(castType) >= genTypeSize(effectiveOp1)))
{
tree->AsOp()->gtOp2 = op2 = op2->AsCast()->CastOp();
}
}
op1 = tree->gtGetOp1();
op2 = tree->gtGetOp2();
}
fgAssignSetVarDef(tree);
......@@ -12256,6 +12241,75 @@ GenTree* Compiler::fgOptimizeCast(GenTreeCast* cast)
return cast;
}
//------------------------------------------------------------------------
// fgOptimizeCastOnAssignment: Optimizes the supplied GT_ASG tree with a GT_CAST node.
//
// Arguments:
// tree - the cast tree to optimize
//
// Return Value:
// The optimized tree (must be GT_ASG).
//
GenTree* Compiler::fgOptimizeCastOnAssignment(GenTreeOp* asg)
{
assert(asg->OperIs(GT_ASG));
GenTree* const op1 = asg->gtGetOp1();
GenTree* const op2 = asg->gtGetOp2();
assert(op2->OperIs(GT_CAST));
GenTree* const effectiveOp1 = op1->gtEffectiveVal();
if (!effectiveOp1->OperIs(GT_IND, GT_LCL_VAR))
return asg;
if (effectiveOp1->OperIs(GT_LCL_VAR) &&
!lvaGetDesc(effectiveOp1->AsLclVarCommon()->GetLclNum())->lvNormalizeOnLoad())
return asg;
if (op2->gtOverflow())
return asg;
if (gtIsActiveCSE_Candidate(op2))
return asg;
GenTreeCast* cast = op2->AsCast();
var_types castToType = cast->CastToType();
var_types castFromType = cast->CastFromType();
if (gtIsActiveCSE_Candidate(cast->CastOp()))
return asg;
if (!varTypeIsSmall(effectiveOp1))
return asg;
if (!varTypeIsSmall(castToType))
return asg;
if (!varTypeIsIntegral(castFromType))
return asg;
// If we are performing a narrowing cast and
// castToType is larger or the same as op1's type
// then we can discard the cast.
if (genTypeSize(castToType) < genTypeSize(effectiveOp1))
return asg;
if (genActualType(castFromType) == genActualType(castToType))
{
// Removes the cast.
asg->gtOp2 = cast->CastOp();
}
else
{
// This is a type-changing cast so we cannot remove it entirely.
cast->gtCastType = genActualType(castToType);
}
return asg;
}
//------------------------------------------------------------------------
// fgOptimizeEqualityComparisonWithConst: optimizes various EQ/NE(OP, CONST) patterns.
//
......
// 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 class Program
{
public static int Main()
{
Test();
return 100;
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static void Test()
{
M1(0);
}
public static void M1(byte arg0)
{
long var6 = default(long);
arg0 = (byte)(~(ulong)var6 % 3545460779U);
System.Console.WriteLine(arg0);
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册