Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(342)

Side by Side Diff: src/hydrogen-instructions.h

Issue 17568015: New array bounds check elimination pass (focused on induction variables and bitwise operations). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Switched flag to false by default. Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen-bch.cc ('k') | src/hydrogen-instructions.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 3000 matching lines...) Expand 10 before | Expand all | Expand 10 after
3011 3011
3012 private: 3012 private:
3013 ZoneList<Handle<JSObject> > prototypes_; 3013 ZoneList<Handle<JSObject> > prototypes_;
3014 ZoneList<Handle<Map> > maps_; 3014 ZoneList<Handle<Map> > maps_;
3015 UniqueValueId first_prototype_unique_id_; 3015 UniqueValueId first_prototype_unique_id_;
3016 UniqueValueId last_prototype_unique_id_; 3016 UniqueValueId last_prototype_unique_id_;
3017 bool can_omit_prototype_maps_; 3017 bool can_omit_prototype_maps_;
3018 }; 3018 };
3019 3019
3020 3020
3021 class InductionVariableData;
3022
3023
3024 struct InductionVariableLimitUpdate {
3025 InductionVariableData* updated_variable;
3026 HValue* limit;
3027 bool limit_is_upper;
3028 bool limit_is_included;
3029
3030 InductionVariableLimitUpdate()
3031 : updated_variable(NULL), limit(NULL),
3032 limit_is_upper(false), limit_is_included(false) {}
3033 };
3034
3035
3036 class HBoundsCheck;
3037 class HPhi;
3038 class HConstant;
3039 class HBitwise;
3040
3041
3042 class InductionVariableData : public ZoneObject {
3043 public:
3044 class InductionVariableCheck : public ZoneObject {
3045 public:
3046 HBoundsCheck* check() { return check_; }
3047 InductionVariableCheck* next() { return next_; }
3048 bool HasUpperLimit() { return upper_limit_ >= 0; }
3049 int32_t upper_limit() {
3050 ASSERT(HasUpperLimit());
3051 return upper_limit_;
3052 }
3053 void set_upper_limit(int32_t upper_limit) {
3054 upper_limit_ = upper_limit;
3055 }
3056
3057 bool processed() { return processed_; }
3058 void set_processed() { processed_ = true; }
3059
3060 InductionVariableCheck(HBoundsCheck* check,
3061 InductionVariableCheck* next,
3062 int32_t upper_limit = kNoLimit)
3063 : check_(check), next_(next), upper_limit_(upper_limit),
3064 processed_(false) {}
3065
3066 private:
3067 HBoundsCheck* check_;
3068 InductionVariableCheck* next_;
3069 int32_t upper_limit_;
3070 bool processed_;
3071 };
3072
3073 class ChecksRelatedToLength : public ZoneObject {
3074 public:
3075 HValue* length() { return length_; }
3076 ChecksRelatedToLength* next() { return next_; }
3077 InductionVariableCheck* checks() { return checks_; }
3078
3079 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3080 void CloseCurrentBlock();
3081
3082 ChecksRelatedToLength(HValue* length, ChecksRelatedToLength* next)
3083 : length_(length), next_(next), checks_(NULL),
3084 first_check_in_block_(NULL),
3085 added_index_(NULL),
3086 added_constant_(NULL),
3087 current_and_mask_in_block_(0),
3088 current_or_mask_in_block_(0) {}
3089
3090 private:
3091 void UseNewIndexInCurrentBlock(Token::Value token,
3092 int32_t mask,
3093 HValue* index_base,
3094 HValue* context);
3095
3096 HBoundsCheck* first_check_in_block() { return first_check_in_block_; }
3097 HBitwise* added_index() { return added_index_; }
3098 void set_added_index(HBitwise* index) { added_index_ = index; }
3099 HConstant* added_constant() { return added_constant_; }
3100 void set_added_constant(HConstant* constant) { added_constant_ = constant; }
3101 int32_t current_and_mask_in_block() { return current_and_mask_in_block_; }
3102 int32_t current_or_mask_in_block() { return current_or_mask_in_block_; }
3103 int32_t current_upper_limit() { return current_upper_limit_; }
3104
3105 HValue* length_;
3106 ChecksRelatedToLength* next_;
3107 InductionVariableCheck* checks_;
3108
3109 HBoundsCheck* first_check_in_block_;
3110 HBitwise* added_index_;
3111 HConstant* added_constant_;
3112 int32_t current_and_mask_in_block_;
3113 int32_t current_or_mask_in_block_;
3114 int32_t current_upper_limit_;
3115 };
3116
3117 struct LimitFromPredecessorBlock {
3118 InductionVariableData* variable;
3119 Token::Value token;
3120 HValue* limit;
3121 HBasicBlock* other_target;
3122
3123 bool LimitIsValid() { return token != Token::ILLEGAL; }
3124
3125 bool LimitIsIncluded() {
3126 return Token::IsEqualityOp(token) ||
3127 token == Token::GTE || token == Token::LTE;
3128 }
3129 bool LimitIsUpper() {
3130 return token == Token::LTE || token == Token::LT || token == Token::NE;
3131 }
3132
3133 LimitFromPredecessorBlock()
3134 : variable(NULL),
3135 token(Token::ILLEGAL),
3136 limit(NULL),
3137 other_target(NULL) {}
3138 };
3139
3140 static const int32_t kNoLimit = -1;
3141
3142 static InductionVariableData* ExaminePhi(HPhi* phi);
3143 static void ComputeLimitFromPredecessorBlock(
3144 HBasicBlock* block,
3145 LimitFromPredecessorBlock* result);
3146 static bool ComputeInductionVariableLimit(
3147 HBasicBlock* block,
3148 InductionVariableLimitUpdate* additional_limit);
3149
3150 struct BitwiseDecompositionResult {
3151 HValue* base;
3152 int32_t and_mask;
3153 int32_t or_mask;
3154 HValue* context;
3155
3156 BitwiseDecompositionResult()
3157 : base(NULL), and_mask(0), or_mask(0), context(NULL) {}
3158 };
3159 static void DecomposeBitwise(HValue* value,
3160 BitwiseDecompositionResult* result);
3161
3162 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3163
3164 bool CheckIfBranchIsLoopGuard(Token::Value token,
3165 HBasicBlock* current_branch,
3166 HBasicBlock* other_branch);
3167
3168 void UpdateAdditionalLimit(InductionVariableLimitUpdate* update);
3169
3170 HPhi* phi() { return phi_; }
3171 HValue* base() { return base_; }
3172 int32_t increment() { return increment_; }
3173 HValue* limit() { return limit_; }
3174 bool limit_included() { return limit_included_; }
3175 HBasicBlock* limit_validity() { return limit_validity_; }
3176 HBasicBlock* induction_exit_block() { return induction_exit_block_; }
3177 HBasicBlock* induction_exit_target() { return induction_exit_target_; }
3178 ChecksRelatedToLength* checks() { return checks_; }
3179 HValue* additional_upper_limit() { return additional_upper_limit_; }
3180 bool additional_upper_limit_is_included() {
3181 return additional_upper_limit_is_included_;
3182 }
3183 HValue* additional_lower_limit() { return additional_lower_limit_; }
3184 bool additional_lower_limit_is_included() {
3185 return additional_lower_limit_is_included_;
3186 }
3187
3188 bool LowerLimitIsNonNegativeConstant() {
3189 if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) {
3190 return true;
3191 }
3192 if (additional_lower_limit() != NULL &&
3193 additional_lower_limit()->IsInteger32Constant() &&
3194 additional_lower_limit()->GetInteger32Constant() >= 0) {
3195 // Ignoring the corner case of !additional_lower_limit_is_included()
3196 // is safe, handling it adds unneeded complexity.
3197 return true;
3198 }
3199 return false;
3200 }
3201
3202 int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask);
3203
3204 private:
3205 template <class T> void swap(T* a, T* b) {
3206 T c(*a);
3207 *a = *b;
3208 *b = c;
3209 }
3210
3211 InductionVariableData(HPhi* phi, HValue* base, int32_t increment)
3212 : phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment),
3213 limit_(NULL), limit_included_(false), limit_validity_(NULL),
3214 induction_exit_block_(NULL), induction_exit_target_(NULL),
3215 checks_(NULL),
3216 additional_upper_limit_(NULL),
3217 additional_upper_limit_is_included_(false),
3218 additional_lower_limit_(NULL),
3219 additional_lower_limit_is_included_(false) {}
3220
3221 static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand);
3222
3223 static HValue* IgnoreOsrValue(HValue* v);
3224 static InductionVariableData* GetInductionVariableData(HValue* v);
3225
3226 HPhi* phi_;
3227 HValue* base_;
3228 int32_t increment_;
3229 HValue* limit_;
3230 bool limit_included_;
3231 HBasicBlock* limit_validity_;
3232 HBasicBlock* induction_exit_block_;
3233 HBasicBlock* induction_exit_target_;
3234 ChecksRelatedToLength* checks_;
3235 HValue* additional_upper_limit_;
3236 bool additional_upper_limit_is_included_;
3237 HValue* additional_lower_limit_;
3238 bool additional_lower_limit_is_included_;
3239 };
3240
3241
3021 class HPhi: public HValue { 3242 class HPhi: public HValue {
3022 public: 3243 public:
3023 HPhi(int merged_index, Zone* zone) 3244 HPhi(int merged_index, Zone* zone)
3024 : inputs_(2, zone), 3245 : inputs_(2, zone),
3025 merged_index_(merged_index), 3246 merged_index_(merged_index),
3026 phi_id_(-1) { 3247 phi_id_(-1),
3248 induction_variable_data_(NULL) {
3027 for (int i = 0; i < Representation::kNumRepresentations; i++) { 3249 for (int i = 0; i < Representation::kNumRepresentations; i++) {
3028 non_phi_uses_[i] = 0; 3250 non_phi_uses_[i] = 0;
3029 indirect_uses_[i] = 0; 3251 indirect_uses_[i] = 0;
3030 } 3252 }
3031 ASSERT(merged_index >= 0); 3253 ASSERT(merged_index >= 0);
3032 SetFlag(kFlexibleRepresentation); 3254 SetFlag(kFlexibleRepresentation);
3033 SetFlag(kAllowUndefinedAsNaN); 3255 SetFlag(kAllowUndefinedAsNaN);
3034 } 3256 }
3035 3257
3036 virtual Representation RepresentationFromInputs(); 3258 virtual Representation RepresentationFromInputs();
(...skipping 10 matching lines...) Expand all
3047 virtual int OperandCount() { return inputs_.length(); } 3269 virtual int OperandCount() { return inputs_.length(); }
3048 virtual HValue* OperandAt(int index) const { return inputs_[index]; } 3270 virtual HValue* OperandAt(int index) const { return inputs_[index]; }
3049 HValue* GetRedundantReplacement(); 3271 HValue* GetRedundantReplacement();
3050 void AddInput(HValue* value); 3272 void AddInput(HValue* value);
3051 bool HasRealUses(); 3273 bool HasRealUses();
3052 3274
3053 bool IsReceiver() const { return merged_index_ == 0; } 3275 bool IsReceiver() const { return merged_index_ == 0; }
3054 3276
3055 int merged_index() const { return merged_index_; } 3277 int merged_index() const { return merged_index_; }
3056 3278
3279 InductionVariableData* induction_variable_data() {
3280 return induction_variable_data_;
3281 }
3282 bool IsInductionVariable() {
3283 return induction_variable_data_ != NULL;
3284 }
3285 bool IsLimitedInductionVariable() {
3286 return IsInductionVariable() &&
3287 induction_variable_data_->limit() != NULL;
3288 }
3289 void DetectInductionVariable() {
3290 ASSERT(induction_variable_data_ == NULL);
3291 induction_variable_data_ = InductionVariableData::ExaminePhi(this);
3292 }
3293
3057 virtual void AddInformativeDefinitions(); 3294 virtual void AddInformativeDefinitions();
3058 3295
3059 virtual void PrintTo(StringStream* stream); 3296 virtual void PrintTo(StringStream* stream);
3060 3297
3061 #ifdef DEBUG 3298 #ifdef DEBUG
3062 virtual void Verify(); 3299 virtual void Verify();
3063 #endif 3300 #endif
3064 3301
3065 void InitRealUses(int id); 3302 void InitRealUses(int id);
3066 void AddNonPhiUsesFrom(HPhi* other); 3303 void AddNonPhiUsesFrom(HPhi* other);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3114 int offset = 0, 3351 int offset = 0,
3115 int scale = 0); 3352 int scale = 0);
3116 3353
3117 private: 3354 private:
3118 ZoneList<HValue*> inputs_; 3355 ZoneList<HValue*> inputs_;
3119 int merged_index_; 3356 int merged_index_;
3120 3357
3121 int non_phi_uses_[Representation::kNumRepresentations]; 3358 int non_phi_uses_[Representation::kNumRepresentations];
3122 int indirect_uses_[Representation::kNumRepresentations]; 3359 int indirect_uses_[Representation::kNumRepresentations];
3123 int phi_id_; 3360 int phi_id_;
3361 InductionVariableData* induction_variable_data_;
3124 }; 3362 };
3125 3363
3126 3364
3127 class HInductionVariableAnnotation : public HUnaryOperation { 3365 class HInductionVariableAnnotation : public HUnaryOperation {
3128 public: 3366 public:
3129 static HInductionVariableAnnotation* AddToGraph(HPhi* phi, 3367 static HInductionVariableAnnotation* AddToGraph(HPhi* phi,
3130 NumericRelation relation, 3368 NumericRelation relation,
3131 int operand_index); 3369 int operand_index);
3132 3370
3133 NumericRelation relation() { return relation_; } 3371 NumericRelation relation() { return relation_; }
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after
3638 3876
3639 class HBoundsCheck: public HTemplateInstruction<2> { 3877 class HBoundsCheck: public HTemplateInstruction<2> {
3640 public: 3878 public:
3641 // Normally HBoundsCheck should be created using the 3879 // Normally HBoundsCheck should be created using the
3642 // HGraphBuilder::AddBoundsCheck() helper. 3880 // HGraphBuilder::AddBoundsCheck() helper.
3643 // However when building stubs, where we know that the arguments are Int32, 3881 // However when building stubs, where we know that the arguments are Int32,
3644 // it makes sense to invoke this constructor directly. 3882 // it makes sense to invoke this constructor directly.
3645 HBoundsCheck(HValue* index, HValue* length) 3883 HBoundsCheck(HValue* index, HValue* length)
3646 : skip_check_(false), 3884 : skip_check_(false),
3647 base_(NULL), offset_(0), scale_(0), 3885 base_(NULL), offset_(0), scale_(0),
3648 responsibility_direction_(DIRECTION_NONE) { 3886 responsibility_direction_(DIRECTION_NONE),
3887 allow_equality_(false) {
3649 SetOperandAt(0, index); 3888 SetOperandAt(0, index);
3650 SetOperandAt(1, length); 3889 SetOperandAt(1, length);
3651 SetFlag(kFlexibleRepresentation); 3890 SetFlag(kFlexibleRepresentation);
3652 SetFlag(kUseGVN); 3891 SetFlag(kUseGVN);
3653 } 3892 }
3654 3893
3655 bool skip_check() { return skip_check_; } 3894 bool skip_check() const { return skip_check_; }
3656 void set_skip_check(bool skip_check) { skip_check_ = skip_check; } 3895 void set_skip_check() { skip_check_ = true; }
3657 HValue* base() { return base_; } 3896 HValue* base() { return base_; }
3658 int offset() { return offset_; } 3897 int offset() { return offset_; }
3659 int scale() { return scale_; } 3898 int scale() { return scale_; }
3660 bool index_can_increase() { 3899 bool index_can_increase() {
3661 return (responsibility_direction_ & DIRECTION_LOWER) == 0; 3900 return (responsibility_direction_ & DIRECTION_LOWER) == 0;
3662 } 3901 }
3663 bool index_can_decrease() { 3902 bool index_can_decrease() {
3664 return (responsibility_direction_ & DIRECTION_UPPER) == 0; 3903 return (responsibility_direction_ & DIRECTION_UPPER) == 0;
3665 } 3904 }
3666 3905
(...skipping 11 matching lines...) Expand all
3678 base_ = index(); 3917 base_ = index();
3679 offset_ = 0; 3918 offset_ = 0;
3680 scale_ = 0; 3919 scale_ = 0;
3681 return false; 3920 return false;
3682 } 3921 }
3683 } 3922 }
3684 3923
3685 virtual Representation RequiredInputRepresentation(int arg_index) { 3924 virtual Representation RequiredInputRepresentation(int arg_index) {
3686 return representation(); 3925 return representation();
3687 } 3926 }
3927 virtual bool IsDeletable() const {
3928 return skip_check() && !FLAG_debug_code;
3929 }
3688 3930
3689 virtual bool IsRelationTrueInternal(NumericRelation relation, 3931 virtual bool IsRelationTrueInternal(NumericRelation relation,
3690 HValue* related_value, 3932 HValue* related_value,
3691 int offset = 0, 3933 int offset = 0,
3692 int scale = 0); 3934 int scale = 0);
3693 3935
3694 virtual void PrintDataTo(StringStream* stream); 3936 virtual void PrintDataTo(StringStream* stream);
3695 virtual void InferRepresentation(HInferRepresentationPhase* h_infer); 3937 virtual void InferRepresentation(HInferRepresentationPhase* h_infer);
3696 3938
3697 HValue* index() { return OperandAt(0); } 3939 HValue* index() { return OperandAt(0); }
3698 HValue* length() { return OperandAt(1); } 3940 HValue* length() { return OperandAt(1); }
3941 bool allow_equality() { return allow_equality_; }
3942 void set_allow_equality(bool v) { allow_equality_ = v; }
3699 3943
3700 virtual int RedefinedOperandIndex() { return 0; } 3944 virtual int RedefinedOperandIndex() { return 0; }
3701 virtual bool IsPurelyInformativeDefinition() { return skip_check(); } 3945 virtual bool IsPurelyInformativeDefinition() { return skip_check(); }
3702 virtual void AddInformativeDefinitions(); 3946 virtual void AddInformativeDefinitions();
3703 3947
3704 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) 3948 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
3705 3949
3706 protected: 3950 protected:
3707 friend class HBoundsCheckBaseIndexInformation; 3951 friend class HBoundsCheckBaseIndexInformation;
3708 3952
3709 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) { 3953 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {
3710 responsibility_direction_ = static_cast<RangeGuaranteeDirection>( 3954 responsibility_direction_ = static_cast<RangeGuaranteeDirection>(
3711 responsibility_direction_ | direction); 3955 responsibility_direction_ | direction);
3712 } 3956 }
3713 3957
3714 virtual bool DataEquals(HValue* other) { return true; } 3958 virtual bool DataEquals(HValue* other) { return true; }
3715 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context); 3959 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context);
3716 bool skip_check_; 3960 bool skip_check_;
3717 HValue* base_; 3961 HValue* base_;
3718 int offset_; 3962 int offset_;
3719 int scale_; 3963 int scale_;
3720 RangeGuaranteeDirection responsibility_direction_; 3964 RangeGuaranteeDirection responsibility_direction_;
3965 bool allow_equality_;
3721 }; 3966 };
3722 3967
3723 3968
3724 class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> { 3969 class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> {
3725 public: 3970 public:
3726 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) { 3971 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) {
3727 DecompositionResult decomposition; 3972 DecompositionResult decomposition;
3728 if (check->index()->TryDecompose(&decomposition)) { 3973 if (check->index()->TryDecompose(&decomposition)) {
3729 SetOperandAt(0, decomposition.base()); 3974 SetOperandAt(0, decomposition.base());
3730 SetOperandAt(1, check); 3975 SetOperandAt(1, check);
(...skipping 2913 matching lines...) Expand 10 before | Expand all | Expand 10 after
6644 virtual bool IsDeletable() const { return true; } 6889 virtual bool IsDeletable() const { return true; }
6645 }; 6890 };
6646 6891
6647 6892
6648 #undef DECLARE_INSTRUCTION 6893 #undef DECLARE_INSTRUCTION
6649 #undef DECLARE_CONCRETE_INSTRUCTION 6894 #undef DECLARE_CONCRETE_INSTRUCTION
6650 6895
6651 } } // namespace v8::internal 6896 } } // namespace v8::internal
6652 6897
6653 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ 6898 #endif // V8_HYDROGEN_INSTRUCTIONS_H_
OLDNEW
« no previous file with comments | « src/hydrogen-bch.cc ('k') | src/hydrogen-instructions.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698