blob: 70ad408fdf31bc6e97f5b688024304af8faa4c62 [file] [log] [blame]
Mingyao Yangf384f882014-10-22 16:08:18 -07001/*
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
Mathieu Chartierb666f482015-02-18 14:33:14 -080017#include "base/arena_containers.h"
Mingyao Yangf384f882014-10-22 16:08:18 -070018#include "bounds_check_elimination.h"
19#include "nodes.h"
Mingyao Yangf384f882014-10-22 16:08:18 -070020
21namespace art {
22
23class MonotonicValueRange;
24
25/**
26 * A value bound is represented as a pair of value and constant,
27 * e.g. array.length - 1.
28 */
29class ValueBound : public ValueObject {
30 public:
Mingyao Yang0304e182015-01-30 16:41:29 -080031 ValueBound(HInstruction* instruction, int32_t constant) {
Mingyao Yang64197522014-12-05 15:56:23 -080032 if (instruction != nullptr && instruction->IsIntConstant()) {
Mingyao Yang0304e182015-01-30 16:41:29 -080033 // Normalize ValueBound with constant instruction.
34 int32_t instr_const = instruction->AsIntConstant()->GetValue();
Mingyao Yang8c8bad82015-02-09 18:13:26 -080035 if (!WouldAddOverflowOrUnderflow(instr_const, constant)) {
Mingyao Yang64197522014-12-05 15:56:23 -080036 instruction_ = nullptr;
37 constant_ = instr_const + constant;
38 return;
39 }
Mingyao Yangf384f882014-10-22 16:08:18 -070040 }
Mingyao Yang64197522014-12-05 15:56:23 -080041 instruction_ = instruction;
42 constant_ = constant;
43 }
44
Mingyao Yang8c8bad82015-02-09 18:13:26 -080045 // Return whether (left + right) overflows or underflows.
46 static bool WouldAddOverflowOrUnderflow(int32_t left, int32_t right) {
47 if (right == 0) {
48 return false;
49 }
50 if ((right > 0) && (left <= INT_MAX - right)) {
51 // No overflow.
52 return false;
53 }
54 if ((right < 0) && (left >= INT_MIN - right)) {
55 // No underflow.
56 return false;
57 }
58 return true;
59 }
60
Mingyao Yang0304e182015-01-30 16:41:29 -080061 static bool IsAddOrSubAConstant(HInstruction* instruction,
62 HInstruction** left_instruction,
63 int* right_constant) {
64 if (instruction->IsAdd() || instruction->IsSub()) {
65 HBinaryOperation* bin_op = instruction->AsBinaryOperation();
66 HInstruction* left = bin_op->GetLeft();
67 HInstruction* right = bin_op->GetRight();
68 if (right->IsIntConstant()) {
69 *left_instruction = left;
70 int32_t c = right->AsIntConstant()->GetValue();
71 *right_constant = instruction->IsAdd() ? c : -c;
72 return true;
73 }
74 }
75 *left_instruction = nullptr;
76 *right_constant = 0;
77 return false;
78 }
79
Mingyao Yang64197522014-12-05 15:56:23 -080080 // Try to detect useful value bound format from an instruction, e.g.
81 // a constant or array length related value.
82 static ValueBound DetectValueBoundFromValue(HInstruction* instruction, bool* found) {
83 DCHECK(instruction != nullptr);
Mingyao Yangf384f882014-10-22 16:08:18 -070084 if (instruction->IsIntConstant()) {
Mingyao Yang64197522014-12-05 15:56:23 -080085 *found = true;
86 return ValueBound(nullptr, instruction->AsIntConstant()->GetValue());
Mingyao Yangf384f882014-10-22 16:08:18 -070087 }
Mingyao Yang64197522014-12-05 15:56:23 -080088
89 if (instruction->IsArrayLength()) {
90 *found = true;
91 return ValueBound(instruction, 0);
92 }
93 // Try to detect (array.length + c) format.
Mingyao Yang0304e182015-01-30 16:41:29 -080094 HInstruction *left;
95 int32_t right;
96 if (IsAddOrSubAConstant(instruction, &left, &right)) {
97 if (left->IsArrayLength()) {
Mingyao Yang64197522014-12-05 15:56:23 -080098 *found = true;
Mingyao Yang0304e182015-01-30 16:41:29 -080099 return ValueBound(left, right);
Mingyao Yang64197522014-12-05 15:56:23 -0800100 }
101 }
102
103 // No useful bound detected.
104 *found = false;
105 return ValueBound::Max();
Mingyao Yangf384f882014-10-22 16:08:18 -0700106 }
107
108 HInstruction* GetInstruction() const { return instruction_; }
Mingyao Yang0304e182015-01-30 16:41:29 -0800109 int32_t GetConstant() const { return constant_; }
Mingyao Yangf384f882014-10-22 16:08:18 -0700110
Mingyao Yang0304e182015-01-30 16:41:29 -0800111 bool IsRelatedToArrayLength() const {
112 // Some bounds are created with HNewArray* as the instruction instead
113 // of HArrayLength*. They are treated the same.
114 return (instruction_ != nullptr) &&
115 (instruction_->IsArrayLength() || instruction_->IsNewArray());
Mingyao Yangf384f882014-10-22 16:08:18 -0700116 }
117
118 bool IsConstant() const {
119 return instruction_ == nullptr;
120 }
121
122 static ValueBound Min() { return ValueBound(nullptr, INT_MIN); }
123 static ValueBound Max() { return ValueBound(nullptr, INT_MAX); }
124
125 bool Equals(ValueBound bound) const {
126 return instruction_ == bound.instruction_ && constant_ == bound.constant_;
127 }
128
Mingyao Yang3584bce2015-05-19 16:01:59 -0700129 static HInstruction* FromArrayLengthToArray(HInstruction* instruction) {
130 DCHECK(instruction->IsArrayLength() || instruction->IsNewArray());
131 if (instruction->IsArrayLength()) {
132 HInstruction* input = instruction->InputAt(0);
133 if (input->IsNullCheck()) {
134 input = input->AsNullCheck()->InputAt(0);
135 }
136 return input;
Mingyao Yang0304e182015-01-30 16:41:29 -0800137 }
138 return instruction;
139 }
140
141 static bool Equal(HInstruction* instruction1, HInstruction* instruction2) {
142 if (instruction1 == instruction2) {
143 return true;
144 }
145
146 if (instruction1 == nullptr || instruction2 == nullptr) {
Mingyao Yangf384f882014-10-22 16:08:18 -0700147 return false;
148 }
Mingyao Yang0304e182015-01-30 16:41:29 -0800149
150 // Some bounds are created with HNewArray* as the instruction instead
151 // of HArrayLength*. They are treated the same.
Mingyao Yang3584bce2015-05-19 16:01:59 -0700152 // HArrayLength with the same array input are considered equal also.
153 instruction1 = FromArrayLengthToArray(instruction1);
154 instruction2 = FromArrayLengthToArray(instruction2);
Mingyao Yang0304e182015-01-30 16:41:29 -0800155 return instruction1 == instruction2;
156 }
157
158 // Returns if it's certain this->bound >= `bound`.
159 bool GreaterThanOrEqualTo(ValueBound bound) const {
160 if (Equal(instruction_, bound.instruction_)) {
161 return constant_ >= bound.constant_;
162 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700163 // Not comparable. Just return false.
164 return false;
165 }
166
Mingyao Yang0304e182015-01-30 16:41:29 -0800167 // Returns if it's certain this->bound <= `bound`.
168 bool LessThanOrEqualTo(ValueBound bound) const {
169 if (Equal(instruction_, bound.instruction_)) {
170 return constant_ <= bound.constant_;
Mingyao Yangf384f882014-10-22 16:08:18 -0700171 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700172 // Not comparable. Just return false.
173 return false;
174 }
175
176 // Try to narrow lower bound. Returns the greatest of the two if possible.
177 // Pick one if they are not comparable.
178 static ValueBound NarrowLowerBound(ValueBound bound1, ValueBound bound2) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800179 if (bound1.GreaterThanOrEqualTo(bound2)) {
180 return bound1;
181 }
182 if (bound2.GreaterThanOrEqualTo(bound1)) {
183 return bound2;
Mingyao Yangf384f882014-10-22 16:08:18 -0700184 }
185
186 // Not comparable. Just pick one. We may lose some info, but that's ok.
187 // Favor constant as lower bound.
188 return bound1.IsConstant() ? bound1 : bound2;
189 }
190
191 // Try to narrow upper bound. Returns the lowest of the two if possible.
192 // Pick one if they are not comparable.
193 static ValueBound NarrowUpperBound(ValueBound bound1, ValueBound bound2) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800194 if (bound1.LessThanOrEqualTo(bound2)) {
195 return bound1;
196 }
197 if (bound2.LessThanOrEqualTo(bound1)) {
198 return bound2;
Mingyao Yangf384f882014-10-22 16:08:18 -0700199 }
200
201 // Not comparable. Just pick one. We may lose some info, but that's ok.
202 // Favor array length as upper bound.
Mingyao Yang0304e182015-01-30 16:41:29 -0800203 return bound1.IsRelatedToArrayLength() ? bound1 : bound2;
Mingyao Yangf384f882014-10-22 16:08:18 -0700204 }
205
Mingyao Yang0304e182015-01-30 16:41:29 -0800206 // Add a constant to a ValueBound.
207 // `overflow` or `underflow` will return whether the resulting bound may
208 // overflow or underflow an int.
209 ValueBound Add(int32_t c, bool* overflow, bool* underflow) const {
210 *overflow = *underflow = false;
Mingyao Yangf384f882014-10-22 16:08:18 -0700211 if (c == 0) {
212 return *this;
213 }
214
Mingyao Yang0304e182015-01-30 16:41:29 -0800215 int32_t new_constant;
Mingyao Yangf384f882014-10-22 16:08:18 -0700216 if (c > 0) {
217 if (constant_ > INT_MAX - c) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800218 *overflow = true;
Mingyao Yang64197522014-12-05 15:56:23 -0800219 return Max();
Mingyao Yangf384f882014-10-22 16:08:18 -0700220 }
Mingyao Yang0304e182015-01-30 16:41:29 -0800221
222 new_constant = constant_ + c;
223 // (array.length + non-positive-constant) won't overflow an int.
224 if (IsConstant() || (IsRelatedToArrayLength() && new_constant <= 0)) {
225 return ValueBound(instruction_, new_constant);
226 }
227 // Be conservative.
228 *overflow = true;
229 return Max();
Mingyao Yangf384f882014-10-22 16:08:18 -0700230 } else {
231 if (constant_ < INT_MIN - c) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800232 *underflow = true;
233 return Min();
Mingyao Yangf384f882014-10-22 16:08:18 -0700234 }
Mingyao Yang0304e182015-01-30 16:41:29 -0800235
236 new_constant = constant_ + c;
237 // Regardless of the value new_constant, (array.length+new_constant) will
238 // never underflow since array.length is no less than 0.
239 if (IsConstant() || IsRelatedToArrayLength()) {
240 return ValueBound(instruction_, new_constant);
241 }
242 // Be conservative.
243 *underflow = true;
244 return Min();
Mingyao Yangf384f882014-10-22 16:08:18 -0700245 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700246 }
247
248 private:
Mingyao Yangf384f882014-10-22 16:08:18 -0700249 HInstruction* instruction_;
Mingyao Yang0304e182015-01-30 16:41:29 -0800250 int32_t constant_;
Mingyao Yangf384f882014-10-22 16:08:18 -0700251};
252
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700253// Collect array access data for a loop.
254// TODO: make it work for multiple arrays inside the loop.
255class ArrayAccessInsideLoopFinder : public ValueObject {
256 public:
257 explicit ArrayAccessInsideLoopFinder(HInstruction* induction_variable)
258 : induction_variable_(induction_variable),
259 found_array_length_(nullptr),
260 offset_low_(INT_MAX),
261 offset_high_(INT_MIN) {
262 Run();
263 }
264
265 HArrayLength* GetFoundArrayLength() const { return found_array_length_; }
266 bool HasFoundArrayLength() const { return found_array_length_ != nullptr; }
267 int32_t GetOffsetLow() const { return offset_low_; }
268 int32_t GetOffsetHigh() const { return offset_high_; }
269
Mingyao Yang9d750ef2015-04-26 18:15:30 -0700270 // Returns if `block` that is in loop_info may exit the loop, unless it's
271 // the loop header for loop_info.
272 static bool EarlyExit(HBasicBlock* block, HLoopInformation* loop_info) {
273 DCHECK(loop_info->Contains(*block));
274 if (block == loop_info->GetHeader()) {
275 // Loop header of loop_info. Exiting loop is normal.
276 return false;
277 }
Vladimir Marko60584552015-09-03 13:35:12 +0000278 for (HBasicBlock* successor : block->GetSuccessors()) {
279 if (!loop_info->Contains(*successor)) {
Mingyao Yang9d750ef2015-04-26 18:15:30 -0700280 // One of the successors exits the loop.
281 return true;
282 }
283 }
284 return false;
285 }
286
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100287 static bool DominatesAllBackEdges(HBasicBlock* block, HLoopInformation* loop_info) {
288 for (size_t i = 0, e = loop_info->GetBackEdges().Size(); i < e; ++i) {
289 HBasicBlock* back_edge = loop_info->GetBackEdges().Get(i);
290 if (!block->Dominates(back_edge)) {
291 return false;
292 }
293 }
294 return true;
295 }
296
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700297 void Run() {
298 HLoopInformation* loop_info = induction_variable_->GetBlock()->GetLoopInformation();
Mingyao Yang3584bce2015-05-19 16:01:59 -0700299 HBlocksInLoopReversePostOrderIterator it_loop(*loop_info);
300 HBasicBlock* block = it_loop.Current();
301 DCHECK(block == induction_variable_->GetBlock());
302 // Skip loop header. Since narrowed value range of a MonotonicValueRange only
303 // applies to the loop body (after the test at the end of the loop header).
304 it_loop.Advance();
305 for (; !it_loop.Done(); it_loop.Advance()) {
306 block = it_loop.Current();
Mingyao Yang9d750ef2015-04-26 18:15:30 -0700307 DCHECK(block->IsInLoop());
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100308 if (!DominatesAllBackEdges(block, loop_info)) {
Mingyao Yang9d750ef2015-04-26 18:15:30 -0700309 // In order not to trigger deoptimization unnecessarily, make sure
310 // that all array accesses collected are really executed in the loop.
311 // For array accesses in a branch inside the loop, don't collect the
312 // access. The bounds check in that branch might not be eliminated.
313 continue;
314 }
315 if (EarlyExit(block, loop_info)) {
316 // If the loop body can exit loop (like break, return, etc.), it's not guaranteed
317 // that the loop will loop through the full monotonic value range from
318 // initial_ to end_. So adding deoptimization might be too aggressive and can
319 // trigger deoptimization unnecessarily even if the loop won't actually throw
Mingyao Yang3584bce2015-05-19 16:01:59 -0700320 // AIOOBE.
Mingyao Yang9d750ef2015-04-26 18:15:30 -0700321 found_array_length_ = nullptr;
322 return;
323 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700324 for (HInstruction* instruction = block->GetFirstInstruction();
325 instruction != nullptr;
326 instruction = instruction->GetNext()) {
Mingyao Yang3584bce2015-05-19 16:01:59 -0700327 if (!instruction->IsBoundsCheck()) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700328 continue;
329 }
330
Mingyao Yang3584bce2015-05-19 16:01:59 -0700331 HInstruction* length_value = instruction->InputAt(1);
332 if (length_value->IsIntConstant()) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700333 // TODO: may optimize for constant case.
334 continue;
335 }
336
Mingyao Yang3584bce2015-05-19 16:01:59 -0700337 if (length_value->IsPhi()) {
Nicolas Geoffray3cde6222015-06-17 10:17:49 +0100338 // When adding deoptimizations in outer loops, we might create
339 // a phi for the array length, and update all uses of the
340 // length in the loop to that phi. Therefore, inner loops having
341 // bounds checks on the same array will use that phi.
342 // TODO: handle these cases.
Mingyao Yang3584bce2015-05-19 16:01:59 -0700343 continue;
344 }
345
346 DCHECK(length_value->IsArrayLength());
347 HArrayLength* array_length = length_value->AsArrayLength();
348
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700349 HInstruction* array = array_length->InputAt(0);
350 if (array->IsNullCheck()) {
351 array = array->AsNullCheck()->InputAt(0);
352 }
353 if (loop_info->Contains(*array->GetBlock())) {
354 // Array is defined inside the loop. Skip.
355 continue;
356 }
357
358 if (found_array_length_ != nullptr && found_array_length_ != array_length) {
359 // There is already access for another array recorded for the loop.
360 // TODO: handle multiple arrays.
361 continue;
362 }
363
Mingyao Yang3584bce2015-05-19 16:01:59 -0700364 HInstruction* index = instruction->AsBoundsCheck()->InputAt(0);
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700365 HInstruction* left = index;
366 int32_t right = 0;
367 if (left == induction_variable_ ||
368 (ValueBound::IsAddOrSubAConstant(index, &left, &right) &&
369 left == induction_variable_)) {
370 // For patterns like array[i] or array[i + 2].
371 if (right < offset_low_) {
372 offset_low_ = right;
373 }
374 if (right > offset_high_) {
375 offset_high_ = right;
376 }
377 } else {
378 // Access not in induction_variable/(induction_variable_ + constant)
379 // format. Skip.
380 continue;
381 }
382 // Record this array.
383 found_array_length_ = array_length;
384 }
385 }
386 }
387
388 private:
389 // The instruction that corresponds to a MonotonicValueRange.
390 HInstruction* induction_variable_;
391
Mingyao Yang3584bce2015-05-19 16:01:59 -0700392 // The array length of the array that's accessed inside the loop body.
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700393 HArrayLength* found_array_length_;
394
395 // The lowest and highest constant offsets relative to induction variable
396 // instruction_ in all array accesses.
397 // If array access are: array[i-1], array[i], array[i+1],
398 // offset_low_ is -1 and offset_high is 1.
399 int32_t offset_low_;
400 int32_t offset_high_;
401
402 DISALLOW_COPY_AND_ASSIGN(ArrayAccessInsideLoopFinder);
403};
404
Mingyao Yangf384f882014-10-22 16:08:18 -0700405/**
406 * Represent a range of lower bound and upper bound, both being inclusive.
407 * Currently a ValueRange may be generated as a result of the following:
408 * comparisons related to array bounds, array bounds check, add/sub on top
Mingyao Yang0304e182015-01-30 16:41:29 -0800409 * of an existing value range, NewArray or a loop phi corresponding to an
Mingyao Yangf384f882014-10-22 16:08:18 -0700410 * incrementing/decrementing array index (MonotonicValueRange).
411 */
412class ValueRange : public ArenaObject<kArenaAllocMisc> {
413 public:
414 ValueRange(ArenaAllocator* allocator, ValueBound lower, ValueBound upper)
415 : allocator_(allocator), lower_(lower), upper_(upper) {}
416
417 virtual ~ValueRange() {}
418
Mingyao Yang57e04752015-02-09 18:13:26 -0800419 virtual MonotonicValueRange* AsMonotonicValueRange() { return nullptr; }
420 bool IsMonotonicValueRange() {
Mingyao Yangf384f882014-10-22 16:08:18 -0700421 return AsMonotonicValueRange() != nullptr;
422 }
423
424 ArenaAllocator* GetAllocator() const { return allocator_; }
425 ValueBound GetLower() const { return lower_; }
426 ValueBound GetUpper() const { return upper_; }
427
Mingyao Yang3584bce2015-05-19 16:01:59 -0700428 bool IsConstantValueRange() { return lower_.IsConstant() && upper_.IsConstant(); }
429
Mingyao Yangf384f882014-10-22 16:08:18 -0700430 // If it's certain that this value range fits in other_range.
431 virtual bool FitsIn(ValueRange* other_range) const {
432 if (other_range == nullptr) {
433 return true;
434 }
435 DCHECK(!other_range->IsMonotonicValueRange());
Mingyao Yang0304e182015-01-30 16:41:29 -0800436 return lower_.GreaterThanOrEqualTo(other_range->lower_) &&
437 upper_.LessThanOrEqualTo(other_range->upper_);
Mingyao Yangf384f882014-10-22 16:08:18 -0700438 }
439
440 // Returns the intersection of this and range.
441 // If it's not possible to do intersection because some
442 // bounds are not comparable, it's ok to pick either bound.
443 virtual ValueRange* Narrow(ValueRange* range) {
444 if (range == nullptr) {
445 return this;
446 }
447
448 if (range->IsMonotonicValueRange()) {
449 return this;
450 }
451
452 return new (allocator_) ValueRange(
453 allocator_,
454 ValueBound::NarrowLowerBound(lower_, range->lower_),
455 ValueBound::NarrowUpperBound(upper_, range->upper_));
456 }
457
Mingyao Yang0304e182015-01-30 16:41:29 -0800458 // Shift a range by a constant.
459 ValueRange* Add(int32_t constant) const {
460 bool overflow, underflow;
461 ValueBound lower = lower_.Add(constant, &overflow, &underflow);
462 if (underflow) {
463 // Lower bound underflow will wrap around to positive values
464 // and invalidate the upper bound.
465 return nullptr;
Mingyao Yangf384f882014-10-22 16:08:18 -0700466 }
Mingyao Yang0304e182015-01-30 16:41:29 -0800467 ValueBound upper = upper_.Add(constant, &overflow, &underflow);
468 if (overflow) {
469 // Upper bound overflow will wrap around to negative values
470 // and invalidate the lower bound.
471 return nullptr;
Mingyao Yangf384f882014-10-22 16:08:18 -0700472 }
473 return new (allocator_) ValueRange(allocator_, lower, upper);
474 }
475
Mingyao Yangf384f882014-10-22 16:08:18 -0700476 private:
477 ArenaAllocator* const allocator_;
478 const ValueBound lower_; // inclusive
479 const ValueBound upper_; // inclusive
480
481 DISALLOW_COPY_AND_ASSIGN(ValueRange);
482};
483
484/**
485 * A monotonically incrementing/decrementing value range, e.g.
486 * the variable i in "for (int i=0; i<array.length; i++)".
487 * Special care needs to be taken to account for overflow/underflow
488 * of such value ranges.
489 */
490class MonotonicValueRange : public ValueRange {
491 public:
Mingyao Yang64197522014-12-05 15:56:23 -0800492 MonotonicValueRange(ArenaAllocator* allocator,
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700493 HPhi* induction_variable,
Mingyao Yang64197522014-12-05 15:56:23 -0800494 HInstruction* initial,
Mingyao Yang0304e182015-01-30 16:41:29 -0800495 int32_t increment,
Mingyao Yang64197522014-12-05 15:56:23 -0800496 ValueBound bound)
497 // To be conservative, give it full range [INT_MIN, INT_MAX] in case it's
498 // used as a regular value range, due to possible overflow/underflow.
499 : ValueRange(allocator, ValueBound::Min(), ValueBound::Max()),
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700500 induction_variable_(induction_variable),
Mingyao Yang64197522014-12-05 15:56:23 -0800501 initial_(initial),
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700502 end_(nullptr),
503 inclusive_(false),
Mingyao Yang64197522014-12-05 15:56:23 -0800504 increment_(increment),
505 bound_(bound) {}
Mingyao Yangf384f882014-10-22 16:08:18 -0700506
507 virtual ~MonotonicValueRange() {}
508
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700509 HInstruction* GetInductionVariable() const { return induction_variable_; }
Mingyao Yang57e04752015-02-09 18:13:26 -0800510 int32_t GetIncrement() const { return increment_; }
Mingyao Yang57e04752015-02-09 18:13:26 -0800511 ValueBound GetBound() const { return bound_; }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700512 void SetEnd(HInstruction* end) { end_ = end; }
513 void SetInclusive(bool inclusive) { inclusive_ = inclusive; }
Mingyao Yang3584bce2015-05-19 16:01:59 -0700514 HBasicBlock* GetLoopHeader() const {
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700515 DCHECK(induction_variable_->GetBlock()->IsLoopHeader());
516 return induction_variable_->GetBlock();
517 }
Mingyao Yang57e04752015-02-09 18:13:26 -0800518
519 MonotonicValueRange* AsMonotonicValueRange() OVERRIDE { return this; }
Mingyao Yangf384f882014-10-22 16:08:18 -0700520
Mingyao Yang3584bce2015-05-19 16:01:59 -0700521 HBasicBlock* GetLoopHeaderSuccesorInLoop() {
522 HBasicBlock* header = GetLoopHeader();
523 HInstruction* instruction = header->GetLastInstruction();
524 DCHECK(instruction->IsIf());
525 HIf* h_if = instruction->AsIf();
526 HLoopInformation* loop_info = header->GetLoopInformation();
527 bool true_successor_in_loop = loop_info->Contains(*h_if->IfTrueSuccessor());
528 bool false_successor_in_loop = loop_info->Contains(*h_if->IfFalseSuccessor());
529
530 // Just in case it's some strange loop structure.
531 if (true_successor_in_loop && false_successor_in_loop) {
532 return nullptr;
533 }
534 DCHECK(true_successor_in_loop || false_successor_in_loop);
535 return false_successor_in_loop ? h_if->IfFalseSuccessor() : h_if->IfTrueSuccessor();
536 }
537
Mingyao Yangf384f882014-10-22 16:08:18 -0700538 // If it's certain that this value range fits in other_range.
539 bool FitsIn(ValueRange* other_range) const OVERRIDE {
540 if (other_range == nullptr) {
541 return true;
542 }
543 DCHECK(!other_range->IsMonotonicValueRange());
544 return false;
545 }
546
547 // Try to narrow this MonotonicValueRange given another range.
548 // Ideally it will return a normal ValueRange. But due to
549 // possible overflow/underflow, that may not be possible.
550 ValueRange* Narrow(ValueRange* range) OVERRIDE {
551 if (range == nullptr) {
552 return this;
553 }
554 DCHECK(!range->IsMonotonicValueRange());
555
556 if (increment_ > 0) {
557 // Monotonically increasing.
Mingyao Yang64197522014-12-05 15:56:23 -0800558 ValueBound lower = ValueBound::NarrowLowerBound(bound_, range->GetLower());
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700559 if (!lower.IsConstant() || lower.GetConstant() == INT_MIN) {
560 // Lower bound isn't useful. Leave it to deoptimization.
561 return this;
562 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700563
564 // We currently conservatively assume max array length is INT_MAX. If we can
565 // make assumptions about the max array length, e.g. due to the max heap size,
566 // divided by the element size (such as 4 bytes for each integer array), we can
567 // lower this number and rule out some possible overflows.
Mingyao Yang0304e182015-01-30 16:41:29 -0800568 int32_t max_array_len = INT_MAX;
Mingyao Yangf384f882014-10-22 16:08:18 -0700569
Mingyao Yang0304e182015-01-30 16:41:29 -0800570 // max possible integer value of range's upper value.
571 int32_t upper = INT_MAX;
572 // Try to lower upper.
573 ValueBound upper_bound = range->GetUpper();
574 if (upper_bound.IsConstant()) {
575 upper = upper_bound.GetConstant();
576 } else if (upper_bound.IsRelatedToArrayLength() && upper_bound.GetConstant() <= 0) {
577 // Normal case. e.g. <= array.length - 1.
578 upper = max_array_len + upper_bound.GetConstant();
Mingyao Yangf384f882014-10-22 16:08:18 -0700579 }
580
581 // If we can prove for the last number in sequence of initial_,
582 // initial_ + increment_, initial_ + 2 x increment_, ...
583 // that's <= upper, (last_num_in_sequence + increment_) doesn't trigger overflow,
584 // then this MonoticValueRange is narrowed to a normal value range.
585
586 // Be conservative first, assume last number in the sequence hits upper.
Mingyao Yang0304e182015-01-30 16:41:29 -0800587 int32_t last_num_in_sequence = upper;
Mingyao Yangf384f882014-10-22 16:08:18 -0700588 if (initial_->IsIntConstant()) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800589 int32_t initial_constant = initial_->AsIntConstant()->GetValue();
Mingyao Yangf384f882014-10-22 16:08:18 -0700590 if (upper <= initial_constant) {
591 last_num_in_sequence = upper;
592 } else {
Mingyao Yang0304e182015-01-30 16:41:29 -0800593 // Cast to int64_t for the substraction part to avoid int32_t overflow.
Mingyao Yangf384f882014-10-22 16:08:18 -0700594 last_num_in_sequence = initial_constant +
595 ((int64_t)upper - (int64_t)initial_constant) / increment_ * increment_;
596 }
597 }
598 if (last_num_in_sequence <= INT_MAX - increment_) {
599 // No overflow. The sequence will be stopped by the upper bound test as expected.
600 return new (GetAllocator()) ValueRange(GetAllocator(), lower, range->GetUpper());
601 }
602
603 // There might be overflow. Give up narrowing.
604 return this;
605 } else {
606 DCHECK_NE(increment_, 0);
607 // Monotonically decreasing.
Mingyao Yang64197522014-12-05 15:56:23 -0800608 ValueBound upper = ValueBound::NarrowUpperBound(bound_, range->GetUpper());
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700609 if ((!upper.IsConstant() || upper.GetConstant() == INT_MAX) &&
610 !upper.IsRelatedToArrayLength()) {
611 // Upper bound isn't useful. Leave it to deoptimization.
612 return this;
613 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700614
615 // Need to take care of underflow. Try to prove underflow won't happen
Mingyao Yang0304e182015-01-30 16:41:29 -0800616 // for common cases.
Mingyao Yangf384f882014-10-22 16:08:18 -0700617 if (range->GetLower().IsConstant()) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800618 int32_t constant = range->GetLower().GetConstant();
Mingyao Yangf384f882014-10-22 16:08:18 -0700619 if (constant >= INT_MIN - increment_) {
620 return new (GetAllocator()) ValueRange(GetAllocator(), range->GetLower(), upper);
621 }
622 }
623
Mingyao Yang0304e182015-01-30 16:41:29 -0800624 // For non-constant lower bound, just assume might be underflow. Give up narrowing.
Mingyao Yangf384f882014-10-22 16:08:18 -0700625 return this;
626 }
627 }
628
Mingyao Yang3584bce2015-05-19 16:01:59 -0700629 // Try to add HDeoptimize's in the loop pre-header first to narrow this range.
630 // For example, this loop:
631 //
632 // for (int i = start; i < end; i++) {
633 // array[i - 1] = array[i] + array[i + 1];
634 // }
635 //
636 // will be transformed to:
637 //
638 // int array_length_in_loop_body_if_needed;
639 // if (start >= end) {
640 // array_length_in_loop_body_if_needed = 0;
641 // } else {
642 // if (start < 1) deoptimize();
643 // if (array == null) deoptimize();
644 // array_length = array.length;
645 // if (end > array_length - 1) deoptimize;
646 // array_length_in_loop_body_if_needed = array_length;
647 // }
648 // for (int i = start; i < end; i++) {
649 // // No more null check and bounds check.
650 // // array.length value is replaced with array_length_in_loop_body_if_needed
651 // // in the loop body.
652 // array[i - 1] = array[i] + array[i + 1];
653 // }
654 //
655 // We basically first go through the loop body and find those array accesses whose
656 // index is at a constant offset from the induction variable ('i' in the above example),
657 // and update offset_low and offset_high along the way. We then add the following
658 // deoptimizations in the loop pre-header (suppose end is not inclusive).
659 // if (start < -offset_low) deoptimize();
660 // if (end >= array.length - offset_high) deoptimize();
661 // It might be necessary to first hoist array.length (and the null check on it) out of
662 // the loop with another deoptimization.
663 //
664 // In order not to trigger deoptimization unnecessarily, we want to make a strong
665 // guarantee that no deoptimization is triggered if the loop body itself doesn't
666 // throw AIOOBE. (It's the same as saying if deoptimization is triggered, the loop
667 // body must throw AIOOBE).
668 // This is achieved by the following:
669 // 1) We only process loops that iterate through the full monotonic range from
670 // initial_ to end_. We do the following checks to make sure that's the case:
671 // a) The loop doesn't have early exit (via break, return, etc.)
672 // b) The increment_ is 1/-1. An increment of 2, for example, may skip end_.
673 // 2) We only collect array accesses of blocks in the loop body that dominate
674 // all loop back edges, these array accesses are guaranteed to happen
675 // at each loop iteration.
676 // With 1) and 2), if the loop body doesn't throw AIOOBE, collected array accesses
677 // when the induction variable is at initial_ and end_ must be in a legal range.
678 // Since the added deoptimizations are basically checking the induction variable
679 // at initial_ and end_ values, no deoptimization will be triggered either.
680 //
681 // A special case is the loop body isn't entered at all. In that case, we may still
682 // add deoptimization due to the analysis described above. In order not to trigger
683 // deoptimization, we do a test between initial_ and end_ first and skip over
684 // the added deoptimization.
685 ValueRange* NarrowWithDeoptimization() {
686 if (increment_ != 1 && increment_ != -1) {
687 // In order not to trigger deoptimization unnecessarily, we want to
688 // make sure the loop iterates through the full range from initial_ to
689 // end_ so that boundaries are covered by the loop. An increment of 2,
690 // for example, may skip end_.
691 return this;
692 }
693
694 if (end_ == nullptr) {
695 // No full info to add deoptimization.
696 return this;
697 }
698
699 HBasicBlock* header = induction_variable_->GetBlock();
700 DCHECK(header->IsLoopHeader());
701 HBasicBlock* pre_header = header->GetLoopInformation()->GetPreHeader();
702 if (!initial_->GetBlock()->Dominates(pre_header) ||
703 !end_->GetBlock()->Dominates(pre_header)) {
704 // Can't add a check in loop pre-header if the value isn't available there.
705 return this;
706 }
707
708 ArrayAccessInsideLoopFinder finder(induction_variable_);
709
710 if (!finder.HasFoundArrayLength()) {
711 // No array access was found inside the loop that can benefit
712 // from deoptimization.
713 return this;
714 }
715
716 if (!AddDeoptimization(finder)) {
717 return this;
718 }
719
720 // After added deoptimizations, induction variable fits in
721 // [-offset_low, array.length-1-offset_high], adjusted with collected offsets.
722 ValueBound lower = ValueBound(0, -finder.GetOffsetLow());
723 ValueBound upper = ValueBound(finder.GetFoundArrayLength(), -1 - finder.GetOffsetHigh());
724 // We've narrowed the range after added deoptimizations.
725 return new (GetAllocator()) ValueRange(GetAllocator(), lower, upper);
726 }
727
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700728 // Returns true if adding a (constant >= value) check for deoptimization
729 // is allowed and will benefit compiled code.
Mingyao Yang3584bce2015-05-19 16:01:59 -0700730 bool CanAddDeoptimizationConstant(HInstruction* value, int32_t constant, bool* is_proven) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700731 *is_proven = false;
Mingyao Yang3584bce2015-05-19 16:01:59 -0700732 HBasicBlock* header = induction_variable_->GetBlock();
733 DCHECK(header->IsLoopHeader());
734 HBasicBlock* pre_header = header->GetLoopInformation()->GetPreHeader();
735 DCHECK(value->GetBlock()->Dominates(pre_header));
736
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700737 // See if we can prove the relationship first.
738 if (value->IsIntConstant()) {
739 if (value->AsIntConstant()->GetValue() >= constant) {
740 // Already true.
741 *is_proven = true;
742 return true;
743 } else {
744 // May throw exception. Don't add deoptimization.
745 // Keep bounds checks in the loops.
746 return false;
747 }
748 }
749 // Can benefit from deoptimization.
750 return true;
751 }
752
Mingyao Yang3584bce2015-05-19 16:01:59 -0700753 // Try to filter out cases that the loop entry test will never be true.
754 bool LoopEntryTestUseful() {
755 if (initial_->IsIntConstant() && end_->IsIntConstant()) {
756 int32_t initial_val = initial_->AsIntConstant()->GetValue();
757 int32_t end_val = end_->AsIntConstant()->GetValue();
758 if (increment_ == 1) {
759 if (inclusive_) {
760 return initial_val > end_val;
761 } else {
762 return initial_val >= end_val;
763 }
764 } else {
Andreas Gampe45d68f12015-06-10 18:33:26 -0700765 DCHECK_EQ(increment_, -1);
Mingyao Yang3584bce2015-05-19 16:01:59 -0700766 if (inclusive_) {
767 return initial_val < end_val;
768 } else {
769 return initial_val <= end_val;
770 }
771 }
772 }
773 return true;
774 }
775
776 // Returns the block for adding deoptimization.
777 HBasicBlock* TransformLoopForDeoptimizationIfNeeded() {
778 HBasicBlock* header = induction_variable_->GetBlock();
779 DCHECK(header->IsLoopHeader());
780 HBasicBlock* pre_header = header->GetLoopInformation()->GetPreHeader();
781 // Deoptimization is only added when both initial_ and end_ are defined
782 // before the loop.
783 DCHECK(initial_->GetBlock()->Dominates(pre_header));
784 DCHECK(end_->GetBlock()->Dominates(pre_header));
785
786 // If it can be proven the loop body is definitely entered (unless exception
787 // is thrown in the loop header for which triggering deoptimization is fine),
788 // there is no need for tranforming the loop. In that case, deoptimization
789 // will just be added in the loop pre-header.
790 if (!LoopEntryTestUseful()) {
791 return pre_header;
792 }
793
794 HGraph* graph = header->GetGraph();
795 graph->TransformLoopHeaderForBCE(header);
796 HBasicBlock* new_pre_header = header->GetDominator();
797 DCHECK(new_pre_header == header->GetLoopInformation()->GetPreHeader());
798 HBasicBlock* if_block = new_pre_header->GetDominator();
Vladimir Marko60584552015-09-03 13:35:12 +0000799 HBasicBlock* dummy_block = if_block->GetSuccessor(0); // True successor.
800 HBasicBlock* deopt_block = if_block->GetSuccessor(1); // False successor.
Mingyao Yang3584bce2015-05-19 16:01:59 -0700801
802 dummy_block->AddInstruction(new (graph->GetArena()) HGoto());
803 deopt_block->AddInstruction(new (graph->GetArena()) HGoto());
804 new_pre_header->AddInstruction(new (graph->GetArena()) HGoto());
805 return deopt_block;
806 }
807
808 // Adds a test between initial_ and end_ to see if the loop body is entered.
809 // If the loop body isn't entered at all, it jumps to the loop pre-header (after
810 // transformation) to avoid any deoptimization.
811 void AddLoopBodyEntryTest() {
812 HBasicBlock* header = induction_variable_->GetBlock();
813 DCHECK(header->IsLoopHeader());
814 HBasicBlock* pre_header = header->GetLoopInformation()->GetPreHeader();
815 HBasicBlock* if_block = pre_header->GetDominator();
816 HGraph* graph = header->GetGraph();
817
818 HCondition* cond;
819 if (increment_ == 1) {
820 if (inclusive_) {
821 cond = new (graph->GetArena()) HGreaterThan(initial_, end_);
822 } else {
823 cond = new (graph->GetArena()) HGreaterThanOrEqual(initial_, end_);
824 }
825 } else {
Andreas Gampe45d68f12015-06-10 18:33:26 -0700826 DCHECK_EQ(increment_, -1);
Mingyao Yang3584bce2015-05-19 16:01:59 -0700827 if (inclusive_) {
828 cond = new (graph->GetArena()) HLessThan(initial_, end_);
829 } else {
830 cond = new (graph->GetArena()) HLessThanOrEqual(initial_, end_);
831 }
832 }
833 HIf* h_if = new (graph->GetArena()) HIf(cond);
834 if_block->AddInstruction(cond);
835 if_block->AddInstruction(h_if);
836 }
837
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700838 // Adds a check that (value >= constant), and HDeoptimize otherwise.
839 void AddDeoptimizationConstant(HInstruction* value,
Mingyao Yang3584bce2015-05-19 16:01:59 -0700840 int32_t constant,
841 HBasicBlock* deopt_block,
842 bool loop_entry_test_block_added) {
843 HBasicBlock* header = induction_variable_->GetBlock();
844 DCHECK(header->IsLoopHeader());
845 HBasicBlock* pre_header = header->GetDominator();
846 if (loop_entry_test_block_added) {
Vladimir Marko60584552015-09-03 13:35:12 +0000847 DCHECK(deopt_block->GetSuccessor(0) == pre_header);
Mingyao Yang3584bce2015-05-19 16:01:59 -0700848 } else {
849 DCHECK(deopt_block == pre_header);
850 }
851 HGraph* graph = header->GetGraph();
852 HSuspendCheck* suspend_check = header->GetLoopInformation()->GetSuspendCheck();
853 if (loop_entry_test_block_added) {
Vladimir Marko60584552015-09-03 13:35:12 +0000854 DCHECK_EQ(deopt_block, header->GetDominator()->GetDominator()->GetSuccessor(1));
Mingyao Yang3584bce2015-05-19 16:01:59 -0700855 }
856
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700857 HIntConstant* const_instr = graph->GetIntConstant(constant);
858 HCondition* cond = new (graph->GetArena()) HLessThan(value, const_instr);
859 HDeoptimize* deoptimize = new (graph->GetArena())
860 HDeoptimize(cond, suspend_check->GetDexPc());
Mingyao Yang3584bce2015-05-19 16:01:59 -0700861 deopt_block->InsertInstructionBefore(cond, deopt_block->GetLastInstruction());
862 deopt_block->InsertInstructionBefore(deoptimize, deopt_block->GetLastInstruction());
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700863 deoptimize->CopyEnvironmentFromWithLoopPhiAdjustment(
Mingyao Yang3584bce2015-05-19 16:01:59 -0700864 suspend_check->GetEnvironment(), header);
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700865 }
866
867 // Returns true if adding a (value <= array_length + offset) check for deoptimization
868 // is allowed and will benefit compiled code.
869 bool CanAddDeoptimizationArrayLength(HInstruction* value,
870 HArrayLength* array_length,
871 int32_t offset,
872 bool* is_proven) {
873 *is_proven = false;
Mingyao Yang3584bce2015-05-19 16:01:59 -0700874 HBasicBlock* header = induction_variable_->GetBlock();
875 DCHECK(header->IsLoopHeader());
876 HBasicBlock* pre_header = header->GetLoopInformation()->GetPreHeader();
877 DCHECK(value->GetBlock()->Dominates(pre_header));
878
879 if (array_length->GetBlock() == header) {
880 // array_length_in_loop_body_if_needed only has correct value when the loop
881 // body is entered. We bail out in this case. Usually array_length defined
882 // in the loop header is already hoisted by licm.
883 return false;
884 } else {
885 // array_length is defined either before the loop header already, or in
886 // the loop body since it's used in the loop body. If it's defined in the loop body,
887 // a phi array_length_in_loop_body_if_needed is used to replace it. In that case,
888 // all the uses of array_length must be dominated by its definition in the loop
889 // body. array_length_in_loop_body_if_needed is guaranteed to be the same as
890 // array_length once the loop body is entered so all the uses of the phi will
891 // use the correct value.
892 }
893
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700894 if (offset > 0) {
895 // There might be overflow issue.
896 // TODO: handle this, possibly with some distance relationship between
897 // offset_low and offset_high, or using another deoptimization to make
898 // sure (array_length + offset) doesn't overflow.
899 return false;
900 }
901
902 // See if we can prove the relationship first.
903 if (value == array_length) {
904 if (offset >= 0) {
905 // Already true.
906 *is_proven = true;
907 return true;
908 } else {
909 // May throw exception. Don't add deoptimization.
910 // Keep bounds checks in the loops.
911 return false;
912 }
913 }
914 // Can benefit from deoptimization.
915 return true;
916 }
917
918 // Adds a check that (value <= array_length + offset), and HDeoptimize otherwise.
919 void AddDeoptimizationArrayLength(HInstruction* value,
920 HArrayLength* array_length,
Mingyao Yang3584bce2015-05-19 16:01:59 -0700921 int32_t offset,
922 HBasicBlock* deopt_block,
923 bool loop_entry_test_block_added) {
924 HBasicBlock* header = induction_variable_->GetBlock();
925 DCHECK(header->IsLoopHeader());
926 HBasicBlock* pre_header = header->GetDominator();
927 if (loop_entry_test_block_added) {
Vladimir Marko60584552015-09-03 13:35:12 +0000928 DCHECK(deopt_block->GetSuccessor(0) == pre_header);
Mingyao Yang3584bce2015-05-19 16:01:59 -0700929 } else {
930 DCHECK(deopt_block == pre_header);
931 }
932 HGraph* graph = header->GetGraph();
933 HSuspendCheck* suspend_check = header->GetLoopInformation()->GetSuspendCheck();
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700934
935 // We may need to hoist null-check and array_length out of loop first.
Mingyao Yang3584bce2015-05-19 16:01:59 -0700936 if (!array_length->GetBlock()->Dominates(deopt_block)) {
937 // array_length must be defined in the loop body.
938 DCHECK(header->GetLoopInformation()->Contains(*array_length->GetBlock()));
939 DCHECK(array_length->GetBlock() != header);
940
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700941 HInstruction* array = array_length->InputAt(0);
942 HNullCheck* null_check = array->AsNullCheck();
943 if (null_check != nullptr) {
944 array = null_check->InputAt(0);
945 }
Mingyao Yang3584bce2015-05-19 16:01:59 -0700946 // We've already made sure the array is defined before the loop when collecting
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700947 // array accesses for the loop.
Mingyao Yang3584bce2015-05-19 16:01:59 -0700948 DCHECK(array->GetBlock()->Dominates(deopt_block));
949 if (null_check != nullptr && !null_check->GetBlock()->Dominates(deopt_block)) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700950 // Hoist null check out of loop with a deoptimization.
951 HNullConstant* null_constant = graph->GetNullConstant();
952 HCondition* null_check_cond = new (graph->GetArena()) HEqual(array, null_constant);
953 // TODO: for one dex_pc, share the same deoptimization slow path.
954 HDeoptimize* null_check_deoptimize = new (graph->GetArena())
955 HDeoptimize(null_check_cond, suspend_check->GetDexPc());
Mingyao Yang3584bce2015-05-19 16:01:59 -0700956 deopt_block->InsertInstructionBefore(
957 null_check_cond, deopt_block->GetLastInstruction());
958 deopt_block->InsertInstructionBefore(
959 null_check_deoptimize, deopt_block->GetLastInstruction());
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700960 // Eliminate null check in the loop.
961 null_check->ReplaceWith(array);
962 null_check->GetBlock()->RemoveInstruction(null_check);
963 null_check_deoptimize->CopyEnvironmentFromWithLoopPhiAdjustment(
Mingyao Yang3584bce2015-05-19 16:01:59 -0700964 suspend_check->GetEnvironment(), header);
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700965 }
Mingyao Yang3584bce2015-05-19 16:01:59 -0700966
967 HArrayLength* new_array_length = new (graph->GetArena()) HArrayLength(array);
968 deopt_block->InsertInstructionBefore(new_array_length, deopt_block->GetLastInstruction());
969
970 if (loop_entry_test_block_added) {
971 // Replace array_length defined inside the loop body with a phi
972 // array_length_in_loop_body_if_needed. This is a synthetic phi so there is
973 // no vreg number for it.
974 HPhi* phi = new (graph->GetArena()) HPhi(
975 graph->GetArena(), kNoRegNumber, 2, Primitive::kPrimInt);
976 // Set to 0 if the loop body isn't entered.
977 phi->SetRawInputAt(0, graph->GetIntConstant(0));
978 // Set to array.length if the loop body is entered.
979 phi->SetRawInputAt(1, new_array_length);
980 pre_header->AddPhi(phi);
981 array_length->ReplaceWith(phi);
982 // Make sure phi is only used after the loop body is entered.
983 if (kIsDebugBuild) {
984 for (HUseIterator<HInstruction*> it(phi->GetUses());
985 !it.Done();
986 it.Advance()) {
987 HInstruction* user = it.Current()->GetUser();
988 DCHECK(GetLoopHeaderSuccesorInLoop()->Dominates(user->GetBlock()));
989 }
990 }
991 } else {
992 array_length->ReplaceWith(new_array_length);
993 }
994
995 array_length->GetBlock()->RemoveInstruction(array_length);
996 // Use new_array_length for deopt.
997 array_length = new_array_length;
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700998 }
999
Mingyao Yang3584bce2015-05-19 16:01:59 -07001000 HInstruction* added = array_length;
1001 if (offset != 0) {
1002 HIntConstant* offset_instr = graph->GetIntConstant(offset);
1003 added = new (graph->GetArena()) HAdd(Primitive::kPrimInt, array_length, offset_instr);
1004 deopt_block->InsertInstructionBefore(added, deopt_block->GetLastInstruction());
1005 }
1006 HCondition* cond = new (graph->GetArena()) HGreaterThan(value, added);
1007 HDeoptimize* deopt = new (graph->GetArena()) HDeoptimize(cond, suspend_check->GetDexPc());
1008 deopt_block->InsertInstructionBefore(cond, deopt_block->GetLastInstruction());
1009 deopt_block->InsertInstructionBefore(deopt, deopt_block->GetLastInstruction());
1010 deopt->CopyEnvironmentFromWithLoopPhiAdjustment(suspend_check->GetEnvironment(), header);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001011 }
1012
Mingyao Yang3584bce2015-05-19 16:01:59 -07001013 // Adds deoptimizations in loop pre-header with the collected array access
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001014 // data so that value ranges can be established in loop body.
1015 // Returns true if deoptimizations are successfully added, or if it's proven
1016 // it's not necessary.
1017 bool AddDeoptimization(const ArrayAccessInsideLoopFinder& finder) {
1018 int32_t offset_low = finder.GetOffsetLow();
1019 int32_t offset_high = finder.GetOffsetHigh();
1020 HArrayLength* array_length = finder.GetFoundArrayLength();
1021
1022 HBasicBlock* pre_header =
1023 induction_variable_->GetBlock()->GetLoopInformation()->GetPreHeader();
1024 if (!initial_->GetBlock()->Dominates(pre_header) ||
1025 !end_->GetBlock()->Dominates(pre_header)) {
1026 // Can't move initial_ or end_ into pre_header for comparisons.
1027 return false;
1028 }
1029
Mingyao Yang3584bce2015-05-19 16:01:59 -07001030 HBasicBlock* deopt_block;
1031 bool loop_entry_test_block_added = false;
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001032 bool is_constant_proven, is_length_proven;
Mingyao Yang3584bce2015-05-19 16:01:59 -07001033
1034 HInstruction* const_comparing_instruction;
1035 int32_t const_compared_to;
1036 HInstruction* array_length_comparing_instruction;
1037 int32_t array_length_offset;
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001038 if (increment_ == 1) {
1039 // Increasing from initial_ to end_.
Mingyao Yang3584bce2015-05-19 16:01:59 -07001040 const_comparing_instruction = initial_;
1041 const_compared_to = -offset_low;
1042 array_length_comparing_instruction = end_;
1043 array_length_offset = inclusive_ ? -offset_high - 1 : -offset_high;
1044 } else {
1045 const_comparing_instruction = end_;
1046 const_compared_to = inclusive_ ? -offset_low : -offset_low - 1;
1047 array_length_comparing_instruction = initial_;
1048 array_length_offset = -offset_high - 1;
1049 }
1050
1051 if (CanAddDeoptimizationConstant(const_comparing_instruction,
1052 const_compared_to,
1053 &is_constant_proven) &&
1054 CanAddDeoptimizationArrayLength(array_length_comparing_instruction,
1055 array_length,
1056 array_length_offset,
1057 &is_length_proven)) {
1058 if (!is_constant_proven || !is_length_proven) {
1059 deopt_block = TransformLoopForDeoptimizationIfNeeded();
1060 loop_entry_test_block_added = (deopt_block != pre_header);
1061 if (loop_entry_test_block_added) {
1062 // Loop body may be entered.
1063 AddLoopBodyEntryTest();
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001064 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001065 }
Mingyao Yang3584bce2015-05-19 16:01:59 -07001066 if (!is_constant_proven) {
1067 AddDeoptimizationConstant(const_comparing_instruction,
1068 const_compared_to,
1069 deopt_block,
1070 loop_entry_test_block_added);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001071 }
Mingyao Yang3584bce2015-05-19 16:01:59 -07001072 if (!is_length_proven) {
1073 AddDeoptimizationArrayLength(array_length_comparing_instruction,
1074 array_length,
1075 array_length_offset,
1076 deopt_block,
1077 loop_entry_test_block_added);
1078 }
1079 return true;
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001080 }
1081 return false;
1082 }
1083
Mingyao Yangf384f882014-10-22 16:08:18 -07001084 private:
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001085 HPhi* const induction_variable_; // Induction variable for this monotonic value range.
1086 HInstruction* const initial_; // Initial value.
1087 HInstruction* end_; // End value.
1088 bool inclusive_; // Whether end value is inclusive.
1089 const int32_t increment_; // Increment for each loop iteration.
1090 const ValueBound bound_; // Additional value bound info for initial_.
Mingyao Yangf384f882014-10-22 16:08:18 -07001091
1092 DISALLOW_COPY_AND_ASSIGN(MonotonicValueRange);
1093};
1094
1095class BCEVisitor : public HGraphVisitor {
1096 public:
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001097 // The least number of bounds checks that should be eliminated by triggering
1098 // the deoptimization technique.
1099 static constexpr size_t kThresholdForAddingDeoptimize = 2;
1100
1101 // Very large constant index is considered as an anomaly. This is a threshold
1102 // beyond which we don't bother to apply the deoptimization technique since
1103 // it's likely some AIOOBE will be thrown.
1104 static constexpr int32_t kMaxConstantForAddingDeoptimize = INT_MAX - 1024 * 1024;
1105
Mingyao Yang3584bce2015-05-19 16:01:59 -07001106 // Added blocks for loop body entry test.
1107 bool IsAddedBlock(HBasicBlock* block) const {
1108 return block->GetBlockId() >= initial_block_size_;
1109 }
1110
Andreas Gampe0418b5b2014-12-04 17:24:50 -08001111 explicit BCEVisitor(HGraph* graph)
Mingyao Yang3584bce2015-05-19 16:01:59 -07001112 : HGraphVisitor(graph), maps_(graph->GetBlocks().Size()),
1113 need_to_revisit_block_(false), initial_block_size_(graph->GetBlocks().Size()) {}
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001114
1115 void VisitBasicBlock(HBasicBlock* block) OVERRIDE {
Mingyao Yang3584bce2015-05-19 16:01:59 -07001116 DCHECK(!IsAddedBlock(block));
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001117 first_constant_index_bounds_check_map_.clear();
1118 HGraphVisitor::VisitBasicBlock(block);
1119 if (need_to_revisit_block_) {
1120 AddComparesWithDeoptimization(block);
1121 need_to_revisit_block_ = false;
1122 first_constant_index_bounds_check_map_.clear();
1123 GetValueRangeMap(block)->clear();
1124 HGraphVisitor::VisitBasicBlock(block);
1125 }
1126 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001127
1128 private:
1129 // Return the map of proven value ranges at the beginning of a basic block.
1130 ArenaSafeMap<int, ValueRange*>* GetValueRangeMap(HBasicBlock* basic_block) {
Mingyao Yang3584bce2015-05-19 16:01:59 -07001131 if (IsAddedBlock(basic_block)) {
1132 // Added blocks don't keep value ranges.
1133 return nullptr;
1134 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001135 int block_id = basic_block->GetBlockId();
1136 if (maps_.at(block_id) == nullptr) {
1137 std::unique_ptr<ArenaSafeMap<int, ValueRange*>> map(
1138 new ArenaSafeMap<int, ValueRange*>(
1139 std::less<int>(), GetGraph()->GetArena()->Adapter()));
1140 maps_.at(block_id) = std::move(map);
1141 }
1142 return maps_.at(block_id).get();
1143 }
1144
1145 // Traverse up the dominator tree to look for value range info.
1146 ValueRange* LookupValueRange(HInstruction* instruction, HBasicBlock* basic_block) {
1147 while (basic_block != nullptr) {
1148 ArenaSafeMap<int, ValueRange*>* map = GetValueRangeMap(basic_block);
Mingyao Yang3584bce2015-05-19 16:01:59 -07001149 if (map != nullptr) {
1150 if (map->find(instruction->GetId()) != map->end()) {
1151 return map->Get(instruction->GetId());
1152 }
1153 } else {
1154 DCHECK(IsAddedBlock(basic_block));
Mingyao Yangf384f882014-10-22 16:08:18 -07001155 }
1156 basic_block = basic_block->GetDominator();
1157 }
1158 // Didn't find any.
1159 return nullptr;
1160 }
1161
Mingyao Yang0304e182015-01-30 16:41:29 -08001162 // Narrow the value range of `instruction` at the end of `basic_block` with `range`,
1163 // and push the narrowed value range to `successor`.
Mingyao Yangf384f882014-10-22 16:08:18 -07001164 void ApplyRangeFromComparison(HInstruction* instruction, HBasicBlock* basic_block,
Mingyao Yang8c8bad82015-02-09 18:13:26 -08001165 HBasicBlock* successor, ValueRange* range) {
Mingyao Yangf384f882014-10-22 16:08:18 -07001166 ValueRange* existing_range = LookupValueRange(instruction, basic_block);
Mingyao Yang8c8bad82015-02-09 18:13:26 -08001167 if (existing_range == nullptr) {
1168 if (range != nullptr) {
1169 GetValueRangeMap(successor)->Overwrite(instruction->GetId(), range);
1170 }
1171 return;
1172 }
1173 if (existing_range->IsMonotonicValueRange()) {
1174 DCHECK(instruction->IsLoopHeaderPhi());
1175 // Make sure the comparison is in the loop header so each increment is
1176 // checked with a comparison.
1177 if (instruction->GetBlock() != basic_block) {
1178 return;
1179 }
1180 }
1181 ValueRange* narrowed_range = existing_range->Narrow(range);
Nicolas Geoffraya09ff9c2015-06-24 10:38:27 +01001182 GetValueRangeMap(successor)->Overwrite(instruction->GetId(), narrowed_range);
Mingyao Yangf384f882014-10-22 16:08:18 -07001183 }
1184
Mingyao Yang57e04752015-02-09 18:13:26 -08001185 // Special case that we may simultaneously narrow two MonotonicValueRange's to
1186 // regular value ranges.
1187 void HandleIfBetweenTwoMonotonicValueRanges(HIf* instruction,
1188 HInstruction* left,
1189 HInstruction* right,
1190 IfCondition cond,
1191 MonotonicValueRange* left_range,
1192 MonotonicValueRange* right_range) {
1193 DCHECK(left->IsLoopHeaderPhi());
1194 DCHECK(right->IsLoopHeaderPhi());
1195 if (instruction->GetBlock() != left->GetBlock()) {
1196 // Comparison needs to be in loop header to make sure it's done after each
1197 // increment/decrement.
1198 return;
1199 }
1200
1201 // Handle common cases which also don't have overflow/underflow concerns.
1202 if (left_range->GetIncrement() == 1 &&
1203 left_range->GetBound().IsConstant() &&
1204 right_range->GetIncrement() == -1 &&
1205 right_range->GetBound().IsRelatedToArrayLength() &&
1206 right_range->GetBound().GetConstant() < 0) {
Mingyao Yang57e04752015-02-09 18:13:26 -08001207 HBasicBlock* successor = nullptr;
1208 int32_t left_compensation = 0;
1209 int32_t right_compensation = 0;
1210 if (cond == kCondLT) {
1211 left_compensation = -1;
1212 right_compensation = 1;
1213 successor = instruction->IfTrueSuccessor();
1214 } else if (cond == kCondLE) {
1215 successor = instruction->IfTrueSuccessor();
1216 } else if (cond == kCondGT) {
1217 successor = instruction->IfFalseSuccessor();
1218 } else if (cond == kCondGE) {
1219 left_compensation = -1;
1220 right_compensation = 1;
1221 successor = instruction->IfFalseSuccessor();
1222 } else {
1223 // We don't handle '=='/'!=' test in case left and right can cross and
1224 // miss each other.
1225 return;
1226 }
1227
1228 if (successor != nullptr) {
1229 bool overflow;
1230 bool underflow;
1231 ValueRange* new_left_range = new (GetGraph()->GetArena()) ValueRange(
1232 GetGraph()->GetArena(),
1233 left_range->GetBound(),
1234 right_range->GetBound().Add(left_compensation, &overflow, &underflow));
1235 if (!overflow && !underflow) {
1236 ApplyRangeFromComparison(left, instruction->GetBlock(), successor,
1237 new_left_range);
1238 }
1239
1240 ValueRange* new_right_range = new (GetGraph()->GetArena()) ValueRange(
1241 GetGraph()->GetArena(),
1242 left_range->GetBound().Add(right_compensation, &overflow, &underflow),
1243 right_range->GetBound());
1244 if (!overflow && !underflow) {
1245 ApplyRangeFromComparison(right, instruction->GetBlock(), successor,
1246 new_right_range);
1247 }
1248 }
1249 }
1250 }
1251
Mingyao Yangf384f882014-10-22 16:08:18 -07001252 // Handle "if (left cmp_cond right)".
1253 void HandleIf(HIf* instruction, HInstruction* left, HInstruction* right, IfCondition cond) {
1254 HBasicBlock* block = instruction->GetBlock();
1255
1256 HBasicBlock* true_successor = instruction->IfTrueSuccessor();
1257 // There should be no critical edge at this point.
Vladimir Marko60584552015-09-03 13:35:12 +00001258 DCHECK_EQ(true_successor->GetPredecessors().size(), 1u);
Mingyao Yangf384f882014-10-22 16:08:18 -07001259
1260 HBasicBlock* false_successor = instruction->IfFalseSuccessor();
1261 // There should be no critical edge at this point.
Vladimir Marko60584552015-09-03 13:35:12 +00001262 DCHECK_EQ(false_successor->GetPredecessors().size(), 1u);
Mingyao Yangf384f882014-10-22 16:08:18 -07001263
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001264 ValueRange* left_range = LookupValueRange(left, block);
1265 MonotonicValueRange* left_monotonic_range = nullptr;
1266 if (left_range != nullptr) {
1267 left_monotonic_range = left_range->AsMonotonicValueRange();
1268 if (left_monotonic_range != nullptr) {
Mingyao Yang3584bce2015-05-19 16:01:59 -07001269 HBasicBlock* loop_head = left_monotonic_range->GetLoopHeader();
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001270 if (instruction->GetBlock() != loop_head) {
1271 // For monotonic value range, don't handle `instruction`
1272 // if it's not defined in the loop header.
1273 return;
1274 }
1275 }
1276 }
1277
Mingyao Yang64197522014-12-05 15:56:23 -08001278 bool found;
1279 ValueBound bound = ValueBound::DetectValueBoundFromValue(right, &found);
Mingyao Yang0304e182015-01-30 16:41:29 -08001280 // Each comparison can establish a lower bound and an upper bound
1281 // for the left hand side.
Mingyao Yangf384f882014-10-22 16:08:18 -07001282 ValueBound lower = bound;
1283 ValueBound upper = bound;
1284 if (!found) {
Mingyao Yang0304e182015-01-30 16:41:29 -08001285 // No constant or array.length+c format bound found.
Mingyao Yangf384f882014-10-22 16:08:18 -07001286 // For i<j, we can still use j's upper bound as i's upper bound. Same for lower.
Mingyao Yang57e04752015-02-09 18:13:26 -08001287 ValueRange* right_range = LookupValueRange(right, block);
1288 if (right_range != nullptr) {
1289 if (right_range->IsMonotonicValueRange()) {
Mingyao Yang57e04752015-02-09 18:13:26 -08001290 if (left_range != nullptr && left_range->IsMonotonicValueRange()) {
1291 HandleIfBetweenTwoMonotonicValueRanges(instruction, left, right, cond,
1292 left_range->AsMonotonicValueRange(),
1293 right_range->AsMonotonicValueRange());
1294 return;
1295 }
1296 }
1297 lower = right_range->GetLower();
1298 upper = right_range->GetUpper();
Mingyao Yangf384f882014-10-22 16:08:18 -07001299 } else {
1300 lower = ValueBound::Min();
1301 upper = ValueBound::Max();
1302 }
1303 }
1304
Mingyao Yang0304e182015-01-30 16:41:29 -08001305 bool overflow, underflow;
Mingyao Yangf384f882014-10-22 16:08:18 -07001306 if (cond == kCondLT || cond == kCondLE) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001307 if (left_monotonic_range != nullptr) {
1308 // Update the info for monotonic value range.
1309 if (left_monotonic_range->GetInductionVariable() == left &&
1310 left_monotonic_range->GetIncrement() < 0 &&
Mingyao Yang3584bce2015-05-19 16:01:59 -07001311 block == left_monotonic_range->GetLoopHeader() &&
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001312 instruction->IfFalseSuccessor()->GetLoopInformation() == block->GetLoopInformation()) {
1313 left_monotonic_range->SetEnd(right);
1314 left_monotonic_range->SetInclusive(cond == kCondLT);
1315 }
1316 }
1317
Mingyao Yangf384f882014-10-22 16:08:18 -07001318 if (!upper.Equals(ValueBound::Max())) {
Mingyao Yang0304e182015-01-30 16:41:29 -08001319 int32_t compensation = (cond == kCondLT) ? -1 : 0; // upper bound is inclusive
1320 ValueBound new_upper = upper.Add(compensation, &overflow, &underflow);
1321 if (overflow || underflow) {
1322 return;
Mingyao Yang64197522014-12-05 15:56:23 -08001323 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001324 ValueRange* new_range = new (GetGraph()->GetArena())
1325 ValueRange(GetGraph()->GetArena(), ValueBound::Min(), new_upper);
1326 ApplyRangeFromComparison(left, block, true_successor, new_range);
1327 }
1328
1329 // array.length as a lower bound isn't considered useful.
Mingyao Yang0304e182015-01-30 16:41:29 -08001330 if (!lower.Equals(ValueBound::Min()) && !lower.IsRelatedToArrayLength()) {
1331 int32_t compensation = (cond == kCondLE) ? 1 : 0; // lower bound is inclusive
1332 ValueBound new_lower = lower.Add(compensation, &overflow, &underflow);
1333 if (overflow || underflow) {
1334 return;
Mingyao Yang64197522014-12-05 15:56:23 -08001335 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001336 ValueRange* new_range = new (GetGraph()->GetArena())
1337 ValueRange(GetGraph()->GetArena(), new_lower, ValueBound::Max());
1338 ApplyRangeFromComparison(left, block, false_successor, new_range);
1339 }
1340 } else if (cond == kCondGT || cond == kCondGE) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001341 if (left_monotonic_range != nullptr) {
1342 // Update the info for monotonic value range.
1343 if (left_monotonic_range->GetInductionVariable() == left &&
1344 left_monotonic_range->GetIncrement() > 0 &&
Mingyao Yang3584bce2015-05-19 16:01:59 -07001345 block == left_monotonic_range->GetLoopHeader() &&
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001346 instruction->IfFalseSuccessor()->GetLoopInformation() == block->GetLoopInformation()) {
1347 left_monotonic_range->SetEnd(right);
1348 left_monotonic_range->SetInclusive(cond == kCondGT);
1349 }
1350 }
1351
Mingyao Yangf384f882014-10-22 16:08:18 -07001352 // array.length as a lower bound isn't considered useful.
Mingyao Yang0304e182015-01-30 16:41:29 -08001353 if (!lower.Equals(ValueBound::Min()) && !lower.IsRelatedToArrayLength()) {
1354 int32_t compensation = (cond == kCondGT) ? 1 : 0; // lower bound is inclusive
1355 ValueBound new_lower = lower.Add(compensation, &overflow, &underflow);
1356 if (overflow || underflow) {
1357 return;
Mingyao Yang64197522014-12-05 15:56:23 -08001358 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001359 ValueRange* new_range = new (GetGraph()->GetArena())
1360 ValueRange(GetGraph()->GetArena(), new_lower, ValueBound::Max());
1361 ApplyRangeFromComparison(left, block, true_successor, new_range);
1362 }
1363
1364 if (!upper.Equals(ValueBound::Max())) {
Mingyao Yang0304e182015-01-30 16:41:29 -08001365 int32_t compensation = (cond == kCondGE) ? -1 : 0; // upper bound is inclusive
1366 ValueBound new_upper = upper.Add(compensation, &overflow, &underflow);
1367 if (overflow || underflow) {
1368 return;
Mingyao Yang64197522014-12-05 15:56:23 -08001369 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001370 ValueRange* new_range = new (GetGraph()->GetArena())
1371 ValueRange(GetGraph()->GetArena(), ValueBound::Min(), new_upper);
1372 ApplyRangeFromComparison(left, block, false_successor, new_range);
1373 }
1374 }
1375 }
1376
1377 void VisitBoundsCheck(HBoundsCheck* bounds_check) {
1378 HBasicBlock* block = bounds_check->GetBlock();
1379 HInstruction* index = bounds_check->InputAt(0);
1380 HInstruction* array_length = bounds_check->InputAt(1);
Mingyao Yang3584bce2015-05-19 16:01:59 -07001381 DCHECK(array_length->IsIntConstant() ||
1382 array_length->IsArrayLength() ||
1383 array_length->IsPhi());
1384
1385 if (array_length->IsPhi()) {
1386 // Input 1 of the phi contains the real array.length once the loop body is
1387 // entered. That value will be used for bound analysis. The graph is still
Nicolas Geoffray8df886b2015-06-24 14:57:44 +01001388 // strictly in SSA form.
Mingyao Yang3584bce2015-05-19 16:01:59 -07001389 array_length = array_length->AsPhi()->InputAt(1)->AsArrayLength();
1390 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001391
Mingyao Yang0304e182015-01-30 16:41:29 -08001392 if (!index->IsIntConstant()) {
1393 ValueRange* index_range = LookupValueRange(index, block);
1394 if (index_range != nullptr) {
1395 ValueBound lower = ValueBound(nullptr, 0); // constant 0
1396 ValueBound upper = ValueBound(array_length, -1); // array_length - 1
1397 ValueRange* array_range = new (GetGraph()->GetArena())
1398 ValueRange(GetGraph()->GetArena(), lower, upper);
1399 if (index_range->FitsIn(array_range)) {
Mingyao Yangf384f882014-10-22 16:08:18 -07001400 ReplaceBoundsCheck(bounds_check, index);
1401 return;
1402 }
1403 }
Mingyao Yang0304e182015-01-30 16:41:29 -08001404 } else {
1405 int32_t constant = index->AsIntConstant()->GetValue();
1406 if (constant < 0) {
1407 // Will always throw exception.
1408 return;
1409 }
1410 if (array_length->IsIntConstant()) {
1411 if (constant < array_length->AsIntConstant()->GetValue()) {
1412 ReplaceBoundsCheck(bounds_check, index);
1413 }
1414 return;
1415 }
1416
1417 DCHECK(array_length->IsArrayLength());
1418 ValueRange* existing_range = LookupValueRange(array_length, block);
1419 if (existing_range != nullptr) {
1420 ValueBound lower = existing_range->GetLower();
1421 DCHECK(lower.IsConstant());
1422 if (constant < lower.GetConstant()) {
1423 ReplaceBoundsCheck(bounds_check, index);
1424 return;
1425 } else {
1426 // Existing range isn't strong enough to eliminate the bounds check.
1427 // Fall through to update the array_length range with info from this
1428 // bounds check.
1429 }
1430 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001431
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001432 if (first_constant_index_bounds_check_map_.find(array_length->GetId()) ==
1433 first_constant_index_bounds_check_map_.end()) {
1434 // Remember the first bounds check against array_length of a constant index.
1435 // That bounds check instruction has an associated HEnvironment where we
1436 // may add an HDeoptimize to eliminate bounds checks of constant indices
1437 // against array_length.
1438 first_constant_index_bounds_check_map_.Put(array_length->GetId(), bounds_check);
1439 } else {
1440 // We've seen it at least twice. It's beneficial to introduce a compare with
1441 // deoptimization fallback to eliminate the bounds checks.
1442 need_to_revisit_block_ = true;
1443 }
1444
Mingyao Yangf384f882014-10-22 16:08:18 -07001445 // Once we have an array access like 'array[5] = 1', we record array.length >= 6.
Mingyao Yang0304e182015-01-30 16:41:29 -08001446 // We currently don't do it for non-constant index since a valid array[i] can't prove
1447 // a valid array[i-1] yet due to the lower bound side.
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001448 if (constant == INT_MAX) {
1449 // INT_MAX as an index will definitely throw AIOOBE.
1450 return;
1451 }
Mingyao Yang64197522014-12-05 15:56:23 -08001452 ValueBound lower = ValueBound(nullptr, constant + 1);
Mingyao Yangf384f882014-10-22 16:08:18 -07001453 ValueBound upper = ValueBound::Max();
1454 ValueRange* range = new (GetGraph()->GetArena())
1455 ValueRange(GetGraph()->GetArena(), lower, upper);
Mingyao Yang0304e182015-01-30 16:41:29 -08001456 GetValueRangeMap(block)->Overwrite(array_length->GetId(), range);
Mingyao Yangf384f882014-10-22 16:08:18 -07001457 }
1458 }
1459
1460 void ReplaceBoundsCheck(HInstruction* bounds_check, HInstruction* index) {
1461 bounds_check->ReplaceWith(index);
1462 bounds_check->GetBlock()->RemoveInstruction(bounds_check);
1463 }
1464
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01001465 static bool HasSameInputAtBackEdges(HPhi* phi) {
1466 DCHECK(phi->IsLoopHeaderPhi());
1467 // Start with input 1. Input 0 is from the incoming block.
1468 HInstruction* input1 = phi->InputAt(1);
1469 DCHECK(phi->GetBlock()->GetLoopInformation()->IsBackEdge(
Vladimir Marko60584552015-09-03 13:35:12 +00001470 *phi->GetBlock()->GetPredecessor(1)));
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01001471 for (size_t i = 2, e = phi->InputCount(); i < e; ++i) {
1472 DCHECK(phi->GetBlock()->GetLoopInformation()->IsBackEdge(
Vladimir Marko60584552015-09-03 13:35:12 +00001473 *phi->GetBlock()->GetPredecessor(i)));
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01001474 if (input1 != phi->InputAt(i)) {
1475 return false;
1476 }
1477 }
1478 return true;
1479 }
1480
Mingyao Yangf384f882014-10-22 16:08:18 -07001481 void VisitPhi(HPhi* phi) {
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01001482 if (phi->IsLoopHeaderPhi()
1483 && (phi->GetType() == Primitive::kPrimInt)
1484 && HasSameInputAtBackEdges(phi)) {
Mingyao Yangf384f882014-10-22 16:08:18 -07001485 HInstruction* instruction = phi->InputAt(1);
Mingyao Yang0304e182015-01-30 16:41:29 -08001486 HInstruction *left;
1487 int32_t increment;
1488 if (ValueBound::IsAddOrSubAConstant(instruction, &left, &increment)) {
1489 if (left == phi) {
Mingyao Yangf384f882014-10-22 16:08:18 -07001490 HInstruction* initial_value = phi->InputAt(0);
1491 ValueRange* range = nullptr;
Mingyao Yang64197522014-12-05 15:56:23 -08001492 if (increment == 0) {
Mingyao Yangf384f882014-10-22 16:08:18 -07001493 // Add constant 0. It's really a fixed value.
1494 range = new (GetGraph()->GetArena()) ValueRange(
1495 GetGraph()->GetArena(),
Mingyao Yang64197522014-12-05 15:56:23 -08001496 ValueBound(initial_value, 0),
1497 ValueBound(initial_value, 0));
Mingyao Yangf384f882014-10-22 16:08:18 -07001498 } else {
1499 // Monotonically increasing/decreasing.
Mingyao Yang64197522014-12-05 15:56:23 -08001500 bool found;
1501 ValueBound bound = ValueBound::DetectValueBoundFromValue(
1502 initial_value, &found);
1503 if (!found) {
1504 // No constant or array.length+c bound found.
1505 // For i=j, we can still use j's upper bound as i's upper bound.
1506 // Same for lower.
1507 ValueRange* initial_range = LookupValueRange(initial_value, phi->GetBlock());
1508 if (initial_range != nullptr) {
1509 bound = increment > 0 ? initial_range->GetLower() :
1510 initial_range->GetUpper();
1511 } else {
1512 bound = increment > 0 ? ValueBound::Min() : ValueBound::Max();
1513 }
1514 }
1515 range = new (GetGraph()->GetArena()) MonotonicValueRange(
Mingyao Yangf384f882014-10-22 16:08:18 -07001516 GetGraph()->GetArena(),
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001517 phi,
Mingyao Yangf384f882014-10-22 16:08:18 -07001518 initial_value,
Mingyao Yang64197522014-12-05 15:56:23 -08001519 increment,
1520 bound);
Mingyao Yangf384f882014-10-22 16:08:18 -07001521 }
1522 GetValueRangeMap(phi->GetBlock())->Overwrite(phi->GetId(), range);
1523 }
1524 }
1525 }
1526 }
1527
1528 void VisitIf(HIf* instruction) {
1529 if (instruction->InputAt(0)->IsCondition()) {
1530 HCondition* cond = instruction->InputAt(0)->AsCondition();
1531 IfCondition cmp = cond->GetCondition();
1532 if (cmp == kCondGT || cmp == kCondGE ||
1533 cmp == kCondLT || cmp == kCondLE) {
1534 HInstruction* left = cond->GetLeft();
1535 HInstruction* right = cond->GetRight();
1536 HandleIf(instruction, left, right, cmp);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001537
1538 HBasicBlock* block = instruction->GetBlock();
1539 ValueRange* left_range = LookupValueRange(left, block);
1540 if (left_range == nullptr) {
1541 return;
1542 }
1543
1544 if (left_range->IsMonotonicValueRange() &&
Mingyao Yang3584bce2015-05-19 16:01:59 -07001545 block == left_range->AsMonotonicValueRange()->GetLoopHeader()) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001546 // The comparison is for an induction variable in the loop header.
1547 DCHECK(left == left_range->AsMonotonicValueRange()->GetInductionVariable());
Mingyao Yang3584bce2015-05-19 16:01:59 -07001548 HBasicBlock* loop_body_successor =
1549 left_range->AsMonotonicValueRange()->GetLoopHeaderSuccesorInLoop();
1550 if (loop_body_successor == nullptr) {
1551 // In case it's some strange loop structure.
1552 return;
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001553 }
1554 ValueRange* new_left_range = LookupValueRange(left, loop_body_successor);
Mingyao Yang3584bce2015-05-19 16:01:59 -07001555 if ((new_left_range == left_range) ||
1556 // Range narrowed with deoptimization is usually more useful than
1557 // a constant range.
1558 new_left_range->IsConstantValueRange()) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001559 // We are not successful in narrowing the monotonic value range to
1560 // a regular value range. Try using deoptimization.
1561 new_left_range = left_range->AsMonotonicValueRange()->
1562 NarrowWithDeoptimization();
1563 if (new_left_range != left_range) {
Mingyao Yang3584bce2015-05-19 16:01:59 -07001564 GetValueRangeMap(loop_body_successor)->Overwrite(left->GetId(), new_left_range);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001565 }
1566 }
1567 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001568 }
1569 }
1570 }
1571
1572 void VisitAdd(HAdd* add) {
1573 HInstruction* right = add->GetRight();
1574 if (right->IsIntConstant()) {
1575 ValueRange* left_range = LookupValueRange(add->GetLeft(), add->GetBlock());
1576 if (left_range == nullptr) {
1577 return;
1578 }
1579 ValueRange* range = left_range->Add(right->AsIntConstant()->GetValue());
1580 if (range != nullptr) {
1581 GetValueRangeMap(add->GetBlock())->Overwrite(add->GetId(), range);
1582 }
1583 }
1584 }
1585
1586 void VisitSub(HSub* sub) {
1587 HInstruction* left = sub->GetLeft();
1588 HInstruction* right = sub->GetRight();
1589 if (right->IsIntConstant()) {
1590 ValueRange* left_range = LookupValueRange(left, sub->GetBlock());
1591 if (left_range == nullptr) {
1592 return;
1593 }
1594 ValueRange* range = left_range->Add(-right->AsIntConstant()->GetValue());
1595 if (range != nullptr) {
1596 GetValueRangeMap(sub->GetBlock())->Overwrite(sub->GetId(), range);
1597 return;
1598 }
1599 }
1600
1601 // Here we are interested in the typical triangular case of nested loops,
1602 // such as the inner loop 'for (int j=0; j<array.length-i; j++)' where i
1603 // is the index for outer loop. In this case, we know j is bounded by array.length-1.
Mingyao Yang8c8bad82015-02-09 18:13:26 -08001604
1605 // Try to handle (array.length - i) or (array.length + c - i) format.
1606 HInstruction* left_of_left; // left input of left.
1607 int32_t right_const = 0;
1608 if (ValueBound::IsAddOrSubAConstant(left, &left_of_left, &right_const)) {
1609 left = left_of_left;
1610 }
1611 // The value of left input of the sub equals (left + right_const).
1612
Mingyao Yangf384f882014-10-22 16:08:18 -07001613 if (left->IsArrayLength()) {
1614 HInstruction* array_length = left->AsArrayLength();
1615 ValueRange* right_range = LookupValueRange(right, sub->GetBlock());
1616 if (right_range != nullptr) {
1617 ValueBound lower = right_range->GetLower();
1618 ValueBound upper = right_range->GetUpper();
Mingyao Yang0304e182015-01-30 16:41:29 -08001619 if (lower.IsConstant() && upper.IsRelatedToArrayLength()) {
Mingyao Yangf384f882014-10-22 16:08:18 -07001620 HInstruction* upper_inst = upper.GetInstruction();
Mingyao Yang0304e182015-01-30 16:41:29 -08001621 // Make sure it's the same array.
1622 if (ValueBound::Equal(array_length, upper_inst)) {
Mingyao Yang8c8bad82015-02-09 18:13:26 -08001623 int32_t c0 = right_const;
1624 int32_t c1 = lower.GetConstant();
1625 int32_t c2 = upper.GetConstant();
1626 // (array.length + c0 - v) where v is in [c1, array.length + c2]
1627 // gets [c0 - c2, array.length + c0 - c1] as its value range.
1628 if (!ValueBound::WouldAddOverflowOrUnderflow(c0, -c2) &&
1629 !ValueBound::WouldAddOverflowOrUnderflow(c0, -c1)) {
1630 if ((c0 - c1) <= 0) {
1631 // array.length + (c0 - c1) won't overflow/underflow.
1632 ValueRange* range = new (GetGraph()->GetArena()) ValueRange(
1633 GetGraph()->GetArena(),
1634 ValueBound(nullptr, right_const - upper.GetConstant()),
1635 ValueBound(array_length, right_const - lower.GetConstant()));
1636 GetValueRangeMap(sub->GetBlock())->Overwrite(sub->GetId(), range);
1637 }
1638 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001639 }
1640 }
1641 }
1642 }
1643 }
1644
Mingyao Yang8c8bad82015-02-09 18:13:26 -08001645 void FindAndHandlePartialArrayLength(HBinaryOperation* instruction) {
1646 DCHECK(instruction->IsDiv() || instruction->IsShr() || instruction->IsUShr());
1647 HInstruction* right = instruction->GetRight();
1648 int32_t right_const;
1649 if (right->IsIntConstant()) {
1650 right_const = right->AsIntConstant()->GetValue();
1651 // Detect division by two or more.
1652 if ((instruction->IsDiv() && right_const <= 1) ||
1653 (instruction->IsShr() && right_const < 1) ||
1654 (instruction->IsUShr() && right_const < 1)) {
1655 return;
1656 }
1657 } else {
1658 return;
1659 }
1660
1661 // Try to handle array.length/2 or (array.length-1)/2 format.
1662 HInstruction* left = instruction->GetLeft();
1663 HInstruction* left_of_left; // left input of left.
1664 int32_t c = 0;
1665 if (ValueBound::IsAddOrSubAConstant(left, &left_of_left, &c)) {
1666 left = left_of_left;
1667 }
1668 // The value of left input of instruction equals (left + c).
1669
1670 // (array_length + 1) or smaller divided by two or more
1671 // always generate a value in [INT_MIN, array_length].
1672 // This is true even if array_length is INT_MAX.
1673 if (left->IsArrayLength() && c <= 1) {
1674 if (instruction->IsUShr() && c < 0) {
1675 // Make sure for unsigned shift, left side is not negative.
1676 // e.g. if array_length is 2, ((array_length - 3) >>> 2) is way bigger
1677 // than array_length.
1678 return;
1679 }
1680 ValueRange* range = new (GetGraph()->GetArena()) ValueRange(
1681 GetGraph()->GetArena(),
1682 ValueBound(nullptr, INT_MIN),
1683 ValueBound(left, 0));
1684 GetValueRangeMap(instruction->GetBlock())->Overwrite(instruction->GetId(), range);
1685 }
1686 }
1687
1688 void VisitDiv(HDiv* div) {
1689 FindAndHandlePartialArrayLength(div);
1690 }
1691
1692 void VisitShr(HShr* shr) {
1693 FindAndHandlePartialArrayLength(shr);
1694 }
1695
1696 void VisitUShr(HUShr* ushr) {
1697 FindAndHandlePartialArrayLength(ushr);
1698 }
1699
Mingyao Yang4559f002015-02-27 14:43:53 -08001700 void VisitAnd(HAnd* instruction) {
1701 if (instruction->GetRight()->IsIntConstant()) {
1702 int32_t constant = instruction->GetRight()->AsIntConstant()->GetValue();
1703 if (constant > 0) {
1704 // constant serves as a mask so any number masked with it
1705 // gets a [0, constant] value range.
1706 ValueRange* range = new (GetGraph()->GetArena()) ValueRange(
1707 GetGraph()->GetArena(),
1708 ValueBound(nullptr, 0),
1709 ValueBound(nullptr, constant));
1710 GetValueRangeMap(instruction->GetBlock())->Overwrite(instruction->GetId(), range);
1711 }
1712 }
1713 }
1714
Mingyao Yang0304e182015-01-30 16:41:29 -08001715 void VisitNewArray(HNewArray* new_array) {
1716 HInstruction* len = new_array->InputAt(0);
1717 if (!len->IsIntConstant()) {
1718 HInstruction *left;
1719 int32_t right_const;
1720 if (ValueBound::IsAddOrSubAConstant(len, &left, &right_const)) {
1721 // (left + right_const) is used as size to new the array.
1722 // We record "-right_const <= left <= new_array - right_const";
1723 ValueBound lower = ValueBound(nullptr, -right_const);
1724 // We use new_array for the bound instead of new_array.length,
1725 // which isn't available as an instruction yet. new_array will
1726 // be treated the same as new_array.length when it's used in a ValueBound.
1727 ValueBound upper = ValueBound(new_array, -right_const);
1728 ValueRange* range = new (GetGraph()->GetArena())
1729 ValueRange(GetGraph()->GetArena(), lower, upper);
Nicolas Geoffraya09ff9c2015-06-24 10:38:27 +01001730 ValueRange* existing_range = LookupValueRange(left, new_array->GetBlock());
1731 if (existing_range != nullptr) {
1732 range = existing_range->Narrow(range);
1733 }
Mingyao Yang0304e182015-01-30 16:41:29 -08001734 GetValueRangeMap(new_array->GetBlock())->Overwrite(left->GetId(), range);
1735 }
1736 }
1737 }
1738
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001739 void VisitDeoptimize(HDeoptimize* deoptimize) {
1740 // Right now it's only HLessThanOrEqual.
1741 DCHECK(deoptimize->InputAt(0)->IsLessThanOrEqual());
1742 HLessThanOrEqual* less_than_or_equal = deoptimize->InputAt(0)->AsLessThanOrEqual();
1743 HInstruction* instruction = less_than_or_equal->InputAt(0);
1744 if (instruction->IsArrayLength()) {
1745 HInstruction* constant = less_than_or_equal->InputAt(1);
1746 DCHECK(constant->IsIntConstant());
1747 DCHECK(constant->AsIntConstant()->GetValue() <= kMaxConstantForAddingDeoptimize);
1748 ValueBound lower = ValueBound(nullptr, constant->AsIntConstant()->GetValue() + 1);
1749 ValueRange* range = new (GetGraph()->GetArena())
1750 ValueRange(GetGraph()->GetArena(), lower, ValueBound::Max());
1751 GetValueRangeMap(deoptimize->GetBlock())->Overwrite(instruction->GetId(), range);
1752 }
1753 }
1754
1755 void AddCompareWithDeoptimization(HInstruction* array_length,
1756 HIntConstant* const_instr,
1757 HBasicBlock* block) {
1758 DCHECK(array_length->IsArrayLength());
1759 ValueRange* range = LookupValueRange(array_length, block);
1760 ValueBound lower_bound = range->GetLower();
1761 DCHECK(lower_bound.IsConstant());
1762 DCHECK(const_instr->GetValue() <= kMaxConstantForAddingDeoptimize);
Nicolas Geoffray8d82a0c2015-06-20 23:49:01 +01001763 // Note that the lower bound of the array length may have been refined
1764 // through other instructions (such as `HNewArray(length - 4)`).
1765 DCHECK_LE(const_instr->GetValue() + 1, lower_bound.GetConstant());
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001766
1767 // If array_length is less than lower_const, deoptimize.
1768 HBoundsCheck* bounds_check = first_constant_index_bounds_check_map_.Get(
1769 array_length->GetId())->AsBoundsCheck();
1770 HCondition* cond = new (GetGraph()->GetArena()) HLessThanOrEqual(array_length, const_instr);
1771 HDeoptimize* deoptimize = new (GetGraph()->GetArena())
1772 HDeoptimize(cond, bounds_check->GetDexPc());
1773 block->InsertInstructionBefore(cond, bounds_check);
1774 block->InsertInstructionBefore(deoptimize, bounds_check);
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001775 deoptimize->CopyEnvironmentFrom(bounds_check->GetEnvironment());
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001776 }
1777
1778 void AddComparesWithDeoptimization(HBasicBlock* block) {
1779 for (ArenaSafeMap<int, HBoundsCheck*>::iterator it =
1780 first_constant_index_bounds_check_map_.begin();
1781 it != first_constant_index_bounds_check_map_.end();
1782 ++it) {
1783 HBoundsCheck* bounds_check = it->second;
Nicolas Geoffray8df886b2015-06-24 14:57:44 +01001784 HInstruction* array_length = bounds_check->InputAt(1);
1785 if (!array_length->IsArrayLength()) {
1786 // Prior deoptimizations may have changed the array length to a phi.
1787 // TODO(mingyao): propagate the range to the phi?
1788 DCHECK(array_length->IsPhi()) << array_length->DebugName();
1789 continue;
1790 }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001791 HIntConstant* lower_bound_const_instr = nullptr;
1792 int32_t lower_bound_const = INT_MIN;
1793 size_t counter = 0;
1794 // Count the constant indexing for which bounds checks haven't
1795 // been removed yet.
1796 for (HUseIterator<HInstruction*> it2(array_length->GetUses());
1797 !it2.Done();
1798 it2.Advance()) {
1799 HInstruction* user = it2.Current()->GetUser();
1800 if (user->GetBlock() == block &&
1801 user->IsBoundsCheck() &&
1802 user->AsBoundsCheck()->InputAt(0)->IsIntConstant()) {
1803 DCHECK_EQ(array_length, user->AsBoundsCheck()->InputAt(1));
1804 HIntConstant* const_instr = user->AsBoundsCheck()->InputAt(0)->AsIntConstant();
1805 if (const_instr->GetValue() > lower_bound_const) {
1806 lower_bound_const = const_instr->GetValue();
1807 lower_bound_const_instr = const_instr;
1808 }
1809 counter++;
1810 }
1811 }
1812 if (counter >= kThresholdForAddingDeoptimize &&
1813 lower_bound_const_instr->GetValue() <= kMaxConstantForAddingDeoptimize) {
1814 AddCompareWithDeoptimization(array_length, lower_bound_const_instr, block);
1815 }
1816 }
1817 }
1818
Mingyao Yangf384f882014-10-22 16:08:18 -07001819 std::vector<std::unique_ptr<ArenaSafeMap<int, ValueRange*>>> maps_;
1820
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001821 // Map an HArrayLength instruction's id to the first HBoundsCheck instruction in
1822 // a block that checks a constant index against that HArrayLength.
1823 SafeMap<int, HBoundsCheck*> first_constant_index_bounds_check_map_;
1824
1825 // For the block, there is at least one HArrayLength instruction for which there
1826 // is more than one bounds check instruction with constant indexing. And it's
1827 // beneficial to add a compare instruction that has deoptimization fallback and
1828 // eliminate those bounds checks.
1829 bool need_to_revisit_block_;
1830
Mingyao Yang3584bce2015-05-19 16:01:59 -07001831 // Initial number of blocks.
1832 int32_t initial_block_size_;
1833
Mingyao Yangf384f882014-10-22 16:08:18 -07001834 DISALLOW_COPY_AND_ASSIGN(BCEVisitor);
1835};
1836
1837void BoundsCheckElimination::Run() {
Mark Mendell1152c922015-04-24 17:06:35 -04001838 if (!graph_->HasBoundsChecks()) {
Mingyao Yange4335eb2015-03-02 15:14:13 -08001839 return;
1840 }
1841
Mingyao Yangf384f882014-10-22 16:08:18 -07001842 BCEVisitor visitor(graph_);
1843 // Reverse post order guarantees a node's dominators are visited first.
1844 // We want to visit in the dominator-based order since if a value is known to
1845 // be bounded by a range at one instruction, it must be true that all uses of
1846 // that value dominated by that instruction fits in that range. Range of that
1847 // value can be narrowed further down in the dominator tree.
1848 //
1849 // TODO: only visit blocks that dominate some array accesses.
Mingyao Yang3584bce2015-05-19 16:01:59 -07001850 HBasicBlock* last_visited_block = nullptr;
1851 for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
1852 HBasicBlock* current = it.Current();
1853 if (current == last_visited_block) {
1854 // We may insert blocks into the reverse post order list when processing
1855 // a loop header. Don't process it again.
1856 DCHECK(current->IsLoopHeader());
1857 continue;
1858 }
1859 if (visitor.IsAddedBlock(current)) {
1860 // Skip added blocks. Their effects are already taken care of.
1861 continue;
1862 }
1863 visitor.VisitBasicBlock(current);
1864 last_visited_block = current;
1865 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001866}
1867
1868} // namespace art