OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ | 5 #ifndef V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ |
6 #define V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ | 6 #define V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ |
7 | 7 |
8 #include <cstring> | 8 #include <cstring> |
9 #include <iosfwd> | 9 #include <iosfwd> |
10 | 10 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 V(AccessArgumentsAt) \ | 49 V(AccessArgumentsAt) \ |
50 V(Add) \ | 50 V(Add) \ |
51 V(Allocate) \ | 51 V(Allocate) \ |
52 V(ApplyArguments) \ | 52 V(ApplyArguments) \ |
53 V(ArgumentsElements) \ | 53 V(ArgumentsElements) \ |
54 V(ArgumentsLength) \ | 54 V(ArgumentsLength) \ |
55 V(ArgumentsObject) \ | 55 V(ArgumentsObject) \ |
56 V(Bitwise) \ | 56 V(Bitwise) \ |
57 V(BlockEntry) \ | 57 V(BlockEntry) \ |
58 V(BoundsCheck) \ | 58 V(BoundsCheck) \ |
59 V(BoundsCheckBaseIndexInformation) \ | |
60 V(Branch) \ | 59 V(Branch) \ |
61 V(CallWithDescriptor) \ | 60 V(CallWithDescriptor) \ |
62 V(CallNewArray) \ | 61 V(CallNewArray) \ |
63 V(CallRuntime) \ | 62 V(CallRuntime) \ |
64 V(CapturedObject) \ | 63 V(CapturedObject) \ |
65 V(Change) \ | 64 V(Change) \ |
66 V(CheckArrayBufferNotNeutered) \ | 65 V(CheckArrayBufferNotNeutered) \ |
67 V(CheckHeapObject) \ | 66 V(CheckHeapObject) \ |
68 V(CheckInstanceType) \ | 67 V(CheckInstanceType) \ |
69 V(CheckMaps) \ | 68 V(CheckMaps) \ |
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 | 724 |
726 // Check if this instruction has some reason that prevents elimination. | 725 // Check if this instruction has some reason that prevents elimination. |
727 bool CannotBeEliminated() const { | 726 bool CannotBeEliminated() const { |
728 return HasObservableSideEffects() || !IsDeletable(); | 727 return HasObservableSideEffects() || !IsDeletable(); |
729 } | 728 } |
730 | 729 |
731 #ifdef DEBUG | 730 #ifdef DEBUG |
732 virtual void Verify() = 0; | 731 virtual void Verify() = 0; |
733 #endif | 732 #endif |
734 | 733 |
735 virtual bool TryDecompose(DecompositionResult* decomposition) { | |
736 if (RedefinedOperand() != NULL) { | |
737 return RedefinedOperand()->TryDecompose(decomposition); | |
738 } else { | |
739 return false; | |
740 } | |
741 } | |
742 | |
743 // Returns true conservatively if the program might be able to observe a | 734 // Returns true conservatively if the program might be able to observe a |
744 // ToString() operation on this value. | 735 // ToString() operation on this value. |
745 bool ToStringCanBeObserved() const { | 736 bool ToStringCanBeObserved() const { |
746 return ToStringOrToNumberCanBeObserved(); | 737 return ToStringOrToNumberCanBeObserved(); |
747 } | 738 } |
748 | 739 |
749 // Returns true conservatively if the program might be able to observe a | 740 // Returns true conservatively if the program might be able to observe a |
750 // ToNumber() operation on this value. | 741 // ToNumber() operation on this value. |
751 bool ToNumberCanBeObserved() const { | 742 bool ToNumberCanBeObserved() const { |
752 return ToStringOrToNumberCanBeObserved(); | 743 return ToStringOrToNumberCanBeObserved(); |
(...skipping 2188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2941 bool DataEquals(HValue* other) override { return true; } | 2932 bool DataEquals(HValue* other) override { return true; } |
2942 | 2933 |
2943 private: | 2934 private: |
2944 explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) { | 2935 explicit HCheckHeapObject(HValue* value) : HUnaryOperation(value) { |
2945 set_representation(Representation::Tagged()); | 2936 set_representation(Representation::Tagged()); |
2946 SetFlag(kUseGVN); | 2937 SetFlag(kUseGVN); |
2947 } | 2938 } |
2948 }; | 2939 }; |
2949 | 2940 |
2950 | 2941 |
2951 class InductionVariableData; | |
2952 | |
2953 | |
2954 struct InductionVariableLimitUpdate { | |
2955 InductionVariableData* updated_variable; | |
2956 HValue* limit; | |
2957 bool limit_is_upper; | |
2958 bool limit_is_included; | |
2959 | |
2960 InductionVariableLimitUpdate() | |
2961 : updated_variable(NULL), limit(NULL), | |
2962 limit_is_upper(false), limit_is_included(false) {} | |
2963 }; | |
2964 | |
2965 | |
2966 class HBoundsCheck; | |
2967 class HPhi; | |
2968 class HBitwise; | |
2969 | |
2970 | |
2971 class InductionVariableData final : public ZoneObject { | |
2972 public: | |
2973 class InductionVariableCheck : public ZoneObject { | |
2974 public: | |
2975 HBoundsCheck* check() { return check_; } | |
2976 InductionVariableCheck* next() { return next_; } | |
2977 bool HasUpperLimit() { return upper_limit_ >= 0; } | |
2978 int32_t upper_limit() { | |
2979 DCHECK(HasUpperLimit()); | |
2980 return upper_limit_; | |
2981 } | |
2982 void set_upper_limit(int32_t upper_limit) { | |
2983 upper_limit_ = upper_limit; | |
2984 } | |
2985 | |
2986 bool processed() { return processed_; } | |
2987 void set_processed() { processed_ = true; } | |
2988 | |
2989 InductionVariableCheck(HBoundsCheck* check, | |
2990 InductionVariableCheck* next, | |
2991 int32_t upper_limit = kNoLimit) | |
2992 : check_(check), next_(next), upper_limit_(upper_limit), | |
2993 processed_(false) {} | |
2994 | |
2995 private: | |
2996 HBoundsCheck* check_; | |
2997 InductionVariableCheck* next_; | |
2998 int32_t upper_limit_; | |
2999 bool processed_; | |
3000 }; | |
3001 | |
3002 class ChecksRelatedToLength : public ZoneObject { | |
3003 public: | |
3004 HValue* length() { return length_; } | |
3005 ChecksRelatedToLength* next() { return next_; } | |
3006 InductionVariableCheck* checks() { return checks_; } | |
3007 | |
3008 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit); | |
3009 void CloseCurrentBlock(); | |
3010 | |
3011 ChecksRelatedToLength(HValue* length, ChecksRelatedToLength* next) | |
3012 : length_(length), next_(next), checks_(NULL), | |
3013 first_check_in_block_(NULL), | |
3014 added_index_(NULL), | |
3015 added_constant_(NULL), | |
3016 current_and_mask_in_block_(0), | |
3017 current_or_mask_in_block_(0) {} | |
3018 | |
3019 private: | |
3020 void UseNewIndexInCurrentBlock(Token::Value token, | |
3021 int32_t mask, | |
3022 HValue* index_base, | |
3023 HValue* context); | |
3024 | |
3025 HBoundsCheck* first_check_in_block() { return first_check_in_block_; } | |
3026 HBitwise* added_index() { return added_index_; } | |
3027 void set_added_index(HBitwise* index) { added_index_ = index; } | |
3028 HConstant* added_constant() { return added_constant_; } | |
3029 void set_added_constant(HConstant* constant) { added_constant_ = constant; } | |
3030 int32_t current_and_mask_in_block() { return current_and_mask_in_block_; } | |
3031 int32_t current_or_mask_in_block() { return current_or_mask_in_block_; } | |
3032 int32_t current_upper_limit() { return current_upper_limit_; } | |
3033 | |
3034 HValue* length_; | |
3035 ChecksRelatedToLength* next_; | |
3036 InductionVariableCheck* checks_; | |
3037 | |
3038 HBoundsCheck* first_check_in_block_; | |
3039 HBitwise* added_index_; | |
3040 HConstant* added_constant_; | |
3041 int32_t current_and_mask_in_block_; | |
3042 int32_t current_or_mask_in_block_; | |
3043 int32_t current_upper_limit_; | |
3044 }; | |
3045 | |
3046 struct LimitFromPredecessorBlock { | |
3047 InductionVariableData* variable; | |
3048 Token::Value token; | |
3049 HValue* limit; | |
3050 HBasicBlock* other_target; | |
3051 | |
3052 bool LimitIsValid() { return token != Token::ILLEGAL; } | |
3053 | |
3054 bool LimitIsIncluded() { | |
3055 return Token::IsEqualityOp(token) || | |
3056 token == Token::GTE || token == Token::LTE; | |
3057 } | |
3058 bool LimitIsUpper() { | |
3059 return token == Token::LTE || token == Token::LT || token == Token::NE; | |
3060 } | |
3061 | |
3062 LimitFromPredecessorBlock() | |
3063 : variable(NULL), | |
3064 token(Token::ILLEGAL), | |
3065 limit(NULL), | |
3066 other_target(NULL) {} | |
3067 }; | |
3068 | |
3069 static const int32_t kNoLimit = -1; | |
3070 | |
3071 static InductionVariableData* ExaminePhi(HPhi* phi); | |
3072 static void ComputeLimitFromPredecessorBlock( | |
3073 HBasicBlock* block, | |
3074 LimitFromPredecessorBlock* result); | |
3075 static bool ComputeInductionVariableLimit( | |
3076 HBasicBlock* block, | |
3077 InductionVariableLimitUpdate* additional_limit); | |
3078 | |
3079 struct BitwiseDecompositionResult { | |
3080 HValue* base; | |
3081 int32_t and_mask; | |
3082 int32_t or_mask; | |
3083 HValue* context; | |
3084 | |
3085 BitwiseDecompositionResult() | |
3086 : base(NULL), and_mask(0), or_mask(0), context(NULL) {} | |
3087 }; | |
3088 static void DecomposeBitwise(HValue* value, | |
3089 BitwiseDecompositionResult* result); | |
3090 | |
3091 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit); | |
3092 | |
3093 bool CheckIfBranchIsLoopGuard(Token::Value token, | |
3094 HBasicBlock* current_branch, | |
3095 HBasicBlock* other_branch); | |
3096 | |
3097 void UpdateAdditionalLimit(InductionVariableLimitUpdate* update); | |
3098 | |
3099 HPhi* phi() { return phi_; } | |
3100 HValue* base() { return base_; } | |
3101 int32_t increment() { return increment_; } | |
3102 HValue* limit() { return limit_; } | |
3103 bool limit_included() { return limit_included_; } | |
3104 HBasicBlock* limit_validity() { return limit_validity_; } | |
3105 HBasicBlock* induction_exit_block() { return induction_exit_block_; } | |
3106 HBasicBlock* induction_exit_target() { return induction_exit_target_; } | |
3107 ChecksRelatedToLength* checks() { return checks_; } | |
3108 HValue* additional_upper_limit() { return additional_upper_limit_; } | |
3109 bool additional_upper_limit_is_included() { | |
3110 return additional_upper_limit_is_included_; | |
3111 } | |
3112 HValue* additional_lower_limit() { return additional_lower_limit_; } | |
3113 bool additional_lower_limit_is_included() { | |
3114 return additional_lower_limit_is_included_; | |
3115 } | |
3116 | |
3117 bool LowerLimitIsNonNegativeConstant() { | |
3118 if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) { | |
3119 return true; | |
3120 } | |
3121 if (additional_lower_limit() != NULL && | |
3122 additional_lower_limit()->IsInteger32Constant() && | |
3123 additional_lower_limit()->GetInteger32Constant() >= 0) { | |
3124 // Ignoring the corner case of !additional_lower_limit_is_included() | |
3125 // is safe, handling it adds unneeded complexity. | |
3126 return true; | |
3127 } | |
3128 return false; | |
3129 } | |
3130 | |
3131 int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask); | |
3132 | |
3133 private: | |
3134 template <class T> void swap(T* a, T* b) { | |
3135 T c(*a); | |
3136 *a = *b; | |
3137 *b = c; | |
3138 } | |
3139 | |
3140 InductionVariableData(HPhi* phi, HValue* base, int32_t increment) | |
3141 : phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment), | |
3142 limit_(NULL), limit_included_(false), limit_validity_(NULL), | |
3143 induction_exit_block_(NULL), induction_exit_target_(NULL), | |
3144 checks_(NULL), | |
3145 additional_upper_limit_(NULL), | |
3146 additional_upper_limit_is_included_(false), | |
3147 additional_lower_limit_(NULL), | |
3148 additional_lower_limit_is_included_(false) {} | |
3149 | |
3150 static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand); | |
3151 | |
3152 static HValue* IgnoreOsrValue(HValue* v); | |
3153 static InductionVariableData* GetInductionVariableData(HValue* v); | |
3154 | |
3155 HPhi* phi_; | |
3156 HValue* base_; | |
3157 int32_t increment_; | |
3158 HValue* limit_; | |
3159 bool limit_included_; | |
3160 HBasicBlock* limit_validity_; | |
3161 HBasicBlock* induction_exit_block_; | |
3162 HBasicBlock* induction_exit_target_; | |
3163 ChecksRelatedToLength* checks_; | |
3164 HValue* additional_upper_limit_; | |
3165 bool additional_upper_limit_is_included_; | |
3166 HValue* additional_lower_limit_; | |
3167 bool additional_lower_limit_is_included_; | |
3168 }; | |
3169 | |
3170 | |
3171 class HPhi final : public HValue { | 2942 class HPhi final : public HValue { |
3172 public: | 2943 public: |
3173 HPhi(int merged_index, Zone* zone) | 2944 HPhi(int merged_index, Zone* zone) |
3174 : inputs_(2, zone), merged_index_(merged_index) { | 2945 : inputs_(2, zone), merged_index_(merged_index) { |
3175 DCHECK(merged_index >= 0 || merged_index == kInvalidMergedIndex); | 2946 DCHECK(merged_index >= 0 || merged_index == kInvalidMergedIndex); |
3176 SetFlag(kFlexibleRepresentation); | 2947 SetFlag(kFlexibleRepresentation); |
3177 SetFlag(kAllowUndefinedAsNaN); | 2948 SetFlag(kAllowUndefinedAsNaN); |
3178 } | 2949 } |
3179 | 2950 |
3180 Representation RepresentationFromInputs() override; | 2951 Representation RepresentationFromInputs() override; |
(...skipping 13 matching lines...) Expand all Loading... |
3194 void AddInput(HValue* value); | 2965 void AddInput(HValue* value); |
3195 bool HasRealUses(); | 2966 bool HasRealUses(); |
3196 | 2967 |
3197 bool IsReceiver() const { return merged_index_ == 0; } | 2968 bool IsReceiver() const { return merged_index_ == 0; } |
3198 bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; } | 2969 bool HasMergedIndex() const { return merged_index_ != kInvalidMergedIndex; } |
3199 | 2970 |
3200 SourcePosition position() const override; | 2971 SourcePosition position() const override; |
3201 | 2972 |
3202 int merged_index() const { return merged_index_; } | 2973 int merged_index() const { return merged_index_; } |
3203 | 2974 |
3204 InductionVariableData* induction_variable_data() { | |
3205 return induction_variable_data_; | |
3206 } | |
3207 bool IsInductionVariable() { | |
3208 return induction_variable_data_ != NULL; | |
3209 } | |
3210 bool IsLimitedInductionVariable() { | |
3211 return IsInductionVariable() && | |
3212 induction_variable_data_->limit() != NULL; | |
3213 } | |
3214 void DetectInductionVariable() { | |
3215 DCHECK(induction_variable_data_ == NULL); | |
3216 induction_variable_data_ = InductionVariableData::ExaminePhi(this); | |
3217 } | |
3218 | |
3219 std::ostream& PrintTo(std::ostream& os) const override; // NOLINT | 2975 std::ostream& PrintTo(std::ostream& os) const override; // NOLINT |
3220 | 2976 |
3221 #ifdef DEBUG | 2977 #ifdef DEBUG |
3222 void Verify() override; | 2978 void Verify() override; |
3223 #endif | 2979 #endif |
3224 | 2980 |
3225 void InitRealUses(int id); | 2981 void InitRealUses(int id); |
3226 void AddNonPhiUsesFrom(HPhi* other); | 2982 void AddNonPhiUsesFrom(HPhi* other); |
3227 | 2983 |
3228 Representation representation_from_indirect_uses() const { | 2984 Representation representation_from_indirect_uses() const { |
(...skipping 25 matching lines...) Expand all Loading... |
3254 | 3010 |
3255 private: | 3011 private: |
3256 Representation representation_from_non_phi_uses() const { | 3012 Representation representation_from_non_phi_uses() const { |
3257 return representation_from_non_phi_uses_; | 3013 return representation_from_non_phi_uses_; |
3258 } | 3014 } |
3259 | 3015 |
3260 ZoneList<HValue*> inputs_; | 3016 ZoneList<HValue*> inputs_; |
3261 int merged_index_ = 0; | 3017 int merged_index_ = 0; |
3262 | 3018 |
3263 int phi_id_ = -1; | 3019 int phi_id_ = -1; |
3264 InductionVariableData* induction_variable_data_ = nullptr; | |
3265 | 3020 |
3266 Representation representation_from_indirect_uses_ = Representation::None(); | 3021 Representation representation_from_indirect_uses_ = Representation::None(); |
3267 Representation representation_from_non_phi_uses_ = Representation::None(); | 3022 Representation representation_from_non_phi_uses_ = Representation::None(); |
3268 bool has_type_feedback_from_uses_ = false; | 3023 bool has_type_feedback_from_uses_ = false; |
3269 | 3024 |
3270 bool IsDeletable() const override { return !IsReceiver(); } | 3025 bool IsDeletable() const override { return !IsReceiver(); } |
3271 }; | 3026 }; |
3272 | 3027 |
3273 | 3028 |
3274 // Common base class for HArgumentsObject and HCapturedObject. | 3029 // Common base class for HArgumentsObject and HCapturedObject. |
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3931 SetFlag(kUseGVN); | 3686 SetFlag(kUseGVN); |
3932 SetOperandAt(0, arguments); | 3687 SetOperandAt(0, arguments); |
3933 SetOperandAt(1, length); | 3688 SetOperandAt(1, length); |
3934 SetOperandAt(2, index); | 3689 SetOperandAt(2, index); |
3935 } | 3690 } |
3936 | 3691 |
3937 bool DataEquals(HValue* other) override { return true; } | 3692 bool DataEquals(HValue* other) override { return true; } |
3938 }; | 3693 }; |
3939 | 3694 |
3940 | 3695 |
3941 class HBoundsCheckBaseIndexInformation; | |
3942 | |
3943 | |
3944 class HBoundsCheck final : public HTemplateInstruction<2> { | 3696 class HBoundsCheck final : public HTemplateInstruction<2> { |
3945 public: | 3697 public: |
3946 DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*); | 3698 DECLARE_INSTRUCTION_FACTORY_P2(HBoundsCheck, HValue*, HValue*); |
3947 | 3699 |
3948 bool skip_check() const { return skip_check_; } | 3700 bool skip_check() const { return skip_check_; } |
3949 void set_skip_check() { skip_check_ = true; } | 3701 void set_skip_check() { skip_check_ = true; } |
3950 | 3702 |
3951 HValue* base() const { return base_; } | 3703 HValue* base() const { return base_; } |
3952 int offset() const { return offset_; } | 3704 int offset() const { return offset_; } |
3953 int scale() const { return scale_; } | 3705 int scale() const { return scale_; } |
3954 | 3706 |
3955 void ApplyIndexChange(); | |
3956 bool DetectCompoundIndex() { | |
3957 DCHECK(base() == NULL); | |
3958 | |
3959 DecompositionResult decomposition; | |
3960 if (index()->TryDecompose(&decomposition)) { | |
3961 base_ = decomposition.base(); | |
3962 offset_ = decomposition.offset(); | |
3963 scale_ = decomposition.scale(); | |
3964 return true; | |
3965 } else { | |
3966 base_ = index(); | |
3967 offset_ = 0; | |
3968 scale_ = 0; | |
3969 return false; | |
3970 } | |
3971 } | |
3972 | |
3973 Representation RequiredInputRepresentation(int index) override { | 3707 Representation RequiredInputRepresentation(int index) override { |
3974 return representation(); | 3708 return representation(); |
3975 } | 3709 } |
3976 | 3710 |
3977 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT | 3711 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT |
3978 void InferRepresentation(HInferRepresentationPhase* h_infer) override; | 3712 void InferRepresentation(HInferRepresentationPhase* h_infer) override; |
3979 | 3713 |
3980 HValue* index() const { return OperandAt(0); } | 3714 HValue* index() const { return OperandAt(0); } |
3981 HValue* length() const { return OperandAt(1); } | 3715 HValue* length() const { return OperandAt(1); } |
3982 bool allow_equality() const { return allow_equality_; } | 3716 bool allow_equality() const { return allow_equality_; } |
3983 void set_allow_equality(bool v) { allow_equality_ = v; } | 3717 void set_allow_equality(bool v) { allow_equality_ = v; } |
3984 | 3718 |
3985 int RedefinedOperandIndex() override { return 0; } | 3719 int RedefinedOperandIndex() override { return 0; } |
3986 bool IsPurelyInformativeDefinition() override { return skip_check(); } | 3720 bool IsPurelyInformativeDefinition() override { return skip_check(); } |
3987 | 3721 |
3988 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) | 3722 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) |
3989 | 3723 |
3990 protected: | 3724 protected: |
3991 friend class HBoundsCheckBaseIndexInformation; | |
3992 | |
3993 Range* InferRange(Zone* zone) override; | 3725 Range* InferRange(Zone* zone) override; |
3994 | 3726 |
3995 bool DataEquals(HValue* other) override { return true; } | 3727 bool DataEquals(HValue* other) override { return true; } |
3996 bool skip_check_; | 3728 bool skip_check_; |
3997 HValue* base_; | 3729 HValue* base_; |
3998 int offset_; | 3730 int offset_; |
3999 int scale_; | 3731 int scale_; |
4000 bool allow_equality_; | 3732 bool allow_equality_; |
4001 | 3733 |
4002 private: | 3734 private: |
4003 // Normally HBoundsCheck should be created using the | 3735 // Normally HBoundsCheck should be created using the |
4004 // HGraphBuilder::AddBoundsCheck() helper. | 3736 // HGraphBuilder::AddBoundsCheck() helper. |
4005 // However when building stubs, where we know that the arguments are Int32, | 3737 // However when building stubs, where we know that the arguments are Int32, |
4006 // it makes sense to invoke this constructor directly. | 3738 // it makes sense to invoke this constructor directly. |
4007 HBoundsCheck(HValue* index, HValue* length) | 3739 HBoundsCheck(HValue* index, HValue* length) |
4008 : skip_check_(false), | 3740 : skip_check_(false), |
4009 base_(NULL), offset_(0), scale_(0), | 3741 base_(NULL), offset_(0), scale_(0), |
4010 allow_equality_(false) { | 3742 allow_equality_(false) { |
4011 SetOperandAt(0, index); | 3743 SetOperandAt(0, index); |
4012 SetOperandAt(1, length); | 3744 SetOperandAt(1, length); |
4013 SetFlag(kFlexibleRepresentation); | 3745 SetFlag(kFlexibleRepresentation); |
4014 SetFlag(kUseGVN); | 3746 SetFlag(kUseGVN); |
4015 } | 3747 } |
4016 | 3748 |
4017 bool IsDeletable() const override { return skip_check() && !FLAG_debug_code; } | 3749 bool IsDeletable() const override { return skip_check() && !FLAG_debug_code; } |
4018 }; | 3750 }; |
4019 | 3751 |
4020 | 3752 |
4021 class HBoundsCheckBaseIndexInformation final : public HTemplateInstruction<2> { | |
4022 public: | |
4023 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) { | |
4024 DecompositionResult decomposition; | |
4025 if (check->index()->TryDecompose(&decomposition)) { | |
4026 SetOperandAt(0, decomposition.base()); | |
4027 SetOperandAt(1, check); | |
4028 } else { | |
4029 UNREACHABLE(); | |
4030 } | |
4031 } | |
4032 | |
4033 HValue* base_index() const { return OperandAt(0); } | |
4034 HBoundsCheck* bounds_check() { return HBoundsCheck::cast(OperandAt(1)); } | |
4035 | |
4036 DECLARE_CONCRETE_INSTRUCTION(BoundsCheckBaseIndexInformation) | |
4037 | |
4038 Representation RequiredInputRepresentation(int index) override { | |
4039 return representation(); | |
4040 } | |
4041 | |
4042 std::ostream& PrintDataTo(std::ostream& os) const override; // NOLINT | |
4043 | |
4044 int RedefinedOperandIndex() override { return 0; } | |
4045 bool IsPurelyInformativeDefinition() override { return true; } | |
4046 }; | |
4047 | |
4048 | |
4049 class HBitwiseBinaryOperation : public HBinaryOperation { | 3753 class HBitwiseBinaryOperation : public HBinaryOperation { |
4050 public: | 3754 public: |
4051 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right, | 3755 HBitwiseBinaryOperation(HValue* context, HValue* left, HValue* right, |
4052 HType type = HType::TaggedNumber()) | 3756 HType type = HType::TaggedNumber()) |
4053 : HBinaryOperation(context, left, right, type) { | 3757 : HBinaryOperation(context, left, right, type) { |
4054 SetFlag(kFlexibleRepresentation); | 3758 SetFlag(kFlexibleRepresentation); |
4055 SetFlag(kTruncatingToInt32); | 3759 SetFlag(kTruncatingToInt32); |
4056 SetAllSideEffects(); | 3760 SetAllSideEffects(); |
4057 } | 3761 } |
4058 | 3762 |
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4661 | 4365 |
4662 // Add is only commutative if two integer values are added and not if two | 4366 // Add is only commutative if two integer values are added and not if two |
4663 // tagged values are added (because it might be a String concatenation). | 4367 // tagged values are added (because it might be a String concatenation). |
4664 // We also do not commute (pointer + offset). | 4368 // We also do not commute (pointer + offset). |
4665 bool IsCommutative() const override { | 4369 bool IsCommutative() const override { |
4666 return !representation().IsTagged() && !representation().IsExternal(); | 4370 return !representation().IsTagged() && !representation().IsExternal(); |
4667 } | 4371 } |
4668 | 4372 |
4669 HValue* Canonicalize() override; | 4373 HValue* Canonicalize() override; |
4670 | 4374 |
4671 bool TryDecompose(DecompositionResult* decomposition) override { | |
4672 if (left()->IsInteger32Constant()) { | |
4673 decomposition->Apply(right(), left()->GetInteger32Constant()); | |
4674 return true; | |
4675 } else if (right()->IsInteger32Constant()) { | |
4676 decomposition->Apply(left(), right()->GetInteger32Constant()); | |
4677 return true; | |
4678 } else { | |
4679 return false; | |
4680 } | |
4681 } | |
4682 | |
4683 void RepresentationChanged(Representation to) override { | 4375 void RepresentationChanged(Representation to) override { |
4684 if (to.IsTagged() && | 4376 if (to.IsTagged() && |
4685 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() || | 4377 (left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() || |
4686 left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) { | 4378 left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) { |
4687 SetAllSideEffects(); | 4379 SetAllSideEffects(); |
4688 ClearFlag(kUseGVN); | 4380 ClearFlag(kUseGVN); |
4689 } else { | 4381 } else { |
4690 ClearAllSideEffects(); | 4382 ClearAllSideEffects(); |
4691 SetFlag(kUseGVN); | 4383 SetFlag(kUseGVN); |
4692 } | 4384 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4752 }; | 4444 }; |
4753 | 4445 |
4754 | 4446 |
4755 class HSub final : public HArithmeticBinaryOperation { | 4447 class HSub final : public HArithmeticBinaryOperation { |
4756 public: | 4448 public: |
4757 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context, | 4449 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context, |
4758 HValue* left, HValue* right); | 4450 HValue* left, HValue* right); |
4759 | 4451 |
4760 HValue* Canonicalize() override; | 4452 HValue* Canonicalize() override; |
4761 | 4453 |
4762 bool TryDecompose(DecompositionResult* decomposition) override { | |
4763 if (right()->IsInteger32Constant()) { | |
4764 decomposition->Apply(left(), -right()->GetInteger32Constant()); | |
4765 return true; | |
4766 } else { | |
4767 return false; | |
4768 } | |
4769 } | |
4770 | |
4771 DECLARE_CONCRETE_INSTRUCTION(Sub) | 4454 DECLARE_CONCRETE_INSTRUCTION(Sub) |
4772 | 4455 |
4773 protected: | 4456 protected: |
4774 bool DataEquals(HValue* other) override { return true; } | 4457 bool DataEquals(HValue* other) override { return true; } |
4775 | 4458 |
4776 Range* InferRange(Zone* zone) override; | 4459 Range* InferRange(Zone* zone) override; |
4777 | 4460 |
4778 private: | 4461 private: |
4779 HSub(HValue* context, HValue* left, HValue* right) | 4462 HSub(HValue* context, HValue* left, HValue* right) |
4780 : HArithmeticBinaryOperation(context, left, right) { | 4463 : HArithmeticBinaryOperation(context, left, right) { |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5015 HShl(HValue* context, HValue* left, HValue* right) | 4698 HShl(HValue* context, HValue* left, HValue* right) |
5016 : HBitwiseBinaryOperation(context, left, right) {} | 4699 : HBitwiseBinaryOperation(context, left, right) {} |
5017 }; | 4700 }; |
5018 | 4701 |
5019 | 4702 |
5020 class HShr final : public HBitwiseBinaryOperation { | 4703 class HShr final : public HBitwiseBinaryOperation { |
5021 public: | 4704 public: |
5022 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context, | 4705 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context, |
5023 HValue* left, HValue* right); | 4706 HValue* left, HValue* right); |
5024 | 4707 |
5025 bool TryDecompose(DecompositionResult* decomposition) override { | |
5026 if (right()->IsInteger32Constant()) { | |
5027 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) { | |
5028 // This is intended to look for HAdd and HSub, to handle compounds | |
5029 // like ((base + offset) >> scale) with one single decomposition. | |
5030 left()->TryDecompose(decomposition); | |
5031 return true; | |
5032 } | |
5033 } | |
5034 return false; | |
5035 } | |
5036 | |
5037 Range* InferRange(Zone* zone) override; | 4708 Range* InferRange(Zone* zone) override; |
5038 | 4709 |
5039 void UpdateRepresentation(Representation new_rep, | 4710 void UpdateRepresentation(Representation new_rep, |
5040 HInferRepresentationPhase* h_infer, | 4711 HInferRepresentationPhase* h_infer, |
5041 const char* reason) override { | 4712 const char* reason) override { |
5042 if (new_rep.IsSmi()) new_rep = Representation::Integer32(); | 4713 if (new_rep.IsSmi()) new_rep = Representation::Integer32(); |
5043 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); | 4714 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); |
5044 } | 4715 } |
5045 | 4716 |
5046 DECLARE_CONCRETE_INSTRUCTION(Shr) | 4717 DECLARE_CONCRETE_INSTRUCTION(Shr) |
5047 | 4718 |
5048 protected: | 4719 protected: |
5049 bool DataEquals(HValue* other) override { return true; } | 4720 bool DataEquals(HValue* other) override { return true; } |
5050 | 4721 |
5051 private: | 4722 private: |
5052 HShr(HValue* context, HValue* left, HValue* right) | 4723 HShr(HValue* context, HValue* left, HValue* right) |
5053 : HBitwiseBinaryOperation(context, left, right) {} | 4724 : HBitwiseBinaryOperation(context, left, right) {} |
5054 }; | 4725 }; |
5055 | 4726 |
5056 | 4727 |
5057 class HSar final : public HBitwiseBinaryOperation { | 4728 class HSar final : public HBitwiseBinaryOperation { |
5058 public: | 4729 public: |
5059 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context, | 4730 static HInstruction* New(Isolate* isolate, Zone* zone, HValue* context, |
5060 HValue* left, HValue* right); | 4731 HValue* left, HValue* right); |
5061 | 4732 |
5062 bool TryDecompose(DecompositionResult* decomposition) override { | |
5063 if (right()->IsInteger32Constant()) { | |
5064 if (decomposition->Apply(left(), 0, right()->GetInteger32Constant())) { | |
5065 // This is intended to look for HAdd and HSub, to handle compounds | |
5066 // like ((base + offset) >> scale) with one single decomposition. | |
5067 left()->TryDecompose(decomposition); | |
5068 return true; | |
5069 } | |
5070 } | |
5071 return false; | |
5072 } | |
5073 | |
5074 Range* InferRange(Zone* zone) override; | 4733 Range* InferRange(Zone* zone) override; |
5075 | 4734 |
5076 void UpdateRepresentation(Representation new_rep, | 4735 void UpdateRepresentation(Representation new_rep, |
5077 HInferRepresentationPhase* h_infer, | 4736 HInferRepresentationPhase* h_infer, |
5078 const char* reason) override { | 4737 const char* reason) override { |
5079 if (new_rep.IsSmi()) new_rep = Representation::Integer32(); | 4738 if (new_rep.IsSmi()) new_rep = Representation::Integer32(); |
5080 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); | 4739 HBitwiseBinaryOperation::UpdateRepresentation(new_rep, h_infer, reason); |
5081 } | 4740 } |
5082 | 4741 |
5083 DECLARE_CONCRETE_INSTRUCTION(Sar) | 4742 DECLARE_CONCRETE_INSTRUCTION(Sar) |
(...skipping 2507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7591 | 7250 |
7592 | 7251 |
7593 | 7252 |
7594 #undef DECLARE_INSTRUCTION | 7253 #undef DECLARE_INSTRUCTION |
7595 #undef DECLARE_CONCRETE_INSTRUCTION | 7254 #undef DECLARE_CONCRETE_INSTRUCTION |
7596 | 7255 |
7597 } // namespace internal | 7256 } // namespace internal |
7598 } // namespace v8 | 7257 } // namespace v8 |
7599 | 7258 |
7600 #endif // V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ | 7259 #endif // V8_CRANKSHAFT_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |