ART: ArrayGet hoisting restriction added.

Currently if we hoist ArrayGet from loop there is no guarantee
that insn will be executed at runtime. Because of that we could
face issues like crashes in generated code.

This patch introduces restriction for ArrayGet hoisting. We say
that ArrayGet execution is guaranteed at least one time if its bb
dominates all exit blocks.

Change-Id: I9f72c0f4c33b358341109238bea46cb5a82f490f
Signed-off-by: Anton Shamin <anton.shamin@intel.com>
diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc
index 6c6e5af..96c9e3d 100644
--- a/compiler/optimizing/bounds_check_elimination.cc
+++ b/compiler/optimizing/bounds_check_elimination.cc
@@ -1169,7 +1169,11 @@
           loop->IsDefinedOutOfTheLoop(array_get->InputAt(1))) {
         SideEffects loop_effects = side_effects_.GetLoopEffects(loop->GetHeader());
         if (!array_get->GetSideEffects().MayDependOn(loop_effects)) {
-          HoistToPreHeaderOrDeoptBlock(loop, array_get);
+          // We can hoist ArrayGet only if its execution is guaranteed on every iteration.
+          // In other words only if array_get_bb dominates all back branches.
+          if (loop->DominatesAllBackEdges(array_get->GetBlock())) {
+            HoistToPreHeaderOrDeoptBlock(loop, array_get);
+          }
         }
       }
     }
@@ -1394,13 +1398,7 @@
       }
       // Does the current basic block dominate all back edges? If not,
       // don't apply dynamic bce to something that may not be executed.
-      for (HBasicBlock* back_edge : loop->GetBackEdges()) {
-        if (!block->Dominates(back_edge)) {
-          return false;
-        }
-      }
-      // Success!
-      return true;
+      return loop->DominatesAllBackEdges(block);
     }
     return false;
   }