Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIT: Use faster mod for uint16 values #111535

Closed
wants to merge 11 commits into from
Prev Previous commit
Next Next commit
Skip the opt on Arm for now
MihaZupan committed Jan 26, 2025
commit be5e488830fe9a983e1d7a9c1e8a38b2aa4deca3
4 changes: 3 additions & 1 deletion src/coreclr/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
@@ -4180,14 +4180,16 @@ GenTree* Compiler::optAssertionProp_ModDiv(ASSERT_VALARG_TP assertions, GenTreeO
changed = true;
}

#ifdef TARGET_AMD64
if (((tree->gtFlags & GTF_UMOD_UINT16_OPERANDS) == 0) && tree->OperIs(GT_UMOD) && op2->IsCnsIntOrI() &&
FitsIn<uint16_t>(op2->AsIntCon()->IconValue()) &&
FitsIn<uint16_t>(op2->AsIntCon()->IconValue()) && op2->AsIntCon()->IconValue() > 0 &&
IntegralRange::ForType(TYP_USHORT).Contains(IntegralRange::ForNode(op1, this)))
{
JITDUMP("Both operands for UMOD are in uint16 range...\n")
tree->gtFlags |= GTF_UMOD_UINT16_OPERANDS;
changed = true;
}
#endif

return changed ? optAssertionProp_Update(tree, tree, stmt) : nullptr;
}
2 changes: 1 addition & 1 deletion src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
@@ -540,7 +540,7 @@ enum GenTreeFlags : unsigned int

GTF_DIV_MOD_NO_OVERFLOW = 0x40000000, // GT_DIV, GT_MOD -- Div or mod definitely does not overflow.

GTF_UMOD_UINT16_OPERANDS = 0x80000000, // UMOD -- Both operands to a mod are in uint16 range.
GTF_UMOD_UINT16_OPERANDS = 0x80000000, // UMOD -- Both operands to a mod are in uint16 range. The divisor is non-zero constant.

GTF_CHK_INDEX_INBND = 0x80000000, // GT_BOUNDS_CHECK -- have proven this check is always in-bounds

12 changes: 4 additions & 8 deletions src/coreclr/jit/lower.cpp
Original file line number Diff line number Diff line change
@@ -7184,17 +7184,13 @@ bool Lowering::LowerUnsignedDivOrMod(GenTreeOp* divMod)

assert(divisorValue >= 3);

if (comp->opts.MinOpts())
{
return false;
}

#if defined(TARGET_64BIT)
#ifdef TARGET_AMD64
// Replace (uint16 % uint16) with a cheaper variant of FastMod, specialized for 16-bit operands.
if ((divMod->gtFlags & GTF_UMOD_UINT16_OPERANDS) != 0)
{
assert(!isDiv);
assert(divisorValue > 0 && divisorValue <= UINT16_MAX);
assert(!comp->opts.MinOpts());

// uint multiplier = uint.MaxValue / divisor + 1;
// ulong result = ((ulong)(dividend * multiplier) * divisor) >> 32;
@@ -7230,11 +7226,11 @@ bool Lowering::LowerUnsignedDivOrMod(GenTreeOp* divMod)
ContainCheckRange(multiplier, divMod);
return true;
}
#endif
#endif // TARGET_AMD64

// TODO-ARM-CQ: Currently there's no GT_MULHI for ARM32
#if defined(TARGET_XARCH) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
if (divisorValue >= 3)
if (!comp->opts.MinOpts() && (divisorValue >= 3))
{
size_t magic;
bool increment;