@@ -3487,42 +3487,35 @@ class BoundsCheckBbData: public ZoneObject {
34873487 keep_new_check = true ;
34883488 upper_check_ = new_check;
34893489 } else {
3490- BuildOffsetAdd (upper_check_,
3491- &added_upper_index_,
3492- &added_upper_offset_,
3493- Key ()->IndexBase (),
3494- new_check->index ()->representation (),
3495- new_offset);
3496- upper_check_->SetOperandAt (0 , added_upper_index_);
3490+ TightenCheck (upper_check_, new_check);
34973491 }
34983492 } else if (new_offset < lower_offset_) {
34993493 lower_offset_ = new_offset;
35003494 if (HasSingleCheck ()) {
35013495 keep_new_check = true ;
35023496 lower_check_ = new_check;
35033497 } else {
3504- BuildOffsetAdd (lower_check_,
3505- &added_lower_index_,
3506- &added_lower_offset_,
3507- Key ()->IndexBase (),
3508- new_check->index ()->representation (),
3509- new_offset);
3510- lower_check_->SetOperandAt (0 , added_lower_index_);
3498+ TightenCheck (lower_check_, new_check);
35113499 }
35123500 } else {
3513- ASSERT (false );
3501+ // Should never have called CoverCheck() in this case.
3502+ UNREACHABLE ();
35143503 }
35153504
35163505 if (!keep_new_check) {
35173506 new_check->DeleteAndReplaceWith (NULL );
3507+ } else {
3508+ HBoundsCheck* first_check = new_check == lower_check_ ? upper_check_
3509+ : lower_check_;
3510+ // The length is guaranteed to be live at first_check.
3511+ ASSERT (new_check->length () == first_check->length ());
3512+ HInstruction* old_position = new_check->next ();
3513+ new_check->Unlink ();
3514+ new_check->InsertAfter (first_check);
3515+ MoveIndexIfNecessary (new_check->index (), new_check, old_position);
35183516 }
35193517 }
35203518
3521- void RemoveZeroOperations () {
3522- RemoveZeroAdd (&added_lower_index_, &added_lower_offset_);
3523- RemoveZeroAdd (&added_upper_index_, &added_upper_offset_);
3524- }
3525-
35263519 BoundsCheckBbData (BoundsCheckKey* key,
35273520 int32_t lower_offset,
35283521 int32_t upper_offset,
@@ -3537,10 +3530,6 @@ class BoundsCheckBbData: public ZoneObject {
35373530 basic_block_(bb),
35383531 lower_check_(lower_check),
35393532 upper_check_(upper_check),
3540- added_lower_index_(NULL ),
3541- added_lower_offset_(NULL ),
3542- added_upper_index_(NULL ),
3543- added_upper_offset_(NULL ),
35443533 next_in_bb_(next_in_bb),
35453534 father_in_dt_(father_in_dt) { }
35463535
@@ -3551,44 +3540,50 @@ class BoundsCheckBbData: public ZoneObject {
35513540 HBasicBlock* basic_block_;
35523541 HBoundsCheck* lower_check_;
35533542 HBoundsCheck* upper_check_;
3554- HAdd* added_lower_index_;
3555- HConstant* added_lower_offset_;
3556- HAdd* added_upper_index_;
3557- HConstant* added_upper_offset_;
35583543 BoundsCheckBbData* next_in_bb_;
35593544 BoundsCheckBbData* father_in_dt_;
35603545
3561- void BuildOffsetAdd (HBoundsCheck* check,
3562- HAdd** add,
3563- HConstant** constant,
3564- HValue* original_value,
3565- Representation representation,
3566- int32_t new_offset) {
3567- HConstant* new_constant = new (BasicBlock ()->zone ())
3568- HConstant (new_offset, Representation::Integer32 ());
3569- if (*add == NULL ) {
3570- new_constant->InsertBefore (check);
3571- // Because of the bounds checks elimination algorithm, the index is always
3572- // an HAdd or an HSub here, so we can safely cast to an HBinaryOperation.
3573- HValue* context = HBinaryOperation::cast (check->index ())->context ();
3574- *add = new (BasicBlock ()->zone ()) HAdd (context,
3575- original_value,
3576- new_constant);
3577- (*add)->AssumeRepresentation (representation);
3578- (*add)->InsertBefore (check);
3579- } else {
3580- new_constant->InsertBefore (*add);
3581- (*constant)->DeleteAndReplaceWith (new_constant);
3546+ void MoveIndexIfNecessary (HValue* index_raw,
3547+ HBoundsCheck* insert_before,
3548+ HInstruction* end_of_scan_range) {
3549+ ASSERT (index_raw->IsAdd () || index_raw->IsSub ());
3550+ HBinaryOperation* index =
3551+ HArithmeticBinaryOperation::cast (index_raw);
3552+ HValue* left_input = index->left ();
3553+ HValue* right_input = index->right ();
3554+ bool must_move_index = false ;
3555+ bool must_move_left_input = false ;
3556+ bool must_move_right_input = false ;
3557+ for (HInstruction* cursor = end_of_scan_range; cursor != insert_before;) {
3558+ if (cursor == left_input) must_move_left_input = true ;
3559+ if (cursor == right_input) must_move_right_input = true ;
3560+ if (cursor == index) must_move_index = true ;
3561+ if (cursor->previous () == NULL ) {
3562+ cursor = cursor->block ()->dominator ()->end ();
3563+ } else {
3564+ cursor = cursor->previous ();
3565+ }
35823566 }
3583- *constant = new_constant;
3584- }
35853567
3586- void RemoveZeroAdd (HAdd** add, HConstant** constant) {
3587- if (*add != NULL && (*constant)->Integer32Value () == 0 ) {
3588- (*add)->DeleteAndReplaceWith ((*add)->left ());
3589- (*constant)->DeleteAndReplaceWith (NULL );
3568+ // The BCE algorithm only selects mergeable bounds checks that share
3569+ // the same "index_base", so we'll only ever have to move constants.
3570+ if (must_move_left_input) {
3571+ HConstant::cast (left_input)->Unlink ();
3572+ HConstant::cast (left_input)->InsertBefore (index);
3573+ }
3574+ if (must_move_right_input) {
3575+ HConstant::cast (right_input)->Unlink ();
3576+ HConstant::cast (right_input)->InsertBefore (index);
35903577 }
35913578 }
3579+
3580+ void TightenCheck (HBoundsCheck* original_check,
3581+ HBoundsCheck* tighter_check) {
3582+ ASSERT (original_check->length () == tighter_check->length ());
3583+ MoveIndexIfNecessary (tighter_check->index (), original_check, tighter_check);
3584+ original_check->ReplaceAllUsesWith (original_check->index ());
3585+ original_check->SetOperandAt (0 , tighter_check->index ());
3586+ }
35923587};
35933588
35943589
@@ -3683,7 +3678,6 @@ void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb,
36833678 for (BoundsCheckBbData* data = bb_data_list;
36843679 data != NULL ;
36853680 data = data->NextInBasicBlock ()) {
3686- data->RemoveZeroOperations ();
36873681 if (data->FatherInDominatorTree ()) {
36883682 table->Insert (data->Key (), data->FatherInDominatorTree (), zone ());
36893683 } else {
0 commit comments