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

Side by Side Diff: src/hydrogen-bce.cc

Issue 178223011: Reset trunk to 3.24.35.4 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 6 years, 10 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.cc ('k') | src/hydrogen-check-elimination.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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 } else { 84 } else {
85 *offset = 0; 85 *offset = 0;
86 index_base = check->index(); 86 index_base = check->index();
87 } 87 }
88 88
89 return new(zone) BoundsCheckKey(index_base, check->length()); 89 return new(zone) BoundsCheckKey(index_base, check->length());
90 } 90 }
91 91
92 private: 92 private:
93 BoundsCheckKey(HValue* index_base, HValue* length) 93 BoundsCheckKey(HValue* index_base, HValue* length)
94 : index_base_(index_base), 94 : index_base_(index_base),
95 length_(length) { } 95 length_(length) { }
96 96
97 HValue* index_base_; 97 HValue* index_base_;
98 HValue* length_; 98 HValue* length_;
99 99
100 DISALLOW_COPY_AND_ASSIGN(BoundsCheckKey); 100 DISALLOW_COPY_AND_ASSIGN(BoundsCheckKey);
101 }; 101 };
102 102
103 103
104 // Data about each HBoundsCheck that can be eliminated or moved. 104 // Data about each HBoundsCheck that can be eliminated or moved.
105 // It is the "value" in the dictionary indexed by "base-index, length" 105 // It is the "value" in the dictionary indexed by "base-index, length"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 // range grows). 137 // range grows).
138 // 138 //
139 // The precondition is that new_check follows UpperCheck() and 139 // The precondition is that new_check follows UpperCheck() and
140 // LowerCheck() in the same basic block, and that new_offset is not 140 // LowerCheck() in the same basic block, and that new_offset is not
141 // covered (otherwise we could simply remove new_check). 141 // covered (otherwise we could simply remove new_check).
142 // 142 //
143 // If HasSingleCheck() is true then new_check is added as "second check" 143 // If HasSingleCheck() is true then new_check is added as "second check"
144 // (either upper or lower; note that HasSingleCheck() becomes false). 144 // (either upper or lower; note that HasSingleCheck() becomes false).
145 // Otherwise one of the current checks is modified so that it also covers 145 // Otherwise one of the current checks is modified so that it also covers
146 // new_offset, and new_check is removed. 146 // new_offset, and new_check is removed.
147 void CoverCheck(HBoundsCheck* new_check, 147 //
148 // If the check cannot be modified because the context is unknown it
149 // returns false, otherwise it returns true.
150 bool CoverCheck(HBoundsCheck* new_check,
148 int32_t new_offset) { 151 int32_t new_offset) {
149 ASSERT(new_check->index()->representation().IsSmiOrInteger32()); 152 ASSERT(new_check->index()->representation().IsSmiOrInteger32());
150 bool keep_new_check = false; 153 bool keep_new_check = false;
151 154
152 if (new_offset > upper_offset_) { 155 if (new_offset > upper_offset_) {
153 upper_offset_ = new_offset; 156 upper_offset_ = new_offset;
154 if (HasSingleCheck()) { 157 if (HasSingleCheck()) {
155 keep_new_check = true; 158 keep_new_check = true;
156 upper_check_ = new_check; 159 upper_check_ = new_check;
157 } else { 160 } else {
158 TightenCheck(upper_check_, new_check); 161 bool result = BuildOffsetAdd(upper_check_,
162 &added_upper_index_,
163 &added_upper_offset_,
164 Key()->IndexBase(),
165 new_check->index()->representation(),
166 new_offset);
167 if (!result) return false;
168 upper_check_->ReplaceAllUsesWith(upper_check_->index());
169 upper_check_->SetOperandAt(0, added_upper_index_);
159 } 170 }
160 } else if (new_offset < lower_offset_) { 171 } else if (new_offset < lower_offset_) {
161 lower_offset_ = new_offset; 172 lower_offset_ = new_offset;
162 if (HasSingleCheck()) { 173 if (HasSingleCheck()) {
163 keep_new_check = true; 174 keep_new_check = true;
164 lower_check_ = new_check; 175 lower_check_ = new_check;
165 } else { 176 } else {
166 TightenCheck(lower_check_, new_check); 177 bool result = BuildOffsetAdd(lower_check_,
178 &added_lower_index_,
179 &added_lower_offset_,
180 Key()->IndexBase(),
181 new_check->index()->representation(),
182 new_offset);
183 if (!result) return false;
184 lower_check_->ReplaceAllUsesWith(lower_check_->index());
185 lower_check_->SetOperandAt(0, added_lower_index_);
167 } 186 }
168 } else { 187 } else {
169 // Should never have called CoverCheck() in this case. 188 ASSERT(false);
170 UNREACHABLE();
171 } 189 }
172 190
173 if (!keep_new_check) { 191 if (!keep_new_check) {
174 new_check->block()->graph()->isolate()->counters()-> 192 new_check->block()->graph()->isolate()->counters()->
175 bounds_checks_eliminated()->Increment(); 193 bounds_checks_eliminated()->Increment();
176 new_check->DeleteAndReplaceWith(new_check->ActualValue()); 194 new_check->DeleteAndReplaceWith(new_check->ActualValue());
177 } else {
178 HBoundsCheck* first_check = new_check == lower_check_ ? upper_check_
179 : lower_check_;
180 // The length is guaranteed to be live at first_check.
181 ASSERT(new_check->length() == first_check->length());
182 HInstruction* old_position = new_check->next();
183 new_check->Unlink();
184 new_check->InsertAfter(first_check);
185 MoveIndexIfNecessary(new_check->index(), new_check, old_position);
186 } 195 }
196
197 return true;
198 }
199
200 void RemoveZeroOperations() {
201 RemoveZeroAdd(&added_lower_index_, &added_lower_offset_);
202 RemoveZeroAdd(&added_upper_index_, &added_upper_offset_);
187 } 203 }
188 204
189 BoundsCheckBbData(BoundsCheckKey* key, 205 BoundsCheckBbData(BoundsCheckKey* key,
190 int32_t lower_offset, 206 int32_t lower_offset,
191 int32_t upper_offset, 207 int32_t upper_offset,
192 HBasicBlock* bb, 208 HBasicBlock* bb,
193 HBoundsCheck* lower_check, 209 HBoundsCheck* lower_check,
194 HBoundsCheck* upper_check, 210 HBoundsCheck* upper_check,
195 BoundsCheckBbData* next_in_bb, 211 BoundsCheckBbData* next_in_bb,
196 BoundsCheckBbData* father_in_dt) 212 BoundsCheckBbData* father_in_dt)
197 : key_(key), 213 : key_(key),
198 lower_offset_(lower_offset), 214 lower_offset_(lower_offset),
199 upper_offset_(upper_offset), 215 upper_offset_(upper_offset),
200 basic_block_(bb), 216 basic_block_(bb),
201 lower_check_(lower_check), 217 lower_check_(lower_check),
202 upper_check_(upper_check), 218 upper_check_(upper_check),
203 next_in_bb_(next_in_bb), 219 added_lower_index_(NULL),
204 father_in_dt_(father_in_dt) { } 220 added_lower_offset_(NULL),
221 added_upper_index_(NULL),
222 added_upper_offset_(NULL),
223 next_in_bb_(next_in_bb),
224 father_in_dt_(father_in_dt) { }
205 225
206 private: 226 private:
207 BoundsCheckKey* key_; 227 BoundsCheckKey* key_;
208 int32_t lower_offset_; 228 int32_t lower_offset_;
209 int32_t upper_offset_; 229 int32_t upper_offset_;
210 HBasicBlock* basic_block_; 230 HBasicBlock* basic_block_;
211 HBoundsCheck* lower_check_; 231 HBoundsCheck* lower_check_;
212 HBoundsCheck* upper_check_; 232 HBoundsCheck* upper_check_;
233 HInstruction* added_lower_index_;
234 HConstant* added_lower_offset_;
235 HInstruction* added_upper_index_;
236 HConstant* added_upper_offset_;
213 BoundsCheckBbData* next_in_bb_; 237 BoundsCheckBbData* next_in_bb_;
214 BoundsCheckBbData* father_in_dt_; 238 BoundsCheckBbData* father_in_dt_;
215 239
216 void MoveIndexIfNecessary(HValue* index_raw, 240 // Given an existing add instruction and a bounds check it tries to
217 HBoundsCheck* insert_before, 241 // find the current context (either of the add or of the check index).
218 HInstruction* end_of_scan_range) { 242 HValue* IndexContext(HInstruction* add, HBoundsCheck* check) {
219 if (!index_raw->IsAdd() && !index_raw->IsSub()) { 243 if (add != NULL && add->IsAdd()) {
220 // index_raw can be HAdd(index_base, offset), HSub(index_base, offset), 244 return HAdd::cast(add)->context();
221 // or index_base directly. In the latter case, no need to move anything.
222 return;
223 } 245 }
224 HArithmeticBinaryOperation* index = 246 if (check->index()->IsBinaryOperation()) {
225 HArithmeticBinaryOperation::cast(index_raw); 247 return HBinaryOperation::cast(check->index())->context();
226 HValue* left_input = index->left();
227 HValue* right_input = index->right();
228 bool must_move_index = false;
229 bool must_move_left_input = false;
230 bool must_move_right_input = false;
231 for (HInstruction* cursor = end_of_scan_range; cursor != insert_before;) {
232 if (cursor == left_input) must_move_left_input = true;
233 if (cursor == right_input) must_move_right_input = true;
234 if (cursor == index) must_move_index = true;
235 if (cursor->previous() == NULL) {
236 cursor = cursor->block()->dominator()->end();
237 } else {
238 cursor = cursor->previous();
239 }
240 } 248 }
241 if (must_move_index) { 249 return NULL;
242 index->Unlink(); 250 }
243 index->InsertBefore(insert_before); 251
252 // This function returns false if it cannot build the add because the
253 // current context cannot be determined.
254 bool BuildOffsetAdd(HBoundsCheck* check,
255 HInstruction** add,
256 HConstant** constant,
257 HValue* original_value,
258 Representation representation,
259 int32_t new_offset) {
260 HValue* index_context = IndexContext(*add, check);
261 if (index_context == NULL) return false;
262
263 Zone* zone = BasicBlock()->zone();
264 HConstant* new_constant = HConstant::New(zone, index_context,
265 new_offset, representation);
266 if (*add == NULL) {
267 new_constant->InsertBefore(check);
268 (*add) = HAdd::New(zone, index_context, original_value, new_constant);
269 (*add)->AssumeRepresentation(representation);
270 (*add)->InsertBefore(check);
271 } else {
272 new_constant->InsertBefore(*add);
273 (*constant)->DeleteAndReplaceWith(new_constant);
244 } 274 }
245 // The BCE algorithm only selects mergeable bounds checks that share 275 *constant = new_constant;
246 // the same "index_base", so we'll only ever have to move constants. 276 return true;
247 if (must_move_left_input) { 277 }
248 HConstant::cast(left_input)->Unlink(); 278
249 HConstant::cast(left_input)->InsertBefore(index); 279 void RemoveZeroAdd(HInstruction** add, HConstant** constant) {
250 } 280 if (*add != NULL && (*add)->IsAdd() && (*constant)->Integer32Value() == 0) {
251 if (must_move_right_input) { 281 (*add)->DeleteAndReplaceWith(HAdd::cast(*add)->left());
252 HConstant::cast(right_input)->Unlink(); 282 (*constant)->DeleteAndReplaceWith(NULL);
253 HConstant::cast(right_input)->InsertBefore(index);
254 } 283 }
255 } 284 }
256 285
257 void TightenCheck(HBoundsCheck* original_check,
258 HBoundsCheck* tighter_check) {
259 ASSERT(original_check->length() == tighter_check->length());
260 MoveIndexIfNecessary(tighter_check->index(), original_check, tighter_check);
261 original_check->ReplaceAllUsesWith(original_check->index());
262 original_check->SetOperandAt(0, tighter_check->index());
263 }
264
265 DISALLOW_COPY_AND_ASSIGN(BoundsCheckBbData); 286 DISALLOW_COPY_AND_ASSIGN(BoundsCheckBbData);
266 }; 287 };
267 288
268 289
269 static bool BoundsCheckKeyMatch(void* key1, void* key2) { 290 static bool BoundsCheckKeyMatch(void* key1, void* key2) {
270 BoundsCheckKey* k1 = static_cast<BoundsCheckKey*>(key1); 291 BoundsCheckKey* k1 = static_cast<BoundsCheckKey*>(key1);
271 BoundsCheckKey* k2 = static_cast<BoundsCheckKey*>(key2); 292 BoundsCheckKey* k2 = static_cast<BoundsCheckKey*>(key2);
272 return k1->IndexBase() == k2->IndexBase() && k1->Length() == k2->Length(); 293 return k1->IndexBase() == k2->IndexBase() && k1->Length() == k2->Length();
273 } 294 }
274 295
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 bb, 387 bb,
367 check, 388 check,
368 check, 389 check,
369 bb_data_list, 390 bb_data_list,
370 NULL); 391 NULL);
371 *data_p = bb_data_list; 392 *data_p = bb_data_list;
372 } else if (data->OffsetIsCovered(offset)) { 393 } else if (data->OffsetIsCovered(offset)) {
373 bb->graph()->isolate()->counters()-> 394 bb->graph()->isolate()->counters()->
374 bounds_checks_eliminated()->Increment(); 395 bounds_checks_eliminated()->Increment();
375 check->DeleteAndReplaceWith(check->ActualValue()); 396 check->DeleteAndReplaceWith(check->ActualValue());
376 } else if (data->BasicBlock() == bb) { 397 } else if (data->BasicBlock() != bb ||
377 data->CoverCheck(check, offset); 398 !data->CoverCheck(check, offset)) {
378 } else if (graph()->use_optimistic_licm() || 399 // If the check is in the current BB we try to modify it by calling
379 bb->IsLoopSuccessorDominator()) { 400 // "CoverCheck", but if also that fails we record the current offsets
401 // in a new data instance because from now on they are covered.
380 int32_t new_lower_offset = offset < data->LowerOffset() 402 int32_t new_lower_offset = offset < data->LowerOffset()
381 ? offset 403 ? offset
382 : data->LowerOffset(); 404 : data->LowerOffset();
383 int32_t new_upper_offset = offset > data->UpperOffset() 405 int32_t new_upper_offset = offset > data->UpperOffset()
384 ? offset 406 ? offset
385 : data->UpperOffset(); 407 : data->UpperOffset();
386 bb_data_list = new(zone()) BoundsCheckBbData(key, 408 bb_data_list = new(zone()) BoundsCheckBbData(key,
387 new_lower_offset, 409 new_lower_offset,
388 new_upper_offset, 410 new_upper_offset,
389 bb, 411 bb,
390 data->LowerCheck(), 412 data->LowerCheck(),
391 data->UpperCheck(), 413 data->UpperCheck(),
392 bb_data_list, 414 bb_data_list,
393 data); 415 data);
394 table_.Insert(key, bb_data_list, zone()); 416 table_.Insert(key, bb_data_list, zone());
395 } 417 }
396 } 418 }
397 419
398 return bb_data_list; 420 return bb_data_list;
399 } 421 }
400 422
401 423
402 void HBoundsCheckEliminationPhase::PostProcessBlock( 424 void HBoundsCheckEliminationPhase::PostProcessBlock(
403 HBasicBlock* block, BoundsCheckBbData* data) { 425 HBasicBlock* block, BoundsCheckBbData* data) {
404 while (data != NULL) { 426 while (data != NULL) {
427 data->RemoveZeroOperations();
405 if (data->FatherInDominatorTree()) { 428 if (data->FatherInDominatorTree()) {
406 table_.Insert(data->Key(), data->FatherInDominatorTree(), zone()); 429 table_.Insert(data->Key(), data->FatherInDominatorTree(), zone());
407 } else { 430 } else {
408 table_.Delete(data->Key()); 431 table_.Delete(data->Key());
409 } 432 }
410 data = data->NextInBasicBlock(); 433 data = data->NextInBasicBlock();
411 } 434 }
412 } 435 }
413 436
414 } } // namespace v8::internal 437 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.cc ('k') | src/hydrogen-check-elimination.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698