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

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

Issue 179933004: Merged r19475, r19480, r19530 into 3.24 branch. (Closed) Base URL: https://v8.googlecode.com/svn/branches/3.24
Patch Set: Created 6 years, 9 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 | « no previous file | src/version.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 // 147 void CoverCheck(HBoundsCheck* new_check,
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,
151 int32_t new_offset) { 148 int32_t new_offset) {
152 ASSERT(new_check->index()->representation().IsSmiOrInteger32()); 149 ASSERT(new_check->index()->representation().IsSmiOrInteger32());
153 bool keep_new_check = false; 150 bool keep_new_check = false;
154 151
155 if (new_offset > upper_offset_) { 152 if (new_offset > upper_offset_) {
156 upper_offset_ = new_offset; 153 upper_offset_ = new_offset;
157 if (HasSingleCheck()) { 154 if (HasSingleCheck()) {
158 keep_new_check = true; 155 keep_new_check = true;
159 upper_check_ = new_check; 156 upper_check_ = new_check;
160 } else { 157 } else {
161 bool result = BuildOffsetAdd(upper_check_, 158 TightenCheck(upper_check_, new_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_);
170 } 159 }
171 } else if (new_offset < lower_offset_) { 160 } else if (new_offset < lower_offset_) {
172 lower_offset_ = new_offset; 161 lower_offset_ = new_offset;
173 if (HasSingleCheck()) { 162 if (HasSingleCheck()) {
174 keep_new_check = true; 163 keep_new_check = true;
175 lower_check_ = new_check; 164 lower_check_ = new_check;
176 } else { 165 } else {
177 bool result = BuildOffsetAdd(lower_check_, 166 TightenCheck(lower_check_, new_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_);
186 } 167 }
187 } else { 168 } else {
188 ASSERT(false); 169 // Should never have called CoverCheck() in this case.
170 UNREACHABLE();
189 } 171 }
190 172
191 if (!keep_new_check) { 173 if (!keep_new_check) {
192 new_check->block()->graph()->isolate()->counters()-> 174 new_check->block()->graph()->isolate()->counters()->
193 bounds_checks_eliminated()->Increment(); 175 bounds_checks_eliminated()->Increment();
194 new_check->DeleteAndReplaceWith(new_check->ActualValue()); 176 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);
195 } 186 }
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_);
203 } 187 }
204 188
205 BoundsCheckBbData(BoundsCheckKey* key, 189 BoundsCheckBbData(BoundsCheckKey* key,
206 int32_t lower_offset, 190 int32_t lower_offset,
207 int32_t upper_offset, 191 int32_t upper_offset,
208 HBasicBlock* bb, 192 HBasicBlock* bb,
209 HBoundsCheck* lower_check, 193 HBoundsCheck* lower_check,
210 HBoundsCheck* upper_check, 194 HBoundsCheck* upper_check,
211 BoundsCheckBbData* next_in_bb, 195 BoundsCheckBbData* next_in_bb,
212 BoundsCheckBbData* father_in_dt) 196 BoundsCheckBbData* father_in_dt)
213 : key_(key), 197 : key_(key),
214 lower_offset_(lower_offset), 198 lower_offset_(lower_offset),
215 upper_offset_(upper_offset), 199 upper_offset_(upper_offset),
216 basic_block_(bb), 200 basic_block_(bb),
217 lower_check_(lower_check), 201 lower_check_(lower_check),
218 upper_check_(upper_check), 202 upper_check_(upper_check),
219 added_lower_index_(NULL), 203 next_in_bb_(next_in_bb),
220 added_lower_offset_(NULL), 204 father_in_dt_(father_in_dt) { }
221 added_upper_index_(NULL),
222 added_upper_offset_(NULL),
223 next_in_bb_(next_in_bb),
224 father_in_dt_(father_in_dt) { }
225 205
226 private: 206 private:
227 BoundsCheckKey* key_; 207 BoundsCheckKey* key_;
228 int32_t lower_offset_; 208 int32_t lower_offset_;
229 int32_t upper_offset_; 209 int32_t upper_offset_;
230 HBasicBlock* basic_block_; 210 HBasicBlock* basic_block_;
231 HBoundsCheck* lower_check_; 211 HBoundsCheck* lower_check_;
232 HBoundsCheck* upper_check_; 212 HBoundsCheck* upper_check_;
233 HInstruction* added_lower_index_;
234 HConstant* added_lower_offset_;
235 HInstruction* added_upper_index_;
236 HConstant* added_upper_offset_;
237 BoundsCheckBbData* next_in_bb_; 213 BoundsCheckBbData* next_in_bb_;
238 BoundsCheckBbData* father_in_dt_; 214 BoundsCheckBbData* father_in_dt_;
239 215
240 // Given an existing add instruction and a bounds check it tries to 216 void MoveIndexIfNecessary(HValue* index_raw,
241 // find the current context (either of the add or of the check index). 217 HBoundsCheck* insert_before,
242 HValue* IndexContext(HInstruction* add, HBoundsCheck* check) { 218 HInstruction* end_of_scan_range) {
243 if (add != NULL && add->IsAdd()) { 219 if (!index_raw->IsAdd() && !index_raw->IsSub()) {
244 return HAdd::cast(add)->context(); 220 // index_raw can be HAdd(index_base, offset), HSub(index_base, offset),
221 // or index_base directly. In the latter case, no need to move anything.
222 return;
245 } 223 }
246 if (check->index()->IsBinaryOperation()) { 224 HArithmeticBinaryOperation* index =
247 return HBinaryOperation::cast(check->index())->context(); 225 HArithmeticBinaryOperation::cast(index_raw);
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 }
248 } 240 }
249 return NULL; 241 if (must_move_index) {
250 } 242 index->Unlink();
251 243 index->InsertBefore(insert_before);
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);
274 } 244 }
275 *constant = new_constant; 245 // The BCE algorithm only selects mergeable bounds checks that share
276 return true; 246 // the same "index_base", so we'll only ever have to move constants.
277 } 247 if (must_move_left_input) {
278 248 HConstant::cast(left_input)->Unlink();
279 void RemoveZeroAdd(HInstruction** add, HConstant** constant) { 249 HConstant::cast(left_input)->InsertBefore(index);
280 if (*add != NULL && (*add)->IsAdd() && (*constant)->Integer32Value() == 0) { 250 }
281 (*add)->DeleteAndReplaceWith(HAdd::cast(*add)->left()); 251 if (must_move_right_input) {
282 (*constant)->DeleteAndReplaceWith(NULL); 252 HConstant::cast(right_input)->Unlink();
253 HConstant::cast(right_input)->InsertBefore(index);
283 } 254 }
284 } 255 }
285 256
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
286 DISALLOW_COPY_AND_ASSIGN(BoundsCheckBbData); 265 DISALLOW_COPY_AND_ASSIGN(BoundsCheckBbData);
287 }; 266 };
288 267
289 268
290 static bool BoundsCheckKeyMatch(void* key1, void* key2) { 269 static bool BoundsCheckKeyMatch(void* key1, void* key2) {
291 BoundsCheckKey* k1 = static_cast<BoundsCheckKey*>(key1); 270 BoundsCheckKey* k1 = static_cast<BoundsCheckKey*>(key1);
292 BoundsCheckKey* k2 = static_cast<BoundsCheckKey*>(key2); 271 BoundsCheckKey* k2 = static_cast<BoundsCheckKey*>(key2);
293 return k1->IndexBase() == k2->IndexBase() && k1->Length() == k2->Length(); 272 return k1->IndexBase() == k2->IndexBase() && k1->Length() == k2->Length();
294 } 273 }
295 274
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 bb, 366 bb,
388 check, 367 check,
389 check, 368 check,
390 bb_data_list, 369 bb_data_list,
391 NULL); 370 NULL);
392 *data_p = bb_data_list; 371 *data_p = bb_data_list;
393 } else if (data->OffsetIsCovered(offset)) { 372 } else if (data->OffsetIsCovered(offset)) {
394 bb->graph()->isolate()->counters()-> 373 bb->graph()->isolate()->counters()->
395 bounds_checks_eliminated()->Increment(); 374 bounds_checks_eliminated()->Increment();
396 check->DeleteAndReplaceWith(check->ActualValue()); 375 check->DeleteAndReplaceWith(check->ActualValue());
397 } else if (data->BasicBlock() != bb || 376 } else if (data->BasicBlock() == bb) {
398 !data->CoverCheck(check, offset)) { 377 data->CoverCheck(check, offset);
399 // If the check is in the current BB we try to modify it by calling 378 } else if (graph()->use_optimistic_licm() ||
400 // "CoverCheck", but if also that fails we record the current offsets 379 bb->IsLoopSuccessorDominator()) {
401 // in a new data instance because from now on they are covered.
402 int32_t new_lower_offset = offset < data->LowerOffset() 380 int32_t new_lower_offset = offset < data->LowerOffset()
403 ? offset 381 ? offset
404 : data->LowerOffset(); 382 : data->LowerOffset();
405 int32_t new_upper_offset = offset > data->UpperOffset() 383 int32_t new_upper_offset = offset > data->UpperOffset()
406 ? offset 384 ? offset
407 : data->UpperOffset(); 385 : data->UpperOffset();
408 bb_data_list = new(zone()) BoundsCheckBbData(key, 386 bb_data_list = new(zone()) BoundsCheckBbData(key,
409 new_lower_offset, 387 new_lower_offset,
410 new_upper_offset, 388 new_upper_offset,
411 bb, 389 bb,
412 data->LowerCheck(), 390 data->LowerCheck(),
413 data->UpperCheck(), 391 data->UpperCheck(),
414 bb_data_list, 392 bb_data_list,
415 data); 393 data);
416 table_.Insert(key, bb_data_list, zone()); 394 table_.Insert(key, bb_data_list, zone());
417 } 395 }
418 } 396 }
419 397
420 return bb_data_list; 398 return bb_data_list;
421 } 399 }
422 400
423 401
424 void HBoundsCheckEliminationPhase::PostProcessBlock( 402 void HBoundsCheckEliminationPhase::PostProcessBlock(
425 HBasicBlock* block, BoundsCheckBbData* data) { 403 HBasicBlock* block, BoundsCheckBbData* data) {
426 while (data != NULL) { 404 while (data != NULL) {
427 data->RemoveZeroOperations();
428 if (data->FatherInDominatorTree()) { 405 if (data->FatherInDominatorTree()) {
429 table_.Insert(data->Key(), data->FatherInDominatorTree(), zone()); 406 table_.Insert(data->Key(), data->FatherInDominatorTree(), zone());
430 } else { 407 } else {
431 table_.Delete(data->Key()); 408 table_.Delete(data->Key());
432 } 409 }
433 data = data->NextInBasicBlock(); 410 data = data->NextInBasicBlock();
434 } 411 }
435 } 412 }
436 413
437 } } // namespace v8::internal 414 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | src/version.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698