1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "base/arena_containers.h"
18 #include "bounds_check_elimination.h"
19 #include "nodes.h"
20 
21 namespace art {
22 
23 class MonotonicValueRange;
24 
25 /**
26  * A value bound is represented as a pair of value and constant,
27  * e.g. array.length - 1.
28  */
29 class ValueBound : public ValueObject {
30  public:
ValueBound(HInstruction * instruction,int32_t constant)31   ValueBound(HInstruction* instruction, int32_t constant) {
32     if (instruction != nullptr && instruction->IsIntConstant()) {
33       // Normalize ValueBound with constant instruction.
34       int32_t instr_const = instruction->AsIntConstant()->GetValue();
35       if (!WouldAddOverflowOrUnderflow(instr_const, constant)) {
36         instruction_ = nullptr;
37         constant_ = instr_const + constant;
38         return;
39       }
40     }
41     instruction_ = instruction;
42     constant_ = constant;
43   }
44 
45   // Return whether (left + right) overflows or underflows.
WouldAddOverflowOrUnderflow(int32_t left,int32_t right)46   static bool WouldAddOverflowOrUnderflow(int32_t left, int32_t right) {
47     if (right == 0) {
48       return false;
49     }
50     if ((right > 0) && (left <= INT_MAX - right)) {
51       // No overflow.
52       return false;
53     }
54     if ((right < 0) && (left >= INT_MIN - right)) {
55       // No underflow.
56       return false;
57     }
58     return true;
59   }
60 
IsAddOrSubAConstant(HInstruction * instruction,HInstruction ** left_instruction,int * right_constant)61   static bool IsAddOrSubAConstant(HInstruction* instruction,
62                                   HInstruction** left_instruction,
63                                   int* right_constant) {
64     if (instruction->IsAdd() || instruction->IsSub()) {
65       HBinaryOperation* bin_op = instruction->AsBinaryOperation();
66       HInstruction* left = bin_op->GetLeft();
67       HInstruction* right = bin_op->GetRight();
68       if (right->IsIntConstant()) {
69         *left_instruction = left;
70         int32_t c = right->AsIntConstant()->GetValue();
71         *right_constant = instruction->IsAdd() ? c : -c;
72         return true;
73       }
74     }
75     *left_instruction = nullptr;
76     *right_constant = 0;
77     return false;
78   }
79 
80   // Try to detect useful value bound format from an instruction, e.g.
81   // a constant or array length related value.
DetectValueBoundFromValue(HInstruction * instruction,bool * found)82   static ValueBound DetectValueBoundFromValue(HInstruction* instruction, bool* found) {
83     DCHECK(instruction != nullptr);
84     if (instruction->IsIntConstant()) {
85       *found = true;
86       return ValueBound(nullptr, instruction->AsIntConstant()->GetValue());
87     }
88 
89     if (instruction->IsArrayLength()) {
90       *found = true;
91       return ValueBound(instruction, 0);
92     }
93     // Try to detect (array.length + c) format.
94     HInstruction *left;
95     int32_t right;
96     if (IsAddOrSubAConstant(instruction, &left, &right)) {
97       if (left->IsArrayLength()) {
98         *found = true;
99         return ValueBound(left, right);
100       }
101     }
102 
103     // No useful bound detected.
104     *found = false;
105     return ValueBound::Max();
106   }
107 
GetInstruction() const108   HInstruction* GetInstruction() const { return instruction_; }
GetConstant() const109   int32_t GetConstant() const { return constant_; }
110 
IsRelatedToArrayLength() const111   bool IsRelatedToArrayLength() const {
112     // Some bounds are created with HNewArray* as the instruction instead
113     // of HArrayLength*. They are treated the same.
114     return (instruction_ != nullptr) &&
115            (instruction_->IsArrayLength() || instruction_->IsNewArray());
116   }
117 
IsConstant() const118   bool IsConstant() const {
119     return instruction_ == nullptr;
120   }
121 
Min()122   static ValueBound Min() { return ValueBound(nullptr, INT_MIN); }
Max()123   static ValueBound Max() { return ValueBound(nullptr, INT_MAX); }
124 
Equals(ValueBound bound) const125   bool Equals(ValueBound bound) const {
126     return instruction_ == bound.instruction_ && constant_ == bound.constant_;
127   }
128 
FromArrayLengthToArray(HInstruction * instruction)129   static HInstruction* FromArrayLengthToArray(HInstruction* instruction) {
130     DCHECK(instruction->IsArrayLength() || instruction->IsNewArray());
131     if (instruction->IsArrayLength()) {
132       HInstruction* input = instruction->InputAt(0);
133       if (input->IsNullCheck()) {
134         input = input->AsNullCheck()->InputAt(0);
135       }
136       return input;
137     }
138     return instruction;
139   }
140 
Equal(HInstruction * instruction1,HInstruction * instruction2)141   static bool Equal(HInstruction* instruction1, HInstruction* instruction2) {
142     if (instruction1 == instruction2) {
143       return true;
144     }
145 
146     if (instruction1 == nullptr || instruction2 == nullptr) {
147       return false;
148     }
149 
150     // Some bounds are created with HNewArray* as the instruction instead
151     // of HArrayLength*. They are treated the same.
152     // HArrayLength with the same array input are considered equal also.
153     instruction1 = FromArrayLengthToArray(instruction1);
154     instruction2 = FromArrayLengthToArray(instruction2);
155     return instruction1 == instruction2;
156   }
157 
158   // Returns if it's certain this->bound >= `bound`.
GreaterThanOrEqualTo(ValueBound bound) const159   bool GreaterThanOrEqualTo(ValueBound bound) const {
160     if (Equal(instruction_, bound.instruction_)) {
161       return constant_ >= bound.constant_;
162     }
163     // Not comparable. Just return false.
164     return false;
165   }
166 
167   // Returns if it's certain this->bound <= `bound`.
LessThanOrEqualTo(ValueBound bound) const168   bool LessThanOrEqualTo(ValueBound bound) const {
169     if (Equal(instruction_, bound.instruction_)) {
170       return constant_ <= bound.constant_;
171     }
172     // Not comparable. Just return false.
173     return false;
174   }
175 
176   // Try to narrow lower bound. Returns the greatest of the two if possible.
177   // Pick one if they are not comparable.
NarrowLowerBound(ValueBound bound1,ValueBound bound2)178   static ValueBound NarrowLowerBound(ValueBound bound1, ValueBound bound2) {
179     if (bound1.GreaterThanOrEqualTo(bound2)) {
180       return bound1;
181     }
182     if (bound2.GreaterThanOrEqualTo(bound1)) {
183       return bound2;
184     }
185 
186     // Not comparable. Just pick one. We may lose some info, but that's ok.
187     // Favor constant as lower bound.
188     return bound1.IsConstant() ? bound1 : bound2;
189   }
190 
191   // Try to narrow upper bound. Returns the lowest of the two if possible.
192   // Pick one if they are not comparable.
NarrowUpperBound(ValueBound bound1,ValueBound bound2)193   static ValueBound NarrowUpperBound(ValueBound bound1, ValueBound bound2) {
194     if (bound1.LessThanOrEqualTo(bound2)) {
195       return bound1;
196     }
197     if (bound2.LessThanOrEqualTo(bound1)) {
198       return bound2;
199     }
200 
201     // Not comparable. Just pick one. We may lose some info, but that's ok.
202     // Favor array length as upper bound.
203     return bound1.IsRelatedToArrayLength() ? bound1 : bound2;
204   }
205 
206   // Add a constant to a ValueBound.
207   // `overflow` or `underflow` will return whether the resulting bound may
208   // overflow or underflow an int.
Add(int32_t c,bool * overflow,bool * underflow) const209   ValueBound Add(int32_t c, bool* overflow, bool* underflow) const {
210     *overflow = *underflow = false;
211     if (c == 0) {
212       return *this;
213     }
214 
215     int32_t new_constant;
216     if (c > 0) {
217       if (constant_ > INT_MAX - c) {
218         *overflow = true;
219         return Max();
220       }
221 
222       new_constant = constant_ + c;
223       // (array.length + non-positive-constant) won't overflow an int.
224       if (IsConstant() || (IsRelatedToArrayLength() && new_constant <= 0)) {
225         return ValueBound(instruction_, new_constant);
226       }
227       // Be conservative.
228       *overflow = true;
229       return Max();
230     } else {
231       if (constant_ < INT_MIN - c) {
232         *underflow = true;
233         return Min();
234       }
235 
236       new_constant = constant_ + c;
237       // Regardless of the value new_constant, (array.length+new_constant) will
238       // never underflow since array.length is no less than 0.
239       if (IsConstant() || IsRelatedToArrayLength()) {
240         return ValueBound(instruction_, new_constant);
241       }
242       // Be conservative.
243       *underflow = true;
244       return Min();
245     }
246   }
247 
248  private:
249   HInstruction* instruction_;
250   int32_t constant_;
251 };
252 
253 // Collect array access data for a loop.
254 // TODO: make it work for multiple arrays inside the loop.
255 class ArrayAccessInsideLoopFinder : public ValueObject {
256  public:
ArrayAccessInsideLoopFinder(HInstruction * induction_variable)257   explicit ArrayAccessInsideLoopFinder(HInstruction* induction_variable)
258       : induction_variable_(induction_variable),
259         found_array_length_(nullptr),
260         offset_low_(INT_MAX),
261         offset_high_(INT_MIN) {
262     Run();
263   }
264 
GetFoundArrayLength() const265   HArrayLength* GetFoundArrayLength() const { return found_array_length_; }
HasFoundArrayLength() const266   bool HasFoundArrayLength() const { return found_array_length_ != nullptr; }
GetOffsetLow() const267   int32_t GetOffsetLow() const { return offset_low_; }
GetOffsetHigh() const268   int32_t GetOffsetHigh() const { return offset_high_; }
269 
270   // Returns if `block` that is in loop_info may exit the loop, unless it's
271   // the loop header for loop_info.
EarlyExit(HBasicBlock * block,HLoopInformation * loop_info)272   static bool EarlyExit(HBasicBlock* block, HLoopInformation* loop_info) {
273     DCHECK(loop_info->Contains(*block));
274     if (block == loop_info->GetHeader()) {
275       // Loop header of loop_info. Exiting loop is normal.
276       return false;
277     }
278     const GrowableArray<HBasicBlock*>& successors = block->GetSuccessors();
279     for (size_t i = 0; i < successors.Size(); i++) {
280       if (!loop_info->Contains(*successors.Get(i))) {
281         // One of the successors exits the loop.
282         return true;
283       }
284     }
285     return false;
286   }
287 
DominatesAllBackEdges(HBasicBlock * block,HLoopInformation * loop_info)288   static bool DominatesAllBackEdges(HBasicBlock* block, HLoopInformation* loop_info) {
289     for (size_t i = 0, e = loop_info->GetBackEdges().Size(); i < e; ++i) {
290       HBasicBlock* back_edge = loop_info->GetBackEdges().Get(i);
291       if (!block->Dominates(back_edge)) {
292         return false;
293       }
294     }
295     return true;
296   }
297 
Run()298   void Run() {
299     HLoopInformation* loop_info = induction_variable_->GetBlock()->GetLoopInformation();
300     HBlocksInLoopReversePostOrderIterator it_loop(*loop_info);
301     HBasicBlock* block = it_loop.Current();
302     DCHECK(block == induction_variable_->GetBlock());
303     // Skip loop header. Since narrowed value range of a MonotonicValueRange only
304     // applies to the loop body (after the test at the end of the loop header).
305     it_loop.Advance();
306     for (; !it_loop.Done(); it_loop.Advance()) {
307       block = it_loop.Current();
308       DCHECK(block->IsInLoop());
309       if (!DominatesAllBackEdges(block, loop_info)) {
310         // In order not to trigger deoptimization unnecessarily, make sure
311         // that all array accesses collected are really executed in the loop.
312         // For array accesses in a branch inside the loop, don't collect the
313         // access. The bounds check in that branch might not be eliminated.
314         continue;
315       }
316       if (EarlyExit(block, loop_info)) {
317         // If the loop body can exit loop (like break, return, etc.), it's not guaranteed
318         // that the loop will loop through the full monotonic value range from
319         // initial_ to end_. So adding deoptimization might be too aggressive and can
320         // trigger deoptimization unnecessarily even if the loop won't actually throw
321         // AIOOBE.
322         found_array_length_ = nullptr;
323         return;
324       }
325       for (HInstruction* instruction = block->GetFirstInstruction();
326            instruction != nullptr;
327            instruction = instruction->GetNext()) {
328         if (!instruction->IsBoundsCheck()) {
329           continue;
330         }
331 
332         HInstruction* length_value = instruction->InputAt(1);
333         if (length_value->IsIntConstant()) {
334           // TODO: may optimize for constant case.
335           continue;
336         }
337 
338         if (length_value->IsPhi()) {
339           // When adding deoptimizations in outer loops, we might create
340           // a phi for the array length, and update all uses of the
341           // length in the loop to that phi. Therefore, inner loops having
342           // bounds checks on the same array will use that phi.
343           // TODO: handle these cases.
344           continue;
345         }
346 
347         DCHECK(length_value->IsArrayLength());
348         HArrayLength* array_length = length_value->AsArrayLength();
349 
350         HInstruction* array = array_length->InputAt(0);
351         if (array->IsNullCheck()) {
352           array = array->AsNullCheck()->InputAt(0);
353         }
354         if (loop_info->Contains(*array->GetBlock())) {
355           // Array is defined inside the loop. Skip.
356           continue;
357         }
358 
359         if (found_array_length_ != nullptr && found_array_length_ != array_length) {
360           // There is already access for another array recorded for the loop.
361           // TODO: handle multiple arrays.
362           continue;
363         }
364 
365         HInstruction* index = instruction->AsBoundsCheck()->InputAt(0);
366         HInstruction* left = index;
367         int32_t right = 0;
368         if (left == induction_variable_ ||
369             (ValueBound::IsAddOrSubAConstant(index, &left, &right) &&
370              left == induction_variable_)) {
371           // For patterns like array[i] or array[i + 2].
372           if (right < offset_low_) {
373             offset_low_ = right;
374           }
375           if (right > offset_high_) {
376             offset_high_ = right;
377           }
378         } else {
379           // Access not in induction_variable/(induction_variable_ + constant)
380           // format. Skip.
381           continue;
382         }
383         // Record this array.
384         found_array_length_ = array_length;
385       }
386     }
387   }
388 
389  private:
390   // The instruction that corresponds to a MonotonicValueRange.
391   HInstruction* induction_variable_;
392 
393   // The array length of the array that's accessed inside the loop body.
394   HArrayLength* found_array_length_;
395 
396   // The lowest and highest constant offsets relative to induction variable
397   // instruction_ in all array accesses.
398   // If array access are: array[i-1], array[i], array[i+1],
399   // offset_low_ is -1 and offset_high is 1.
400   int32_t offset_low_;
401   int32_t offset_high_;
402 
403   DISALLOW_COPY_AND_ASSIGN(ArrayAccessInsideLoopFinder);
404 };
405 
406 /**
407  * Represent a range of lower bound and upper bound, both being inclusive.
408  * Currently a ValueRange may be generated as a result of the following:
409  * comparisons related to array bounds, array bounds check, add/sub on top
410  * of an existing value range, NewArray or a loop phi corresponding to an
411  * incrementing/decrementing array index (MonotonicValueRange).
412  */
413 class ValueRange : public ArenaObject<kArenaAllocMisc> {
414  public:
ValueRange(ArenaAllocator * allocator,ValueBound lower,ValueBound upper)415   ValueRange(ArenaAllocator* allocator, ValueBound lower, ValueBound upper)
416       : allocator_(allocator), lower_(lower), upper_(upper) {}
417 
~ValueRange()418   virtual ~ValueRange() {}
419 
AsMonotonicValueRange()420   virtual MonotonicValueRange* AsMonotonicValueRange() { return nullptr; }
IsMonotonicValueRange()421   bool IsMonotonicValueRange() {
422     return AsMonotonicValueRange() != nullptr;
423   }
424 
GetAllocator() const425   ArenaAllocator* GetAllocator() const { return allocator_; }
GetLower() const426   ValueBound GetLower() const { return lower_; }
GetUpper() const427   ValueBound GetUpper() const { return upper_; }
428 
IsConstantValueRange()429   bool IsConstantValueRange() { return lower_.IsConstant() && upper_.IsConstant(); }
430 
431   // If it's certain that this value range fits in other_range.
FitsIn(ValueRange * other_range) const432   virtual bool FitsIn(ValueRange* other_range) const {
433     if (other_range == nullptr) {
434       return true;
435     }
436     DCHECK(!other_range->IsMonotonicValueRange());
437     return lower_.GreaterThanOrEqualTo(other_range->lower_) &&
438            upper_.LessThanOrEqualTo(other_range->upper_);
439   }
440 
441   // Returns the intersection of this and range.
442   // If it's not possible to do intersection because some
443   // bounds are not comparable, it's ok to pick either bound.
Narrow(ValueRange * range)444   virtual ValueRange* Narrow(ValueRange* range) {
445     if (range == nullptr) {
446       return this;
447     }
448 
449     if (range->IsMonotonicValueRange()) {
450       return this;
451     }
452 
453     return new (allocator_) ValueRange(
454         allocator_,
455         ValueBound::NarrowLowerBound(lower_, range->lower_),
456         ValueBound::NarrowUpperBound(upper_, range->upper_));
457   }
458 
459   // Shift a range by a constant.
Add(int32_t constant) const460   ValueRange* Add(int32_t constant) const {
461     bool overflow, underflow;
462     ValueBound lower = lower_.Add(constant, &overflow, &underflow);
463     if (underflow) {
464       // Lower bound underflow will wrap around to positive values
465       // and invalidate the upper bound.
466       return nullptr;
467     }
468     ValueBound upper = upper_.Add(constant, &overflow, &underflow);
469     if (overflow) {
470       // Upper bound overflow will wrap around to negative values
471       // and invalidate the lower bound.
472       return nullptr;
473     }
474     return new (allocator_) ValueRange(allocator_, lower, upper);
475   }
476 
477  private:
478   ArenaAllocator* const allocator_;
479   const ValueBound lower_;  // inclusive
480   const ValueBound upper_;  // inclusive
481 
482   DISALLOW_COPY_AND_ASSIGN(ValueRange);
483 };
484 
485 /**
486  * A monotonically incrementing/decrementing value range, e.g.
487  * the variable i in "for (int i=0; i<array.length; i++)".
488  * Special care needs to be taken to account for overflow/underflow
489  * of such value ranges.
490  */
491 class MonotonicValueRange : public ValueRange {
492  public:
MonotonicValueRange(ArenaAllocator * allocator,HPhi * induction_variable,HInstruction * initial,int32_t increment,ValueBound bound)493   MonotonicValueRange(ArenaAllocator* allocator,
494                       HPhi* induction_variable,
495                       HInstruction* initial,
496                       int32_t increment,
497                       ValueBound bound)
498       // To be conservative, give it full range [INT_MIN, INT_MAX] in case it's
499       // used as a regular value range, due to possible overflow/underflow.
500       : ValueRange(allocator, ValueBound::Min(), ValueBound::Max()),
501         induction_variable_(induction_variable),
502         initial_(initial),
503         end_(nullptr),
504         inclusive_(false),
505         increment_(increment),
506         bound_(bound) {}
507 
~MonotonicValueRange()508   virtual ~MonotonicValueRange() {}
509 
GetInductionVariable() const510   HInstruction* GetInductionVariable() const { return induction_variable_; }
GetIncrement() const511   int32_t GetIncrement() const { return increment_; }
GetBound() const512   ValueBound GetBound() const { return bound_; }
SetEnd(HInstruction * end)513   void SetEnd(HInstruction* end) { end_ = end; }
SetInclusive(bool inclusive)514   void SetInclusive(bool inclusive) { inclusive_ = inclusive; }
GetLoopHeader() const515   HBasicBlock* GetLoopHeader() const {
516     DCHECK(induction_variable_->GetBlock()->IsLoopHeader());
517     return induction_variable_->GetBlock();
518   }
519 
AsMonotonicValueRange()520   MonotonicValueRange* AsMonotonicValueRange() OVERRIDE { return this; }
521 
GetLoopHeaderSuccesorInLoop()522   HBasicBlock* GetLoopHeaderSuccesorInLoop() {
523     HBasicBlock* header = GetLoopHeader();
524     HInstruction* instruction = header->GetLastInstruction();
525     DCHECK(instruction->IsIf());
526     HIf* h_if = instruction->AsIf();
527     HLoopInformation* loop_info = header->GetLoopInformation();
528     bool true_successor_in_loop = loop_info->Contains(*h_if->IfTrueSuccessor());
529     bool false_successor_in_loop = loop_info->Contains(*h_if->IfFalseSuccessor());
530 
531     // Just in case it's some strange loop structure.
532     if (true_successor_in_loop && false_successor_in_loop) {
533       return nullptr;
534     }
535     DCHECK(true_successor_in_loop || false_successor_in_loop);
536     return false_successor_in_loop ? h_if->IfFalseSuccessor() : h_if->IfTrueSuccessor();
537   }
538 
539   // If it's certain that this value range fits in other_range.
FitsIn(ValueRange * other_range) const540   bool FitsIn(ValueRange* other_range) const OVERRIDE {
541     if (other_range == nullptr) {
542       return true;
543     }
544     DCHECK(!other_range->IsMonotonicValueRange());
545     return false;
546   }
547 
548   // Try to narrow this MonotonicValueRange given another range.
549   // Ideally it will return a normal ValueRange. But due to
550   // possible overflow/underflow, that may not be possible.
Narrow(ValueRange * range)551   ValueRange* Narrow(ValueRange* range) OVERRIDE {
552     if (range == nullptr) {
553       return this;
554     }
555     DCHECK(!range->IsMonotonicValueRange());
556 
557     if (increment_ > 0) {
558       // Monotonically increasing.
559       ValueBound lower = ValueBound::NarrowLowerBound(bound_, range->GetLower());
560       if (!lower.IsConstant() || lower.GetConstant() == INT_MIN) {
561         // Lower bound isn't useful. Leave it to deoptimization.
562         return this;
563       }
564 
565       // We currently conservatively assume max array length is INT_MAX. If we can
566       // make assumptions about the max array length, e.g. due to the max heap size,
567       // divided by the element size (such as 4 bytes for each integer array), we can
568       // lower this number and rule out some possible overflows.
569       int32_t max_array_len = INT_MAX;
570 
571       // max possible integer value of range's upper value.
572       int32_t upper = INT_MAX;
573       // Try to lower upper.
574       ValueBound upper_bound = range->GetUpper();
575       if (upper_bound.IsConstant()) {
576         upper = upper_bound.GetConstant();
577       } else if (upper_bound.IsRelatedToArrayLength() && upper_bound.GetConstant() <= 0) {
578         // Normal case. e.g. <= array.length - 1.
579         upper = max_array_len + upper_bound.GetConstant();
580       }
581 
582       // If we can prove for the last number in sequence of initial_,
583       // initial_ + increment_, initial_ + 2 x increment_, ...
584       // that's <= upper, (last_num_in_sequence + increment_) doesn't trigger overflow,
585       // then this MonoticValueRange is narrowed to a normal value range.
586 
587       // Be conservative first, assume last number in the sequence hits upper.
588       int32_t last_num_in_sequence = upper;
589       if (initial_->IsIntConstant()) {
590         int32_t initial_constant = initial_->AsIntConstant()->GetValue();
591         if (upper <= initial_constant) {
592           last_num_in_sequence = upper;
593         } else {
594           // Cast to int64_t for the substraction part to avoid int32_t overflow.
595           last_num_in_sequence = initial_constant +
596               ((int64_t)upper - (int64_t)initial_constant) / increment_ * increment_;
597         }
598       }
599       if (last_num_in_sequence <= INT_MAX - increment_) {
600         // No overflow. The sequence will be stopped by the upper bound test as expected.
601         return new (GetAllocator()) ValueRange(GetAllocator(), lower, range->GetUpper());
602       }
603 
604       // There might be overflow. Give up narrowing.
605       return this;
606     } else {
607       DCHECK_NE(increment_, 0);
608       // Monotonically decreasing.
609       ValueBound upper = ValueBound::NarrowUpperBound(bound_, range->GetUpper());
610       if ((!upper.IsConstant() || upper.GetConstant() == INT_MAX) &&
611           !upper.IsRelatedToArrayLength()) {
612         // Upper bound isn't useful. Leave it to deoptimization.
613         return this;
614       }
615 
616       // Need to take care of underflow. Try to prove underflow won't happen
617       // for common cases.
618       if (range->GetLower().IsConstant()) {
619         int32_t constant = range->GetLower().GetConstant();
620         if (constant >= INT_MIN - increment_) {
621           return new (GetAllocator()) ValueRange(GetAllocator(), range->GetLower(), upper);
622         }
623       }
624 
625       // For non-constant lower bound, just assume might be underflow. Give up narrowing.
626       return this;
627     }
628   }
629 
630   // Try to add HDeoptimize's in the loop pre-header first to narrow this range.
631   // For example, this loop:
632   //
633   //   for (int i = start; i < end; i++) {
634   //     array[i - 1] = array[i] + array[i + 1];
635   //   }
636   //
637   // will be transformed to:
638   //
639   //   int array_length_in_loop_body_if_needed;
640   //   if (start >= end) {
641   //     array_length_in_loop_body_if_needed = 0;
642   //   } else {
643   //     if (start < 1) deoptimize();
644   //     if (array == null) deoptimize();
645   //     array_length = array.length;
646   //     if (end > array_length - 1) deoptimize;
647   //     array_length_in_loop_body_if_needed = array_length;
648   //   }
649   //   for (int i = start; i < end; i++) {
650   //     // No more null check and bounds check.
651   //     // array.length value is replaced with array_length_in_loop_body_if_needed
652   //     // in the loop body.
653   //     array[i - 1] = array[i] + array[i + 1];
654   //   }
655   //
656   // We basically first go through the loop body and find those array accesses whose
657   // index is at a constant offset from the induction variable ('i' in the above example),
658   // and update offset_low and offset_high along the way. We then add the following
659   // deoptimizations in the loop pre-header (suppose end is not inclusive).
660   //   if (start < -offset_low) deoptimize();
661   //   if (end >= array.length - offset_high) deoptimize();
662   // It might be necessary to first hoist array.length (and the null check on it) out of
663   // the loop with another deoptimization.
664   //
665   // In order not to trigger deoptimization unnecessarily, we want to make a strong
666   // guarantee that no deoptimization is triggered if the loop body itself doesn't
667   // throw AIOOBE. (It's the same as saying if deoptimization is triggered, the loop
668   // body must throw AIOOBE).
669   // This is achieved by the following:
670   // 1) We only process loops that iterate through the full monotonic range from
671   //    initial_ to end_. We do the following checks to make sure that's the case:
672   //    a) The loop doesn't have early exit (via break, return, etc.)
673   //    b) The increment_ is 1/-1. An increment of 2, for example, may skip end_.
674   // 2) We only collect array accesses of blocks in the loop body that dominate
675   //    all loop back edges, these array accesses are guaranteed to happen
676   //    at each loop iteration.
677   // With 1) and 2), if the loop body doesn't throw AIOOBE, collected array accesses
678   // when the induction variable is at initial_ and end_ must be in a legal range.
679   // Since the added deoptimizations are basically checking the induction variable
680   // at initial_ and end_ values, no deoptimization will be triggered either.
681   //
682   // A special case is the loop body isn't entered at all. In that case, we may still
683   // add deoptimization due to the analysis described above. In order not to trigger
684   // deoptimization, we do a test between initial_ and end_ first and skip over
685   // the added deoptimization.
NarrowWithDeoptimization()686   ValueRange* NarrowWithDeoptimization() {
687     if (increment_ != 1 && increment_ != -1) {
688       // In order not to trigger deoptimization unnecessarily, we want to
689       // make sure the loop iterates through the full range from initial_ to
690       // end_ so that boundaries are covered by the loop. An increment of 2,
691       // for example, may skip end_.
692       return this;
693     }
694 
695     if (end_ == nullptr) {
696       // No full info to add deoptimization.
697       return this;
698     }
699 
700     HBasicBlock* header = induction_variable_->GetBlock();
701     DCHECK(header->IsLoopHeader());
702     HBasicBlock* pre_header = header->GetLoopInformation()->GetPreHeader();
703     if (!initial_->GetBlock()->Dominates(pre_header) ||
704         !end_->GetBlock()->Dominates(pre_header)) {
705       // Can't add a check in loop pre-header if the value isn't available there.
706       return this;
707     }
708 
709     ArrayAccessInsideLoopFinder finder(induction_variable_);
710 
711     if (!finder.HasFoundArrayLength()) {
712       // No array access was found inside the loop that can benefit
713       // from deoptimization.
714       return this;
715     }
716 
717     if (!AddDeoptimization(finder)) {
718       return this;
719     }
720 
721     // After added deoptimizations, induction variable fits in
722     // [-offset_low, array.length-1-offset_high], adjusted with collected offsets.
723     ValueBound lower = ValueBound(0, -finder.GetOffsetLow());
724     ValueBound upper = ValueBound(finder.GetFoundArrayLength(), -1 - finder.GetOffsetHigh());
725     // We've narrowed the range after added deoptimizations.
726     return new (GetAllocator()) ValueRange(GetAllocator(), lower, upper);
727   }
728 
729   // Returns true if adding a (constant >= value) check for deoptimization
730   // is allowed and will benefit compiled code.
CanAddDeoptimizationConstant(HInstruction * value,int32_t constant,bool * is_proven)731   bool CanAddDeoptimizationConstant(HInstruction* value, int32_t constant, bool* is_proven) {
732     *is_proven = false;
733     HBasicBlock* header = induction_variable_->GetBlock();
734     DCHECK(header->IsLoopHeader());
735     HBasicBlock* pre_header = header->GetLoopInformation()->GetPreHeader();
736     DCHECK(value->GetBlock()->Dominates(pre_header));
737 
738     // See if we can prove the relationship first.
739     if (value->IsIntConstant()) {
740       if (value->AsIntConstant()->GetValue() >= constant) {
741         // Already true.
742         *is_proven = true;
743         return true;
744       } else {
745         // May throw exception. Don't add deoptimization.
746         // Keep bounds checks in the loops.
747         return false;
748       }
749     }
750     // Can benefit from deoptimization.
751     return true;
752   }
753 
754   // Try to filter out cases that the loop entry test will never be true.
LoopEntryTestUseful()755   bool LoopEntryTestUseful() {
756     if (initial_->IsIntConstant() && end_->IsIntConstant()) {
757       int32_t initial_val = initial_->AsIntConstant()->GetValue();
758       int32_t end_val = end_->AsIntConstant()->GetValue();
759       if (increment_ == 1) {
760         if (inclusive_) {
761           return initial_val > end_val;
762         } else {
763           return initial_val >= end_val;
764         }
765       } else {
766         DCHECK_EQ(increment_, -1);
767         if (inclusive_) {
768           return initial_val < end_val;
769         } else {
770           return initial_val <= end_val;
771         }
772       }
773     }
774     return true;
775   }
776 
777   // Returns the block for adding deoptimization.
TransformLoopForDeoptimizationIfNeeded()778   HBasicBlock* TransformLoopForDeoptimizationIfNeeded() {
779     HBasicBlock* header = induction_variable_->GetBlock();
780     DCHECK(header->IsLoopHeader());
781     HBasicBlock* pre_header = header->GetLoopInformation()->GetPreHeader();
782     // Deoptimization is only added when both initial_ and end_ are defined
783     // before the loop.
784     DCHECK(initial_->GetBlock()->Dominates(pre_header));
785     DCHECK(end_->GetBlock()->Dominates(pre_header));
786 
787     // If it can be proven the loop body is definitely entered (unless exception
788     // is thrown in the loop header for which triggering deoptimization is fine),
789     // there is no need for tranforming the loop. In that case, deoptimization
790     // will just be added in the loop pre-header.
791     if (!LoopEntryTestUseful()) {
792       return pre_header;
793     }
794 
795     HGraph* graph = header->GetGraph();
796     graph->TransformLoopHeaderForBCE(header);
797     HBasicBlock* new_pre_header = header->GetDominator();
798     DCHECK(new_pre_header == header->GetLoopInformation()->GetPreHeader());
799     HBasicBlock* if_block = new_pre_header->GetDominator();
800     HBasicBlock* dummy_block = if_block->GetSuccessors().Get(0);  // True successor.
801     HBasicBlock* deopt_block = if_block->GetSuccessors().Get(1);  // False successor.
802 
803     dummy_block->AddInstruction(new (graph->GetArena()) HGoto());
804     deopt_block->AddInstruction(new (graph->GetArena()) HGoto());
805     new_pre_header->AddInstruction(new (graph->GetArena()) HGoto());
806     return deopt_block;
807   }
808 
809   // Adds a test between initial_ and end_ to see if the loop body is entered.
810   // If the loop body isn't entered at all, it jumps to the loop pre-header (after
811   // transformation) to avoid any deoptimization.
AddLoopBodyEntryTest()812   void AddLoopBodyEntryTest() {
813     HBasicBlock* header = induction_variable_->GetBlock();
814     DCHECK(header->IsLoopHeader());
815     HBasicBlock* pre_header = header->GetLoopInformation()->GetPreHeader();
816     HBasicBlock* if_block = pre_header->GetDominator();
817     HGraph* graph = header->GetGraph();
818 
819     HCondition* cond;
820     if (increment_ == 1) {
821       if (inclusive_) {
822         cond = new (graph->GetArena()) HGreaterThan(initial_, end_);
823       } else {
824         cond = new (graph->GetArena()) HGreaterThanOrEqual(initial_, end_);
825       }
826     } else {
827       DCHECK_EQ(increment_, -1);
828       if (inclusive_) {
829         cond = new (graph->GetArena()) HLessThan(initial_, end_);
830       } else {
831         cond = new (graph->GetArena()) HLessThanOrEqual(initial_, end_);
832       }
833     }
834     HIf* h_if = new (graph->GetArena()) HIf(cond);
835     if_block->AddInstruction(cond);
836     if_block->AddInstruction(h_if);
837   }
838 
839   // Adds a check that (value >= constant), and HDeoptimize otherwise.
AddDeoptimizationConstant(HInstruction * value,int32_t constant,HBasicBlock * deopt_block,bool loop_entry_test_block_added)840   void AddDeoptimizationConstant(HInstruction* value,
841                                  int32_t constant,
842                                  HBasicBlock* deopt_block,
843                                  bool loop_entry_test_block_added) {
844     HBasicBlock* header = induction_variable_->GetBlock();
845     DCHECK(header->IsLoopHeader());
846     HBasicBlock* pre_header = header->GetDominator();
847     if (loop_entry_test_block_added) {
848       DCHECK(deopt_block->GetSuccessors().Get(0) == pre_header);
849     } else {
850       DCHECK(deopt_block == pre_header);
851     }
852     HGraph* graph = header->GetGraph();
853     HSuspendCheck* suspend_check = header->GetLoopInformation()->GetSuspendCheck();
854     if (loop_entry_test_block_added) {
855       DCHECK_EQ(deopt_block, header->GetDominator()->GetDominator()->GetSuccessors().Get(1));
856     }
857 
858     HIntConstant* const_instr = graph->GetIntConstant(constant);
859     HCondition* cond = new (graph->GetArena()) HLessThan(value, const_instr);
860     HDeoptimize* deoptimize = new (graph->GetArena())
861         HDeoptimize(cond, suspend_check->GetDexPc());
862     deopt_block->InsertInstructionBefore(cond, deopt_block->GetLastInstruction());
863     deopt_block->InsertInstructionBefore(deoptimize, deopt_block->GetLastInstruction());
864     deoptimize->CopyEnvironmentFromWithLoopPhiAdjustment(
865         suspend_check->GetEnvironment(), header);
866   }
867 
868   // Returns true if adding a (value <= array_length + offset) check for deoptimization
869   // is allowed and will benefit compiled code.
CanAddDeoptimizationArrayLength(HInstruction * value,HArrayLength * array_length,int32_t offset,bool * is_proven)870   bool CanAddDeoptimizationArrayLength(HInstruction* value,
871                                        HArrayLength* array_length,
872                                        int32_t offset,
873                                        bool* is_proven) {
874     *is_proven = false;
875     HBasicBlock* header = induction_variable_->GetBlock();
876     DCHECK(header->IsLoopHeader());
877     HBasicBlock* pre_header = header->GetLoopInformation()->GetPreHeader();
878     DCHECK(value->GetBlock()->Dominates(pre_header));
879 
880     if (array_length->GetBlock() == header) {
881       // array_length_in_loop_body_if_needed only has correct value when the loop
882       // body is entered. We bail out in this case. Usually array_length defined
883       // in the loop header is already hoisted by licm.
884       return false;
885     } else {
886       // array_length is defined either before the loop header already, or in
887       // the loop body since it's used in the loop body. If it's defined in the loop body,
888       // a phi array_length_in_loop_body_if_needed is used to replace it. In that case,
889       // all the uses of array_length must be dominated by its definition in the loop
890       // body. array_length_in_loop_body_if_needed is guaranteed to be the same as
891       // array_length once the loop body is entered so all the uses of the phi will
892       // use the correct value.
893     }
894 
895     if (offset > 0) {
896       // There might be overflow issue.
897       // TODO: handle this, possibly with some distance relationship between
898       // offset_low and offset_high, or using another deoptimization to make
899       // sure (array_length + offset) doesn't overflow.
900       return false;
901     }
902 
903     // See if we can prove the relationship first.
904     if (value == array_length) {
905       if (offset >= 0) {
906         // Already true.
907         *is_proven = true;
908         return true;
909       } else {
910         // May throw exception. Don't add deoptimization.
911         // Keep bounds checks in the loops.
912         return false;
913       }
914     }
915     // Can benefit from deoptimization.
916     return true;
917   }
918 
919   // Adds a check that (value <= array_length + offset), and HDeoptimize otherwise.
AddDeoptimizationArrayLength(HInstruction * value,HArrayLength * array_length,int32_t offset,HBasicBlock * deopt_block,bool loop_entry_test_block_added)920   void AddDeoptimizationArrayLength(HInstruction* value,
921                                     HArrayLength* array_length,
922                                     int32_t offset,
923                                     HBasicBlock* deopt_block,
924                                     bool loop_entry_test_block_added) {
925     HBasicBlock* header = induction_variable_->GetBlock();
926     DCHECK(header->IsLoopHeader());
927     HBasicBlock* pre_header = header->GetDominator();
928     if (loop_entry_test_block_added) {
929       DCHECK(deopt_block->GetSuccessors().Get(0) == pre_header);
930     } else {
931       DCHECK(deopt_block == pre_header);
932     }
933     HGraph* graph = header->GetGraph();
934     HSuspendCheck* suspend_check = header->GetLoopInformation()->GetSuspendCheck();
935 
936     // We may need to hoist null-check and array_length out of loop first.
937     if (!array_length->GetBlock()->Dominates(deopt_block)) {
938       // array_length must be defined in the loop body.
939       DCHECK(header->GetLoopInformation()->Contains(*array_length->GetBlock()));
940       DCHECK(array_length->GetBlock() != header);
941 
942       HInstruction* array = array_length->InputAt(0);
943       HNullCheck* null_check = array->AsNullCheck();
944       if (null_check != nullptr) {
945         array = null_check->InputAt(0);
946       }
947       // We've already made sure the array is defined before the loop when collecting
948       // array accesses for the loop.
949       DCHECK(array->GetBlock()->Dominates(deopt_block));
950       if (null_check != nullptr && !null_check->GetBlock()->Dominates(deopt_block)) {
951         // Hoist null check out of loop with a deoptimization.
952         HNullConstant* null_constant = graph->GetNullConstant();
953         HCondition* null_check_cond = new (graph->GetArena()) HEqual(array, null_constant);
954         // TODO: for one dex_pc, share the same deoptimization slow path.
955         HDeoptimize* null_check_deoptimize = new (graph->GetArena())
956             HDeoptimize(null_check_cond, suspend_check->GetDexPc());
957         deopt_block->InsertInstructionBefore(
958             null_check_cond, deopt_block->GetLastInstruction());
959         deopt_block->InsertInstructionBefore(
960             null_check_deoptimize, deopt_block->GetLastInstruction());
961         // Eliminate null check in the loop.
962         null_check->ReplaceWith(array);
963         null_check->GetBlock()->RemoveInstruction(null_check);
964         null_check_deoptimize->CopyEnvironmentFromWithLoopPhiAdjustment(
965             suspend_check->GetEnvironment(), header);
966       }
967 
968       HArrayLength* new_array_length = new (graph->GetArena()) HArrayLength(array);
969       deopt_block->InsertInstructionBefore(new_array_length, deopt_block->GetLastInstruction());
970 
971       if (loop_entry_test_block_added) {
972         // Replace array_length defined inside the loop body with a phi
973         // array_length_in_loop_body_if_needed. This is a synthetic phi so there is
974         // no vreg number for it.
975         HPhi* phi = new (graph->GetArena()) HPhi(
976             graph->GetArena(), kNoRegNumber, 2, Primitive::kPrimInt);
977         // Set to 0 if the loop body isn't entered.
978         phi->SetRawInputAt(0, graph->GetIntConstant(0));
979         // Set to array.length if the loop body is entered.
980         phi->SetRawInputAt(1, new_array_length);
981         pre_header->AddPhi(phi);
982         array_length->ReplaceWith(phi);
983         // Make sure phi is only used after the loop body is entered.
984         if (kIsDebugBuild) {
985           for (HUseIterator<HInstruction*> it(phi->GetUses());
986                !it.Done();
987                it.Advance()) {
988             HInstruction* user = it.Current()->GetUser();
989             DCHECK(GetLoopHeaderSuccesorInLoop()->Dominates(user->GetBlock()));
990           }
991         }
992       } else {
993         array_length->ReplaceWith(new_array_length);
994       }
995 
996       array_length->GetBlock()->RemoveInstruction(array_length);
997       // Use new_array_length for deopt.
998       array_length = new_array_length;
999     }
1000 
1001     HInstruction* added = array_length;
1002     if (offset != 0) {
1003       HIntConstant* offset_instr = graph->GetIntConstant(offset);
1004       added = new (graph->GetArena()) HAdd(Primitive::kPrimInt, array_length, offset_instr);
1005       deopt_block->InsertInstructionBefore(added, deopt_block->GetLastInstruction());
1006     }
1007     HCondition* cond = new (graph->GetArena()) HGreaterThan(value, added);
1008     HDeoptimize* deopt = new (graph->GetArena()) HDeoptimize(cond, suspend_check->GetDexPc());
1009     deopt_block->InsertInstructionBefore(cond, deopt_block->GetLastInstruction());
1010     deopt_block->InsertInstructionBefore(deopt, deopt_block->GetLastInstruction());
1011     deopt->CopyEnvironmentFromWithLoopPhiAdjustment(suspend_check->GetEnvironment(), header);
1012   }
1013 
1014   // Adds deoptimizations in loop pre-header with the collected array access
1015   // data so that value ranges can be established in loop body.
1016   // Returns true if deoptimizations are successfully added, or if it's proven
1017   // it's not necessary.
AddDeoptimization(const ArrayAccessInsideLoopFinder & finder)1018   bool AddDeoptimization(const ArrayAccessInsideLoopFinder& finder) {
1019     int32_t offset_low = finder.GetOffsetLow();
1020     int32_t offset_high = finder.GetOffsetHigh();
1021     HArrayLength* array_length = finder.GetFoundArrayLength();
1022 
1023     HBasicBlock* pre_header =
1024         induction_variable_->GetBlock()->GetLoopInformation()->GetPreHeader();
1025     if (!initial_->GetBlock()->Dominates(pre_header) ||
1026         !end_->GetBlock()->Dominates(pre_header)) {
1027       // Can't move initial_ or end_ into pre_header for comparisons.
1028       return false;
1029     }
1030 
1031     HBasicBlock* deopt_block;
1032     bool loop_entry_test_block_added = false;
1033     bool is_constant_proven, is_length_proven;
1034 
1035     HInstruction* const_comparing_instruction;
1036     int32_t const_compared_to;
1037     HInstruction* array_length_comparing_instruction;
1038     int32_t array_length_offset;
1039     if (increment_ == 1) {
1040       // Increasing from initial_ to end_.
1041       const_comparing_instruction = initial_;
1042       const_compared_to = -offset_low;
1043       array_length_comparing_instruction = end_;
1044       array_length_offset = inclusive_ ? -offset_high - 1 : -offset_high;
1045     } else {
1046       const_comparing_instruction = end_;
1047       const_compared_to = inclusive_ ? -offset_low : -offset_low - 1;
1048       array_length_comparing_instruction = initial_;
1049       array_length_offset = -offset_high - 1;
1050     }
1051 
1052     if (CanAddDeoptimizationConstant(const_comparing_instruction,
1053                                      const_compared_to,
1054                                      &is_constant_proven) &&
1055         CanAddDeoptimizationArrayLength(array_length_comparing_instruction,
1056                                         array_length,
1057                                         array_length_offset,
1058                                         &is_length_proven)) {
1059       if (!is_constant_proven || !is_length_proven) {
1060         deopt_block = TransformLoopForDeoptimizationIfNeeded();
1061         loop_entry_test_block_added = (deopt_block != pre_header);
1062         if (loop_entry_test_block_added) {
1063           // Loop body may be entered.
1064           AddLoopBodyEntryTest();
1065         }
1066       }
1067       if (!is_constant_proven) {
1068         AddDeoptimizationConstant(const_comparing_instruction,
1069                                   const_compared_to,
1070                                   deopt_block,
1071                                   loop_entry_test_block_added);
1072       }
1073       if (!is_length_proven) {
1074         AddDeoptimizationArrayLength(array_length_comparing_instruction,
1075                                      array_length,
1076                                      array_length_offset,
1077                                      deopt_block,
1078                                      loop_entry_test_block_added);
1079       }
1080       return true;
1081     }
1082     return false;
1083   }
1084 
1085  private:
1086   HPhi* const induction_variable_;  // Induction variable for this monotonic value range.
1087   HInstruction* const initial_;     // Initial value.
1088   HInstruction* end_;               // End value.
1089   bool inclusive_;                  // Whether end value is inclusive.
1090   const int32_t increment_;         // Increment for each loop iteration.
1091   const ValueBound bound_;          // Additional value bound info for initial_.
1092 
1093   DISALLOW_COPY_AND_ASSIGN(MonotonicValueRange);
1094 };
1095 
1096 class BCEVisitor : public HGraphVisitor {
1097  public:
1098   // The least number of bounds checks that should be eliminated by triggering
1099   // the deoptimization technique.
1100   static constexpr size_t kThresholdForAddingDeoptimize = 2;
1101 
1102   // Very large constant index is considered as an anomaly. This is a threshold
1103   // beyond which we don't bother to apply the deoptimization technique since
1104   // it's likely some AIOOBE will be thrown.
1105   static constexpr int32_t kMaxConstantForAddingDeoptimize = INT_MAX - 1024 * 1024;
1106 
1107   // Added blocks for loop body entry test.
IsAddedBlock(HBasicBlock * block) const1108   bool IsAddedBlock(HBasicBlock* block) const {
1109     return block->GetBlockId() >= initial_block_size_;
1110   }
1111 
BCEVisitor(HGraph * graph)1112   explicit BCEVisitor(HGraph* graph)
1113       : HGraphVisitor(graph), maps_(graph->GetBlocks().Size()),
1114         need_to_revisit_block_(false), initial_block_size_(graph->GetBlocks().Size()) {}
1115 
VisitBasicBlock(HBasicBlock * block)1116   void VisitBasicBlock(HBasicBlock* block) OVERRIDE {
1117     DCHECK(!IsAddedBlock(block));
1118     first_constant_index_bounds_check_map_.clear();
1119     HGraphVisitor::VisitBasicBlock(block);
1120     if (need_to_revisit_block_) {
1121       AddComparesWithDeoptimization(block);
1122       need_to_revisit_block_ = false;
1123       first_constant_index_bounds_check_map_.clear();
1124       GetValueRangeMap(block)->clear();
1125       HGraphVisitor::VisitBasicBlock(block);
1126     }
1127   }
1128 
1129  private:
1130   // Return the map of proven value ranges at the beginning of a basic block.
GetValueRangeMap(HBasicBlock * basic_block)1131   ArenaSafeMap<int, ValueRange*>* GetValueRangeMap(HBasicBlock* basic_block) {
1132     if (IsAddedBlock(basic_block)) {
1133       // Added blocks don't keep value ranges.
1134       return nullptr;
1135     }
1136     int block_id = basic_block->GetBlockId();
1137     if (maps_.at(block_id) == nullptr) {
1138       std::unique_ptr<ArenaSafeMap<int, ValueRange*>> map(
1139           new ArenaSafeMap<int, ValueRange*>(
1140               std::less<int>(), GetGraph()->GetArena()->Adapter()));
1141       maps_.at(block_id) = std::move(map);
1142     }
1143     return maps_.at(block_id).get();
1144   }
1145 
1146   // Traverse up the dominator tree to look for value range info.
LookupValueRange(HInstruction * instruction,HBasicBlock * basic_block)1147   ValueRange* LookupValueRange(HInstruction* instruction, HBasicBlock* basic_block) {
1148     while (basic_block != nullptr) {
1149       ArenaSafeMap<int, ValueRange*>* map = GetValueRangeMap(basic_block);
1150       if (map != nullptr) {
1151         if (map->find(instruction->GetId()) != map->end()) {
1152           return map->Get(instruction->GetId());
1153         }
1154       } else {
1155         DCHECK(IsAddedBlock(basic_block));
1156       }
1157       basic_block = basic_block->GetDominator();
1158     }
1159     // Didn't find any.
1160     return nullptr;
1161   }
1162 
1163   // Narrow the value range of `instruction` at the end of `basic_block` with `range`,
1164   // and push the narrowed value range to `successor`.
ApplyRangeFromComparison(HInstruction * instruction,HBasicBlock * basic_block,HBasicBlock * successor,ValueRange * range)1165   void ApplyRangeFromComparison(HInstruction* instruction, HBasicBlock* basic_block,
1166                                 HBasicBlock* successor, ValueRange* range) {
1167     ValueRange* existing_range = LookupValueRange(instruction, basic_block);
1168     if (existing_range == nullptr) {
1169       if (range != nullptr) {
1170         GetValueRangeMap(successor)->Overwrite(instruction->GetId(), range);
1171       }
1172       return;
1173     }
1174     if (existing_range->IsMonotonicValueRange()) {
1175       DCHECK(instruction->IsLoopHeaderPhi());
1176       // Make sure the comparison is in the loop header so each increment is
1177       // checked with a comparison.
1178       if (instruction->GetBlock() != basic_block) {
1179         return;
1180       }
1181     }
1182     ValueRange* narrowed_range = existing_range->Narrow(range);
1183     GetValueRangeMap(successor)->Overwrite(instruction->GetId(), narrowed_range);
1184   }
1185 
1186   // Special case that we may simultaneously narrow two MonotonicValueRange's to
1187   // regular value ranges.
HandleIfBetweenTwoMonotonicValueRanges(HIf * instruction,HInstruction * left,HInstruction * right,IfCondition cond,MonotonicValueRange * left_range,MonotonicValueRange * right_range)1188   void HandleIfBetweenTwoMonotonicValueRanges(HIf* instruction,
1189                                               HInstruction* left,
1190                                               HInstruction* right,
1191                                               IfCondition cond,
1192                                               MonotonicValueRange* left_range,
1193                                               MonotonicValueRange* right_range) {
1194     DCHECK(left->IsLoopHeaderPhi());
1195     DCHECK(right->IsLoopHeaderPhi());
1196     if (instruction->GetBlock() != left->GetBlock()) {
1197       // Comparison needs to be in loop header to make sure it's done after each
1198       // increment/decrement.
1199       return;
1200     }
1201 
1202     // Handle common cases which also don't have overflow/underflow concerns.
1203     if (left_range->GetIncrement() == 1 &&
1204         left_range->GetBound().IsConstant() &&
1205         right_range->GetIncrement() == -1 &&
1206         right_range->GetBound().IsRelatedToArrayLength() &&
1207         right_range->GetBound().GetConstant() < 0) {
1208       HBasicBlock* successor = nullptr;
1209       int32_t left_compensation = 0;
1210       int32_t right_compensation = 0;
1211       if (cond == kCondLT) {
1212         left_compensation = -1;
1213         right_compensation = 1;
1214         successor = instruction->IfTrueSuccessor();
1215       } else if (cond == kCondLE) {
1216         successor = instruction->IfTrueSuccessor();
1217       } else if (cond == kCondGT) {
1218         successor = instruction->IfFalseSuccessor();
1219       } else if (cond == kCondGE) {
1220         left_compensation = -1;
1221         right_compensation = 1;
1222         successor = instruction->IfFalseSuccessor();
1223       } else {
1224         // We don't handle '=='/'!=' test in case left and right can cross and
1225         // miss each other.
1226         return;
1227       }
1228 
1229       if (successor != nullptr) {
1230         bool overflow;
1231         bool underflow;
1232         ValueRange* new_left_range = new (GetGraph()->GetArena()) ValueRange(
1233             GetGraph()->GetArena(),
1234             left_range->GetBound(),
1235             right_range->GetBound().Add(left_compensation, &overflow, &underflow));
1236         if (!overflow && !underflow) {
1237           ApplyRangeFromComparison(left, instruction->GetBlock(), successor,
1238                                    new_left_range);
1239         }
1240 
1241         ValueRange* new_right_range = new (GetGraph()->GetArena()) ValueRange(
1242             GetGraph()->GetArena(),
1243             left_range->GetBound().Add(right_compensation, &overflow, &underflow),
1244             right_range->GetBound());
1245         if (!overflow && !underflow) {
1246           ApplyRangeFromComparison(right, instruction->GetBlock(), successor,
1247                                    new_right_range);
1248         }
1249       }
1250     }
1251   }
1252 
1253   // Handle "if (left cmp_cond right)".
HandleIf(HIf * instruction,HInstruction * left,HInstruction * right,IfCondition cond)1254   void HandleIf(HIf* instruction, HInstruction* left, HInstruction* right, IfCondition cond) {
1255     HBasicBlock* block = instruction->GetBlock();
1256 
1257     HBasicBlock* true_successor = instruction->IfTrueSuccessor();
1258     // There should be no critical edge at this point.
1259     DCHECK_EQ(true_successor->GetPredecessors().Size(), 1u);
1260 
1261     HBasicBlock* false_successor = instruction->IfFalseSuccessor();
1262     // There should be no critical edge at this point.
1263     DCHECK_EQ(false_successor->GetPredecessors().Size(), 1u);
1264 
1265     ValueRange* left_range = LookupValueRange(left, block);
1266     MonotonicValueRange* left_monotonic_range = nullptr;
1267     if (left_range != nullptr) {
1268       left_monotonic_range = left_range->AsMonotonicValueRange();
1269       if (left_monotonic_range != nullptr) {
1270         HBasicBlock* loop_head = left_monotonic_range->GetLoopHeader();
1271         if (instruction->GetBlock() != loop_head) {
1272           // For monotonic value range, don't handle `instruction`
1273           // if it's not defined in the loop header.
1274           return;
1275         }
1276       }
1277     }
1278 
1279     bool found;
1280     ValueBound bound = ValueBound::DetectValueBoundFromValue(right, &found);
1281     // Each comparison can establish a lower bound and an upper bound
1282     // for the left hand side.
1283     ValueBound lower = bound;
1284     ValueBound upper = bound;
1285     if (!found) {
1286       // No constant or array.length+c format bound found.
1287       // For i<j, we can still use j's upper bound as i's upper bound. Same for lower.
1288       ValueRange* right_range = LookupValueRange(right, block);
1289       if (right_range != nullptr) {
1290         if (right_range->IsMonotonicValueRange()) {
1291           if (left_range != nullptr && left_range->IsMonotonicValueRange()) {
1292             HandleIfBetweenTwoMonotonicValueRanges(instruction, left, right, cond,
1293                                                    left_range->AsMonotonicValueRange(),
1294                                                    right_range->AsMonotonicValueRange());
1295             return;
1296           }
1297         }
1298         lower = right_range->GetLower();
1299         upper = right_range->GetUpper();
1300       } else {
1301         lower = ValueBound::Min();
1302         upper = ValueBound::Max();
1303       }
1304     }
1305 
1306     bool overflow, underflow;
1307     if (cond == kCondLT || cond == kCondLE) {
1308       if (left_monotonic_range != nullptr) {
1309         // Update the info for monotonic value range.
1310         if (left_monotonic_range->GetInductionVariable() == left &&
1311             left_monotonic_range->GetIncrement() < 0 &&
1312             block == left_monotonic_range->GetLoopHeader() &&
1313             instruction->IfFalseSuccessor()->GetLoopInformation() == block->GetLoopInformation()) {
1314           left_monotonic_range->SetEnd(right);
1315           left_monotonic_range->SetInclusive(cond == kCondLT);
1316         }
1317       }
1318 
1319       if (!upper.Equals(ValueBound::Max())) {
1320         int32_t compensation = (cond == kCondLT) ? -1 : 0;  // upper bound is inclusive
1321         ValueBound new_upper = upper.Add(compensation, &overflow, &underflow);
1322         if (overflow || underflow) {
1323           return;
1324         }
1325         ValueRange* new_range = new (GetGraph()->GetArena())
1326             ValueRange(GetGraph()->GetArena(), ValueBound::Min(), new_upper);
1327         ApplyRangeFromComparison(left, block, true_successor, new_range);
1328       }
1329 
1330       // array.length as a lower bound isn't considered useful.
1331       if (!lower.Equals(ValueBound::Min()) && !lower.IsRelatedToArrayLength()) {
1332         int32_t compensation = (cond == kCondLE) ? 1 : 0;  // lower bound is inclusive
1333         ValueBound new_lower = lower.Add(compensation, &overflow, &underflow);
1334         if (overflow || underflow) {
1335           return;
1336         }
1337         ValueRange* new_range = new (GetGraph()->GetArena())
1338             ValueRange(GetGraph()->GetArena(), new_lower, ValueBound::Max());
1339         ApplyRangeFromComparison(left, block, false_successor, new_range);
1340       }
1341     } else if (cond == kCondGT || cond == kCondGE) {
1342       if (left_monotonic_range != nullptr) {
1343         // Update the info for monotonic value range.
1344         if (left_monotonic_range->GetInductionVariable() == left &&
1345             left_monotonic_range->GetIncrement() > 0 &&
1346             block == left_monotonic_range->GetLoopHeader() &&
1347             instruction->IfFalseSuccessor()->GetLoopInformation() == block->GetLoopInformation()) {
1348           left_monotonic_range->SetEnd(right);
1349           left_monotonic_range->SetInclusive(cond == kCondGT);
1350         }
1351       }
1352 
1353       // array.length as a lower bound isn't considered useful.
1354       if (!lower.Equals(ValueBound::Min()) && !lower.IsRelatedToArrayLength()) {
1355         int32_t compensation = (cond == kCondGT) ? 1 : 0;  // lower bound is inclusive
1356         ValueBound new_lower = lower.Add(compensation, &overflow, &underflow);
1357         if (overflow || underflow) {
1358           return;
1359         }
1360         ValueRange* new_range = new (GetGraph()->GetArena())
1361             ValueRange(GetGraph()->GetArena(), new_lower, ValueBound::Max());
1362         ApplyRangeFromComparison(left, block, true_successor, new_range);
1363       }
1364 
1365       if (!upper.Equals(ValueBound::Max())) {
1366         int32_t compensation = (cond == kCondGE) ? -1 : 0;  // upper bound is inclusive
1367         ValueBound new_upper = upper.Add(compensation, &overflow, &underflow);
1368         if (overflow || underflow) {
1369           return;
1370         }
1371         ValueRange* new_range = new (GetGraph()->GetArena())
1372             ValueRange(GetGraph()->GetArena(), ValueBound::Min(), new_upper);
1373         ApplyRangeFromComparison(left, block, false_successor, new_range);
1374       }
1375     }
1376   }
1377 
VisitBoundsCheck(HBoundsCheck * bounds_check)1378   void VisitBoundsCheck(HBoundsCheck* bounds_check) {
1379     HBasicBlock* block = bounds_check->GetBlock();
1380     HInstruction* index = bounds_check->InputAt(0);
1381     HInstruction* array_length = bounds_check->InputAt(1);
1382     DCHECK(array_length->IsIntConstant() ||
1383            array_length->IsArrayLength() ||
1384            array_length->IsPhi());
1385 
1386     if (array_length->IsPhi()) {
1387       // Input 1 of the phi contains the real array.length once the loop body is
1388       // entered. That value will be used for bound analysis. The graph is still
1389       // strictly in SSA form.
1390       array_length = array_length->AsPhi()->InputAt(1)->AsArrayLength();
1391     }
1392 
1393     if (!index->IsIntConstant()) {
1394       ValueRange* index_range = LookupValueRange(index, block);
1395       if (index_range != nullptr) {
1396         ValueBound lower = ValueBound(nullptr, 0);        // constant 0
1397         ValueBound upper = ValueBound(array_length, -1);  // array_length - 1
1398         ValueRange* array_range = new (GetGraph()->GetArena())
1399             ValueRange(GetGraph()->GetArena(), lower, upper);
1400         if (index_range->FitsIn(array_range)) {
1401           ReplaceBoundsCheck(bounds_check, index);
1402           return;
1403         }
1404       }
1405     } else {
1406       int32_t constant = index->AsIntConstant()->GetValue();
1407       if (constant < 0) {
1408         // Will always throw exception.
1409         return;
1410       }
1411       if (array_length->IsIntConstant()) {
1412         if (constant < array_length->AsIntConstant()->GetValue()) {
1413           ReplaceBoundsCheck(bounds_check, index);
1414         }
1415         return;
1416       }
1417 
1418       DCHECK(array_length->IsArrayLength());
1419       ValueRange* existing_range = LookupValueRange(array_length, block);
1420       if (existing_range != nullptr) {
1421         ValueBound lower = existing_range->GetLower();
1422         DCHECK(lower.IsConstant());
1423         if (constant < lower.GetConstant()) {
1424           ReplaceBoundsCheck(bounds_check, index);
1425           return;
1426         } else {
1427           // Existing range isn't strong enough to eliminate the bounds check.
1428           // Fall through to update the array_length range with info from this
1429           // bounds check.
1430         }
1431       }
1432 
1433       if (first_constant_index_bounds_check_map_.find(array_length->GetId()) ==
1434           first_constant_index_bounds_check_map_.end()) {
1435         // Remember the first bounds check against array_length of a constant index.
1436         // That bounds check instruction has an associated HEnvironment where we
1437         // may add an HDeoptimize to eliminate bounds checks of constant indices
1438         // against array_length.
1439         first_constant_index_bounds_check_map_.Put(array_length->GetId(), bounds_check);
1440       } else {
1441         // We've seen it at least twice. It's beneficial to introduce a compare with
1442         // deoptimization fallback to eliminate the bounds checks.
1443         need_to_revisit_block_ = true;
1444       }
1445 
1446       // Once we have an array access like 'array[5] = 1', we record array.length >= 6.
1447       // We currently don't do it for non-constant index since a valid array[i] can't prove
1448       // a valid array[i-1] yet due to the lower bound side.
1449       if (constant == INT_MAX) {
1450         // INT_MAX as an index will definitely throw AIOOBE.
1451         return;
1452       }
1453       ValueBound lower = ValueBound(nullptr, constant + 1);
1454       ValueBound upper = ValueBound::Max();
1455       ValueRange* range = new (GetGraph()->GetArena())
1456           ValueRange(GetGraph()->GetArena(), lower, upper);
1457       GetValueRangeMap(block)->Overwrite(array_length->GetId(), range);
1458     }
1459   }
1460 
ReplaceBoundsCheck(HInstruction * bounds_check,HInstruction * index)1461   void ReplaceBoundsCheck(HInstruction* bounds_check, HInstruction* index) {
1462     bounds_check->ReplaceWith(index);
1463     bounds_check->GetBlock()->RemoveInstruction(bounds_check);
1464   }
1465 
HasSameInputAtBackEdges(HPhi * phi)1466   static bool HasSameInputAtBackEdges(HPhi* phi) {
1467     DCHECK(phi->IsLoopHeaderPhi());
1468     // Start with input 1. Input 0 is from the incoming block.
1469     HInstruction* input1 = phi->InputAt(1);
1470     DCHECK(phi->GetBlock()->GetLoopInformation()->IsBackEdge(
1471         *phi->GetBlock()->GetPredecessors().Get(1)));
1472     for (size_t i = 2, e = phi->InputCount(); i < e; ++i) {
1473       DCHECK(phi->GetBlock()->GetLoopInformation()->IsBackEdge(
1474           *phi->GetBlock()->GetPredecessors().Get(i)));
1475       if (input1 != phi->InputAt(i)) {
1476         return false;
1477       }
1478     }
1479     return true;
1480   }
1481 
VisitPhi(HPhi * phi)1482   void VisitPhi(HPhi* phi) {
1483     if (phi->IsLoopHeaderPhi()
1484         && (phi->GetType() == Primitive::kPrimInt)
1485         && HasSameInputAtBackEdges(phi)) {
1486       HInstruction* instruction = phi->InputAt(1);
1487       HInstruction *left;
1488       int32_t increment;
1489       if (ValueBound::IsAddOrSubAConstant(instruction, &left, &increment)) {
1490         if (left == phi) {
1491           HInstruction* initial_value = phi->InputAt(0);
1492           ValueRange* range = nullptr;
1493           if (increment == 0) {
1494             // Add constant 0. It's really a fixed value.
1495             range = new (GetGraph()->GetArena()) ValueRange(
1496                 GetGraph()->GetArena(),
1497                 ValueBound(initial_value, 0),
1498                 ValueBound(initial_value, 0));
1499           } else {
1500             // Monotonically increasing/decreasing.
1501             bool found;
1502             ValueBound bound = ValueBound::DetectValueBoundFromValue(
1503                 initial_value, &found);
1504             if (!found) {
1505               // No constant or array.length+c bound found.
1506               // For i=j, we can still use j's upper bound as i's upper bound.
1507               // Same for lower.
1508               ValueRange* initial_range = LookupValueRange(initial_value, phi->GetBlock());
1509               if (initial_range != nullptr) {
1510                 bound = increment > 0 ? initial_range->GetLower() :
1511                                         initial_range->GetUpper();
1512               } else {
1513                 bound = increment > 0 ? ValueBound::Min() : ValueBound::Max();
1514               }
1515             }
1516             range = new (GetGraph()->GetArena()) MonotonicValueRange(
1517                 GetGraph()->GetArena(),
1518                 phi,
1519                 initial_value,
1520                 increment,
1521                 bound);
1522           }
1523           GetValueRangeMap(phi->GetBlock())->Overwrite(phi->GetId(), range);
1524         }
1525       }
1526     }
1527   }
1528 
VisitIf(HIf * instruction)1529   void VisitIf(HIf* instruction) {
1530     if (instruction->InputAt(0)->IsCondition()) {
1531       HCondition* cond = instruction->InputAt(0)->AsCondition();
1532       IfCondition cmp = cond->GetCondition();
1533       if (cmp == kCondGT || cmp == kCondGE ||
1534           cmp == kCondLT || cmp == kCondLE) {
1535         HInstruction* left = cond->GetLeft();
1536         HInstruction* right = cond->GetRight();
1537         HandleIf(instruction, left, right, cmp);
1538 
1539         HBasicBlock* block = instruction->GetBlock();
1540         ValueRange* left_range = LookupValueRange(left, block);
1541         if (left_range == nullptr) {
1542           return;
1543         }
1544 
1545         if (left_range->IsMonotonicValueRange() &&
1546             block == left_range->AsMonotonicValueRange()->GetLoopHeader()) {
1547           // The comparison is for an induction variable in the loop header.
1548           DCHECK(left == left_range->AsMonotonicValueRange()->GetInductionVariable());
1549           HBasicBlock* loop_body_successor =
1550             left_range->AsMonotonicValueRange()->GetLoopHeaderSuccesorInLoop();
1551           if (loop_body_successor == nullptr) {
1552             // In case it's some strange loop structure.
1553             return;
1554           }
1555           ValueRange* new_left_range = LookupValueRange(left, loop_body_successor);
1556           if ((new_left_range == left_range) ||
1557               // Range narrowed with deoptimization is usually more useful than
1558               // a constant range.
1559               new_left_range->IsConstantValueRange()) {
1560             // We are not successful in narrowing the monotonic value range to
1561             // a regular value range. Try using deoptimization.
1562             new_left_range = left_range->AsMonotonicValueRange()->
1563                 NarrowWithDeoptimization();
1564             if (new_left_range != left_range) {
1565               GetValueRangeMap(loop_body_successor)->Overwrite(left->GetId(), new_left_range);
1566             }
1567           }
1568         }
1569       }
1570     }
1571   }
1572 
VisitAdd(HAdd * add)1573   void VisitAdd(HAdd* add) {
1574     HInstruction* right = add->GetRight();
1575     if (right->IsIntConstant()) {
1576       ValueRange* left_range = LookupValueRange(add->GetLeft(), add->GetBlock());
1577       if (left_range == nullptr) {
1578         return;
1579       }
1580       ValueRange* range = left_range->Add(right->AsIntConstant()->GetValue());
1581       if (range != nullptr) {
1582         GetValueRangeMap(add->GetBlock())->Overwrite(add->GetId(), range);
1583       }
1584     }
1585   }
1586 
VisitSub(HSub * sub)1587   void VisitSub(HSub* sub) {
1588     HInstruction* left = sub->GetLeft();
1589     HInstruction* right = sub->GetRight();
1590     if (right->IsIntConstant()) {
1591       ValueRange* left_range = LookupValueRange(left, sub->GetBlock());
1592       if (left_range == nullptr) {
1593         return;
1594       }
1595       ValueRange* range = left_range->Add(-right->AsIntConstant()->GetValue());
1596       if (range != nullptr) {
1597         GetValueRangeMap(sub->GetBlock())->Overwrite(sub->GetId(), range);
1598         return;
1599       }
1600     }
1601 
1602     // Here we are interested in the typical triangular case of nested loops,
1603     // such as the inner loop 'for (int j=0; j<array.length-i; j++)' where i
1604     // is the index for outer loop. In this case, we know j is bounded by array.length-1.
1605 
1606     // Try to handle (array.length - i) or (array.length + c - i) format.
1607     HInstruction* left_of_left;  // left input of left.
1608     int32_t right_const = 0;
1609     if (ValueBound::IsAddOrSubAConstant(left, &left_of_left, &right_const)) {
1610       left = left_of_left;
1611     }
1612     // The value of left input of the sub equals (left + right_const).
1613 
1614     if (left->IsArrayLength()) {
1615       HInstruction* array_length = left->AsArrayLength();
1616       ValueRange* right_range = LookupValueRange(right, sub->GetBlock());
1617       if (right_range != nullptr) {
1618         ValueBound lower = right_range->GetLower();
1619         ValueBound upper = right_range->GetUpper();
1620         if (lower.IsConstant() && upper.IsRelatedToArrayLength()) {
1621           HInstruction* upper_inst = upper.GetInstruction();
1622           // Make sure it's the same array.
1623           if (ValueBound::Equal(array_length, upper_inst)) {
1624             int32_t c0 = right_const;
1625             int32_t c1 = lower.GetConstant();
1626             int32_t c2 = upper.GetConstant();
1627             // (array.length + c0 - v) where v is in [c1, array.length + c2]
1628             // gets [c0 - c2, array.length + c0 - c1] as its value range.
1629             if (!ValueBound::WouldAddOverflowOrUnderflow(c0, -c2) &&
1630                 !ValueBound::WouldAddOverflowOrUnderflow(c0, -c1)) {
1631               if ((c0 - c1) <= 0) {
1632                 // array.length + (c0 - c1) won't overflow/underflow.
1633                 ValueRange* range = new (GetGraph()->GetArena()) ValueRange(
1634                     GetGraph()->GetArena(),
1635                     ValueBound(nullptr, right_const - upper.GetConstant()),
1636                     ValueBound(array_length, right_const - lower.GetConstant()));
1637                 GetValueRangeMap(sub->GetBlock())->Overwrite(sub->GetId(), range);
1638               }
1639             }
1640           }
1641         }
1642       }
1643     }
1644   }
1645 
FindAndHandlePartialArrayLength(HBinaryOperation * instruction)1646   void FindAndHandlePartialArrayLength(HBinaryOperation* instruction) {
1647     DCHECK(instruction->IsDiv() || instruction->IsShr() || instruction->IsUShr());
1648     HInstruction* right = instruction->GetRight();
1649     int32_t right_const;
1650     if (right->IsIntConstant()) {
1651       right_const = right->AsIntConstant()->GetValue();
1652       // Detect division by two or more.
1653       if ((instruction->IsDiv() && right_const <= 1) ||
1654           (instruction->IsShr() && right_const < 1) ||
1655           (instruction->IsUShr() && right_const < 1)) {
1656         return;
1657       }
1658     } else {
1659       return;
1660     }
1661 
1662     // Try to handle array.length/2 or (array.length-1)/2 format.
1663     HInstruction* left = instruction->GetLeft();
1664     HInstruction* left_of_left;  // left input of left.
1665     int32_t c = 0;
1666     if (ValueBound::IsAddOrSubAConstant(left, &left_of_left, &c)) {
1667       left = left_of_left;
1668     }
1669     // The value of left input of instruction equals (left + c).
1670 
1671     // (array_length + 1) or smaller divided by two or more
1672     // always generate a value in [INT_MIN, array_length].
1673     // This is true even if array_length is INT_MAX.
1674     if (left->IsArrayLength() && c <= 1) {
1675       if (instruction->IsUShr() && c < 0) {
1676         // Make sure for unsigned shift, left side is not negative.
1677         // e.g. if array_length is 2, ((array_length - 3) >>> 2) is way bigger
1678         // than array_length.
1679         return;
1680       }
1681       ValueRange* range = new (GetGraph()->GetArena()) ValueRange(
1682           GetGraph()->GetArena(),
1683           ValueBound(nullptr, INT_MIN),
1684           ValueBound(left, 0));
1685       GetValueRangeMap(instruction->GetBlock())->Overwrite(instruction->GetId(), range);
1686     }
1687   }
1688 
VisitDiv(HDiv * div)1689   void VisitDiv(HDiv* div) {
1690     FindAndHandlePartialArrayLength(div);
1691   }
1692 
VisitShr(HShr * shr)1693   void VisitShr(HShr* shr) {
1694     FindAndHandlePartialArrayLength(shr);
1695   }
1696 
VisitUShr(HUShr * ushr)1697   void VisitUShr(HUShr* ushr) {
1698     FindAndHandlePartialArrayLength(ushr);
1699   }
1700 
VisitAnd(HAnd * instruction)1701   void VisitAnd(HAnd* instruction) {
1702     if (instruction->GetRight()->IsIntConstant()) {
1703       int32_t constant = instruction->GetRight()->AsIntConstant()->GetValue();
1704       if (constant > 0) {
1705         // constant serves as a mask so any number masked with it
1706         // gets a [0, constant] value range.
1707         ValueRange* range = new (GetGraph()->GetArena()) ValueRange(
1708             GetGraph()->GetArena(),
1709             ValueBound(nullptr, 0),
1710             ValueBound(nullptr, constant));
1711         GetValueRangeMap(instruction->GetBlock())->Overwrite(instruction->GetId(), range);
1712       }
1713     }
1714   }
1715 
VisitNewArray(HNewArray * new_array)1716   void VisitNewArray(HNewArray* new_array) {
1717     HInstruction* len = new_array->InputAt(0);
1718     if (!len->IsIntConstant()) {
1719       HInstruction *left;
1720       int32_t right_const;
1721       if (ValueBound::IsAddOrSubAConstant(len, &left, &right_const)) {
1722         // (left + right_const) is used as size to new the array.
1723         // We record "-right_const <= left <= new_array - right_const";
1724         ValueBound lower = ValueBound(nullptr, -right_const);
1725         // We use new_array for the bound instead of new_array.length,
1726         // which isn't available as an instruction yet. new_array will
1727         // be treated the same as new_array.length when it's used in a ValueBound.
1728         ValueBound upper = ValueBound(new_array, -right_const);
1729         ValueRange* range = new (GetGraph()->GetArena())
1730             ValueRange(GetGraph()->GetArena(), lower, upper);
1731         ValueRange* existing_range = LookupValueRange(left, new_array->GetBlock());
1732         if (existing_range != nullptr) {
1733           range = existing_range->Narrow(range);
1734         }
1735         GetValueRangeMap(new_array->GetBlock())->Overwrite(left->GetId(), range);
1736       }
1737     }
1738   }
1739 
VisitDeoptimize(HDeoptimize * deoptimize)1740   void VisitDeoptimize(HDeoptimize* deoptimize) {
1741     // Right now it's only HLessThanOrEqual.
1742     DCHECK(deoptimize->InputAt(0)->IsLessThanOrEqual());
1743     HLessThanOrEqual* less_than_or_equal = deoptimize->InputAt(0)->AsLessThanOrEqual();
1744     HInstruction* instruction = less_than_or_equal->InputAt(0);
1745     if (instruction->IsArrayLength()) {
1746       HInstruction* constant = less_than_or_equal->InputAt(1);
1747       DCHECK(constant->IsIntConstant());
1748       DCHECK(constant->AsIntConstant()->GetValue() <= kMaxConstantForAddingDeoptimize);
1749       ValueBound lower = ValueBound(nullptr, constant->AsIntConstant()->GetValue() + 1);
1750       ValueRange* range = new (GetGraph()->GetArena())
1751           ValueRange(GetGraph()->GetArena(), lower, ValueBound::Max());
1752       GetValueRangeMap(deoptimize->GetBlock())->Overwrite(instruction->GetId(), range);
1753     }
1754   }
1755 
AddCompareWithDeoptimization(HInstruction * array_length,HIntConstant * const_instr,HBasicBlock * block)1756   void AddCompareWithDeoptimization(HInstruction* array_length,
1757                                     HIntConstant* const_instr,
1758                                     HBasicBlock* block) {
1759     DCHECK(array_length->IsArrayLength());
1760     ValueRange* range = LookupValueRange(array_length, block);
1761     ValueBound lower_bound = range->GetLower();
1762     DCHECK(lower_bound.IsConstant());
1763     DCHECK(const_instr->GetValue() <= kMaxConstantForAddingDeoptimize);
1764     // Note that the lower bound of the array length may have been refined
1765     // through other instructions (such as `HNewArray(length - 4)`).
1766     DCHECK_LE(const_instr->GetValue() + 1, lower_bound.GetConstant());
1767 
1768     // If array_length is less than lower_const, deoptimize.
1769     HBoundsCheck* bounds_check = first_constant_index_bounds_check_map_.Get(
1770         array_length->GetId())->AsBoundsCheck();
1771     HCondition* cond = new (GetGraph()->GetArena()) HLessThanOrEqual(array_length, const_instr);
1772     HDeoptimize* deoptimize = new (GetGraph()->GetArena())
1773         HDeoptimize(cond, bounds_check->GetDexPc());
1774     block->InsertInstructionBefore(cond, bounds_check);
1775     block->InsertInstructionBefore(deoptimize, bounds_check);
1776     deoptimize->CopyEnvironmentFrom(bounds_check->GetEnvironment());
1777   }
1778 
AddComparesWithDeoptimization(HBasicBlock * block)1779   void AddComparesWithDeoptimization(HBasicBlock* block) {
1780     for (ArenaSafeMap<int, HBoundsCheck*>::iterator it =
1781              first_constant_index_bounds_check_map_.begin();
1782          it != first_constant_index_bounds_check_map_.end();
1783          ++it) {
1784       HBoundsCheck* bounds_check = it->second;
1785       HInstruction* array_length = bounds_check->InputAt(1);
1786       if (!array_length->IsArrayLength()) {
1787         // Prior deoptimizations may have changed the array length to a phi.
1788         // TODO(mingyao): propagate the range to the phi?
1789         DCHECK(array_length->IsPhi()) << array_length->DebugName();
1790         continue;
1791       }
1792       HIntConstant* lower_bound_const_instr = nullptr;
1793       int32_t lower_bound_const = INT_MIN;
1794       size_t counter = 0;
1795       // Count the constant indexing for which bounds checks haven't
1796       // been removed yet.
1797       for (HUseIterator<HInstruction*> it2(array_length->GetUses());
1798            !it2.Done();
1799            it2.Advance()) {
1800         HInstruction* user = it2.Current()->GetUser();
1801         if (user->GetBlock() == block &&
1802             user->IsBoundsCheck() &&
1803             user->AsBoundsCheck()->InputAt(0)->IsIntConstant()) {
1804           DCHECK_EQ(array_length, user->AsBoundsCheck()->InputAt(1));
1805           HIntConstant* const_instr = user->AsBoundsCheck()->InputAt(0)->AsIntConstant();
1806           if (const_instr->GetValue() > lower_bound_const) {
1807             lower_bound_const = const_instr->GetValue();
1808             lower_bound_const_instr = const_instr;
1809           }
1810           counter++;
1811         }
1812       }
1813       if (counter >= kThresholdForAddingDeoptimize &&
1814           lower_bound_const_instr->GetValue() <= kMaxConstantForAddingDeoptimize) {
1815         AddCompareWithDeoptimization(array_length, lower_bound_const_instr, block);
1816       }
1817     }
1818   }
1819 
1820   std::vector<std::unique_ptr<ArenaSafeMap<int, ValueRange*>>> maps_;
1821 
1822   // Map an HArrayLength instruction's id to the first HBoundsCheck instruction in
1823   // a block that checks a constant index against that HArrayLength.
1824   SafeMap<int, HBoundsCheck*> first_constant_index_bounds_check_map_;
1825 
1826   // For the block, there is at least one HArrayLength instruction for which there
1827   // is more than one bounds check instruction with constant indexing. And it's
1828   // beneficial to add a compare instruction that has deoptimization fallback and
1829   // eliminate those bounds checks.
1830   bool need_to_revisit_block_;
1831 
1832   // Initial number of blocks.
1833   int32_t initial_block_size_;
1834 
1835   DISALLOW_COPY_AND_ASSIGN(BCEVisitor);
1836 };
1837 
Run()1838 void BoundsCheckElimination::Run() {
1839   if (!graph_->HasBoundsChecks()) {
1840     return;
1841   }
1842 
1843   BCEVisitor visitor(graph_);
1844   // Reverse post order guarantees a node's dominators are visited first.
1845   // We want to visit in the dominator-based order since if a value is known to
1846   // be bounded by a range at one instruction, it must be true that all uses of
1847   // that value dominated by that instruction fits in that range. Range of that
1848   // value can be narrowed further down in the dominator tree.
1849   //
1850   // TODO: only visit blocks that dominate some array accesses.
1851   HBasicBlock* last_visited_block = nullptr;
1852   for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
1853     HBasicBlock* current = it.Current();
1854     if (current == last_visited_block) {
1855       // We may insert blocks into the reverse post order list when processing
1856       // a loop header. Don't process it again.
1857       DCHECK(current->IsLoopHeader());
1858       continue;
1859     }
1860     if (visitor.IsAddedBlock(current)) {
1861       // Skip added blocks. Their effects are already taken care of.
1862       continue;
1863     }
1864     visitor.VisitBasicBlock(current);
1865     last_visited_block = current;
1866   }
1867 }
1868 
1869 }  // namespace art
1870