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

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: Reimplemented CheckHoistability with no recursive calls. 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
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 3032 matching lines...) Expand 10 before | Expand all | Expand 10 after
3043 3043
3044 private: 3044 private:
3045 ZoneList<Handle<JSObject> > prototypes_; 3045 ZoneList<Handle<JSObject> > prototypes_;
3046 ZoneList<Handle<Map> > maps_; 3046 ZoneList<Handle<Map> > maps_;
3047 UniqueValueId first_prototype_unique_id_; 3047 UniqueValueId first_prototype_unique_id_;
3048 UniqueValueId last_prototype_unique_id_; 3048 UniqueValueId last_prototype_unique_id_;
3049 bool can_omit_prototype_maps_; 3049 bool can_omit_prototype_maps_;
3050 }; 3050 };
3051 3051
3052 3052
3053 class InductionVariableData;
3054
3055
3056 struct InductionVariableLimitUpdate {
3057 InductionVariableData* updated_variable;
3058 HValue* limit;
3059 bool limit_is_upper;
3060 bool limit_is_included;
3061
3062 InductionVariableLimitUpdate()
3063 : updated_variable(NULL), limit(NULL),
3064 limit_is_upper(false), limit_is_included(false) {}
3065 };
3066
3067
3068 class HBoundsCheck;
3069 class HPhi;
3070 class HConstant;
3071 class HBitwise;
3072
3073
3074 class InductionVariableData : public ZoneObject {
3075 public:
3076 class InductionVariableCheck : public ZoneObject {
3077 public:
3078 HBoundsCheck* check() { return check_; }
3079 InductionVariableCheck* next() { return next_; }
3080 bool HasUpperLimit() { return upper_limit_ >= 0; }
3081 int32_t upper_limit() {
3082 ASSERT(HasUpperLimit());
3083 return upper_limit_;
3084 }
3085 void set_upper_limit(int32_t upper_limit) {
3086 upper_limit_ = upper_limit;
3087 }
3088
3089 bool processed() { return processed_; }
3090 void set_processed() { processed_ = true; }
3091
3092 InductionVariableCheck(HBoundsCheck* check,
3093 InductionVariableCheck* next,
3094 int32_t upper_limit = kNoLimit)
3095 : check_(check), next_(next), upper_limit_(upper_limit),
3096 processed_(false) {}
3097
3098 private:
3099 HBoundsCheck* check_;
3100 InductionVariableCheck* next_;
3101 int32_t upper_limit_;
3102 bool processed_;
3103 };
3104
3105 class ChecksRelatedToLength : public ZoneObject {
3106 public:
3107 HValue* length() { return length_; }
3108 ChecksRelatedToLength* next() { return next_; }
3109 InductionVariableCheck* checks() { return checks_; }
3110
3111 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3112 void CloseCurrentBlock();
3113
3114 ChecksRelatedToLength(HValue* length, ChecksRelatedToLength* next)
3115 : length_(length), next_(next), checks_(NULL),
3116 first_check_in_block_(NULL),
3117 added_index_(NULL),
3118 added_constant_(NULL),
3119 current_and_mask_in_block_(0),
3120 current_or_mask_in_block_(0) {}
3121
3122 private:
3123 void UseNewIndexInCurrentBlock(Token::Value token,
3124 int32_t mask,
3125 HValue* index_base,
3126 HValue* context);
3127
3128 HBoundsCheck* first_check_in_block() { return first_check_in_block_; }
3129 HBitwise* added_index() { return added_index_; }
3130 void set_added_index(HBitwise* index) { added_index_ = index; }
3131 HConstant* added_constant() { return added_constant_; }
3132 void set_added_constant(HConstant* constant) { added_constant_ = constant; }
3133 int32_t current_and_mask_in_block() { return current_and_mask_in_block_; }
3134 int32_t current_or_mask_in_block() { return current_or_mask_in_block_; }
3135 int32_t current_upper_limit() { return current_upper_limit_; }
3136
3137 HValue* length_;
3138 ChecksRelatedToLength* next_;
3139 InductionVariableCheck* checks_;
3140
3141 HBoundsCheck* first_check_in_block_;
3142 HBitwise* added_index_;
3143 HConstant* added_constant_;
3144 int32_t current_and_mask_in_block_;
3145 int32_t current_or_mask_in_block_;
3146 int32_t current_upper_limit_;
3147 };
3148
3149 struct LimitFromPredecessorBlock {
3150 InductionVariableData* variable;
3151 Token::Value token;
3152 HValue* limit;
3153 HBasicBlock* other_target;
3154
3155 bool LimitIsValid() { return token != Token::ILLEGAL; }
3156
3157 bool LimitIsIncluded() {
3158 return Token::IsEqualityOp(token) ||
3159 token == Token::GTE || token == Token::LTE;
3160 }
3161 bool LimitIsUpper() {
3162 return token == Token::LTE || token == Token::LT || token == Token::NE;
3163 }
3164
3165 LimitFromPredecessorBlock()
3166 : variable(NULL),
3167 token(Token::ILLEGAL),
3168 limit(NULL),
3169 other_target(NULL) {}
3170 };
3171
3172 static const int32_t kNoLimit = -1;
3173
3174 static InductionVariableData* ExaminePhi(HPhi* phi);
3175 static void ComputeLimitFromPredecessorBlock(
3176 HBasicBlock* block,
3177 LimitFromPredecessorBlock* result);
3178 static bool ComputeInductionVariableLimit(
3179 HBasicBlock* block,
3180 InductionVariableLimitUpdate* additional_limit);
3181
3182 struct BitwiseDecompositionResult {
3183 HValue* base;
3184 int32_t and_mask;
3185 int32_t or_mask;
3186 HValue* context;
3187
3188 BitwiseDecompositionResult()
3189 : base(NULL), and_mask(0), or_mask(0), context(NULL) {}
3190 };
3191 static void DecomposeBitwise(HValue* value,
3192 BitwiseDecompositionResult* result);
3193
3194 void AddCheck(HBoundsCheck* check, int32_t upper_limit = kNoLimit);
3195
3196 bool CheckIfBranchIsLoopGuard(Token::Value token,
3197 HBasicBlock* current_branch,
3198 HBasicBlock* other_branch);
3199
3200 void UpdateAdditionalLimit(InductionVariableLimitUpdate* update);
3201
3202 HPhi* phi() { return phi_; }
3203 HValue* base() { return base_; }
3204 int32_t increment() { return increment_; }
3205 HValue* limit() { return limit_; }
3206 bool limit_included() { return limit_included_; }
3207 HBasicBlock* limit_validity() { return limit_validity_; }
3208 HBasicBlock* induction_exit_block() { return induction_exit_block_; }
3209 HBasicBlock* induction_exit_target() { return induction_exit_target_; }
3210 ChecksRelatedToLength* checks() { return checks_; }
3211 HValue* additional_upper_limit() { return additional_upper_limit_; }
3212 bool additional_upper_limit_is_included() {
3213 return additional_upper_limit_is_included_;
3214 }
3215 HValue* additional_lower_limit() { return additional_lower_limit_; }
3216 bool additional_lower_limit_is_included() {
3217 return additional_lower_limit_is_included_;
3218 }
3219
3220 bool LowerLimitIsNonNegativeConstant() {
3221 if (base()->IsInteger32Constant() && base()->GetInteger32Constant() >= 0) {
3222 return true;
3223 }
3224 if (additional_lower_limit() != NULL &&
3225 additional_lower_limit()->IsInteger32Constant() &&
3226 additional_lower_limit()->GetInteger32Constant() >= 0) {
3227 // Ignoring the corner case of !additional_lower_limit_is_included()
3228 // is safe, handling it adds unneeded complexity.
3229 return true;
3230 }
3231 return false;
3232 }
3233
3234 int32_t ComputeUpperLimit(int32_t and_mask, int32_t or_mask);
3235
3236 private:
3237 template <class T> void swap(T* a, T* b) {
3238 T c(*a);
3239 *a = *b;
3240 *b = c;
3241 }
3242
3243 InductionVariableData(HPhi* phi, HValue* base, int32_t increment)
3244 : phi_(phi), base_(IgnoreOsrValue(base)), increment_(increment),
3245 limit_(NULL), limit_included_(false), limit_validity_(NULL),
3246 induction_exit_block_(NULL), induction_exit_target_(NULL),
3247 checks_(NULL),
3248 additional_upper_limit_(NULL),
3249 additional_upper_limit_is_included_(false),
3250 additional_lower_limit_(NULL),
3251 additional_lower_limit_is_included_(false) {}
3252
3253 static int32_t ComputeIncrement(HPhi* phi, HValue* phi_operand);
3254
3255 static HValue* IgnoreOsrValue(HValue* v);
3256 static InductionVariableData* GetInductionVariableData(HValue* v);
3257
3258 HPhi* phi_;
3259 HValue* base_;
3260 int32_t increment_;
3261 HValue* limit_;
3262 bool limit_included_;
3263 HBasicBlock* limit_validity_;
3264 HBasicBlock* induction_exit_block_;
3265 HBasicBlock* induction_exit_target_;
3266 ChecksRelatedToLength* checks_;
3267 HValue* additional_upper_limit_;
3268 bool additional_upper_limit_is_included_;
3269 HValue* additional_lower_limit_;
3270 bool additional_lower_limit_is_included_;
3271 };
3272
3273
3053 class HPhi: public HValue { 3274 class HPhi: public HValue {
3054 public: 3275 public:
3055 HPhi(int merged_index, Zone* zone) 3276 HPhi(int merged_index, Zone* zone)
3056 : inputs_(2, zone), 3277 : inputs_(2, zone),
3057 merged_index_(merged_index), 3278 merged_index_(merged_index),
3058 phi_id_(-1) { 3279 phi_id_(-1),
3280 induction_variable_data_(NULL) {
3059 for (int i = 0; i < Representation::kNumRepresentations; i++) { 3281 for (int i = 0; i < Representation::kNumRepresentations; i++) {
3060 non_phi_uses_[i] = 0; 3282 non_phi_uses_[i] = 0;
3061 indirect_uses_[i] = 0; 3283 indirect_uses_[i] = 0;
3062 } 3284 }
3063 ASSERT(merged_index >= 0); 3285 ASSERT(merged_index >= 0);
3064 SetFlag(kFlexibleRepresentation); 3286 SetFlag(kFlexibleRepresentation);
3065 SetFlag(kAllowUndefinedAsNaN); 3287 SetFlag(kAllowUndefinedAsNaN);
3066 } 3288 }
3067 3289
3068 virtual Representation RepresentationFromInputs(); 3290 virtual Representation RepresentationFromInputs();
(...skipping 10 matching lines...) Expand all
3079 virtual int OperandCount() { return inputs_.length(); } 3301 virtual int OperandCount() { return inputs_.length(); }
3080 virtual HValue* OperandAt(int index) const { return inputs_[index]; } 3302 virtual HValue* OperandAt(int index) const { return inputs_[index]; }
3081 HValue* GetRedundantReplacement(); 3303 HValue* GetRedundantReplacement();
3082 void AddInput(HValue* value); 3304 void AddInput(HValue* value);
3083 bool HasRealUses(); 3305 bool HasRealUses();
3084 3306
3085 bool IsReceiver() const { return merged_index_ == 0; } 3307 bool IsReceiver() const { return merged_index_ == 0; }
3086 3308
3087 int merged_index() const { return merged_index_; } 3309 int merged_index() const { return merged_index_; }
3088 3310
3311 InductionVariableData* induction_variable_data() {
3312 return induction_variable_data_;
3313 }
3314 bool IsInductionVariable() {
3315 return induction_variable_data_ != NULL;
3316 }
3317 bool IsLimitedInductionVariable() {
3318 return IsInductionVariable() &&
3319 induction_variable_data_->limit() != NULL;
3320 }
3321 void DetectInductionVariable() {
3322 ASSERT(induction_variable_data_ == NULL);
3323 induction_variable_data_ = InductionVariableData::ExaminePhi(this);
3324 }
3325
3089 virtual void AddInformativeDefinitions(); 3326 virtual void AddInformativeDefinitions();
3090 3327
3091 virtual void PrintTo(StringStream* stream); 3328 virtual void PrintTo(StringStream* stream);
3092 3329
3093 #ifdef DEBUG 3330 #ifdef DEBUG
3094 virtual void Verify(); 3331 virtual void Verify();
3095 #endif 3332 #endif
3096 3333
3097 void InitRealUses(int id); 3334 void InitRealUses(int id);
3098 void AddNonPhiUsesFrom(HPhi* other); 3335 void AddNonPhiUsesFrom(HPhi* other);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3146 int offset = 0, 3383 int offset = 0,
3147 int scale = 0); 3384 int scale = 0);
3148 3385
3149 private: 3386 private:
3150 ZoneList<HValue*> inputs_; 3387 ZoneList<HValue*> inputs_;
3151 int merged_index_; 3388 int merged_index_;
3152 3389
3153 int non_phi_uses_[Representation::kNumRepresentations]; 3390 int non_phi_uses_[Representation::kNumRepresentations];
3154 int indirect_uses_[Representation::kNumRepresentations]; 3391 int indirect_uses_[Representation::kNumRepresentations];
3155 int phi_id_; 3392 int phi_id_;
3393 InductionVariableData* induction_variable_data_;
3156 }; 3394 };
3157 3395
3158 3396
3159 class HInductionVariableAnnotation : public HUnaryOperation { 3397 class HInductionVariableAnnotation : public HUnaryOperation {
3160 public: 3398 public:
3161 static HInductionVariableAnnotation* AddToGraph(HPhi* phi, 3399 static HInductionVariableAnnotation* AddToGraph(HPhi* phi,
3162 NumericRelation relation, 3400 NumericRelation relation,
3163 int operand_index); 3401 int operand_index);
3164 3402
3165 NumericRelation relation() { return relation_; } 3403 NumericRelation relation() { return relation_; }
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after
3653 3891
3654 class HBoundsCheck: public HTemplateInstruction<2> { 3892 class HBoundsCheck: public HTemplateInstruction<2> {
3655 public: 3893 public:
3656 // Normally HBoundsCheck should be created using the 3894 // Normally HBoundsCheck should be created using the
3657 // HGraphBuilder::AddBoundsCheck() helper. 3895 // HGraphBuilder::AddBoundsCheck() helper.
3658 // However when building stubs, where we know that the arguments are Int32, 3896 // However when building stubs, where we know that the arguments are Int32,
3659 // it makes sense to invoke this constructor directly. 3897 // it makes sense to invoke this constructor directly.
3660 HBoundsCheck(HValue* index, HValue* length) 3898 HBoundsCheck(HValue* index, HValue* length)
3661 : skip_check_(false), 3899 : skip_check_(false),
3662 base_(NULL), offset_(0), scale_(0), 3900 base_(NULL), offset_(0), scale_(0),
3663 responsibility_direction_(DIRECTION_NONE) { 3901 responsibility_direction_(DIRECTION_NONE),
3902 allow_equality_(false) {
3664 SetOperandAt(0, index); 3903 SetOperandAt(0, index);
3665 SetOperandAt(1, length); 3904 SetOperandAt(1, length);
3666 SetFlag(kFlexibleRepresentation); 3905 SetFlag(kFlexibleRepresentation);
3667 SetFlag(kUseGVN); 3906 SetFlag(kUseGVN);
3668 } 3907 }
3669 3908
3670 bool skip_check() { return skip_check_; } 3909 bool skip_check() const { return skip_check_; }
3671 void set_skip_check(bool skip_check) { skip_check_ = skip_check; } 3910 void set_skip_check() { skip_check_ = true; }
3672 HValue* base() { return base_; } 3911 HValue* base() { return base_; }
3673 int offset() { return offset_; } 3912 int offset() { return offset_; }
3674 int scale() { return scale_; } 3913 int scale() { return scale_; }
3675 bool index_can_increase() { 3914 bool index_can_increase() {
3676 return (responsibility_direction_ & DIRECTION_LOWER) == 0; 3915 return (responsibility_direction_ & DIRECTION_LOWER) == 0;
3677 } 3916 }
3678 bool index_can_decrease() { 3917 bool index_can_decrease() {
3679 return (responsibility_direction_ & DIRECTION_UPPER) == 0; 3918 return (responsibility_direction_ & DIRECTION_UPPER) == 0;
3680 } 3919 }
3681 3920
(...skipping 11 matching lines...) Expand all
3693 base_ = index(); 3932 base_ = index();
3694 offset_ = 0; 3933 offset_ = 0;
3695 scale_ = 0; 3934 scale_ = 0;
3696 return false; 3935 return false;
3697 } 3936 }
3698 } 3937 }
3699 3938
3700 virtual Representation RequiredInputRepresentation(int arg_index) { 3939 virtual Representation RequiredInputRepresentation(int arg_index) {
3701 return representation(); 3940 return representation();
3702 } 3941 }
3942 virtual bool IsDeletable() const {
3943 return skip_check() && !FLAG_debug_code;
3944 }
3703 3945
3704 virtual bool IsRelationTrueInternal(NumericRelation relation, 3946 virtual bool IsRelationTrueInternal(NumericRelation relation,
3705 HValue* related_value, 3947 HValue* related_value,
3706 int offset = 0, 3948 int offset = 0,
3707 int scale = 0); 3949 int scale = 0);
3708 3950
3709 virtual void PrintDataTo(StringStream* stream); 3951 virtual void PrintDataTo(StringStream* stream);
3710 virtual void InferRepresentation(HInferRepresentation* h_infer); 3952 virtual void InferRepresentation(HInferRepresentation* h_infer);
3711 3953
3712 HValue* index() { return OperandAt(0); } 3954 HValue* index() { return OperandAt(0); }
3713 HValue* length() { return OperandAt(1); } 3955 HValue* length() { return OperandAt(1); }
3956 bool allow_equality() { return allow_equality_; }
3957 void set_allow_equality(bool v) { allow_equality_ = v; }
3714 3958
3715 virtual int RedefinedOperandIndex() { return 0; } 3959 virtual int RedefinedOperandIndex() { return 0; }
3716 virtual bool IsPurelyInformativeDefinition() { return skip_check(); } 3960 virtual bool IsPurelyInformativeDefinition() { return skip_check(); }
3717 virtual void AddInformativeDefinitions(); 3961 virtual void AddInformativeDefinitions();
3718 3962
3719 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck) 3963 DECLARE_CONCRETE_INSTRUCTION(BoundsCheck)
3720 3964
3721 protected: 3965 protected:
3722 friend class HBoundsCheckBaseIndexInformation; 3966 friend class HBoundsCheckBaseIndexInformation;
3723 3967
3724 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) { 3968 virtual void SetResponsibilityForRange(RangeGuaranteeDirection direction) {
3725 responsibility_direction_ = static_cast<RangeGuaranteeDirection>( 3969 responsibility_direction_ = static_cast<RangeGuaranteeDirection>(
3726 responsibility_direction_ | direction); 3970 responsibility_direction_ | direction);
3727 } 3971 }
3728 3972
3729 virtual bool DataEquals(HValue* other) { return true; } 3973 virtual bool DataEquals(HValue* other) { return true; }
3730 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context); 3974 virtual void TryGuaranteeRangeChanging(RangeEvaluationContext* context);
3731 bool skip_check_; 3975 bool skip_check_;
3732 HValue* base_; 3976 HValue* base_;
3733 int offset_; 3977 int offset_;
3734 int scale_; 3978 int scale_;
3735 RangeGuaranteeDirection responsibility_direction_; 3979 RangeGuaranteeDirection responsibility_direction_;
3980 bool allow_equality_;
3736 }; 3981 };
3737 3982
3738 3983
3739 class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> { 3984 class HBoundsCheckBaseIndexInformation: public HTemplateInstruction<2> {
3740 public: 3985 public:
3741 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) { 3986 explicit HBoundsCheckBaseIndexInformation(HBoundsCheck* check) {
3742 DecompositionResult decomposition; 3987 DecompositionResult decomposition;
3743 if (check->index()->TryDecompose(&decomposition)) { 3988 if (check->index()->TryDecompose(&decomposition)) {
3744 SetOperandAt(0, decomposition.base()); 3989 SetOperandAt(0, decomposition.base());
3745 SetOperandAt(1, check); 3990 SetOperandAt(1, check);
(...skipping 2862 matching lines...) Expand 10 before | Expand all | Expand 10 after
6608 virtual bool IsDeletable() const { return true; } 6853 virtual bool IsDeletable() const { return true; }
6609 }; 6854 };
6610 6855
6611 6856
6612 #undef DECLARE_INSTRUCTION 6857 #undef DECLARE_INSTRUCTION
6613 #undef DECLARE_CONCRETE_INSTRUCTION 6858 #undef DECLARE_CONCRETE_INSTRUCTION
6614 6859
6615 } } // namespace v8::internal 6860 } } // namespace v8::internal
6616 6861
6617 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ 6862 #endif // V8_HYDROGEN_INSTRUCTIONS_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698