| Index: src/hydrogen-instructions.cc
|
| diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
|
| index 2033ea422b2d09530e4463712bc35a91334c5d55..b36706b49b48119b6332a54e6782a9904e929ee5 100644
|
| --- a/src/hydrogen-instructions.cc
|
| +++ b/src/hydrogen-instructions.cc
|
| @@ -528,6 +528,17 @@ bool HValue::CheckUsesForFlag(Flag f) {
|
| }
|
|
|
|
|
| +bool HValue::HasAtLeastOneUseWithFlagAndNoneWithout(Flag f) {
|
| + bool return_value = false;
|
| + for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
|
| + if (it.value()->IsSimulate()) continue;
|
| + if (!it.value()->CheckFlag(f)) return false;
|
| + return_value = true;
|
| + }
|
| + return return_value;
|
| +}
|
| +
|
| +
|
| HUseIterator::HUseIterator(HUseListNode* head) : next_(head) {
|
| Advance();
|
| }
|
| @@ -1429,14 +1440,6 @@ HValue* HBitNot::Canonicalize() {
|
| }
|
|
|
|
|
| -HValue* HArithmeticBinaryOperation::Canonicalize() {
|
| - if (representation().IsInteger32() && CheckUsesForFlag(kTruncatingToInt32)) {
|
| - ClearFlag(kCanOverflow);
|
| - }
|
| - return this;
|
| -}
|
| -
|
| -
|
| static bool IsIdentityOperation(HValue* arg1, HValue* arg2, int32_t identity) {
|
| return arg1->representation().IsSpecialization() &&
|
| arg2->EqualsInteger32Constant(identity);
|
| @@ -1446,13 +1449,13 @@ static bool IsIdentityOperation(HValue* arg1, HValue* arg2, int32_t identity) {
|
| HValue* HAdd::Canonicalize() {
|
| if (IsIdentityOperation(left(), right(), 0)) return left();
|
| if (IsIdentityOperation(right(), left(), 0)) return right();
|
| - return HArithmeticBinaryOperation::Canonicalize();
|
| + return this;
|
| }
|
|
|
|
|
| HValue* HSub::Canonicalize() {
|
| if (IsIdentityOperation(left(), right(), 0)) return left();
|
| - return HArithmeticBinaryOperation::Canonicalize();
|
| + return this;
|
| }
|
|
|
|
|
| @@ -1758,11 +1761,13 @@ Range* HAdd::InferRange(Zone* zone) {
|
| Range* a = left()->range();
|
| Range* b = right()->range();
|
| Range* res = a->Copy(zone);
|
| - if (!res->AddAndCheckOverflow(b)) {
|
| + if (!res->AddAndCheckOverflow(b) ||
|
| + CheckFlag(kAllUsesTruncatingToInt32)) {
|
| ClearFlag(kCanOverflow);
|
| }
|
| - bool m0 = a->CanBeMinusZero() && b->CanBeMinusZero();
|
| - res->set_can_be_minus_zero(m0);
|
| + if (!CheckFlag(kAllUsesTruncatingToInt32)) {
|
| + res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeMinusZero());
|
| + }
|
| return res;
|
| } else {
|
| return HValue::InferRange(zone);
|
| @@ -1775,10 +1780,13 @@ Range* HSub::InferRange(Zone* zone) {
|
| Range* a = left()->range();
|
| Range* b = right()->range();
|
| Range* res = a->Copy(zone);
|
| - if (!res->SubAndCheckOverflow(b)) {
|
| + if (!res->SubAndCheckOverflow(b) ||
|
| + CheckFlag(kAllUsesTruncatingToInt32)) {
|
| ClearFlag(kCanOverflow);
|
| }
|
| - res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero());
|
| + if (!CheckFlag(kAllUsesTruncatingToInt32)) {
|
| + res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero());
|
| + }
|
| return res;
|
| } else {
|
| return HValue::InferRange(zone);
|
| @@ -1792,11 +1800,16 @@ Range* HMul::InferRange(Zone* zone) {
|
| Range* b = right()->range();
|
| Range* res = a->Copy(zone);
|
| if (!res->MulAndCheckOverflow(b)) {
|
| + // Clearing the kCanOverflow flag when kAllUsesAreTruncatingToInt32
|
| + // would be wrong, because truncated integer multiplication is too
|
| + // precise and therefore not the same as converting to Double and back.
|
| ClearFlag(kCanOverflow);
|
| }
|
| - bool m0 = (a->CanBeZero() && b->CanBeNegative()) ||
|
| - (a->CanBeNegative() && b->CanBeZero());
|
| - res->set_can_be_minus_zero(m0);
|
| + if (!CheckFlag(kAllUsesTruncatingToInt32)) {
|
| + bool m0 = (a->CanBeZero() && b->CanBeNegative()) ||
|
| + (a->CanBeNegative() && b->CanBeZero());
|
| + res->set_can_be_minus_zero(m0);
|
| + }
|
| return res;
|
| } else {
|
| return HValue::InferRange(zone);
|
| @@ -1809,12 +1822,14 @@ Range* HDiv::InferRange(Zone* zone) {
|
| Range* a = left()->range();
|
| Range* b = right()->range();
|
| Range* result = new(zone) Range();
|
| - if (a->CanBeMinusZero()) {
|
| - result->set_can_be_minus_zero(true);
|
| - }
|
| + if (!CheckFlag(kAllUsesTruncatingToInt32)) {
|
| + if (a->CanBeMinusZero()) {
|
| + result->set_can_be_minus_zero(true);
|
| + }
|
|
|
| - if (a->CanBeZero() && b->CanBeNegative()) {
|
| - result->set_can_be_minus_zero(true);
|
| + if (a->CanBeZero() && b->CanBeNegative()) {
|
| + result->set_can_be_minus_zero(true);
|
| + }
|
| }
|
|
|
| if (!a->Includes(kMinInt) || !b->Includes(-1)) {
|
| @@ -1846,7 +1861,7 @@ Range* HMod::InferRange(Zone* zone) {
|
| Range* result = new(zone) Range(left_can_be_negative ? -positive_bound : 0,
|
| a->CanBePositive() ? positive_bound : 0);
|
|
|
| - if (left_can_be_negative) {
|
| + if (left_can_be_negative && !CheckFlag(kAllUsesTruncatingToInt32)) {
|
| result->set_can_be_minus_zero(true);
|
| }
|
|
|
| @@ -2298,10 +2313,6 @@ bool HBinaryOperation::IgnoreObservedOutputRepresentation(
|
| current_rep.IsInteger32() &&
|
| // Mul in Integer32 mode would be too precise.
|
| !this->IsMul() &&
|
| - // TODO(jkummerow): Remove blacklisting of Div when the Div
|
| - // instruction has learned not to deopt when the remainder is
|
| - // non-zero but all uses are truncating.
|
| - !this->IsDiv() &&
|
| CheckUsesForFlag(kTruncatingToInt32);
|
| }
|
|
|
|
|