Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/coreclr/jit/optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3389,14 +3389,27 @@ bool Compiler::optNarrowTree(GenTree* tree, var_types srct, var_types dstt, Valu
}
#endif

if ((tree->CastToType() != srct) || tree->gtOverflow())
// We are called recursively to push a narrowing cast down through `tree`.
// In this GT_CAST case, `tree` is an inner cast whose result feeds the outer
// narrowing operation; `srct` is that result type (the inner cast's TypeGet)
// and `dstt` is the type we are narrowing to.
//
// We recognize the pattern (simplified):
// CAST<dstt <- srct>( CAST<srct <- op1>(op1) ) e.g. (int)(long)x
// and below rewrite the inner cast to int<->int so the chain folds away.
//
// CastToType carries signedness independently of tree->TypeGet() (e.g.
// CAST_LONG <- ULONG <- uint has CastToType=ULONG while tree->TypeGet()==LONG).
// Use genActualType on both sides of the compare so an unsigned-widening inner
// cast still matches a LONG `srct`.
if ((genActualType(tree->CastToType()) != genActualType(srct)) || tree->gtOverflow())
Comment thread
AndyAyersMS marked this conversation as resolved.
{
return false;
}

if (varTypeIsInt(op1) && varTypeIsInt(dstt) && tree->TypeIs(TYP_LONG))
{
// We have a CAST that converts into to long while dstt is int.
// We have a CAST that converts int to long while dstt is int.
// so we can just convert the cast to int -> int and someone will clean it up.
if (doit)
{
Expand Down
2 changes: 1 addition & 1 deletion src/tests/JIT/opt/InstructionCombining/Casts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ static ulong CastUIntUShortULong(uint x)
[MethodImpl(MethodImplOptions.NoInlining)]
static uint CastUIntULongUInt(uint x)
{
//ARM64-FULL-LINE: mov {{w[0-9]+}}, {{w[0-9]+}}
//ARM64-NOT: mov {{w[0-9]+}}, {{w[0-9]+}}
return (uint)(ulong)x;
}

Expand Down
3 changes: 1 addition & 2 deletions src/tests/JIT/opt/InstructionCombining/Cmn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ static bool CmnLSLSwap(int a, int b)
[MethodImpl(MethodImplOptions.NoInlining)]
static bool CmnLSR(uint a, uint b)
{
//ARM64-FULL-LINE: lsr {{w[0-9]+}}, {{w[0-9]+}}, #2
//ARM64-FULL-LINE: cmn {{w[0-9]+}}, {{w[0-9]+}}
//ARM64-FULL-LINE: cmn {{w[0-9]+}}, {{w[0-9]+}}, LSR #2
if (a == (uint)-(b>>2))
{
return true;
Expand Down
12 changes: 12 additions & 0 deletions src/tests/JIT/opt/InstructionCombining/Mvn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ public static int CheckMvn()
fail = true;
}

if (MvnCastChainLSR(0x10) != 0xFFFFFFFD)
{
fail = true;
}

if (fail)
{
return 101;
Expand Down Expand Up @@ -93,5 +98,12 @@ static ulong MvnLargeShift64Bit(ulong a)
//ARM64-FULL-LINE: mvn {{x[0-9]+}}, {{x[0-9]+}}, LSR #32
return ~(a>>160);
}

[MethodImpl(MethodImplOptions.NoInlining)]
static uint MvnCastChainLSR(uint a)
{
//ARM64-FULL-LINE: mvn {{w[0-9]+}}, {{w[0-9]+}}, LSR #3
return (uint)~(ulong)(a>>3);
}
}
}
3 changes: 1 addition & 2 deletions src/tests/JIT/opt/InstructionCombining/Neg.cs
Original file line number Diff line number Diff line change
Expand Up @@ -573,8 +573,7 @@ static int NegLSL(int a)
[MethodImpl(MethodImplOptions.NoInlining)]
static uint NegLSR(uint a)
{
//ARM64-FULL-LINE: lsr {{w[0-9]+}}, {{w[0-9]+}}, #20
//ARM64-FULL-LINE: neg {{w[0-9]+}}, {{w[0-9]+}}
//ARM64-FULL-LINE: neg {{w[0-9]+}}, {{w[0-9]+}}, LSR #20
return (uint)-(a >> 20);
}

Expand Down
Loading