Index: src/hydrogen-instructions.cc |
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc |
index a685198ba6288e54e0913695f6e6f4e5cc797f09..8f3a1eb3d6a4f2794607d1556c871debab53f83d 100644 |
--- a/src/hydrogen-instructions.cc |
+++ b/src/hydrogen-instructions.cc |
@@ -1237,6 +1237,16 @@ HValue* HMul::Canonicalize() { |
} |
+bool HMul::MulMinusOne() { |
+ if (left()->EqualsInteger32Constant(-1) || |
+ right()->EqualsInteger32Constant(-1)) { |
+ return true; |
+ } |
+ |
+ return false; |
+} |
+ |
+ |
HValue* HMod::Canonicalize() { |
return this; |
} |
@@ -1622,10 +1632,13 @@ Range* HMul::InferRange(Zone* zone) { |
Range* a = left()->range(); |
Range* b = right()->range(); |
Range* res = a->Copy(zone); |
- if (!res->MulAndCheckOverflow(r, 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. |
+ if (!res->MulAndCheckOverflow(r, b) || |
+ (((r.IsInteger32() && CheckFlag(kAllUsesTruncatingToInt32)) || |
+ (r.IsSmi() && CheckFlag(kAllUsesTruncatingToSmi))) && |
+ MulMinusOne())) { |
+ // Truncated int multiplication is too precise and therefore not the |
+ // same as converting to Double and back. |
+ // Handle truncated integer multiplication by -1 special. |
ClearFlag(kCanOverflow); |
} |
res->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToSmi) && |
@@ -1647,7 +1660,10 @@ Range* HDiv::InferRange(Zone* zone) { |
result->set_can_be_minus_zero(!CheckFlag(kAllUsesTruncatingToInt32) && |
(a->CanBeMinusZero() || |
(a->CanBeZero() && b->CanBeNegative()))); |
- if (!a->Includes(kMinInt) || !b->Includes(-1)) { |
+ if (!a->Includes(kMinInt) || |
+ !b->Includes(-1) || |
+ CheckFlag(kAllUsesTruncatingToInt32)) { |
+ // It is safe to clear kCanOverflow when kAllUsesTruncatingToInt32. |
ClearFlag(HValue::kCanOverflow); |
} |
@@ -2620,6 +2636,12 @@ void HBinaryOperation::InferRepresentation(HInferRepresentationPhase* h_infer) { |
ASSERT(CheckFlag(kFlexibleRepresentation)); |
Representation new_rep = RepresentationFromInputs(); |
UpdateRepresentation(new_rep, h_infer, "inputs"); |
+ |
+ if (representation().IsSmi() && HasNonSmiUse()) { |
+ UpdateRepresentation( |
+ Representation::Integer32(), h_infer, "use requirements"); |
+ } |
+ |
if (observed_output_representation_.IsNone()) { |
new_rep = RepresentationFromUses(); |
UpdateRepresentation(new_rep, h_infer, "uses"); |
@@ -2627,11 +2649,6 @@ void HBinaryOperation::InferRepresentation(HInferRepresentationPhase* h_infer) { |
new_rep = RepresentationFromOutput(); |
UpdateRepresentation(new_rep, h_infer, "output"); |
} |
- |
- if (representation().IsSmi() && HasNonSmiUse()) { |
- UpdateRepresentation( |
- Representation::Integer32(), h_infer, "use requirements"); |
- } |
} |
@@ -2658,7 +2675,7 @@ bool HBinaryOperation::IgnoreObservedOutputRepresentation( |
return ((current_rep.IsInteger32() && CheckUsesForFlag(kTruncatingToInt32)) || |
(current_rep.IsSmi() && CheckUsesForFlag(kTruncatingToSmi))) && |
// Mul in Integer32 mode would be too precise. |
- !this->IsMul(); |
+ (!this->IsMul() || HMul::cast(this)->MulMinusOne()); |
} |