Skip to content

Commit 850b702

Browse files
committed
Fix: Only skip AND masking for unsigned narrow types in NarrowWithSaturation
The inputsAlreadyClamped optimization was incorrectly applied to all types, but it's only valid for unsigned narrow types (TYP_UBYTE, TYP_USHORT). For signed narrow types, the AND masking is still required to clear the sign-extended upper bits before PackUnsignedSaturate can correctly pack the values. Without this masking, negative values would have incorrect upper bits that would cause PackUnsignedSaturate to produce wrong results. This fixes System.Numerics.Tests.GenericVectorTests.NarrowWithSaturationInt32Test
1 parent 3ab1a8a commit 850b702

1 file changed

Lines changed: 9 additions & 2 deletions

File tree

src/coreclr/jit/hwintrinsicxarch.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3541,8 +3541,15 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
35413541
op2 = gtNewSimdMinMaxNode(retType, op2, gtCloneExpr(maxCns), simdBaseType, simdSize,
35423542
/* isMax */ false, /* isMagnitude */ false, /* isNumber */ false);
35433543

3544-
retNode = gtNewSimdNarrowNode(retType, op1, op2, narrowSimdBaseType, simdSize,
3545-
/* inputsAlreadyClamped */ true);
3544+
// For unsigned narrow types (TYP_UBYTE, TYP_USHORT, TYP_UINT), the clamping
3545+
// already ensures the upper bits are zero, so the AND masking in
3546+
// gtNewSimdNarrowNode is redundant. For signed narrow types, we still need
3547+
// the AND masking to clear sign-extended bits before PackUnsignedSaturate
3548+
// can correctly pack the values.
3549+
bool inputsAlreadyClamped = varTypeIsUnsigned(narrowSimdBaseType);
3550+
3551+
retNode =
3552+
gtNewSimdNarrowNode(retType, op1, op2, narrowSimdBaseType, simdSize, inputsAlreadyClamped);
35463553
}
35473554
}
35483555
break;

0 commit comments

Comments
 (0)