mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1160911
- JIT: precise shift right derived result range for all int32 input ranges. r=sunfish
This commit is contained in:
parent
0c9d568ddd
commit
9f2d52bd7f
@ -1035,7 +1035,32 @@ Range::rsh(TempAllocator& alloc, const Range* lhs, const Range* rhs)
|
||||
{
|
||||
MOZ_ASSERT(lhs->isInt32());
|
||||
MOZ_ASSERT(rhs->isInt32());
|
||||
return Range::NewInt32Range(alloc, Min(lhs->lower(), 0), Max(lhs->upper(), 0));
|
||||
|
||||
// Canonicalize the shift range to 0 to 31.
|
||||
int32_t shiftLower = rhs->lower();
|
||||
int32_t shiftUpper = rhs->upper();
|
||||
if ((int64_t(shiftUpper) - int64_t(shiftLower)) >= 31) {
|
||||
shiftLower = 0;
|
||||
shiftUpper = 31;
|
||||
} else {
|
||||
shiftLower &= 0x1f;
|
||||
shiftUpper &= 0x1f;
|
||||
if (shiftLower > shiftUpper) {
|
||||
shiftLower = 0;
|
||||
shiftUpper = 31;
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(shiftLower >= 0 && shiftUpper <= 31);
|
||||
|
||||
// The lhs bounds are signed, thus the minimum is either the lower bound
|
||||
// shift by the smallest shift if negative or the lower bound shifted by the
|
||||
// biggest shift otherwise. And the opposite for the maximum.
|
||||
int32_t lhsLower = lhs->lower();
|
||||
int32_t min = lhsLower < 0 ? lhsLower >> shiftLower : lhsLower >> shiftUpper;
|
||||
int32_t lhsUpper = lhs->upper();
|
||||
int32_t max = lhsUpper >= 0 ? lhsUpper >> shiftLower : lhsUpper >> shiftUpper;
|
||||
|
||||
return Range::NewInt32Range(alloc, min, max);
|
||||
}
|
||||
|
||||
Range*
|
||||
|
@ -277,3 +277,59 @@ BEGIN_TEST(testJitRangeAnalysis_StrictCompareBeta)
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitRangeAnalysis_StrictCompareBeta)
|
||||
|
||||
|
||||
static void
|
||||
deriveShiftRightRange(int32_t lhsLower, int32_t lhsUpper,
|
||||
int32_t rhsLower, int32_t rhsUpper,
|
||||
int32_t* min, int32_t* max)
|
||||
{
|
||||
// This is the reference algorithm and should be verifiable by inspection.
|
||||
int64_t i, j;
|
||||
*min = INT32_MAX; *max = INT32_MIN;
|
||||
for (i = lhsLower; i <= lhsUpper; i++) {
|
||||
for (j = rhsLower; j <= rhsUpper; j++) {
|
||||
int32_t r = int32_t(i) >> (int32_t(j) & 0x1f);
|
||||
if (r > *max) *max = r;
|
||||
if (r < *min) *min = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
checkShiftRightRange(int32_t lhsLow, int32_t lhsHigh, int32_t lhsInc,
|
||||
int32_t rhsLow, int32_t rhsHigh, int32_t rhsInc)
|
||||
{
|
||||
MinimalAlloc func;
|
||||
int64_t lhsLower, lhsUpper, rhsLower, rhsUpper;
|
||||
|
||||
for (lhsLower = lhsLow; lhsLower <= lhsHigh; lhsLower += lhsInc) {
|
||||
for (lhsUpper = lhsLower; lhsUpper <= lhsHigh; lhsUpper += lhsInc) {
|
||||
Range* lhsRange = Range::NewInt32Range(func.alloc, lhsLower, lhsUpper);
|
||||
for (rhsLower = rhsLow; rhsLower <= rhsHigh; rhsLower += rhsInc) {
|
||||
for (rhsUpper = rhsLower; rhsUpper <= rhsHigh; rhsUpper += rhsInc) {
|
||||
Range* rhsRange = Range::NewInt32Range(func.alloc, rhsLower, rhsUpper);
|
||||
Range* result = Range::rsh(func.alloc, lhsRange, rhsRange);
|
||||
int32_t min, max;
|
||||
deriveShiftRightRange(lhsLower, lhsUpper,
|
||||
rhsLower, rhsUpper,
|
||||
&min, &max);
|
||||
if (!result->isInt32() ||
|
||||
result->lower() != min ||
|
||||
result->upper() != max) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BEGIN_TEST(testJitRangeAnalysis_shiftRight)
|
||||
{
|
||||
CHECK(checkShiftRightRange(-16, 15, 1, 0, 31, 1));
|
||||
CHECK(checkShiftRightRange( -8, 7, 1, -64, 63, 1));
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitRangeAnalysis_shiftRight)
|
||||
|
Loading…
Reference in New Issue
Block a user