Blob Blame History Raw
From fd80a31e0697d6317ce8c2d289575399f4e06d21 Mon Sep 17 00:00:00 2001
From: Fedor Indutny <fedor@indutny.com>
Date: Thu, 14 Aug 2014 19:29:28 +0400
Subject: [PATCH] deps: backport 5f836c from v8 upstream

Original commit message:

    Fix Hydrogen bounds check elimination

    When combining bounds checks, they must all be moved before the first load/store
    that they are guarding.

    BUG=chromium:344186
    LOG=y
    R=svenpanne@chromium.org

    Review URL: https://codereview.chromium.org/172093002

    git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@19475 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

fix #8070
---
 src/hydrogen.cc | 106 +++++++++++++++++++++++-------------------------
 1 file changed, 50 insertions(+), 56 deletions(-)

diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index e3f79ee..50d8e49 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -3487,13 +3487,7 @@ class BoundsCheckBbData: public ZoneObject {
         keep_new_check = true;
         upper_check_ = new_check;
       } else {
-        BuildOffsetAdd(upper_check_,
-                       &added_upper_index_,
-                       &added_upper_offset_,
-                       Key()->IndexBase(),
-                       new_check->index()->representation(),
-                       new_offset);
-        upper_check_->SetOperandAt(0, added_upper_index_);
+        TightenCheck(upper_check_, new_check);
       }
     } else if (new_offset < lower_offset_) {
       lower_offset_ = new_offset;
@@ -3501,28 +3495,27 @@ class BoundsCheckBbData: public ZoneObject {
         keep_new_check = true;
         lower_check_ = new_check;
       } else {
-        BuildOffsetAdd(lower_check_,
-                       &added_lower_index_,
-                       &added_lower_offset_,
-                       Key()->IndexBase(),
-                       new_check->index()->representation(),
-                       new_offset);
-        lower_check_->SetOperandAt(0, added_lower_index_);
+        TightenCheck(lower_check_, new_check);
       }
     } else {
-      ASSERT(false);
+      // Should never have called CoverCheck() in this case.
+      UNREACHABLE();
     }
 
     if (!keep_new_check) {
       new_check->DeleteAndReplaceWith(NULL);
+    } else {
+      HBoundsCheck* first_check = new_check == lower_check_ ? upper_check_
+                                                            : lower_check_;
+      // The length is guaranteed to be live at first_check.
+      ASSERT(new_check->length() == first_check->length());
+      HInstruction* old_position = new_check->next();
+      new_check->Unlink();
+      new_check->InsertAfter(first_check);
+      MoveIndexIfNecessary(new_check->index(), new_check, old_position);
     }
   }
 
-  void RemoveZeroOperations() {
-    RemoveZeroAdd(&added_lower_index_, &added_lower_offset_);
-    RemoveZeroAdd(&added_upper_index_, &added_upper_offset_);
-  }
-
   BoundsCheckBbData(BoundsCheckKey* key,
                     int32_t lower_offset,
                     int32_t upper_offset,
@@ -3537,10 +3530,6 @@ class BoundsCheckBbData: public ZoneObject {
     basic_block_(bb),
     lower_check_(lower_check),
     upper_check_(upper_check),
-    added_lower_index_(NULL),
-    added_lower_offset_(NULL),
-    added_upper_index_(NULL),
-    added_upper_offset_(NULL),
     next_in_bb_(next_in_bb),
     father_in_dt_(father_in_dt) { }
 
@@ -3551,44 +3540,50 @@ class BoundsCheckBbData: public ZoneObject {
   HBasicBlock* basic_block_;
   HBoundsCheck* lower_check_;
   HBoundsCheck* upper_check_;
-  HAdd* added_lower_index_;
-  HConstant* added_lower_offset_;
-  HAdd* added_upper_index_;
-  HConstant* added_upper_offset_;
   BoundsCheckBbData* next_in_bb_;
   BoundsCheckBbData* father_in_dt_;
 
-  void BuildOffsetAdd(HBoundsCheck* check,
-                      HAdd** add,
-                      HConstant** constant,
-                      HValue* original_value,
-                      Representation representation,
-                      int32_t new_offset) {
-    HConstant* new_constant = new(BasicBlock()->zone())
-       HConstant(new_offset, Representation::Integer32());
-    if (*add == NULL) {
-      new_constant->InsertBefore(check);
-      // Because of the bounds checks elimination algorithm, the index is always
-      // an HAdd or an HSub here, so we can safely cast to an HBinaryOperation.
-      HValue* context = HBinaryOperation::cast(check->index())->context();
-      *add = new(BasicBlock()->zone()) HAdd(context,
-                                            original_value,
-                                            new_constant);
-      (*add)->AssumeRepresentation(representation);
-      (*add)->InsertBefore(check);
-    } else {
-      new_constant->InsertBefore(*add);
-      (*constant)->DeleteAndReplaceWith(new_constant);
+  void MoveIndexIfNecessary(HValue* index_raw,
+                            HBoundsCheck* insert_before,
+                            HInstruction* end_of_scan_range) {
+    ASSERT(index_raw->IsAdd() || index_raw->IsSub());
+    HBinaryOperation* index =
+        HArithmeticBinaryOperation::cast(index_raw);
+    HValue* left_input = index->left();
+    HValue* right_input = index->right();
+    bool must_move_index = false;
+    bool must_move_left_input = false;
+    bool must_move_right_input = false;
+    for (HInstruction* cursor = end_of_scan_range; cursor != insert_before;) {
+      if (cursor == left_input) must_move_left_input = true;
+      if (cursor == right_input) must_move_right_input = true;
+      if (cursor == index) must_move_index = true;
+      if (cursor->previous() == NULL) {
+        cursor = cursor->block()->dominator()->end();
+      } else {
+        cursor = cursor->previous();
+      }
     }
-    *constant = new_constant;
-  }
 
-  void RemoveZeroAdd(HAdd** add, HConstant** constant) {
-    if (*add != NULL && (*constant)->Integer32Value() == 0) {
-      (*add)->DeleteAndReplaceWith((*add)->left());
-      (*constant)->DeleteAndReplaceWith(NULL);
+    // The BCE algorithm only selects mergeable bounds checks that share
+    // the same "index_base", so we'll only ever have to move constants.
+    if (must_move_left_input) {
+      HConstant::cast(left_input)->Unlink();
+      HConstant::cast(left_input)->InsertBefore(index);
+    }
+    if (must_move_right_input) {
+      HConstant::cast(right_input)->Unlink();
+      HConstant::cast(right_input)->InsertBefore(index);
     }
   }
+
+  void TightenCheck(HBoundsCheck* original_check,
+                    HBoundsCheck* tighter_check) {
+    ASSERT(original_check->length() == tighter_check->length());
+    MoveIndexIfNecessary(tighter_check->index(), original_check, tighter_check);
+    original_check->ReplaceAllUsesWith(original_check->index());
+    original_check->SetOperandAt(0, tighter_check->index());
+  }
 };
 
 
@@ -3683,7 +3678,6 @@ void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb,
   for (BoundsCheckBbData* data = bb_data_list;
        data != NULL;
        data = data->NextInBasicBlock()) {
-    data->RemoveZeroOperations();
     if (data->FatherInDominatorTree()) {
       table->Insert(data->Key(), data->FatherInDominatorTree(), zone());
     } else {