Chromium Code Reviews| Index: runtime/vm/intermediate_language.h |
| diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h |
| index ff3822cf9754846491807a5a7f95e99c5ca8b044..5eac2c7ab3ab64a25f2bdec46fcd83a5585f01e3 100644 |
| --- a/runtime/vm/intermediate_language.h |
| +++ b/runtime/vm/intermediate_language.h |
| @@ -453,7 +453,7 @@ class EmbeddedArray<T, 0> { |
| M(OneByteStringFromCharCode) \ |
| M(StringInterpolate) \ |
| M(InvokeMathCFunction) \ |
| - M(MergedMath) \ |
| + M(TruncDivMod) \ |
| M(GuardFieldClass) \ |
| M(GuardFieldLength) \ |
| M(IfThenElse) \ |
| @@ -6929,7 +6929,8 @@ class BinarySmiOpInstr : public BinaryIntegerOpInstr { |
| Value* left, |
| Value* right, |
| intptr_t deopt_id) |
| - : BinaryIntegerOpInstr(op_kind, left, right, deopt_id) {} |
| + : BinaryIntegerOpInstr(op_kind, left, right, deopt_id), |
| + right_range_(NULL) {} |
| virtual bool ComputeCanDeoptimize() const; |
| @@ -6938,7 +6939,11 @@ class BinarySmiOpInstr : public BinaryIntegerOpInstr { |
| DECLARE_INSTRUCTION(BinarySmiOp) |
| + Range* right_range() const { return right_range_; } |
| + |
| private: |
| + Range* right_range_; |
| + |
| DISALLOW_COPY_AND_ASSIGN(BinarySmiOpInstr); |
| }; |
| @@ -6967,7 +6972,11 @@ class BinaryInt32OpInstr : public BinaryIntegerOpInstr { |
| case Token::kSHL: |
| case Token::kSHR: |
| - return right->BindsToConstant(); |
| + if (right->BindsToConstant() && right->BoundConstant().IsSmi()) { |
| + const intptr_t value = Smi::Cast(right->BoundConstant()).Value(); |
| + return 0 <= value && value < kBitsPerWord; |
| + } |
| + return false; |
| default: |
| return false; |
| @@ -7089,10 +7098,13 @@ class ShiftMintOpInstr : public BinaryIntegerOpInstr { |
| Value* left, |
| Value* right, |
| intptr_t deopt_id) |
| - : BinaryIntegerOpInstr(op_kind, left, right, deopt_id) { |
| + : BinaryIntegerOpInstr(op_kind, left, right, deopt_id), |
| + shift_range_(NULL) { |
| ASSERT((op_kind == Token::kSHR) || (op_kind == Token::kSHL)); |
| } |
| + Range* shift_range() const { return shift_range_; } |
| + |
| virtual bool ComputeCanDeoptimize() const { |
| return has_shift_count_check() || |
| (can_overflow() && (op_kind() == Token::kSHL)); |
| @@ -7111,8 +7123,11 @@ class ShiftMintOpInstr : public BinaryIntegerOpInstr { |
| DECLARE_INSTRUCTION(ShiftMintOp) |
| private: |
| + static const intptr_t kMintShiftCountLimit = 63; |
| bool has_shift_count_check() const; |
| + Range* shift_range_; |
| + |
| DISALLOW_COPY_AND_ASSIGN(ShiftMintOpInstr); |
| }; |
| @@ -7545,90 +7560,45 @@ class ExtractNthOutputInstr : public TemplateDefinition<1, NoThrow, Pure> { |
| }; |
| -class MergedMathInstr : public PureDefinition { |
| +class TruncDivModInstr : public TemplateDefinition<2, NoThrow, Pure> { |
| public: |
| - enum Kind { |
| - kTruncDivMod, |
| - }; |
| - |
| - MergedMathInstr(ZoneGrowableArray<Value*>* inputs, |
| - intptr_t original_deopt_id, |
| - MergedMathInstr::Kind kind); |
| - |
| - static intptr_t InputCountFor(MergedMathInstr::Kind kind) { |
| - if (kind == kTruncDivMod) { |
| - return 2; |
| - } else { |
| - UNIMPLEMENTED(); |
| - return -1; |
| - } |
| - } |
| - |
| - MergedMathInstr::Kind kind() const { return kind_; } |
| - |
| - virtual intptr_t InputCount() const { return inputs_->length(); } |
| - |
| - virtual Value* InputAt(intptr_t i) const { return (*inputs_)[i]; } |
| + TruncDivModInstr(Value* lhs, Value* rhs, intptr_t deopt_id); |
| - static intptr_t OutputIndexOf(MethodRecognizer::Kind kind); |
| static intptr_t OutputIndexOf(Token::Kind token); |
| virtual CompileType ComputeType() const; |
| - virtual bool ComputeCanDeoptimize() const { |
| - if (kind_ == kTruncDivMod) { |
| - return true; |
| - } else { |
| - UNIMPLEMENTED(); |
| - return false; |
| - } |
| - } |
| + virtual bool ComputeCanDeoptimize() const { return true; } |
| - virtual Representation representation() const { |
| - if (kind_ == kTruncDivMod) { |
| - return kPairOfTagged; |
| - } else { |
| - UNIMPLEMENTED(); |
| - return kTagged; |
| - } |
| - } |
| + virtual Representation representation() const { return kPairOfTagged; } |
| virtual Representation RequiredInputRepresentation(intptr_t idx) const { |
| ASSERT((0 <= idx) && (idx < InputCount())); |
| - if (kind_ == kTruncDivMod) { |
| - return kTagged; |
| - } else { |
| - UNIMPLEMENTED(); |
| - return kTagged; |
| - } |
| + return kTagged; |
| } |
| virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); } |
| - DECLARE_INSTRUCTION(MergedMath) |
| - |
| - virtual bool AttributesEqual(Instruction* other) const { |
| - MergedMathInstr* other_invoke = other->AsMergedMath(); |
| - return other_invoke->kind() == kind(); |
| - } |
| - |
| - virtual bool MayThrow() const { return false; } |
| + DECLARE_INSTRUCTION(TruncDivMod) |
| - static const char* KindToCString(MergedMathInstr::Kind kind) { |
| - if (kind == kTruncDivMod) return "TruncDivMod"; |
| - UNIMPLEMENTED(); |
| - return ""; |
| - } |
| + virtual bool AttributesEqual(Instruction* other) const { return true; } |
| PRINT_OPERANDS_TO_SUPPORT |
| private: |
| - virtual void RawSetInputAt(intptr_t i, Value* value) { |
| - (*inputs_)[i] = value; |
| + Range* divisor_range() const { |
| + // Note: this range is only used to remove check for zero divisor from |
| + // the emitted pattern. It is not used for decising whether instruction |
|
rmacnak
2017/05/18 20:02:45
deciding
Vyacheslav Egorov (Google)
2017/05/19 08:07:08
Done.
|
| + // will deoptimize or not - that is why it is ok to access range of |
| + // the definition directly. Otherwise range analysis or another pass |
| + // needs to cache range of the divisor in the operation to prevent |
| + // bugs when range information gets out of sync with the final decision |
| + // whether some instruction can deoptimize or not made in |
| + // EliminateEnvironments(). |
| + return InputAt(1)->definition()->range(); |
| } |
| - ZoneGrowableArray<Value*>* inputs_; |
| - MergedMathInstr::Kind kind_; |
| - DISALLOW_COPY_AND_ASSIGN(MergedMathInstr); |
| + |
| + DISALLOW_COPY_AND_ASSIGN(TruncDivModInstr); |
| }; |