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

Optimize division by constant after AND or RSZ #55778

Merged
merged 2 commits into from
Oct 4, 2021
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
33 changes: 28 additions & 5 deletions src/coreclr/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5215,10 +5215,33 @@ bool Lowering::LowerUnsignedDivOrMod(GenTreeOp* divMod)
int postShift;
bool simpleMul = false;

unsigned bits = type == TYP_INT ? 32 : 64;
// if the dividend operand is AND or RSZ with a constant then the number of input bits can be reduced
if (dividend->OperIs(GT_AND) && dividend->gtGetOp2()->IsCnsIntOrI())
{
size_t maskCns = static_cast<size_t>(dividend->gtGetOp2()->AsIntCon()->IconValue());
if (maskCns != 0)
{
unsigned maskBits = 1;
while (maskCns >>= 1)
maskBits++;
if (maskBits < bits)
bits = maskBits;
}
}
else if (dividend->OperIs(GT_RSZ) && dividend->gtGetOp2()->IsCnsIntOrI())
{
size_t shiftCns = static_cast<size_t>(dividend->gtGetOp2()->AsIntCon()->IconValue());
if (shiftCns < bits)
{
bits -= static_cast<unsigned>(shiftCns);
}
}

if (type == TYP_INT)
{
magic =
MagicDivide::GetUnsigned32Magic(static_cast<uint32_t>(divisorValue), &increment, &preShift, &postShift);
magic = MagicDivide::GetUnsigned32Magic(static_cast<uint32_t>(divisorValue), &increment, &preShift,
&postShift, bits);

#ifdef TARGET_64BIT
// avoid inc_saturate/multiple shifts by widening to 32x64 MULHI
Expand All @@ -5230,7 +5253,7 @@ bool Lowering::LowerUnsignedDivOrMod(GenTreeOp* divMod)
))
{
magic = MagicDivide::GetUnsigned64Magic(static_cast<uint64_t>(divisorValue), &increment, &preShift,
&postShift, 32);
&postShift, bits);
}
// otherwise just widen to regular multiplication
else
Expand All @@ -5243,8 +5266,8 @@ bool Lowering::LowerUnsignedDivOrMod(GenTreeOp* divMod)
else
{
#ifdef TARGET_64BIT
magic =
MagicDivide::GetUnsigned64Magic(static_cast<uint64_t>(divisorValue), &increment, &preShift, &postShift);
magic = MagicDivide::GetUnsigned64Magic(static_cast<uint64_t>(divisorValue), &increment, &preShift,
&postShift, bits);
#else
unreached();
#endif
Expand Down
7 changes: 5 additions & 2 deletions src/coreclr/jit/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2414,15 +2414,18 @@ T GetUnsignedMagic(T d, bool* increment /*out*/, int* preShift /*out*/, int* pos
}
}

uint32_t GetUnsigned32Magic(uint32_t d, bool* increment /*out*/, int* preShift /*out*/, int* postShift /*out*/)
uint32_t GetUnsigned32Magic(
uint32_t d, bool* increment /*out*/, int* preShift /*out*/, int* postShift /*out*/, unsigned bits)
{
return GetUnsignedMagic<uint32_t>(d, increment, preShift, postShift, 32);
assert(bits <= 32);
return GetUnsignedMagic<uint32_t>(d, increment, preShift, postShift, bits);
}

#ifdef TARGET_64BIT
uint64_t GetUnsigned64Magic(
uint64_t d, bool* increment /*out*/, int* preShift /*out*/, int* postShift /*out*/, unsigned bits)
{
assert(bits <= 64);
return GetUnsignedMagic<uint64_t>(d, increment, preShift, postShift, bits);
}
#endif
Expand Down
5 changes: 3 additions & 2 deletions src/coreclr/jit/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -761,10 +761,11 @@ class CritSecHolder

namespace MagicDivide
{
uint32_t GetUnsigned32Magic(uint32_t d, bool* increment /*out*/, int* preShift /*out*/, int* postShift /*out*/);
uint32_t GetUnsigned32Magic(
uint32_t d, bool* increment /*out*/, int* preShift /*out*/, int* postShift /*out*/, unsigned bits);
#ifdef TARGET_64BIT
uint64_t GetUnsigned64Magic(
uint64_t d, bool* increment /*out*/, int* preShift /*out*/, int* postShift /*out*/, unsigned bits = 64);
uint64_t d, bool* increment /*out*/, int* preShift /*out*/, int* postShift /*out*/, unsigned bits);
#endif
int32_t GetSigned32Magic(int32_t d, int* shift /*out*/);
#ifdef TARGET_64BIT
Expand Down
4 changes: 2 additions & 2 deletions src/libraries/System.Private.CoreLib/src/System/Convert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2528,14 +2528,14 @@ private static unsafe int ConvertToBase64Array(char* outChars, byte* inData, int
private static int ToBase64_CalculateAndValidateOutputLength(int inputLength, bool insertLineBreaks)
{
// the base length - we want integer division here, at most 4 more chars for the remainder
long outlen = ((long)inputLength + 2) / 3 * 4;
uint outlen = ((uint)inputLength + 2) / 3 * 4;

if (outlen == 0)
return 0;

if (insertLineBreaks)
{
(long newLines, long remainder) = Math.DivRem(outlen, base64LineBreakPosition);
(uint newLines, uint remainder) = Math.DivRem(outlen, base64LineBreakPosition);
if (remainder == 0)
{
--newLines;
Expand Down
4 changes: 2 additions & 2 deletions src/libraries/System.Private.CoreLib/src/System/DateOnly.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace System
// Maps to December 31 year 9999. The value calculated from "new DateTime(9999, 12, 31).Ticks / TimeSpan.TicksPerDay"
private const int MaxDayNumber = 3_652_058;

private static int DayNumberFromDateTime(DateTime dt) => (int)(dt.Ticks / TimeSpan.TicksPerDay);
private static int DayNumberFromDateTime(DateTime dt) => (int)((ulong)dt.Ticks / TimeSpan.TicksPerDay);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this cast help?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It changes the division from signed to unsigned.


private DateTime GetEquivalentDateTime() => DateTime.UnsafeCreate(_dayNumber * TimeSpan.TicksPerDay);

Expand Down Expand Up @@ -97,7 +97,7 @@ public static DateOnly FromDayNumber(int dayNumber)
/// <summary>
/// Gets the day of the week represented by this instance.
/// </summary>
public DayOfWeek DayOfWeek => GetEquivalentDateTime().DayOfWeek;
public DayOfWeek DayOfWeek => (DayOfWeek)(((uint)_dayNumber + 1) % 7);

/// <summary>
/// Gets the day of the year represented by this instance.
Expand Down
14 changes: 3 additions & 11 deletions src/libraries/System.Private.CoreLib/src/System/DateTime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -461,17 +461,9 @@ public DateTime AddMonths(int months)
GetDate(out int year, out int month, out int day);
int y = year, d = day;
int m = month + months;
if (m > 0)
{
int q = (int)((uint)(m - 1) / 12);
y += q;
m -= q * 12;
}
else
{
y += m / 12 - 1;
m = 12 + m % 12;
}
int q = m > 0 ? (int)((uint)(m - 1) / 12) : m / 12 - 1;
y += q;
m -= q * 12;
if (y < 1 || y > 9999) ThrowDateArithmetic(2);
uint[] daysTo = IsLeapYear(y) ? s_daysToMonth366 : s_daysToMonth365;
uint daysToMonth = daysTo[m - 1];
Expand Down