mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 809472: Add truncate analysis for MMul, r=mjrosenb
This commit is contained in:
parent
6b2b2ee5c8
commit
4ecc61cba4
@ -958,9 +958,20 @@ MMul::analyzeEdgeCasesBackward()
|
||||
canBeNegativeZero_ = NeedNegativeZeroCheck(this);
|
||||
}
|
||||
|
||||
bool
|
||||
MMul::updateForReplacement(MDefinition *ins)
|
||||
void
|
||||
MMul::analyzeTruncateBackward()
|
||||
{
|
||||
if (!isPossibleTruncated())
|
||||
setPossibleTruncated(js::ion::EdgeCaseAnalysis::AllUsesTruncate(this));
|
||||
}
|
||||
|
||||
bool
|
||||
MMul::updateForReplacement(MDefinition *ins_)
|
||||
{
|
||||
JS_ASSERT(ins_->isMul());
|
||||
MMul *ins = ins_->toMul();
|
||||
if (isPossibleTruncated())
|
||||
setPossibleTruncated(ins->isPossibleTruncated());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2498,11 +2498,24 @@ class MSub : public MBinaryArithInstruction
|
||||
|
||||
class MMul : public MBinaryArithInstruction
|
||||
{
|
||||
// Annotation the result could be a negative zero
|
||||
// and we need to guard this during execution.
|
||||
bool canBeNegativeZero_;
|
||||
|
||||
// Annotation the result of this Mul is only used in int32 domain
|
||||
// and we could possible truncate the result.
|
||||
bool possibleTruncate_;
|
||||
|
||||
// Annotation the Mul can truncate. This is only set after range analysis,
|
||||
// because the result could be in the imprecise double range.
|
||||
// In that case the truncated result isn't correct.
|
||||
bool implicitTruncate_;
|
||||
|
||||
MMul(MDefinition *left, MDefinition *right, MIRType type)
|
||||
: MBinaryArithInstruction(left, right),
|
||||
canBeNegativeZero_(true)
|
||||
canBeNegativeZero_(true),
|
||||
possibleTruncate_(false),
|
||||
implicitTruncate_(false)
|
||||
{
|
||||
if (type != MIRType_Value)
|
||||
specialization_ = type;
|
||||
@ -2521,13 +2534,14 @@ class MMul : public MBinaryArithInstruction
|
||||
MDefinition *foldsTo(bool useValueNumbers);
|
||||
void analyzeEdgeCasesForward();
|
||||
void analyzeEdgeCasesBackward();
|
||||
void analyzeTruncateBackward();
|
||||
|
||||
double getIdentity() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool canOverflow() {
|
||||
return !range()->isFinite();
|
||||
return !implicitTruncate_ && !range()->isFinite();
|
||||
}
|
||||
|
||||
bool canBeNegativeZero() {
|
||||
@ -2546,8 +2560,18 @@ class MMul : public MBinaryArithInstruction
|
||||
return false;
|
||||
Range *left = getOperand(0)->range();
|
||||
Range *right = getOperand(1)->range();
|
||||
if (isPossibleTruncated())
|
||||
implicitTruncate_ = !Range::precisionLossMul(left, right);
|
||||
return range()->update(Range::mul(left, right));
|
||||
}
|
||||
|
||||
bool isPossibleTruncated() const {
|
||||
return possibleTruncate_;
|
||||
}
|
||||
|
||||
void setPossibleTruncated(bool truncate) {
|
||||
possibleTruncate_ = truncate;
|
||||
}
|
||||
};
|
||||
|
||||
class MDiv : public MBinaryArithInstruction
|
||||
|
@ -417,6 +417,24 @@ Range::shr(const Range *lhs, int32 c)
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
Range::precisionLossMul(const Range *lhs, const Range *rhs)
|
||||
{
|
||||
int64_t loss = 1LL<<53; // result must be lower than 2^53
|
||||
int64_t a = (int64_t)lhs->lower_ * (int64_t)rhs->lower_;
|
||||
int64_t b = (int64_t)lhs->lower_ * (int64_t)rhs->upper_;
|
||||
int64_t c = (int64_t)lhs->upper_ * (int64_t)rhs->lower_;
|
||||
int64_t d = (int64_t)lhs->upper_ * (int64_t)rhs->upper_;
|
||||
int64_t lower = Min( Min(a, b), Min(c, d) );
|
||||
int64_t upper = Max( Max(a, b), Max(c, d) );
|
||||
if (lower < 0)
|
||||
lower = -lower;
|
||||
if (upper < 0)
|
||||
upper = -upper;
|
||||
|
||||
return lower > loss || upper > loss;
|
||||
}
|
||||
|
||||
bool
|
||||
Range::update(const Range *other)
|
||||
{
|
||||
|
@ -126,6 +126,8 @@ class Range {
|
||||
static Range shl(const Range *lhs, int32 c);
|
||||
static Range shr(const Range *lhs, int32 c);
|
||||
|
||||
static bool precisionLossMul(const Range *lhs, const Range *rhs);
|
||||
|
||||
inline void makeLowerInfinite() {
|
||||
lower_infinite_ = true;
|
||||
lower_ = JSVAL_INT_MIN;
|
||||
|
19
js/src/jit-test/tests/ion/bug809472.js
Normal file
19
js/src/jit-test/tests/ion/bug809472.js
Normal file
@ -0,0 +1,19 @@
|
||||
function test1(x) {
|
||||
return (x*((2<<23)-1))|0
|
||||
}
|
||||
function test2(x) {
|
||||
return (x*((2<<22)-1))|0
|
||||
}
|
||||
function test3(x) {
|
||||
return (x*((2<<21)-1))|0
|
||||
}
|
||||
function test4(x) {
|
||||
var b = x + x + 3
|
||||
return (b*b) | 0
|
||||
}
|
||||
//MAX_INT
|
||||
var x = 0x7ffffffe;
|
||||
assertEq(test1(x), 2113929216);
|
||||
assertEq(test2(x), 2130706434);
|
||||
assertEq(test3(x), 2139095042);
|
||||
assertEq(test4(x), 0);
|
Loading…
Reference in New Issue
Block a user