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); |
} |