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 "bounds_check_elimination.h"
18 
19 #include <limits>
20 
21 #include "base/scoped_arena_allocator.h"
22 #include "base/scoped_arena_containers.h"
23 #include "induction_var_range.h"
24 #include "nodes.h"
25 #include "side_effects_analysis.h"
26 
27 namespace art HIDDEN {
28 
29 class MonotonicValueRange;
30 
31 /**
32  * A value bound is represented as a pair of value and constant,
33  * e.g. array.length - 1.
34  */
35 class ValueBound : public ValueObject {
36  public:
ValueBound(HInstruction * instruction,int32_t constant)37   ValueBound(HInstruction* instruction, int32_t constant) {
38     if (instruction != nullptr && instruction->IsIntConstant()) {
39       // Normalize ValueBound with constant instruction.
40       int32_t instr_const = instruction->AsIntConstant()->GetValue();
41       if (!WouldAddOverflowOrUnderflow(instr_const, constant)) {
42         instruction_ = nullptr;
43         constant_ = instr_const + constant;
44         return;
45       }
46     }
47     instruction_ = instruction;
48     constant_ = constant;
49   }
50 
51   // Return whether (left + right) overflows or underflows.
WouldAddOverflowOrUnderflow(int32_t left,int32_t right)52   static bool WouldAddOverflowOrUnderflow(int32_t left, int32_t right) {
53     if (right == 0) {
54       return false;
55     }
56     if ((right > 0) && (left <= (std::numeric_limits<int32_t>::max() - right))) {
57       // No overflow.
58       return false;
59     }
60     if ((right < 0) && (left >= (std::numeric_limits<int32_t>::min() - right))) {
61       // No underflow.
62       return false;
63     }
64     return true;
65   }
66 
67   // Return true if instruction can be expressed as "left_instruction + right_constant".
IsAddOrSubAConstant(HInstruction * instruction,HInstruction ** left_instruction,int32_t * right_constant)68   static bool IsAddOrSubAConstant(HInstruction* instruction,
69                                   /* out */ HInstruction** left_instruction,
70                                   /* out */ int32_t* right_constant) {
71     HInstruction* left_so_far = nullptr;
72     int32_t right_so_far = 0;
73     while (instruction->IsAdd() || instruction->IsSub()) {
74       HBinaryOperation* bin_op = instruction->AsBinaryOperation();
75       HInstruction* left = bin_op->GetLeft();
76       HInstruction* right = bin_op->GetRight();
77       if (right->IsIntConstant()) {
78         int32_t v = right->AsIntConstant()->GetValue();
79         int32_t c = instruction->IsAdd() ? v : -v;
80         if (!WouldAddOverflowOrUnderflow(right_so_far, c)) {
81           instruction = left;
82           left_so_far = left;
83           right_so_far += c;
84           continue;
85         }
86       }
87       break;
88     }
89     // Return result: either false and "null+0" or true and "instr+constant".
90     *left_instruction = left_so_far;
91     *right_constant = right_so_far;
92     return left_so_far != nullptr;
93   }
94 
95   // Expresses any instruction as a value bound.
AsValueBound(HInstruction * instruction)96   static ValueBound AsValueBound(HInstruction* instruction) {
97     if (instruction->IsIntConstant()) {
98       return ValueBound(nullptr, instruction->AsIntConstant()->GetValue());
99     }
100     HInstruction *left;
101     int32_t right;
102     if (IsAddOrSubAConstant(instruction, &left, &right)) {
103       return ValueBound(left, right);
104     }
105     return ValueBound(instruction, 0);
106   }
107 
108   // Try to detect useful value bound format from an instruction, e.g.
109   // a constant or array length related value.
DetectValueBoundFromValue(HInstruction * instruction,bool * found)110   static ValueBound DetectValueBoundFromValue(HInstruction* instruction, /* out */ bool* found) {
111     DCHECK(instruction != nullptr);
112     if (instruction->IsIntConstant()) {
113       *found = true;
114       return ValueBound(nullptr, instruction->AsIntConstant()->GetValue());
115     }
116 
117     if (instruction->IsArrayLength()) {
118       *found = true;
119       return ValueBound(instruction, 0);
120     }
121     // Try to detect (array.length + c) format.
122     HInstruction *left;
123     int32_t right;
124     if (IsAddOrSubAConstant(instruction, &left, &right)) {
125       if (left->IsArrayLength()) {
126         *found = true;
127         return ValueBound(left, right);
128       }
129     }
130 
131     // No useful bound detected.
132     *found = false;
133     return ValueBound::Max();
134   }
135 
GetInstruction() const136   HInstruction* GetInstruction() const { return instruction_; }
GetConstant() const137   int32_t GetConstant() const { return constant_; }
138 
IsRelatedToArrayLength() const139   bool IsRelatedToArrayLength() const {
140     // Some bounds are created with HNewArray* as the instruction instead
141     // of HArrayLength*. They are treated the same.
142     return (instruction_ != nullptr) &&
143            (instruction_->IsArrayLength() || instruction_->IsNewArray());
144   }
145 
IsConstant() const146   bool IsConstant() const {
147     return instruction_ == nullptr;
148   }
149 
Min()150   static ValueBound Min() { return ValueBound(nullptr, std::numeric_limits<int32_t>::min()); }
Max()151   static ValueBound Max() { return ValueBound(nullptr, std::numeric_limits<int32_t>::max()); }
152 
Equals(ValueBound bound) const153   bool Equals(ValueBound bound) const {
154     return instruction_ == bound.instruction_ && constant_ == bound.constant_;
155   }
156 
Equal(HInstruction * instruction1,HInstruction * instruction2)157   static bool Equal(HInstruction* instruction1, HInstruction* instruction2) {
158     if (instruction1 == instruction2) {
159       return true;
160     }
161     if (instruction1 == nullptr || instruction2 == nullptr) {
162       return false;
163     }
164     instruction1 = HuntForDeclaration(instruction1);
165     instruction2 = HuntForDeclaration(instruction2);
166     return instruction1 == instruction2;
167   }
168 
169   // Returns if it's certain this->bound >= `bound`.
GreaterThanOrEqualTo(ValueBound bound) const170   bool GreaterThanOrEqualTo(ValueBound bound) const {
171     if (Equal(instruction_, bound.instruction_)) {
172       return constant_ >= bound.constant_;
173     }
174     // Not comparable. Just return false.
175     return false;
176   }
177 
178   // Returns if it's certain this->bound <= `bound`.
LessThanOrEqualTo(ValueBound bound) const179   bool LessThanOrEqualTo(ValueBound bound) const {
180     if (Equal(instruction_, bound.instruction_)) {
181       return constant_ <= bound.constant_;
182     }
183     // Not comparable. Just return false.
184     return false;
185   }
186 
187   // Returns if it's certain this->bound > `bound`.
GreaterThan(ValueBound bound) const188   bool GreaterThan(ValueBound bound) const {
189     if (Equal(instruction_, bound.instruction_)) {
190       return constant_ > bound.constant_;
191     }
192     // Not comparable. Just return false.
193     return false;
194   }
195 
196   // Returns if it's certain this->bound < `bound`.
LessThan(ValueBound bound) const197   bool LessThan(ValueBound bound) const {
198     if (Equal(instruction_, bound.instruction_)) {
199       return constant_ < bound.constant_;
200     }
201     // Not comparable. Just return false.
202     return false;
203   }
204 
205   // Try to narrow lower bound. Returns the greatest of the two if possible.
206   // Pick one if they are not comparable.
NarrowLowerBound(ValueBound bound1,ValueBound bound2)207   static ValueBound NarrowLowerBound(ValueBound bound1, ValueBound bound2) {
208     if (bound1.GreaterThanOrEqualTo(bound2)) {
209       return bound1;
210     }
211     if (bound2.GreaterThanOrEqualTo(bound1)) {
212       return bound2;
213     }
214 
215     // Not comparable. Just pick one. We may lose some info, but that's ok.
216     // Favor constant as lower bound.
217     return bound1.IsConstant() ? bound1 : bound2;
218   }
219 
220   // Try to narrow upper bound. Returns the lowest of the two if possible.
221   // Pick one if they are not comparable.
NarrowUpperBound(ValueBound bound1,ValueBound bound2)222   static ValueBound NarrowUpperBound(ValueBound bound1, ValueBound bound2) {
223     if (bound1.LessThanOrEqualTo(bound2)) {
224       return bound1;
225     }
226     if (bound2.LessThanOrEqualTo(bound1)) {
227       return bound2;
228     }
229 
230     // Not comparable. Just pick one. We may lose some info, but that's ok.
231     // Favor array length as upper bound.
232     return bound1.IsRelatedToArrayLength() ? bound1 : bound2;
233   }
234 
235   // Add a constant to a ValueBound.
236   // `overflow` or `underflow` will return whether the resulting bound may
237   // overflow or underflow an int.
Add(int32_t c,bool * overflow,bool * underflow) const238   ValueBound Add(int32_t c, /* out */ bool* overflow, /* out */ bool* underflow) const {
239     *overflow = *underflow = false;
240     if (c == 0) {
241       return *this;
242     }
243 
244     int32_t new_constant;
245     if (c > 0) {
246       if (constant_ > (std::numeric_limits<int32_t>::max() - c)) {
247         *overflow = true;
248         return Max();
249       }
250 
251       new_constant = constant_ + c;
252       // (array.length + non-positive-constant) won't overflow an int.
253       if (IsConstant() || (IsRelatedToArrayLength() && new_constant <= 0)) {
254         return ValueBound(instruction_, new_constant);
255       }
256       // Be conservative.
257       *overflow = true;
258       return Max();
259     } else {
260       if (constant_ < (std::numeric_limits<int32_t>::min() - c)) {
261         *underflow = true;
262         return Min();
263       }
264 
265       new_constant = constant_ + c;
266       // Regardless of the value new_constant, (array.length+new_constant) will
267       // never underflow since array.length is no less than 0.
268       if (IsConstant() || IsRelatedToArrayLength()) {
269         return ValueBound(instruction_, new_constant);
270       }
271       // Be conservative.
272       *underflow = true;
273       return Min();
274     }
275   }
276 
277  private:
278   HInstruction* instruction_;
279   int32_t constant_;
280 };
281 
282 /**
283  * Represent a range of lower bound and upper bound, both being inclusive.
284  * Currently a ValueRange may be generated as a result of the following:
285  * comparisons related to array bounds, array bounds check, add/sub on top
286  * of an existing value range, NewArray or a loop phi corresponding to an
287  * incrementing/decrementing array index (MonotonicValueRange).
288  */
289 class ValueRange : public ArenaObject<kArenaAllocBoundsCheckElimination> {
290  public:
ValueRange(ScopedArenaAllocator * allocator,ValueBound lower,ValueBound upper)291   ValueRange(ScopedArenaAllocator* allocator, ValueBound lower, ValueBound upper)
292       : allocator_(allocator), lower_(lower), upper_(upper) {}
293 
~ValueRange()294   virtual ~ValueRange() {}
295 
AsMonotonicValueRange()296   virtual MonotonicValueRange* AsMonotonicValueRange() { return nullptr; }
IsMonotonicValueRange()297   bool IsMonotonicValueRange() {
298     return AsMonotonicValueRange() != nullptr;
299   }
300 
GetAllocator() const301   ScopedArenaAllocator* GetAllocator() const { return allocator_; }
GetLower() const302   ValueBound GetLower() const { return lower_; }
GetUpper() const303   ValueBound GetUpper() const { return upper_; }
304 
IsConstantValueRange() const305   bool IsConstantValueRange() const { return lower_.IsConstant() && upper_.IsConstant(); }
306 
307   // If it's certain that this value range fits in other_range.
FitsIn(ValueRange * other_range) const308   virtual bool FitsIn(ValueRange* other_range) const {
309     if (other_range == nullptr) {
310       return true;
311     }
312     DCHECK(!other_range->IsMonotonicValueRange());
313     return lower_.GreaterThanOrEqualTo(other_range->lower_) &&
314            upper_.LessThanOrEqualTo(other_range->upper_);
315   }
316 
317   // Returns the intersection of this and range.
318   // If it's not possible to do intersection because some
319   // bounds are not comparable, it's ok to pick either bound.
Narrow(ValueRange * range)320   virtual ValueRange* Narrow(ValueRange* range) {
321     if (range == nullptr) {
322       return this;
323     }
324 
325     if (range->IsMonotonicValueRange()) {
326       return this;
327     }
328 
329     return new (allocator_) ValueRange(
330         allocator_,
331         ValueBound::NarrowLowerBound(lower_, range->lower_),
332         ValueBound::NarrowUpperBound(upper_, range->upper_));
333   }
334 
335   // Shift a range by a constant.
Add(int32_t constant) const336   ValueRange* Add(int32_t constant) const {
337     bool overflow, underflow;
338     ValueBound lower = lower_.Add(constant, &overflow, &underflow);
339     if (underflow) {
340       // Lower bound underflow will wrap around to positive values
341       // and invalidate the upper bound.
342       return nullptr;
343     }
344     ValueBound upper = upper_.Add(constant, &overflow, &underflow);
345     if (overflow) {
346       // Upper bound overflow will wrap around to negative values
347       // and invalidate the lower bound.
348       return nullptr;
349     }
350     return new (allocator_) ValueRange(allocator_, lower, upper);
351   }
352 
353  private:
354   ScopedArenaAllocator* const allocator_;
355   const ValueBound lower_;  // inclusive
356   const ValueBound upper_;  // inclusive
357 
358   DISALLOW_COPY_AND_ASSIGN(ValueRange);
359 };
360 
361 /**
362  * A monotonically incrementing/decrementing value range, e.g.
363  * the variable i in "for (int i=0; i<array.length; i++)".
364  * Special care needs to be taken to account for overflow/underflow
365  * of such value ranges.
366  */
367 class MonotonicValueRange : public ValueRange {
368  public:
MonotonicValueRange(ScopedArenaAllocator * allocator,HPhi * induction_variable,HInstruction * initial,int32_t increment,ValueBound bound)369   MonotonicValueRange(ScopedArenaAllocator* allocator,
370                       HPhi* induction_variable,
371                       HInstruction* initial,
372                       int32_t increment,
373                       ValueBound bound)
374       // To be conservative, give it full range [Min(), Max()] in case it's
375       // used as a regular value range, due to possible overflow/underflow.
376       : ValueRange(allocator, ValueBound::Min(), ValueBound::Max()),
377         induction_variable_(induction_variable),
378         initial_(initial),
379         increment_(increment),
380         bound_(bound) {}
381 
~MonotonicValueRange()382   virtual ~MonotonicValueRange() {}
383 
GetIncrement() const384   int32_t GetIncrement() const { return increment_; }
GetBound() const385   ValueBound GetBound() const { return bound_; }
GetLoopHeader() const386   HBasicBlock* GetLoopHeader() const {
387     DCHECK(induction_variable_->GetBlock()->IsLoopHeader());
388     return induction_variable_->GetBlock();
389   }
390 
AsMonotonicValueRange()391   MonotonicValueRange* AsMonotonicValueRange() override { return this; }
392 
393   // If it's certain that this value range fits in other_range.
FitsIn(ValueRange * other_range) const394   bool FitsIn(ValueRange* other_range) const override {
395     if (other_range == nullptr) {
396       return true;
397     }
398     DCHECK(!other_range->IsMonotonicValueRange());
399     return false;
400   }
401 
402   // Try to narrow this MonotonicValueRange given another range.
403   // Ideally it will return a normal ValueRange. But due to
404   // possible overflow/underflow, that may not be possible.
Narrow(ValueRange * range)405   ValueRange* Narrow(ValueRange* range) override {
406     if (range == nullptr) {
407       return this;
408     }
409     DCHECK(!range->IsMonotonicValueRange());
410 
411     if (increment_ > 0) {
412       // Monotonically increasing.
413       ValueBound lower = ValueBound::NarrowLowerBound(bound_, range->GetLower());
414       if (!lower.IsConstant() || lower.GetConstant() == std::numeric_limits<int32_t>::min()) {
415         // Lower bound isn't useful. Leave it to deoptimization.
416         return this;
417       }
418 
419       // We currently conservatively assume max array length is Max().
420       // If we can make assumptions about the max array length, e.g. due to the max heap size,
421       // divided by the element size (such as 4 bytes for each integer array), we can
422       // lower this number and rule out some possible overflows.
423       int32_t max_array_len = std::numeric_limits<int32_t>::max();
424 
425       // max possible integer value of range's upper value.
426       int32_t upper = std::numeric_limits<int32_t>::max();
427       // Try to lower upper.
428       ValueBound upper_bound = range->GetUpper();
429       if (upper_bound.IsConstant()) {
430         upper = upper_bound.GetConstant();
431       } else if (upper_bound.IsRelatedToArrayLength() && upper_bound.GetConstant() <= 0) {
432         // Normal case. e.g. <= array.length - 1.
433         upper = max_array_len + upper_bound.GetConstant();
434       }
435 
436       // If we can prove for the last number in sequence of initial_,
437       // initial_ + increment_, initial_ + 2 x increment_, ...
438       // that's <= upper, (last_num_in_sequence + increment_) doesn't trigger overflow,
439       // then this MonoticValueRange is narrowed to a normal value range.
440 
441       // Be conservative first, assume last number in the sequence hits upper.
442       int32_t last_num_in_sequence = upper;
443       if (initial_->IsIntConstant()) {
444         int32_t initial_constant = initial_->AsIntConstant()->GetValue();
445         if (upper <= initial_constant) {
446           last_num_in_sequence = upper;
447         } else {
448           // Cast to int64_t for the substraction part to avoid int32_t overflow.
449           last_num_in_sequence = initial_constant +
450               ((int64_t)upper - (int64_t)initial_constant) / increment_ * increment_;
451         }
452       }
453       if (last_num_in_sequence <= (std::numeric_limits<int32_t>::max() - increment_)) {
454         // No overflow. The sequence will be stopped by the upper bound test as expected.
455         return new (GetAllocator()) ValueRange(GetAllocator(), lower, range->GetUpper());
456       }
457 
458       // There might be overflow. Give up narrowing.
459       return this;
460     } else {
461       DCHECK_NE(increment_, 0);
462       // Monotonically decreasing.
463       ValueBound upper = ValueBound::NarrowUpperBound(bound_, range->GetUpper());
464       if ((!upper.IsConstant() || upper.GetConstant() == std::numeric_limits<int32_t>::max()) &&
465           !upper.IsRelatedToArrayLength()) {
466         // Upper bound isn't useful. Leave it to deoptimization.
467         return this;
468       }
469 
470       // Need to take care of underflow. Try to prove underflow won't happen
471       // for common cases.
472       if (range->GetLower().IsConstant()) {
473         int32_t constant = range->GetLower().GetConstant();
474         if (constant >= (std::numeric_limits<int32_t>::min() - increment_)) {
475           return new (GetAllocator()) ValueRange(GetAllocator(), range->GetLower(), upper);
476         }
477       }
478 
479       // For non-constant lower bound, just assume might be underflow. Give up narrowing.
480       return this;
481     }
482   }
483 
484  private:
485   HPhi* const induction_variable_;  // Induction variable for this monotonic value range.
486   HInstruction* const initial_;     // Initial value.
487   const int32_t increment_;         // Increment for each loop iteration.
488   const ValueBound bound_;          // Additional value bound info for initial_.
489 
490   DISALLOW_COPY_AND_ASSIGN(MonotonicValueRange);
491 };
492 
493 class BCEVisitor final : public HGraphVisitor {
494  public:
495   // The least number of bounds checks that should be eliminated by triggering
496   // the deoptimization technique.
497   static constexpr size_t kThresholdForAddingDeoptimize = 2;
498 
499   // Very large lengths are considered an anomaly. This is a threshold beyond which we don't
500   // bother to apply the deoptimization technique since it's likely, or sometimes certain,
501   // an AIOOBE will be thrown.
502   static constexpr uint32_t kMaxLengthForAddingDeoptimize =
503       std::numeric_limits<int32_t>::max() - 1024 * 1024;
504 
505   // Added blocks for loop body entry test.
IsAddedBlock(HBasicBlock * block) const506   bool IsAddedBlock(HBasicBlock* block) const {
507     return block->GetBlockId() >= initial_block_size_;
508   }
509 
BCEVisitor(HGraph * graph,const SideEffectsAnalysis & side_effects,HInductionVarAnalysis * induction_analysis)510   BCEVisitor(HGraph* graph,
511              const SideEffectsAnalysis& side_effects,
512              HInductionVarAnalysis* induction_analysis)
513       : HGraphVisitor(graph),
514         allocator_(graph->GetArenaStack()),
515         maps_(graph->GetBlocks().size(),
516               ScopedArenaSafeMap<int, ValueRange*>(
517                   std::less<int>(),
518                   allocator_.Adapter(kArenaAllocBoundsCheckElimination)),
519               allocator_.Adapter(kArenaAllocBoundsCheckElimination)),
520         first_index_bounds_check_map_(std::less<int>(),
521                                       allocator_.Adapter(kArenaAllocBoundsCheckElimination)),
522         early_exit_loop_(std::less<uint32_t>(),
523                          allocator_.Adapter(kArenaAllocBoundsCheckElimination)),
524         taken_test_loop_(std::less<uint32_t>(),
525                          allocator_.Adapter(kArenaAllocBoundsCheckElimination)),
526         finite_loop_(allocator_.Adapter(kArenaAllocBoundsCheckElimination)),
527         has_dom_based_dynamic_bce_(false),
528         initial_block_size_(graph->GetBlocks().size()),
529         side_effects_(side_effects),
530         induction_range_(induction_analysis),
531         next_(nullptr) {}
532 
VisitBasicBlock(HBasicBlock * block)533   void VisitBasicBlock(HBasicBlock* block) override {
534     DCHECK(!IsAddedBlock(block));
535     first_index_bounds_check_map_.clear();
536     // Visit phis and instructions using a safe iterator. The iteration protects
537     // against deleting the current instruction during iteration. However, it
538     // must advance next_ if that instruction is deleted during iteration.
539     for (HInstruction* instruction = block->GetFirstPhi(); instruction != nullptr;) {
540       DCHECK(instruction->IsInBlock());
541       next_ = instruction->GetNext();
542       instruction->Accept(this);
543       instruction = next_;
544     }
545     for (HInstruction* instruction = block->GetFirstInstruction(); instruction != nullptr;) {
546       DCHECK(instruction->IsInBlock());
547       next_ = instruction->GetNext();
548       instruction->Accept(this);
549       instruction = next_;
550     }
551     // We should never deoptimize from an osr method, otherwise we might wrongly optimize
552     // code dominated by the deoptimization.
553     if (!GetGraph()->IsCompilingOsr()) {
554       AddComparesWithDeoptimization(block);
555     }
556   }
557 
Finish()558   void Finish() {
559     // Preserve SSA structure which may have been broken by adding one or more
560     // new taken-test structures (see TransformLoopForDeoptimizationIfNeeded()).
561     InsertPhiNodes();
562 
563     // Clear the loop data structures.
564     early_exit_loop_.clear();
565     taken_test_loop_.clear();
566     finite_loop_.clear();
567 
568     // We may have eliminated all bounds checks so we should update the flag.
569     // TODO(solanes): Do this without a linear pass of the graph?
570     GetGraph()->SetHasBoundsChecks(false);
571     for (HBasicBlock* block : GetGraph()->GetReversePostOrder()) {
572       for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
573         HInstruction* instruction = it.Current();
574         if (instruction->IsBoundsCheck()) {
575           GetGraph()->SetHasBoundsChecks(true);
576           return;
577         }
578       }
579     }
580   }
581 
582  private:
583   // Return the map of proven value ranges at the beginning of a basic block.
GetValueRangeMap(HBasicBlock * basic_block)584   ScopedArenaSafeMap<int, ValueRange*>* GetValueRangeMap(HBasicBlock* basic_block) {
585     if (IsAddedBlock(basic_block)) {
586       // Added blocks don't keep value ranges.
587       return nullptr;
588     }
589     return &maps_[basic_block->GetBlockId()];
590   }
591 
592   // Traverse up the dominator tree to look for value range info.
LookupValueRange(HInstruction * instruction,HBasicBlock * basic_block)593   ValueRange* LookupValueRange(HInstruction* instruction, HBasicBlock* basic_block) {
594     while (basic_block != nullptr) {
595       ScopedArenaSafeMap<int, ValueRange*>* map = GetValueRangeMap(basic_block);
596       if (map != nullptr) {
597         if (map->find(instruction->GetId()) != map->end()) {
598           return map->Get(instruction->GetId());
599         }
600       } else {
601         DCHECK(IsAddedBlock(basic_block));
602       }
603       basic_block = basic_block->GetDominator();
604     }
605     // Didn't find any.
606     return nullptr;
607   }
608 
609   // Helper method to assign a new range to an instruction in given basic block.
AssignRange(HBasicBlock * basic_block,HInstruction * instruction,ValueRange * range)610   void AssignRange(HBasicBlock* basic_block, HInstruction* instruction, ValueRange* range) {
611     DCHECK_IMPLIES(range->IsMonotonicValueRange(), instruction->IsLoopHeaderPhi());
612     GetValueRangeMap(basic_block)->Overwrite(instruction->GetId(), range);
613   }
614 
615   // Narrow the value range of `instruction` at the end of `basic_block` with `range`,
616   // and push the narrowed value range to `successor`.
ApplyRangeFromComparison(HInstruction * instruction,HBasicBlock * basic_block,HBasicBlock * successor,ValueRange * range)617   void ApplyRangeFromComparison(HInstruction* instruction, HBasicBlock* basic_block,
618                                 HBasicBlock* successor, ValueRange* range) {
619     ValueRange* existing_range = LookupValueRange(instruction, basic_block);
620     if (existing_range == nullptr) {
621       if (range != nullptr) {
622         AssignRange(successor, instruction, range);
623       }
624       return;
625     }
626     if (existing_range->IsMonotonicValueRange()) {
627       DCHECK(instruction->IsLoopHeaderPhi());
628       // Make sure the comparison is in the loop header so each increment is
629       // checked with a comparison.
630       if (instruction->GetBlock() != basic_block) {
631         return;
632       }
633     }
634     AssignRange(successor, instruction, existing_range->Narrow(range));
635   }
636 
637   // Special case that we may simultaneously narrow two MonotonicValueRange's to
638   // regular value ranges.
HandleIfBetweenTwoMonotonicValueRanges(HIf * instruction,HInstruction * left,HInstruction * right,IfCondition cond,MonotonicValueRange * left_range,MonotonicValueRange * right_range)639   void HandleIfBetweenTwoMonotonicValueRanges(HIf* instruction,
640                                               HInstruction* left,
641                                               HInstruction* right,
642                                               IfCondition cond,
643                                               MonotonicValueRange* left_range,
644                                               MonotonicValueRange* right_range) {
645     DCHECK(left->IsLoopHeaderPhi());
646     DCHECK(right->IsLoopHeaderPhi());
647     if (instruction->GetBlock() != left->GetBlock()) {
648       // Comparison needs to be in loop header to make sure it's done after each
649       // increment/decrement.
650       return;
651     }
652 
653     // Handle common cases which also don't have overflow/underflow concerns.
654     if (left_range->GetIncrement() == 1 &&
655         left_range->GetBound().IsConstant() &&
656         right_range->GetIncrement() == -1 &&
657         right_range->GetBound().IsRelatedToArrayLength() &&
658         right_range->GetBound().GetConstant() < 0) {
659       HBasicBlock* successor = nullptr;
660       int32_t left_compensation = 0;
661       int32_t right_compensation = 0;
662       if (cond == kCondLT) {
663         left_compensation = -1;
664         right_compensation = 1;
665         successor = instruction->IfTrueSuccessor();
666       } else if (cond == kCondLE) {
667         successor = instruction->IfTrueSuccessor();
668       } else if (cond == kCondGT) {
669         successor = instruction->IfFalseSuccessor();
670       } else if (cond == kCondGE) {
671         left_compensation = -1;
672         right_compensation = 1;
673         successor = instruction->IfFalseSuccessor();
674       } else {
675         // We don't handle '=='/'!=' test in case left and right can cross and
676         // miss each other.
677         return;
678       }
679 
680       if (successor != nullptr) {
681         bool overflow;
682         bool underflow;
683         ValueRange* new_left_range = new (&allocator_) ValueRange(
684             &allocator_,
685             left_range->GetBound(),
686             right_range->GetBound().Add(left_compensation, &overflow, &underflow));
687         if (!overflow && !underflow) {
688           ApplyRangeFromComparison(left, instruction->GetBlock(), successor,
689                                    new_left_range);
690         }
691 
692         ValueRange* new_right_range = new (&allocator_) ValueRange(
693             &allocator_,
694             left_range->GetBound().Add(right_compensation, &overflow, &underflow),
695             right_range->GetBound());
696         if (!overflow && !underflow) {
697           ApplyRangeFromComparison(right, instruction->GetBlock(), successor,
698                                    new_right_range);
699         }
700       }
701     }
702   }
703 
704   // Handle "if (left cmp_cond right)".
HandleIf(HIf * instruction,HInstruction * left,HInstruction * right,IfCondition cond)705   void HandleIf(HIf* instruction, HInstruction* left, HInstruction* right, IfCondition cond) {
706     HBasicBlock* block = instruction->GetBlock();
707 
708     HBasicBlock* true_successor = instruction->IfTrueSuccessor();
709     // There should be no critical edge at this point.
710     DCHECK_EQ(true_successor->GetPredecessors().size(), 1u);
711 
712     HBasicBlock* false_successor = instruction->IfFalseSuccessor();
713     // There should be no critical edge at this point.
714     DCHECK_EQ(false_successor->GetPredecessors().size(), 1u);
715 
716     ValueRange* left_range = LookupValueRange(left, block);
717     MonotonicValueRange* left_monotonic_range = nullptr;
718     if (left_range != nullptr) {
719       left_monotonic_range = left_range->AsMonotonicValueRange();
720       if (left_monotonic_range != nullptr) {
721         HBasicBlock* loop_head = left_monotonic_range->GetLoopHeader();
722         if (instruction->GetBlock() != loop_head) {
723           // For monotonic value range, don't handle `instruction`
724           // if it's not defined in the loop header.
725           return;
726         }
727       }
728     }
729 
730     bool found;
731     ValueBound bound = ValueBound::DetectValueBoundFromValue(right, &found);
732     // Each comparison can establish a lower bound and an upper bound
733     // for the left hand side.
734     ValueBound lower = bound;
735     ValueBound upper = bound;
736     if (!found) {
737       // No constant or array.length+c format bound found.
738       // For i<j, we can still use j's upper bound as i's upper bound. Same for lower.
739       ValueRange* right_range = LookupValueRange(right, block);
740       if (right_range != nullptr) {
741         if (right_range->IsMonotonicValueRange()) {
742           if (left_range != nullptr && left_range->IsMonotonicValueRange()) {
743             HandleIfBetweenTwoMonotonicValueRanges(instruction, left, right, cond,
744                                                    left_range->AsMonotonicValueRange(),
745                                                    right_range->AsMonotonicValueRange());
746             return;
747           }
748         }
749         lower = right_range->GetLower();
750         upper = right_range->GetUpper();
751       } else {
752         lower = ValueBound::Min();
753         upper = ValueBound::Max();
754       }
755     }
756 
757     bool overflow, underflow;
758     if (cond == kCondLT || cond == kCondLE) {
759       if (!upper.Equals(ValueBound::Max())) {
760         int32_t compensation = (cond == kCondLT) ? -1 : 0;  // upper bound is inclusive
761         ValueBound new_upper = upper.Add(compensation, &overflow, &underflow);
762         if (overflow || underflow) {
763           return;
764         }
765         ValueRange* new_range = new (&allocator_) ValueRange(
766             &allocator_, ValueBound::Min(), new_upper);
767         ApplyRangeFromComparison(left, block, true_successor, new_range);
768       }
769 
770       // array.length as a lower bound isn't considered useful.
771       if (!lower.Equals(ValueBound::Min()) && !lower.IsRelatedToArrayLength()) {
772         int32_t compensation = (cond == kCondLE) ? 1 : 0;  // lower bound is inclusive
773         ValueBound new_lower = lower.Add(compensation, &overflow, &underflow);
774         if (overflow || underflow) {
775           return;
776         }
777         ValueRange* new_range = new (&allocator_) ValueRange(
778             &allocator_, new_lower, ValueBound::Max());
779         ApplyRangeFromComparison(left, block, false_successor, new_range);
780       }
781     } else if (cond == kCondGT || cond == kCondGE) {
782       // array.length as a lower bound isn't considered useful.
783       if (!lower.Equals(ValueBound::Min()) && !lower.IsRelatedToArrayLength()) {
784         int32_t compensation = (cond == kCondGT) ? 1 : 0;  // lower bound is inclusive
785         ValueBound new_lower = lower.Add(compensation, &overflow, &underflow);
786         if (overflow || underflow) {
787           return;
788         }
789         ValueRange* new_range = new (&allocator_) ValueRange(
790             &allocator_, new_lower, ValueBound::Max());
791         ApplyRangeFromComparison(left, block, true_successor, new_range);
792       }
793 
794       if (!upper.Equals(ValueBound::Max())) {
795         int32_t compensation = (cond == kCondGE) ? -1 : 0;  // upper bound is inclusive
796         ValueBound new_upper = upper.Add(compensation, &overflow, &underflow);
797         if (overflow || underflow) {
798           return;
799         }
800         ValueRange* new_range = new (&allocator_) ValueRange(
801             &allocator_, ValueBound::Min(), new_upper);
802         ApplyRangeFromComparison(left, block, false_successor, new_range);
803       }
804     } else if (cond == kCondNE || cond == kCondEQ) {
805       if (left->IsArrayLength()) {
806         if (lower.IsConstant() && upper.IsConstant()) {
807           // Special case:
808           //   length == [c,d] yields [c, d] along true
809           //   length != [c,d] yields [c, d] along false
810           if (!lower.Equals(ValueBound::Min()) || !upper.Equals(ValueBound::Max())) {
811             ValueRange* new_range = new (&allocator_) ValueRange(&allocator_, lower, upper);
812             ApplyRangeFromComparison(
813                 left, block, cond == kCondEQ ? true_successor : false_successor, new_range);
814           }
815           // In addition:
816           //   length == 0 yields [1, max] along false
817           //   length != 0 yields [1, max] along true
818           if (lower.GetConstant() == 0 && upper.GetConstant() == 0) {
819             ValueRange* new_range = new (&allocator_) ValueRange(
820                 &allocator_, ValueBound(nullptr, 1), ValueBound::Max());
821             ApplyRangeFromComparison(
822                 left, block, cond == kCondEQ ? false_successor : true_successor, new_range);
823           }
824         }
825       } else if (lower.IsRelatedToArrayLength() && lower.Equals(upper)) {
826         // Special aliasing case, with x not array length itself:
827         //   x == [length,length] yields x == length along true
828         //   x != [length,length] yields x == length along false
829         ValueRange* new_range = new (&allocator_) ValueRange(&allocator_, lower, upper);
830         ApplyRangeFromComparison(
831             left, block, cond == kCondEQ ? true_successor : false_successor, new_range);
832       }
833     }
834   }
835 
VisitBoundsCheck(HBoundsCheck * bounds_check)836   void VisitBoundsCheck(HBoundsCheck* bounds_check) override {
837     HBasicBlock* block = bounds_check->GetBlock();
838     HInstruction* index = bounds_check->InputAt(0);
839     HInstruction* array_length = bounds_check->InputAt(1);
840     DCHECK(array_length->IsIntConstant() ||
841            array_length->IsArrayLength() ||
842            array_length->IsPhi());
843     bool try_dynamic_bce = true;
844     // Analyze index range.
845     if (!index->IsIntConstant()) {
846       // Non-constant index.
847       ValueBound lower = ValueBound(nullptr, 0);        // constant 0
848       ValueBound upper = ValueBound(array_length, -1);  // array_length - 1
849       ValueRange array_range(&allocator_, lower, upper);
850       // Try index range obtained by dominator-based analysis.
851       ValueRange* index_range = LookupValueRange(index, block);
852       if (index_range != nullptr) {
853         if (index_range->FitsIn(&array_range)) {
854           ReplaceInstruction(bounds_check, index);
855           return;
856         } else if (index_range->IsConstantValueRange()) {
857           // If the non-constant index turns out to have a constant range,
858           // make one more attempt to get a constant in the array range.
859           ValueRange* existing_range = LookupValueRange(array_length, block);
860           if (existing_range != nullptr &&
861               existing_range->IsConstantValueRange() &&
862               existing_range->GetLower().GetConstant() > 0) {
863             ValueBound constant_upper(nullptr, existing_range->GetLower().GetConstant() - 1);
864             ValueRange constant_array_range(&allocator_, lower, constant_upper);
865             if (index_range->FitsIn(&constant_array_range)) {
866               ReplaceInstruction(bounds_check, index);
867               return;
868             }
869           }
870         }
871       }
872       // Try index range obtained by induction variable analysis.
873       // Disables dynamic bce if OOB is certain.
874       if (InductionRangeFitsIn(&array_range, bounds_check, &try_dynamic_bce)) {
875         ReplaceInstruction(bounds_check, index);
876         return;
877       }
878     } else {
879       // Constant index.
880       int32_t constant = index->AsIntConstant()->GetValue();
881       if (constant < 0) {
882         // Will always throw exception.
883         return;
884       } else if (array_length->IsIntConstant()) {
885         if (constant < array_length->AsIntConstant()->GetValue()) {
886           ReplaceInstruction(bounds_check, index);
887         }
888         return;
889       }
890       // Analyze array length range.
891       DCHECK(array_length->IsArrayLength());
892       ValueRange* existing_range = LookupValueRange(array_length, block);
893       if (existing_range != nullptr) {
894         ValueBound lower = existing_range->GetLower();
895         DCHECK(lower.IsConstant());
896         if (constant < lower.GetConstant()) {
897           ReplaceInstruction(bounds_check, index);
898           return;
899         } else {
900           // Existing range isn't strong enough to eliminate the bounds check.
901           // Fall through to update the array_length range with info from this
902           // bounds check.
903         }
904       }
905       // Once we have an array access like 'array[5] = 1', we record array.length >= 6.
906       // We currently don't do it for non-constant index since a valid array[i] can't prove
907       // a valid array[i-1] yet due to the lower bound side.
908       if (constant == std::numeric_limits<int32_t>::max()) {
909         // Max() as an index will definitely throw AIOOBE.
910         return;
911       } else {
912         ValueBound lower = ValueBound(nullptr, constant + 1);
913         ValueBound upper = ValueBound::Max();
914         ValueRange* range = new (&allocator_) ValueRange(&allocator_, lower, upper);
915         AssignRange(block, array_length, range);
916       }
917     }
918 
919     // If static analysis fails, and OOB is not certain, try dynamic elimination.
920     if (try_dynamic_bce) {
921       // Try loop-based dynamic elimination.
922       HLoopInformation* loop = bounds_check->GetBlock()->GetLoopInformation();
923       bool needs_finite_test = false;
924       bool needs_taken_test = false;
925       if (DynamicBCESeemsProfitable(loop, bounds_check->GetBlock()) &&
926           induction_range_.CanGenerateRange(
927               bounds_check->GetBlock(), index, &needs_finite_test, &needs_taken_test) &&
928           CanHandleInfiniteLoop(loop, index, needs_finite_test) &&
929           // Do this test last, since it may generate code.
930           CanHandleLength(loop, array_length, needs_taken_test)) {
931         TransformLoopForDeoptimizationIfNeeded(loop, needs_taken_test);
932         TransformLoopForDynamicBCE(loop, bounds_check);
933         return;
934       }
935       // Otherwise, prepare dominator-based dynamic elimination.
936       if (first_index_bounds_check_map_.find(array_length->GetId()) ==
937           first_index_bounds_check_map_.end()) {
938         // Remember the first bounds check against each array_length. That bounds check
939         // instruction has an associated HEnvironment where we may add an HDeoptimize
940         // to eliminate subsequent bounds checks against the same array_length.
941         first_index_bounds_check_map_.Put(array_length->GetId(), bounds_check);
942       }
943     }
944   }
945 
HasSameInputAtBackEdges(HPhi * phi)946   static bool HasSameInputAtBackEdges(HPhi* phi) {
947     DCHECK(phi->IsLoopHeaderPhi());
948     HConstInputsRef inputs = phi->GetInputs();
949     // Start with input 1. Input 0 is from the incoming block.
950     const HInstruction* input1 = inputs[1];
951     DCHECK(phi->GetBlock()->GetLoopInformation()->IsBackEdge(
952         *phi->GetBlock()->GetPredecessors()[1]));
953     for (size_t i = 2; i < inputs.size(); ++i) {
954       DCHECK(phi->GetBlock()->GetLoopInformation()->IsBackEdge(
955           *phi->GetBlock()->GetPredecessors()[i]));
956       if (input1 != inputs[i]) {
957         return false;
958       }
959     }
960     return true;
961   }
962 
VisitPhi(HPhi * phi)963   void VisitPhi(HPhi* phi) override {
964     if (phi->IsLoopHeaderPhi()
965         && (phi->GetType() == DataType::Type::kInt32)
966         && HasSameInputAtBackEdges(phi)) {
967       HInstruction* instruction = phi->InputAt(1);
968       HInstruction *left;
969       int32_t increment;
970       if (ValueBound::IsAddOrSubAConstant(instruction, &left, &increment)) {
971         if (left == phi) {
972           HInstruction* initial_value = phi->InputAt(0);
973           ValueRange* range = nullptr;
974           if (increment == 0) {
975             // Add constant 0. It's really a fixed value.
976             range = new (&allocator_) ValueRange(
977                 &allocator_,
978                 ValueBound(initial_value, 0),
979                 ValueBound(initial_value, 0));
980           } else {
981             // Monotonically increasing/decreasing.
982             bool found;
983             ValueBound bound = ValueBound::DetectValueBoundFromValue(
984                 initial_value, &found);
985             if (!found) {
986               // No constant or array.length+c bound found.
987               // For i=j, we can still use j's upper bound as i's upper bound.
988               // Same for lower.
989               ValueRange* initial_range = LookupValueRange(initial_value, phi->GetBlock());
990               if (initial_range != nullptr) {
991                 bound = increment > 0 ? initial_range->GetLower() :
992                                         initial_range->GetUpper();
993               } else {
994                 bound = increment > 0 ? ValueBound::Min() : ValueBound::Max();
995               }
996             }
997             range = new (&allocator_) MonotonicValueRange(
998                 &allocator_,
999                 phi,
1000                 initial_value,
1001                 increment,
1002                 bound);
1003           }
1004           AssignRange(phi->GetBlock(), phi, range);
1005         }
1006       }
1007     }
1008   }
1009 
VisitIf(HIf * instruction)1010   void VisitIf(HIf* instruction) override {
1011     if (instruction->InputAt(0)->IsCondition()) {
1012       HCondition* cond = instruction->InputAt(0)->AsCondition();
1013       HandleIf(instruction, cond->GetLeft(), cond->GetRight(), cond->GetCondition());
1014     }
1015   }
1016 
1017   // Check whether HSub is a result of the HRem optimization of:
1018   //   q = Div(dividend, const_divisor)
1019   //   r = Rem(dividend, const_divisor)
1020   // into
1021   //   q = Div(dividend, const_divisor)
1022   //   t = Mul(q, const_divisor)
1023   //   r = Sub(dividend, t)
1024   // or for divisors 2^n + 1 into
1025   //   q  = Div(dividend, const_divisor)
1026   //   t1 = Shl(q, n)
1027   //   t2 = Add(q, t1)
1028   //   r  = Sub(dividend, t2)
1029   // or for divisors 2^n - 1 into
1030   //   q  = Div(dividend, const_divisor)
1031   //   t1 = Shl(q, n)
1032   //   t2 = Sub(t1, q)
1033   //   r  = Sub(dividend, t2)
1034   //
1035   // If it is the case, the value range for the instruction is
1036   // [1 - abs(const_divisor), abs(const_divisor) - 1] merged with
1037   // the range of the left input is assigned and true is returned. Otherwise,
1038   // no range is assigned and false is returned.
TryToAssignRangeIfOptimizedRemWithConstantDivisor(HSub * instruction)1039   bool TryToAssignRangeIfOptimizedRemWithConstantDivisor(HSub* instruction) {
1040     if (instruction->GetResultType() != DataType::Type::kInt32) {
1041       return false;
1042     }
1043 
1044     auto is_needed_shl = [](HShl* shl) {
1045       return shl != nullptr && shl->GetRight()->IsConstant() && shl->GetLeft()->IsDiv();
1046     };
1047 
1048     HDiv* div = nullptr;
1049     int64_t const_divisor = 0;
1050     if (HMul* mul = instruction->GetRight()->AsMulOrNull()) {
1051       if (!mul->GetLeft()->IsDiv() || !mul->GetRight()->IsConstant()) {
1052         return false;
1053       }
1054       div = mul->GetLeft()->AsDiv();
1055       const_divisor = Int64FromConstant(mul->GetRight()->AsConstant());
1056     } else if (HAdd* add = instruction->GetRight()->AsAddOrNull()) {
1057       HShl* shl = add->GetRight()->AsShlOrNull();
1058       if (!is_needed_shl(shl)) {
1059         return false;
1060       }
1061 
1062       div = shl->GetLeft()->AsDiv();
1063       if (add->GetLeft() != div) {
1064         return false;
1065       }
1066 
1067       int32_t n = shl->GetRight()->AsIntConstant()->GetValue();
1068       if (n == BitSizeOf<int32_t>() - 1) {
1069         // 2^n + 1 will be negative.
1070         return false;
1071       }
1072       const_divisor = (1LL << n) + 1;
1073     } else if (HSub* sub = instruction->GetRight()->AsSubOrNull()) {
1074       HShl* shl = sub->GetLeft()->AsShlOrNull();
1075       if (!is_needed_shl(shl)) {
1076         return false;
1077       }
1078 
1079       div = shl->GetLeft()->AsDiv();
1080       if (sub->GetRight() != div) {
1081         return false;
1082       }
1083 
1084       int32_t n = shl->GetRight()->AsIntConstant()->GetValue();
1085       const_divisor = (1LL << n) - 1;
1086     }
1087 
1088     if (div == nullptr || !IsInt64Value(div->GetRight(), const_divisor) ||
1089         div->GetLeft() != instruction->GetLeft()) {
1090       return false;
1091     }
1092 
1093     ValueRange* range = nullptr;
1094     if (const_divisor == DataType::MinValueOfIntegralType(DataType::Type::kInt32)) {
1095       range = new (&allocator_) ValueRange(&allocator_,
1096           ValueBound(nullptr, DataType::MinValueOfIntegralType(DataType::Type::kInt32) + 1),
1097           ValueBound(nullptr, DataType::MaxValueOfIntegralType(DataType::Type::kInt32)));
1098     } else {
1099       DCHECK_GT(const_divisor, DataType::MinValueOfIntegralType(DataType::Type::kInt32));
1100       DCHECK_LE(const_divisor, DataType::MaxValueOfIntegralType(DataType::Type::kInt32));
1101       int32_t abs_const_divisor = static_cast<int32_t>(std::abs(const_divisor));
1102       range = new (&allocator_) ValueRange(&allocator_,
1103                                            ValueBound(nullptr, 1 - abs_const_divisor),
1104                                            ValueBound(nullptr, abs_const_divisor - 1));
1105     }
1106     HBasicBlock* basic_block = instruction->GetBlock();
1107     if (ValueRange* left_range = LookupValueRange(instruction->GetLeft(), basic_block)) {
1108       range = range->Narrow(left_range);
1109     }
1110     AssignRange(basic_block, instruction, range);
1111     return true;
1112   }
1113 
VisitAdd(HAdd * add)1114   void VisitAdd(HAdd* add) override {
1115     HInstruction* right = add->GetRight();
1116     if (right->IsIntConstant()) {
1117       ValueRange* left_range = LookupValueRange(add->GetLeft(), add->GetBlock());
1118       if (left_range == nullptr) {
1119         return;
1120       }
1121       ValueRange* range = left_range->Add(right->AsIntConstant()->GetValue());
1122       if (range != nullptr) {
1123         AssignRange(add->GetBlock(), add, range);
1124       }
1125     }
1126   }
1127 
VisitSub(HSub * sub)1128   void VisitSub(HSub* sub) override {
1129     if (TryToAssignRangeIfOptimizedRemWithConstantDivisor(sub)) {
1130       return;
1131     }
1132 
1133     HInstruction* left = sub->GetLeft();
1134     HInstruction* right = sub->GetRight();
1135     if (right->IsIntConstant()) {
1136       ValueRange* left_range = LookupValueRange(left, sub->GetBlock());
1137       if (left_range == nullptr) {
1138         return;
1139       }
1140       ValueRange* range = left_range->Add(-right->AsIntConstant()->GetValue());
1141       if (range != nullptr) {
1142         AssignRange(sub->GetBlock(), sub, range);
1143         return;
1144       }
1145     }
1146 
1147     // Here we are interested in the typical triangular case of nested loops,
1148     // such as the inner loop 'for (int j=0; j<array.length-i; j++)' where i
1149     // is the index for outer loop. In this case, we know j is bounded by array.length-1.
1150 
1151     // Try to handle (array.length - i) or (array.length + c - i) format.
1152     HInstruction* left_of_left;  // left input of left.
1153     int32_t right_const = 0;
1154     if (ValueBound::IsAddOrSubAConstant(left, &left_of_left, &right_const)) {
1155       left = left_of_left;
1156     }
1157     // The value of left input of the sub equals (left + right_const).
1158 
1159     if (left->IsArrayLength()) {
1160       HInstruction* array_length = left->AsArrayLength();
1161       ValueRange* right_range = LookupValueRange(right, sub->GetBlock());
1162       if (right_range != nullptr) {
1163         ValueBound lower = right_range->GetLower();
1164         ValueBound upper = right_range->GetUpper();
1165         if (lower.IsConstant() && upper.IsRelatedToArrayLength()) {
1166           HInstruction* upper_inst = upper.GetInstruction();
1167           // Make sure it's the same array.
1168           if (ValueBound::Equal(array_length, upper_inst)) {
1169             int32_t c0 = right_const;
1170             int32_t c1 = lower.GetConstant();
1171             int32_t c2 = upper.GetConstant();
1172             // (array.length + c0 - v) where v is in [c1, array.length + c2]
1173             // gets [c0 - c2, array.length + c0 - c1] as its value range.
1174             if (!ValueBound::WouldAddOverflowOrUnderflow(c0, -c2) &&
1175                 !ValueBound::WouldAddOverflowOrUnderflow(c0, -c1)) {
1176               if ((c0 - c1) <= 0) {
1177                 // array.length + (c0 - c1) won't overflow/underflow.
1178                 ValueRange* range = new (&allocator_) ValueRange(
1179                     &allocator_,
1180                     ValueBound(nullptr, right_const - upper.GetConstant()),
1181                     ValueBound(array_length, right_const - lower.GetConstant()));
1182                 AssignRange(sub->GetBlock(), sub, range);
1183               }
1184             }
1185           }
1186         }
1187       }
1188     }
1189   }
1190 
FindAndHandlePartialArrayLength(HBinaryOperation * instruction)1191   void FindAndHandlePartialArrayLength(HBinaryOperation* instruction) {
1192     DCHECK(instruction->IsDiv() || instruction->IsShr() || instruction->IsUShr());
1193     HInstruction* right = instruction->GetRight();
1194     int32_t right_const;
1195     if (right->IsIntConstant()) {
1196       right_const = right->AsIntConstant()->GetValue();
1197       // Detect division by two or more.
1198       if ((instruction->IsDiv() && right_const <= 1) ||
1199           (instruction->IsShr() && right_const < 1) ||
1200           (instruction->IsUShr() && right_const < 1)) {
1201         return;
1202       }
1203     } else {
1204       return;
1205     }
1206 
1207     // Try to handle array.length/2 or (array.length-1)/2 format.
1208     HInstruction* left = instruction->GetLeft();
1209     HInstruction* left_of_left;  // left input of left.
1210     int32_t c = 0;
1211     if (ValueBound::IsAddOrSubAConstant(left, &left_of_left, &c)) {
1212       left = left_of_left;
1213     }
1214     // The value of left input of instruction equals (left + c).
1215 
1216     // (array_length + 1) or smaller divided by two or more
1217     // always generate a value in [Min(), array_length].
1218     // This is true even if array_length is Max().
1219     if (left->IsArrayLength() && c <= 1) {
1220       if (instruction->IsUShr() && c < 0) {
1221         // Make sure for unsigned shift, left side is not negative.
1222         // e.g. if array_length is 2, ((array_length - 3) >>> 2) is way bigger
1223         // than array_length.
1224         return;
1225       }
1226       ValueRange* range = new (&allocator_) ValueRange(
1227           &allocator_,
1228           ValueBound(nullptr, std::numeric_limits<int32_t>::min()),
1229           ValueBound(left, 0));
1230       AssignRange(instruction->GetBlock(), instruction, range);
1231     }
1232   }
1233 
VisitDiv(HDiv * div)1234   void VisitDiv(HDiv* div) override {
1235     FindAndHandlePartialArrayLength(div);
1236   }
1237 
VisitShr(HShr * shr)1238   void VisitShr(HShr* shr) override {
1239     FindAndHandlePartialArrayLength(shr);
1240   }
1241 
VisitUShr(HUShr * ushr)1242   void VisitUShr(HUShr* ushr) override {
1243     FindAndHandlePartialArrayLength(ushr);
1244   }
1245 
VisitAnd(HAnd * instruction)1246   void VisitAnd(HAnd* instruction) override {
1247     if (instruction->GetRight()->IsIntConstant()) {
1248       int32_t constant = instruction->GetRight()->AsIntConstant()->GetValue();
1249       if (constant > 0) {
1250         // constant serves as a mask so any number masked with it
1251         // gets a [0, constant] value range.
1252         ValueRange* range = new (&allocator_) ValueRange(
1253             &allocator_,
1254             ValueBound(nullptr, 0),
1255             ValueBound(nullptr, constant));
1256         AssignRange(instruction->GetBlock(), instruction, range);
1257       }
1258     }
1259   }
1260 
VisitRem(HRem * instruction)1261   void VisitRem(HRem* instruction) override {
1262     HInstruction* left = instruction->GetLeft();
1263     HInstruction* right = instruction->GetRight();
1264 
1265     // Handle 'i % CONST' format expression in array index, e.g:
1266     //   array[i % 20];
1267     if (right->IsIntConstant()) {
1268       int32_t right_const = std::abs(right->AsIntConstant()->GetValue());
1269       if (right_const == 0) {
1270         return;
1271       }
1272       // The sign of divisor CONST doesn't affect the sign final value range.
1273       // For example:
1274       // if (i > 0) {
1275       //   array[i % 10];  // index value range [0, 9]
1276       //   array[i % -10]; // index value range [0, 9]
1277       // }
1278       ValueRange* right_range = new (&allocator_) ValueRange(
1279           &allocator_,
1280           ValueBound(nullptr, 1 - right_const),
1281           ValueBound(nullptr, right_const - 1));
1282 
1283       ValueRange* left_range = LookupValueRange(left, instruction->GetBlock());
1284       if (left_range != nullptr) {
1285         right_range = right_range->Narrow(left_range);
1286       }
1287       AssignRange(instruction->GetBlock(), instruction, right_range);
1288       return;
1289     }
1290 
1291     // Handle following pattern:
1292     // i0 NullCheck
1293     // i1 ArrayLength[i0]
1294     // i2 DivByZeroCheck [i1]  <-- right
1295     // i3 Rem [i5, i2]         <-- we are here.
1296     // i4 BoundsCheck [i3,i1]
1297     if (right->IsDivZeroCheck()) {
1298       // if array_length can pass div-by-zero check,
1299       // array_length must be > 0.
1300       right = right->AsDivZeroCheck()->InputAt(0);
1301     }
1302 
1303     // Handle 'i % array.length' format expression in array index, e.g:
1304     //   array[(i+7) % array.length];
1305     if (right->IsArrayLength()) {
1306       ValueBound lower = ValueBound::Min();  // ideally, lower should be '1-array_length'.
1307       ValueBound upper = ValueBound(right, -1);  // array_length - 1
1308       ValueRange* right_range = new (&allocator_) ValueRange(
1309           &allocator_,
1310           lower,
1311           upper);
1312       ValueRange* left_range = LookupValueRange(left, instruction->GetBlock());
1313       if (left_range != nullptr) {
1314         right_range = right_range->Narrow(left_range);
1315       }
1316       AssignRange(instruction->GetBlock(), instruction, right_range);
1317       return;
1318     }
1319   }
1320 
VisitNewArray(HNewArray * new_array)1321   void VisitNewArray(HNewArray* new_array) override {
1322     HInstruction* len = new_array->GetLength();
1323     if (!len->IsIntConstant()) {
1324       HInstruction *left;
1325       int32_t right_const;
1326       if (ValueBound::IsAddOrSubAConstant(len, &left, &right_const)) {
1327         // (left + right_const) is used as size to new the array.
1328         // We record "-right_const <= left <= new_array - right_const";
1329         ValueBound lower = ValueBound(nullptr, -right_const);
1330         // We use new_array for the bound instead of new_array.length,
1331         // which isn't available as an instruction yet. new_array will
1332         // be treated the same as new_array.length when it's used in a ValueBound.
1333         ValueBound upper = ValueBound(new_array, -right_const);
1334         ValueRange* range = new (&allocator_) ValueRange(&allocator_, lower, upper);
1335         ValueRange* existing_range = LookupValueRange(left, new_array->GetBlock());
1336         if (existing_range != nullptr) {
1337           range = existing_range->Narrow(range);
1338         }
1339         AssignRange(new_array->GetBlock(), left, range);
1340       }
1341     }
1342   }
1343 
1344   /**
1345     * After null/bounds checks are eliminated, some invariant array references
1346     * may be exposed underneath which can be hoisted out of the loop to the
1347     * preheader or, in combination with dynamic bce, the deoptimization block.
1348     *
1349     * for (int i = 0; i < n; i++) {
1350     *                                <-------+
1351     *   for (int j = 0; j < n; j++)          |
1352     *     a[i][j] = 0;               --a[i]--+
1353     * }
1354     *
1355     * Note: this optimization is no longer applied after dominator-based dynamic deoptimization
1356     * has occurred (see AddCompareWithDeoptimization()), since in those cases it would be
1357     * unsafe to hoist array references across their deoptimization instruction inside a loop.
1358     */
VisitArrayGet(HArrayGet * array_get)1359   void VisitArrayGet(HArrayGet* array_get) override {
1360     if (!has_dom_based_dynamic_bce_ && array_get->IsInLoop()) {
1361       HLoopInformation* loop = array_get->GetBlock()->GetLoopInformation();
1362       if (loop->IsDefinedOutOfTheLoop(array_get->InputAt(0)) &&
1363           loop->IsDefinedOutOfTheLoop(array_get->InputAt(1))) {
1364         SideEffects loop_effects = side_effects_.GetLoopEffects(loop->GetHeader());
1365         if (!array_get->GetSideEffects().MayDependOn(loop_effects)) {
1366           // We can hoist ArrayGet only if its execution is guaranteed on every iteration.
1367           // In other words only if array_get_bb dominates all back branches.
1368           if (loop->DominatesAllBackEdges(array_get->GetBlock())) {
1369             HoistToPreHeaderOrDeoptBlock(loop, array_get);
1370           }
1371         }
1372       }
1373     }
1374   }
1375 
1376   /** Performs dominator-based dynamic elimination on suitable set of bounds checks. */
AddCompareWithDeoptimization(HBasicBlock * block,HInstruction * array_length,HInstruction * base,int32_t min_c,int32_t max_c)1377   void AddCompareWithDeoptimization(HBasicBlock* block,
1378                                     HInstruction* array_length,
1379                                     HInstruction* base,
1380                                     int32_t min_c, int32_t max_c) {
1381     HBoundsCheck* bounds_check = first_index_bounds_check_map_.Get(array_length->GetId());
1382     // Construct deoptimization on single or double bounds on range [base-min_c,base+max_c],
1383     // for example either for a[0]..a[3] just 3 or for a[base-1]..a[base+3] both base-1
1384     // and base+3, since we made the assumption any in between value may occur too.
1385     // In code, using unsigned comparisons:
1386     // (1) constants only
1387     //       if (max_c >= a.length) deoptimize;
1388     // (2) general case
1389     //       if (base-min_c >  base+max_c) deoptimize;
1390     //       if (base+max_c >= a.length  ) deoptimize;
1391     static_assert(kMaxLengthForAddingDeoptimize < std::numeric_limits<int32_t>::max(),
1392                   "Incorrect max length may be subject to arithmetic wrap-around");
1393     HInstruction* upper = GetGraph()->GetIntConstant(max_c);
1394     if (base == nullptr) {
1395       DCHECK_GE(min_c, 0);
1396     } else {
1397       HInstruction* lower = new (GetGraph()->GetAllocator())
1398           HAdd(DataType::Type::kInt32, base, GetGraph()->GetIntConstant(min_c));
1399       upper = new (GetGraph()->GetAllocator()) HAdd(DataType::Type::kInt32, base, upper);
1400       block->InsertInstructionBefore(lower, bounds_check);
1401       block->InsertInstructionBefore(upper, bounds_check);
1402       InsertDeoptInBlock(bounds_check, new (GetGraph()->GetAllocator()) HAbove(lower, upper));
1403     }
1404     InsertDeoptInBlock(
1405         bounds_check, new (GetGraph()->GetAllocator()) HAboveOrEqual(upper, array_length));
1406     // Flag that this kind of deoptimization has occurred.
1407     has_dom_based_dynamic_bce_ = true;
1408   }
1409 
1410   /** Attempts dominator-based dynamic elimination on remaining candidates. */
AddComparesWithDeoptimization(HBasicBlock * block)1411   void AddComparesWithDeoptimization(HBasicBlock* block) {
1412     for (const auto& entry : first_index_bounds_check_map_) {
1413       HBoundsCheck* bounds_check = entry.second;
1414       HInstruction* index = bounds_check->InputAt(0);
1415       HInstruction* array_length = bounds_check->InputAt(1);
1416       if (!array_length->IsArrayLength()) {
1417         continue;  // disregard phis and constants
1418       }
1419       // Collect all bounds checks that are still there and that are related as "a[base + constant]"
1420       // for a base instruction (possibly absent) and various constants. Note that no attempt
1421       // is made to partition the set into matching subsets (viz. a[0], a[1] and a[base+1] and
1422       // a[base+2] are considered as one set).
1423       // TODO: would such a partitioning be worthwhile?
1424       ValueBound value = ValueBound::AsValueBound(index);
1425       HInstruction* base = value.GetInstruction();
1426       int32_t min_c = base == nullptr ? 0 : value.GetConstant();
1427       int32_t max_c = value.GetConstant();
1428       ScopedArenaVector<HBoundsCheck*> candidates(
1429           allocator_.Adapter(kArenaAllocBoundsCheckElimination));
1430       ScopedArenaVector<HBoundsCheck*> standby(
1431           allocator_.Adapter(kArenaAllocBoundsCheckElimination));
1432       for (const HUseListNode<HInstruction*>& use : array_length->GetUses()) {
1433         // Another bounds check in same or dominated block?
1434         HInstruction* user = use.GetUser();
1435         HBasicBlock* other_block = user->GetBlock();
1436         if (user->IsBoundsCheck() && block->Dominates(other_block)) {
1437           HBoundsCheck* other_bounds_check = user->AsBoundsCheck();
1438           HInstruction* other_index = other_bounds_check->InputAt(0);
1439           HInstruction* other_array_length = other_bounds_check->InputAt(1);
1440           ValueBound other_value = ValueBound::AsValueBound(other_index);
1441           if (array_length == other_array_length && base == other_value.GetInstruction()) {
1442             // Reject certain OOB if BoundsCheck(l, l) occurs on considered subset.
1443             if (array_length == other_index) {
1444               candidates.clear();
1445               standby.clear();
1446               break;
1447             }
1448             // Since a subsequent dominated block could be under a conditional, only accept
1449             // the other bounds check if it is in same block or both blocks dominate the exit.
1450             // TODO: we could improve this by testing proper post-dominance, or even if this
1451             //       constant is seen along *all* conditional paths that follow.
1452             HBasicBlock* exit = GetGraph()->GetExitBlock();
1453             if (block == user->GetBlock() ||
1454                 (block->Dominates(exit) && other_block->Dominates(exit))) {
1455               int32_t other_c = other_value.GetConstant();
1456               min_c = std::min(min_c, other_c);
1457               max_c = std::max(max_c, other_c);
1458               candidates.push_back(other_bounds_check);
1459             } else {
1460               // Add this candidate later only if it falls into the range.
1461               standby.push_back(other_bounds_check);
1462             }
1463           }
1464         }
1465       }
1466       // Add standby candidates that fall in selected range.
1467       for (HBoundsCheck* other_bounds_check : standby) {
1468         HInstruction* other_index = other_bounds_check->InputAt(0);
1469         int32_t other_c = ValueBound::AsValueBound(other_index).GetConstant();
1470         if (min_c <= other_c && other_c <= max_c) {
1471           candidates.push_back(other_bounds_check);
1472         }
1473       }
1474       // Perform dominator-based deoptimization if it seems profitable, where we eliminate
1475       // bounds checks and replace these with deopt checks that guard against any possible
1476       // OOB. Note that we reject cases where the distance min_c:max_c range gets close to
1477       // the maximum possible array length, since those cases are likely to always deopt
1478       // (such situations do not necessarily go OOB, though, since the array could be really
1479       // large, or the programmer could rely on arithmetic wrap-around from max to min).
1480       size_t threshold = kThresholdForAddingDeoptimize + (base == nullptr ? 0 : 1);  // extra test?
1481       uint32_t distance = static_cast<uint32_t>(max_c) - static_cast<uint32_t>(min_c);
1482       if (candidates.size() >= threshold &&
1483           (base != nullptr || min_c >= 0) &&  // reject certain OOB
1484            distance <= kMaxLengthForAddingDeoptimize) {  // reject likely/certain deopt
1485         AddCompareWithDeoptimization(block, array_length, base, min_c, max_c);
1486         for (HBoundsCheck* other_bounds_check : candidates) {
1487           // Only replace if still in the graph. This avoids visiting the same
1488           // bounds check twice if it occurred multiple times in the use list.
1489           if (other_bounds_check->IsInBlock()) {
1490             ReplaceInstruction(other_bounds_check, other_bounds_check->InputAt(0));
1491           }
1492         }
1493       }
1494     }
1495   }
1496 
1497   /**
1498    * Returns true if static range analysis based on induction variables can determine the bounds
1499    * check on the given array range is always satisfied with the computed index range. The output
1500    * parameter try_dynamic_bce is set to false if OOB is certain.
1501    */
InductionRangeFitsIn(ValueRange * array_range,HBoundsCheck * context,bool * try_dynamic_bce)1502   bool InductionRangeFitsIn(ValueRange* array_range,
1503                             HBoundsCheck* context,
1504                             bool* try_dynamic_bce) {
1505     InductionVarRange::Value v1;
1506     InductionVarRange::Value v2;
1507     bool needs_finite_test = false;
1508     HInstruction* index = context->InputAt(0);
1509     HInstruction* hint = HuntForDeclaration(context->InputAt(1));
1510     if (induction_range_.GetInductionRange(
1511             context->GetBlock(), index, hint, &v1, &v2, &needs_finite_test)) {
1512       if (v1.is_known && (v1.a_constant == 0 || v1.a_constant == 1) &&
1513           v2.is_known && (v2.a_constant == 0 || v2.a_constant == 1)) {
1514         DCHECK(v1.a_constant == 1 || v1.instruction == nullptr);
1515         DCHECK(v2.a_constant == 1 || v2.instruction == nullptr);
1516         ValueRange index_range(&allocator_,
1517                                ValueBound(v1.instruction, v1.b_constant),
1518                                ValueBound(v2.instruction, v2.b_constant));
1519         // If analysis reveals a certain OOB, disable dynamic BCE. Otherwise,
1520         // use analysis for static bce only if loop is finite.
1521         if (index_range.GetLower().LessThan(array_range->GetLower()) ||
1522             index_range.GetUpper().GreaterThan(array_range->GetUpper())) {
1523           *try_dynamic_bce = false;
1524         } else if (!needs_finite_test && index_range.FitsIn(array_range)) {
1525           return true;
1526         }
1527       }
1528     }
1529     return false;
1530   }
1531 
1532   /**
1533    * Performs loop-based dynamic elimination on a bounds check. In order to minimize the
1534    * number of eventually generated tests, related bounds checks with tests that can be
1535    * combined with tests for the given bounds check are collected first.
1536    */
TransformLoopForDynamicBCE(HLoopInformation * loop,HBoundsCheck * bounds_check)1537   void TransformLoopForDynamicBCE(HLoopInformation* loop, HBoundsCheck* bounds_check) {
1538     HInstruction* index = bounds_check->InputAt(0);
1539     HInstruction* array_length = bounds_check->InputAt(1);
1540     DCHECK(loop->IsDefinedOutOfTheLoop(array_length));  // pre-checked
1541     DCHECK(loop->DominatesAllBackEdges(bounds_check->GetBlock()));
1542     // Collect all bounds checks in the same loop that are related as "a[base + constant]"
1543     // for a base instruction (possibly absent) and various constants.
1544     ValueBound value = ValueBound::AsValueBound(index);
1545     HInstruction* base = value.GetInstruction();
1546     int32_t min_c = base == nullptr ? 0 : value.GetConstant();
1547     int32_t max_c = value.GetConstant();
1548     ScopedArenaVector<HBoundsCheck*> candidates(
1549         allocator_.Adapter(kArenaAllocBoundsCheckElimination));
1550     ScopedArenaVector<HBoundsCheck*> standby(
1551         allocator_.Adapter(kArenaAllocBoundsCheckElimination));
1552     for (const HUseListNode<HInstruction*>& use : array_length->GetUses()) {
1553       HInstruction* user = use.GetUser();
1554       if (user->IsBoundsCheck() && loop == user->GetBlock()->GetLoopInformation()) {
1555         HBoundsCheck* other_bounds_check = user->AsBoundsCheck();
1556         HInstruction* other_index = other_bounds_check->InputAt(0);
1557         HInstruction* other_array_length = other_bounds_check->InputAt(1);
1558         ValueBound other_value = ValueBound::AsValueBound(other_index);
1559         int32_t other_c = other_value.GetConstant();
1560         if (array_length == other_array_length && base == other_value.GetInstruction()) {
1561           // Ensure every candidate could be picked for code generation.
1562           bool b1 = false, b2 = false;
1563           if (!induction_range_.CanGenerateRange(
1564                   other_bounds_check->GetBlock(), other_index, &b1, &b2)) {
1565             continue;
1566           }
1567           // Does the current basic block dominate all back edges? If not,
1568           // add this candidate later only if it falls into the range.
1569           if (!loop->DominatesAllBackEdges(user->GetBlock())) {
1570             standby.push_back(other_bounds_check);
1571             continue;
1572           }
1573           min_c = std::min(min_c, other_c);
1574           max_c = std::max(max_c, other_c);
1575           candidates.push_back(other_bounds_check);
1576         }
1577       }
1578     }
1579     // Add standby candidates that fall in selected range.
1580     for (HBoundsCheck* other_bounds_check : standby) {
1581       HInstruction* other_index = other_bounds_check->InputAt(0);
1582       int32_t other_c = ValueBound::AsValueBound(other_index).GetConstant();
1583       if (min_c <= other_c && other_c <= max_c) {
1584         candidates.push_back(other_bounds_check);
1585       }
1586     }
1587     // Perform loop-based deoptimization if it seems profitable, where we eliminate bounds
1588     // checks and replace these with deopt checks that guard against any possible OOB.
1589     DCHECK_LT(0u, candidates.size());
1590     uint32_t distance = static_cast<uint32_t>(max_c) - static_cast<uint32_t>(min_c);
1591     if ((base != nullptr || min_c >= 0) &&  // reject certain OOB
1592         distance <= kMaxLengthForAddingDeoptimize) {  // reject likely/certain deopt
1593       HBasicBlock* block = GetPreHeader(loop, bounds_check);
1594       HInstruction* min_lower = nullptr;
1595       HInstruction* min_upper = nullptr;
1596       HInstruction* max_lower = nullptr;
1597       HInstruction* max_upper = nullptr;
1598       // Iterate over all bounds checks.
1599       for (HBoundsCheck* other_bounds_check : candidates) {
1600         // Only handle if still in the graph. This avoids visiting the same
1601         // bounds check twice if it occurred multiple times in the use list.
1602         if (other_bounds_check->IsInBlock()) {
1603           HInstruction* other_index = other_bounds_check->InputAt(0);
1604           int32_t other_c = ValueBound::AsValueBound(other_index).GetConstant();
1605           // Generate code for either the maximum or minimum. Range analysis already was queried
1606           // whether code generation on the original and, thus, related bounds check was possible.
1607           // It handles either loop invariants (lower is not set) or unit strides.
1608           if (other_c == max_c) {
1609             induction_range_.GenerateRange(other_bounds_check->GetBlock(),
1610                                            other_index,
1611                                            GetGraph(),
1612                                            block,
1613                                            &max_lower,
1614                                            &max_upper);
1615           } else if (other_c == min_c && base != nullptr) {
1616             induction_range_.GenerateRange(other_bounds_check->GetBlock(),
1617                                            other_index,
1618                                            GetGraph(),
1619                                            block,
1620                                            &min_lower,
1621                                            &min_upper);
1622           }
1623           ReplaceInstruction(other_bounds_check, other_index);
1624         }
1625       }
1626       // In code, using unsigned comparisons:
1627       // (1) constants only
1628       //       if (max_upper >= a.length ) deoptimize;
1629       // (2) two symbolic invariants
1630       //       if (min_upper >  max_upper) deoptimize;   unless min_c == max_c
1631       //       if (max_upper >= a.length ) deoptimize;
1632       // (3) general case, unit strides (where lower would exceed upper for arithmetic wrap-around)
1633       //       if (min_lower >  max_lower) deoptimize;   unless min_c == max_c
1634       //       if (max_lower >  max_upper) deoptimize;
1635       //       if (max_upper >= a.length ) deoptimize;
1636       if (base == nullptr) {
1637         // Constants only.
1638         DCHECK_GE(min_c, 0);
1639         DCHECK(min_lower == nullptr && min_upper == nullptr &&
1640                max_lower == nullptr && max_upper != nullptr);
1641       } else if (max_lower == nullptr) {
1642         // Two symbolic invariants.
1643         if (min_c != max_c) {
1644           DCHECK(min_lower == nullptr && min_upper != nullptr &&
1645                  max_lower == nullptr && max_upper != nullptr);
1646           InsertDeoptInLoop(
1647               loop, block, new (GetGraph()->GetAllocator()) HAbove(min_upper, max_upper));
1648         } else {
1649           DCHECK(min_lower == nullptr && min_upper == nullptr &&
1650                  max_lower == nullptr && max_upper != nullptr);
1651         }
1652       } else {
1653         // General case, unit strides.
1654         if (min_c != max_c) {
1655           DCHECK(min_lower != nullptr && min_upper != nullptr &&
1656                  max_lower != nullptr && max_upper != nullptr);
1657           InsertDeoptInLoop(
1658               loop, block, new (GetGraph()->GetAllocator()) HAbove(min_lower, max_lower));
1659         } else {
1660           DCHECK(min_lower == nullptr && min_upper == nullptr &&
1661                  max_lower != nullptr && max_upper != nullptr);
1662         }
1663         InsertDeoptInLoop(
1664             loop, block, new (GetGraph()->GetAllocator()) HAbove(max_lower, max_upper));
1665       }
1666       InsertDeoptInLoop(
1667           loop, block, new (GetGraph()->GetAllocator()) HAboveOrEqual(max_upper, array_length));
1668     } else {
1669       // TODO: if rejected, avoid doing this again for subsequent instructions in this set?
1670     }
1671   }
1672 
1673   /**
1674    * Returns true if heuristics indicate that dynamic bce may be profitable.
1675    */
DynamicBCESeemsProfitable(HLoopInformation * loop,HBasicBlock * block)1676   bool DynamicBCESeemsProfitable(HLoopInformation* loop, HBasicBlock* block) {
1677     if (loop != nullptr) {
1678       // The loop preheader of an irreducible loop does not dominate all the blocks in
1679       // the loop. We would need to find the common dominator of all blocks in the loop.
1680       if (loop->IsIrreducible()) {
1681         return false;
1682       }
1683       // We should never deoptimize from an osr method, otherwise we might wrongly optimize
1684       // code dominated by the deoptimization.
1685       if (GetGraph()->IsCompilingOsr()) {
1686         return false;
1687       }
1688       // A try boundary preheader is hard to handle.
1689       // TODO: remove this restriction.
1690       if (loop->GetPreHeader()->GetLastInstruction()->IsTryBoundary()) {
1691         return false;
1692       }
1693       // Does loop have early-exits? If so, the full range may not be covered by the loop
1694       // at runtime and testing the range may apply deoptimization unnecessarily.
1695       if (IsEarlyExitLoop(loop)) {
1696         return false;
1697       }
1698       // Does the current basic block dominate all back edges? If not,
1699       // don't apply dynamic bce to something that may not be executed.
1700       return loop->DominatesAllBackEdges(block);
1701     }
1702     return false;
1703   }
1704 
1705   /**
1706    * Returns true if the loop has early exits, which implies it may not cover
1707    * the full range computed by range analysis based on induction variables.
1708    */
IsEarlyExitLoop(HLoopInformation * loop)1709   bool IsEarlyExitLoop(HLoopInformation* loop) {
1710     const uint32_t loop_id = loop->GetHeader()->GetBlockId();
1711     // If loop has been analyzed earlier for early-exit, don't repeat the analysis.
1712     auto it = early_exit_loop_.find(loop_id);
1713     if (it != early_exit_loop_.end()) {
1714       return it->second;
1715     }
1716     // First time early-exit analysis for this loop. Since analysis requires scanning
1717     // the full loop-body, results of the analysis is stored for subsequent queries.
1718     HBlocksInLoopReversePostOrderIterator it_loop(*loop);
1719     for (it_loop.Advance(); !it_loop.Done(); it_loop.Advance()) {
1720       for (HBasicBlock* successor : it_loop.Current()->GetSuccessors()) {
1721         if (!loop->Contains(*successor)) {
1722           early_exit_loop_.Put(loop_id, true);
1723           return true;
1724         }
1725       }
1726     }
1727     early_exit_loop_.Put(loop_id, false);
1728     return false;
1729   }
1730 
1731   /**
1732    * Returns true if the array length is already loop invariant, or can be made so
1733    * by handling the null check under the hood of the array length operation.
1734    */
CanHandleLength(HLoopInformation * loop,HInstruction * length,bool needs_taken_test)1735   bool CanHandleLength(HLoopInformation* loop, HInstruction* length, bool needs_taken_test) {
1736     if (loop->IsDefinedOutOfTheLoop(length)) {
1737       return true;
1738     } else if (length->IsArrayLength() && length->GetBlock()->GetLoopInformation() == loop) {
1739       if (CanHandleNullCheck(loop, length->InputAt(0), needs_taken_test)) {
1740         HoistToPreHeaderOrDeoptBlock(loop, length);
1741         return true;
1742       }
1743     }
1744     return false;
1745   }
1746 
1747   /**
1748    * Returns true if the null check is already loop invariant, or can be made so
1749    * by generating a deoptimization test.
1750    */
CanHandleNullCheck(HLoopInformation * loop,HInstruction * check,bool needs_taken_test)1751   bool CanHandleNullCheck(HLoopInformation* loop, HInstruction* check, bool needs_taken_test) {
1752     if (loop->IsDefinedOutOfTheLoop(check)) {
1753       return true;
1754     } else if (check->IsNullCheck() && check->GetBlock()->GetLoopInformation() == loop) {
1755       HInstruction* array = check->InputAt(0);
1756       if (loop->IsDefinedOutOfTheLoop(array)) {
1757         // Generate: if (array == null) deoptimize;
1758         TransformLoopForDeoptimizationIfNeeded(loop, needs_taken_test);
1759         HBasicBlock* block = GetPreHeader(loop, check);
1760         HInstruction* cond =
1761             new (GetGraph()->GetAllocator()) HEqual(array, GetGraph()->GetNullConstant());
1762         InsertDeoptInLoop(loop, block, cond, /* is_null_check= */ true);
1763         ReplaceInstruction(check, array);
1764         return true;
1765       }
1766     }
1767     return false;
1768   }
1769 
1770   /**
1771    * Returns true if compiler can apply dynamic bce to loops that may be infinite
1772    * (e.g. for (int i = 0; i <= U; i++) with U = MAX_INT), which would invalidate
1773    * the range analysis evaluation code by "overshooting" the computed range.
1774    * Since deoptimization would be a bad choice, and there is no other version
1775    * of the loop to use, dynamic bce in such cases is only allowed if other tests
1776    * ensure the loop is finite.
1777    */
CanHandleInfiniteLoop(HLoopInformation * loop,HInstruction * index,bool needs_infinite_test)1778   bool CanHandleInfiniteLoop(HLoopInformation* loop, HInstruction* index, bool needs_infinite_test) {
1779     if (needs_infinite_test) {
1780       // If we already forced the loop to be finite, allow directly.
1781       const uint32_t loop_id = loop->GetHeader()->GetBlockId();
1782       if (finite_loop_.find(loop_id) != finite_loop_.end()) {
1783         return true;
1784       }
1785       // Otherwise, allow dynamic bce if the index (which is necessarily an induction at
1786       // this point) is the direct loop index (viz. a[i]), since then the runtime tests
1787       // ensure upper bound cannot cause an infinite loop.
1788       HInstruction* control = loop->GetHeader()->GetLastInstruction();
1789       if (control->IsIf()) {
1790         HInstruction* if_expr = control->AsIf()->InputAt(0);
1791         if (if_expr->IsCondition()) {
1792           HCondition* condition = if_expr->AsCondition();
1793           if (index == condition->InputAt(0) ||
1794               index == condition->InputAt(1)) {
1795             finite_loop_.insert(loop_id);
1796             return true;
1797           }
1798         }
1799       }
1800       return false;
1801     }
1802     return true;
1803   }
1804 
1805   /**
1806    * Returns appropriate preheader for the loop, depending on whether the
1807    * instruction appears in the loop header or proper loop-body.
1808    */
GetPreHeader(HLoopInformation * loop,HInstruction * instruction)1809   HBasicBlock* GetPreHeader(HLoopInformation* loop, HInstruction* instruction) {
1810     // Use preheader unless there is an earlier generated deoptimization block since
1811     // hoisted expressions may depend on and/or used by the deoptimization tests.
1812     HBasicBlock* header = loop->GetHeader();
1813     const uint32_t loop_id = header->GetBlockId();
1814     auto it = taken_test_loop_.find(loop_id);
1815     if (it != taken_test_loop_.end()) {
1816       HBasicBlock* block = it->second;
1817       // If always taken, keep it that way by returning the original preheader,
1818       // which can be found by following the predecessor of the true-block twice.
1819       if (instruction->GetBlock() == header) {
1820         return block->GetSinglePredecessor()->GetSinglePredecessor();
1821       }
1822       return block;
1823     }
1824     return loop->GetPreHeader();
1825   }
1826 
1827   /** Inserts a deoptimization test in a loop preheader. */
InsertDeoptInLoop(HLoopInformation * loop,HBasicBlock * block,HInstruction * condition,bool is_null_check=false)1828   void InsertDeoptInLoop(HLoopInformation* loop,
1829                          HBasicBlock* block,
1830                          HInstruction* condition,
1831                          bool is_null_check = false) {
1832     HInstruction* suspend = loop->GetSuspendCheck();
1833     DCHECK(suspend != nullptr);
1834     block->InsertInstructionBefore(condition, block->GetLastInstruction());
1835     DeoptimizationKind kind =
1836         is_null_check ? DeoptimizationKind::kLoopNullBCE : DeoptimizationKind::kLoopBoundsBCE;
1837     HDeoptimize* deoptimize = new (GetGraph()->GetAllocator()) HDeoptimize(
1838         GetGraph()->GetAllocator(), condition, kind, suspend->GetDexPc());
1839     block->InsertInstructionBefore(deoptimize, block->GetLastInstruction());
1840     if (suspend->HasEnvironment()) {
1841       deoptimize->CopyEnvironmentFromWithLoopPhiAdjustment(
1842           suspend->GetEnvironment(), loop->GetHeader());
1843     }
1844   }
1845 
1846   /** Inserts a deoptimization test right before a bounds check. */
InsertDeoptInBlock(HBoundsCheck * bounds_check,HInstruction * condition)1847   void InsertDeoptInBlock(HBoundsCheck* bounds_check, HInstruction* condition) {
1848     HBasicBlock* block = bounds_check->GetBlock();
1849     block->InsertInstructionBefore(condition, bounds_check);
1850     HDeoptimize* deoptimize = new (GetGraph()->GetAllocator()) HDeoptimize(
1851         GetGraph()->GetAllocator(),
1852         condition,
1853         DeoptimizationKind::kBlockBCE,
1854         bounds_check->GetDexPc());
1855     block->InsertInstructionBefore(deoptimize, bounds_check);
1856     deoptimize->CopyEnvironmentFrom(bounds_check->GetEnvironment());
1857   }
1858 
1859   /** Hoists instruction out of the loop to preheader or deoptimization block. */
HoistToPreHeaderOrDeoptBlock(HLoopInformation * loop,HInstruction * instruction)1860   void HoistToPreHeaderOrDeoptBlock(HLoopInformation* loop, HInstruction* instruction) {
1861     HBasicBlock* block = GetPreHeader(loop, instruction);
1862     DCHECK(!instruction->HasEnvironment());
1863     instruction->MoveBefore(block->GetLastInstruction());
1864   }
1865 
1866   /**
1867    * Adds a new taken-test structure to a loop if needed and not already done.
1868    * The taken-test protects range analysis evaluation code to avoid any
1869    * deoptimization caused by incorrect trip-count evaluation in non-taken loops.
1870    *
1871    *          old_preheader
1872    *               |
1873    *            if_block          <- taken-test protects deoptimization block
1874    *            /      \
1875    *     true_block  false_block  <- deoptimizations/invariants are placed in true_block
1876    *            \       /
1877    *          new_preheader       <- may require phi nodes to preserve SSA structure
1878    *                |
1879    *             header
1880    *
1881    * For example, this loop:
1882    *
1883    *   for (int i = lower; i < upper; i++) {
1884    *     array[i] = 0;
1885    *   }
1886    *
1887    * will be transformed to:
1888    *
1889    *   if (lower < upper) {
1890    *     if (array == null) deoptimize;
1891    *     array_length = array.length;
1892    *     if (lower > upper)         deoptimize;  // unsigned
1893    *     if (upper >= array_length) deoptimize;  // unsigned
1894    *   } else {
1895    *     array_length = 0;
1896    *   }
1897    *   for (int i = lower; i < upper; i++) {
1898    *     // Loop without null check and bounds check, and any array.length replaced with array_length.
1899    *     array[i] = 0;
1900    *   }
1901    */
TransformLoopForDeoptimizationIfNeeded(HLoopInformation * loop,bool needs_taken_test)1902   void TransformLoopForDeoptimizationIfNeeded(HLoopInformation* loop, bool needs_taken_test) {
1903     // Not needed (can use preheader) or already done (can reuse)?
1904     const uint32_t loop_id = loop->GetHeader()->GetBlockId();
1905     if (!needs_taken_test || taken_test_loop_.find(loop_id) != taken_test_loop_.end()) {
1906       return;
1907     }
1908 
1909     // Generate top test structure.
1910     HBasicBlock* header = loop->GetHeader();
1911     GetGraph()->TransformLoopHeaderForBCE(header);
1912     HBasicBlock* new_preheader = loop->GetPreHeader();
1913     HBasicBlock* if_block = new_preheader->GetDominator();
1914     HBasicBlock* true_block = if_block->GetSuccessors()[0];  // True successor.
1915     HBasicBlock* false_block = if_block->GetSuccessors()[1];  // False successor.
1916 
1917     // Goto instructions.
1918     true_block->AddInstruction(new (GetGraph()->GetAllocator()) HGoto());
1919     false_block->AddInstruction(new (GetGraph()->GetAllocator()) HGoto());
1920     new_preheader->AddInstruction(new (GetGraph()->GetAllocator()) HGoto());
1921 
1922     // Insert the taken-test to see if the loop body is entered. If the
1923     // loop isn't entered at all, it jumps around the deoptimization block.
1924     if_block->AddInstruction(new (GetGraph()->GetAllocator()) HGoto());  // placeholder
1925     HInstruction* condition = induction_range_.GenerateTakenTest(
1926         header->GetLastInstruction(), GetGraph(), if_block);
1927     DCHECK(condition != nullptr);
1928     if_block->RemoveInstruction(if_block->GetLastInstruction());
1929     if_block->AddInstruction(new (GetGraph()->GetAllocator()) HIf(condition));
1930 
1931     taken_test_loop_.Put(loop_id, true_block);
1932   }
1933 
1934   /**
1935    * Inserts phi nodes that preserve SSA structure in generated top test structures.
1936    * All uses of instructions in the deoptimization block that reach the loop need
1937    * a phi node in the new loop preheader to fix the dominance relation.
1938    *
1939    * Example:
1940    *           if_block
1941    *            /      \
1942    *         x_0 = ..  false_block
1943    *            \       /
1944    *           x_1 = phi(x_0, null)   <- synthetic phi
1945    *               |
1946    *          new_preheader
1947    */
InsertPhiNodes()1948   void InsertPhiNodes() {
1949     // Scan all new deoptimization blocks.
1950     for (const auto& entry : taken_test_loop_) {
1951       HBasicBlock* true_block = entry.second;
1952       HBasicBlock* new_preheader = true_block->GetSingleSuccessor();
1953       // Scan all instructions in a new deoptimization block.
1954       for (HInstructionIterator it(true_block->GetInstructions()); !it.Done(); it.Advance()) {
1955         HInstruction* instruction = it.Current();
1956         DataType::Type type = instruction->GetType();
1957         HPhi* phi = nullptr;
1958         // Scan all uses of an instruction and replace each later use with a phi node.
1959         const HUseList<HInstruction*>& uses = instruction->GetUses();
1960         for (auto it2 = uses.begin(), end2 = uses.end(); it2 != end2; /* ++it2 below */) {
1961           HInstruction* user = it2->GetUser();
1962           size_t index = it2->GetIndex();
1963           // Increment `it2` now because `*it2` may disappear thanks to user->ReplaceInput().
1964           ++it2;
1965           if (user->GetBlock() != true_block) {
1966             if (phi == nullptr) {
1967               phi = NewPhi(new_preheader, instruction, type);
1968             }
1969             user->ReplaceInput(phi, index);  // Removes the use node from the list.
1970             induction_range_.Replace(user, instruction, phi);  // update induction
1971           }
1972         }
1973         // Scan all environment uses of an instruction and replace each later use with a phi node.
1974         const HUseList<HEnvironment*>& env_uses = instruction->GetEnvUses();
1975         for (auto it2 = env_uses.begin(), end2 = env_uses.end(); it2 != end2; /* ++it2 below */) {
1976           HEnvironment* user = it2->GetUser();
1977           size_t index = it2->GetIndex();
1978           // Increment `it2` now because `*it2` may disappear thanks to user->RemoveAsUserOfInput().
1979           ++it2;
1980           if (user->GetHolder()->GetBlock() != true_block) {
1981             if (phi == nullptr) {
1982               phi = NewPhi(new_preheader, instruction, type);
1983             }
1984             user->RemoveAsUserOfInput(index);
1985             user->SetRawEnvAt(index, phi);
1986             phi->AddEnvUseAt(user, index);
1987           }
1988         }
1989       }
1990     }
1991   }
1992 
1993   /**
1994    * Construct a phi(instruction, 0) in the new preheader to fix the dominance relation.
1995    * These are synthetic phi nodes without a virtual register.
1996    */
NewPhi(HBasicBlock * new_preheader,HInstruction * instruction,DataType::Type type)1997   HPhi* NewPhi(HBasicBlock* new_preheader,
1998                HInstruction* instruction,
1999                DataType::Type type) {
2000     HGraph* graph = GetGraph();
2001     HInstruction* zero;
2002     switch (type) {
2003       case DataType::Type::kReference: zero = graph->GetNullConstant(); break;
2004       case DataType::Type::kFloat32: zero = graph->GetFloatConstant(0); break;
2005       case DataType::Type::kFloat64: zero = graph->GetDoubleConstant(0); break;
2006       default: zero = graph->GetConstant(type, 0); break;
2007     }
2008     HPhi* phi = new (graph->GetAllocator())
2009         HPhi(graph->GetAllocator(), kNoRegNumber, /*number_of_inputs*/ 2, HPhi::ToPhiType(type));
2010     phi->SetRawInputAt(0, instruction);
2011     phi->SetRawInputAt(1, zero);
2012     if (type == DataType::Type::kReference) {
2013       phi->SetReferenceTypeInfoIfValid(instruction->GetReferenceTypeInfo());
2014     }
2015     new_preheader->AddPhi(phi);
2016     return phi;
2017   }
2018 
2019   /** Helper method to replace an instruction with another instruction. */
ReplaceInstruction(HInstruction * instruction,HInstruction * replacement)2020   void ReplaceInstruction(HInstruction* instruction, HInstruction* replacement) {
2021     // Safe iteration.
2022     if (instruction == next_) {
2023       next_ = next_->GetNext();
2024     }
2025     // Replace and remove.
2026     instruction->ReplaceWith(replacement);
2027     instruction->GetBlock()->RemoveInstruction(instruction);
2028   }
2029 
2030   // Use local allocator for allocating memory.
2031   ScopedArenaAllocator allocator_;
2032 
2033   // A set of maps, one per basic block, from instruction to range.
2034   ScopedArenaVector<ScopedArenaSafeMap<int, ValueRange*>> maps_;
2035 
2036   // Map an HArrayLength instruction's id to the first HBoundsCheck instruction
2037   // in a block that checks an index against that HArrayLength.
2038   ScopedArenaSafeMap<int, HBoundsCheck*> first_index_bounds_check_map_;
2039 
2040   // Early-exit loop bookkeeping.
2041   ScopedArenaSafeMap<uint32_t, bool> early_exit_loop_;
2042 
2043   // Taken-test loop bookkeeping.
2044   ScopedArenaSafeMap<uint32_t, HBasicBlock*> taken_test_loop_;
2045 
2046   // Finite loop bookkeeping.
2047   ScopedArenaSet<uint32_t> finite_loop_;
2048 
2049   // Flag that denotes whether dominator-based dynamic elimination has occurred.
2050   bool has_dom_based_dynamic_bce_;
2051 
2052   // Initial number of blocks.
2053   uint32_t initial_block_size_;
2054 
2055   // Side effects.
2056   const SideEffectsAnalysis& side_effects_;
2057 
2058   // Range analysis based on induction variables.
2059   InductionVarRange induction_range_;
2060 
2061   // Safe iteration.
2062   HInstruction* next_;
2063 
2064   DISALLOW_COPY_AND_ASSIGN(BCEVisitor);
2065 };
2066 
Run()2067 bool BoundsCheckElimination::Run() {
2068   if (!graph_->HasBoundsChecks()) {
2069     return false;
2070   }
2071 
2072   // Reverse post order guarantees a node's dominators are visited first.
2073   // We want to visit in the dominator-based order since if a value is known to
2074   // be bounded by a range at one instruction, it must be true that all uses of
2075   // that value dominated by that instruction fits in that range. Range of that
2076   // value can be narrowed further down in the dominator tree.
2077   BCEVisitor visitor(graph_, side_effects_, induction_analysis_);
2078   for (size_t i = 0, size = graph_->GetReversePostOrder().size(); i != size; ++i) {
2079     HBasicBlock* current = graph_->GetReversePostOrder()[i];
2080     if (visitor.IsAddedBlock(current)) {
2081       // Skip added blocks. Their effects are already taken care of.
2082       continue;
2083     }
2084     visitor.VisitBasicBlock(current);
2085     // Skip forward to the current block in case new basic blocks were inserted
2086     // (which always appear earlier in reverse post order) to avoid visiting the
2087     // same basic block twice.
2088     size_t new_size = graph_->GetReversePostOrder().size();
2089     DCHECK_GE(new_size, size);
2090     i += new_size - size;
2091     DCHECK_EQ(current, graph_->GetReversePostOrder()[i]);
2092     size = new_size;
2093   }
2094 
2095   // Perform cleanup.
2096   visitor.Finish();
2097 
2098   return true;
2099 }
2100 
2101 }  // namespace art
2102