Chromium Code Reviews| Index: src/hydrogen-instructions.h |
| diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h |
| index 7acec8bcd5ebc3e2e0757d312ee591f5e5174e72..ff07044eb39da22bb4e6ce3ea1a54f154fda0f80 100644 |
| --- a/src/hydrogen-instructions.h |
| +++ b/src/hydrogen-instructions.h |
| @@ -678,6 +678,41 @@ class NumericRelation { |
| my_offset, my_scale, other_offset, other_scale); |
| } |
| + // CanBeChained returns true when |
| + // "((x + offset) >> scale) rel limit" and "x other_relation y" imply |
| + // "((y + offset) >> scale) rel limit". |
| + // In other words, rel and other_relation go "in the same direction" |
| + // and therefore can be "chained". |
| + bool CanBeChained(NumericRelation other_relation) { |
| + switch (kind_) { |
| + case NONE: return false; |
| + case EQ: return (other_relation.kind_ == EQ); |
| + case GT: |
| + case GE: |
| + return (other_relation.kind_ == GT) || (other_relation.kind_ == GE); |
| + case LT: |
| + case LE: |
| + return (other_relation.kind_ == LT) || (other_relation.kind_ == LE); |
| + case NE: return false; |
| + } |
| + UNREACHABLE(); |
| + return false; |
| + } |
| + |
| + bool ApplyToValues(int32_t value, int32_t other_value) { |
| + switch (kind_) { |
| + case NONE: return false; |
| + case EQ: return value == other_value; |
| + case GT: return value > other_value; |
| + case GE: return value >= other_value; |
| + case LT: return value < other_value; |
| + case LE: return value <= other_value; |
| + case NE: return value != other_value; |
| + } |
| + UNREACHABLE(); |
| + return false; |
| + } |
| + |
| private: |
| // ComponentsImply returns true when |
| // "((x + my_offset) >> my_scale) rel y" implies |
| @@ -752,8 +787,11 @@ class DecompositionResult BASE_EMBEDDED { |
| class RangeEvaluationContext BASE_EMBEDDED { |
| public: |
| - RangeEvaluationContext(HValue* value, HValue* upper); |
| + RangeEvaluationContext(HValue* value, |
| + HValue* upper, |
| + HBasicBlock* starting_block); |
| + HBasicBlock* starting_block() { return starting_block_; } |
| HValue* lower_bound() { return lower_bound_; } |
| HValue* lower_bound_guarantee() { return lower_bound_guarantee_; } |
| HValue* candidate() { return candidate_; } |
| @@ -780,6 +818,7 @@ class RangeEvaluationContext BASE_EMBEDDED { |
| private: |
| HValue* ConvertGuarantee(HValue* guarantee); |
| + HBasicBlock* starting_block_; |
| HValue* lower_bound_; |
| HValue* lower_bound_guarantee_; |
| HValue* candidate_; |
| @@ -1100,7 +1139,8 @@ class HValue: public ZoneObject { |
| int offset = 0, |
| int scale = 0); |
| - bool TryGuaranteeRange(HValue* upper_bound); |
| + bool TryGuaranteeRange(HValue* upper_bound, |
| + HBasicBlock* starting_block_for_hoisting = NULL); |
| virtual bool TryDecompose(DecompositionResult* decomposition) { |
| if (RedefinedOperand() != NULL) { |
| return RedefinedOperand()->TryDecompose(decomposition); |
| @@ -1422,11 +1462,13 @@ class HNumericConstraint : public HTemplateInstruction<2> { |
| static HNumericConstraint* AddToGraph(HValue* constrained_value, |
| NumericRelation relation, |
| HValue* related_value, |
| - HInstruction* insertion_point = NULL); |
| + HInstruction* insertion_point = NULL, |
| + HBasicBlock* other_block = NULL); |
|
Jakob Kummerow
2013/04/17 11:34:15
I think "other_block" either needs a comment or a
Massi
2013/05/07 11:32:03
Done.
|
| HValue* constrained_value() { return OperandAt(0); } |
| HValue* related_value() { return OperandAt(1); } |
| NumericRelation relation() { return relation_; } |
| + HBasicBlock* other_block() { return other_block_; } |
| virtual int RedefinedOperandIndex() { return 0; } |
| virtual bool IsPurelyInformativeDefinition() { return true; } |
| @@ -1444,7 +1486,12 @@ class HNumericConstraint : public HTemplateInstruction<2> { |
| if (related_value() == other_related_value) { |
| return relation().CompoundImplies(other_relation, offset, scale); |
| } else { |
| - return false; |
| + if (relation().CanBeChained(other_relation)) { |
| + return related_value()->IsRelationTrue( |
| + other_relation, other_related_value, offset, scale); |
| + } else { |
| + return false; |
| + } |
| } |
| } |
| @@ -1453,13 +1500,15 @@ class HNumericConstraint : public HTemplateInstruction<2> { |
| private: |
| HNumericConstraint(HValue* constrained_value, |
| NumericRelation relation, |
| - HValue* related_value) |
| - : relation_(relation) { |
| + HValue* related_value, |
| + HBasicBlock* other_block) |
| + : relation_(relation), other_block_(other_block) { |
|
Jakob Kummerow
2013/04/17 11:34:15
nit: indentation
Massi
2013/05/07 11:32:03
Done.
|
| SetOperandAt(0, constrained_value); |
| SetOperandAt(1, related_value); |
| } |
| NumericRelation relation_; |
| + HBasicBlock* other_block_; |
| }; |
| @@ -3101,6 +3150,9 @@ class HPhi: public HValue { |
| }; |
| +class HBoundsCheck; |
| + |
| + |
| class HInductionVariableAnnotation : public HUnaryOperation { |
| public: |
| static HInductionVariableAnnotation* AddToGraph(HPhi* phi, |
| @@ -3116,6 +3168,7 @@ class HInductionVariableAnnotation : public HUnaryOperation { |
| return representation(); |
| } |
| + virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context); |
| virtual void PrintDataTo(StringStream* stream); |
| virtual bool IsRelationTrueInternal(NumericRelation other_relation, |
| @@ -3125,19 +3178,27 @@ class HInductionVariableAnnotation : public HUnaryOperation { |
| if (induction_base() == other_related_value) { |
| return relation().CompoundImplies(other_relation, offset, scale); |
| } else { |
| - return false; |
| + if (relation().CanBeChained(other_relation)) { |
| + return induction_base()->IsRelationTrue( |
| + other_relation, other_related_value, offset, scale); |
| + } else { |
| + return false; |
| + } |
| } |
| } |
| + const ZoneList<HBoundsCheck*>* hoisted_checks() const { |
| + return &hoisted_checks_; |
| + } |
| + void AddHoistedCheck(HBoundsCheck* check); |
| + |
| DECLARE_CONCRETE_INSTRUCTION(InductionVariableAnnotation) |
| private: |
| HInductionVariableAnnotation(HPhi* phi, |
| NumericRelation relation, |
| - int operand_index) |
| - : HUnaryOperation(phi), |
| - phi_(phi), relation_(relation), operand_index_(operand_index) { |
| - } |
| + int operand_index, |
| + Zone* zone); |
| // We need to store the phi both here and in the instruction operand because |
| // the operand can change if a new idef of the phi is added between the phi |
| @@ -3145,6 +3206,7 @@ class HInductionVariableAnnotation : public HUnaryOperation { |
| HPhi* phi_; |
| NumericRelation relation_; |
| int operand_index_; |
| + ZoneList<HBoundsCheck*> hoisted_checks_; |
| }; |
| @@ -3292,6 +3354,20 @@ class HConstant: public HTemplateInstruction<0> { |
| return HasInteger32Value() && (Integer32Value() >= 0); |
| } |
| + virtual bool IsRelationTrueInternal(NumericRelation relation, |
| + HValue* related_value, |
| + int offset = 0, |
| + int scale = 0) { |
| + if (HasInteger32Value() |
| + && related_value->IsInteger32Constant()) { |
|
Jakob Kummerow
2013/04/17 11:34:15
nit: we're pretty consistent about putting binary
Massi
2013/05/07 11:32:03
Done.
|
| + int32_t value = (Integer32Value() + offset) >> scale; |
| + int32_t other_value = related_value->GetInteger32Constant(); |
| + return relation.ApplyToValues(value, other_value); |
| + } else { |
| + return false; |
| + } |
| + } |
| + |
| virtual intptr_t Hashcode() { |
| ASSERT_ALLOCATION_DISABLED; |
| intptr_t hash; |
| @@ -3575,7 +3651,8 @@ class HBoundsCheck: public HTemplateInstruction<2> { |
| Representation r = Representation::None()) |
| : key_mode_(key_mode), skip_check_(false), |
| base_(NULL), offset_(0), scale_(0), |
| - responsibility_direction_(DIRECTION_NONE) { |
| + responsibility_direction_(DIRECTION_NONE), |
| + allow_equality_(false) { |
| SetOperandAt(0, index); |
| SetOperandAt(1, length); |
| if (r.IsNone()) { |
| @@ -3637,6 +3714,8 @@ class HBoundsCheck: public HTemplateInstruction<2> { |
| HValue* index() { return OperandAt(0); } |
| HValue* length() { return OperandAt(1); } |
| + bool allow_equality() { return allow_equality_; } |
| + void set_allow_equality(bool v) { allow_equality_ = v; } |
| virtual int RedefinedOperandIndex() { return 0; } |
| virtual bool IsPurelyInformativeDefinition() { return skip_check(); } |
| @@ -3660,6 +3739,7 @@ class HBoundsCheck: public HTemplateInstruction<2> { |
| int offset_; |
| int scale_; |
| RangeGuaranteeDirection responsibility_direction_; |
| + bool allow_equality_; |
| }; |
| @@ -3676,7 +3756,10 @@ class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> { |
| } |
| HValue* base_index() { return OperandAt(0); } |
| - HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); } |
| + HBoundsCheck* bounds_check() { |
| + return OperandAt(1)->IsBoundsCheck() |
| + ? HBoundsCheck::cast(OperandAt(1)) : NULL; |
| + } |
| DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation) |
| @@ -4304,6 +4387,11 @@ class HAdd: public HArithmeticBinaryOperation { |
| } |
| } |
| + virtual bool IsRelationTrueInternal(NumericRelation relation, |
| + HValue* other, |
| + int offset = 0, |
| + int scale = 0); |
| + |
| DECLARE_CONCRETE_INSTRUCTION(Add) |
| protected: |
| @@ -4548,6 +4636,19 @@ class HShl: public HBitwiseBinaryOperation { |
| HValue* left, |
| HValue* right); |
| + virtual bool TryDecompose(DecompositionResult* decomposition) { |
| + if (right()->IsInteger32Constant() |
| + && right()->GetInteger32Constant() <= 1) { |
|
Jakob Kummerow
2013/04/17 11:34:15
As discussed, I think you need an additional check
Massi
2013/05/07 11:32:03
Done.
|
| + if (decomposition->Apply(left(), 0, - right()->GetInteger32Constant())) { |
| + // This is intended to look for HAdd and HSub, to handle compounds |
| + // like ((base + offset) >> scale) with one single decomposition. |
|
Jakob Kummerow
2013/04/17 11:34:15
s/>>/<</ ?
Massi
2013/05/07 11:32:03
Done.
|
| + left()->TryDecompose(decomposition); |
| + return true; |
| + } |
| + } |
| + return false; |
| + } |
| + |
| virtual Range* InferRange(Zone* zone); |
| DECLARE_CONCRETE_INSTRUCTION(Shl) |