blob: 960f4d9b7c1d5edc95863c48e2a32e01a29e22f9 [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
17#include "bounds_check_elimination.h"
Aart Bikaab5b752015-09-23 11:18:57 -070018
19#include <limits>
20
21#include "base/arena_containers.h"
Aart Bik22af3be2015-09-10 12:50:58 -070022#include "induction_var_range.h"
Mingyao Yangf384f882014-10-22 16:08:18 -070023#include "nodes.h"
Mingyao Yangf384f882014-10-22 16:08:18 -070024
25namespace art {
26
27class MonotonicValueRange;
28
29/**
30 * A value bound is represented as a pair of value and constant,
31 * e.g. array.length - 1.
32 */
33class ValueBound : public ValueObject {
34 public:
Mingyao Yang0304e182015-01-30 16:41:29 -080035 ValueBound(HInstruction* instruction, int32_t constant) {
Mingyao Yang64197522014-12-05 15:56:23 -080036 if (instruction != nullptr && instruction->IsIntConstant()) {
Mingyao Yang0304e182015-01-30 16:41:29 -080037 // Normalize ValueBound with constant instruction.
38 int32_t instr_const = instruction->AsIntConstant()->GetValue();
Mingyao Yang8c8bad82015-02-09 18:13:26 -080039 if (!WouldAddOverflowOrUnderflow(instr_const, constant)) {
Mingyao Yang64197522014-12-05 15:56:23 -080040 instruction_ = nullptr;
41 constant_ = instr_const + constant;
42 return;
43 }
Mingyao Yangf384f882014-10-22 16:08:18 -070044 }
Mingyao Yang64197522014-12-05 15:56:23 -080045 instruction_ = instruction;
46 constant_ = constant;
47 }
48
Mingyao Yang8c8bad82015-02-09 18:13:26 -080049 // Return whether (left + right) overflows or underflows.
50 static bool WouldAddOverflowOrUnderflow(int32_t left, int32_t right) {
51 if (right == 0) {
52 return false;
53 }
Aart Bikaab5b752015-09-23 11:18:57 -070054 if ((right > 0) && (left <= (std::numeric_limits<int32_t>::max() - right))) {
Mingyao Yang8c8bad82015-02-09 18:13:26 -080055 // No overflow.
56 return false;
57 }
Aart Bikaab5b752015-09-23 11:18:57 -070058 if ((right < 0) && (left >= (std::numeric_limits<int32_t>::min() - right))) {
Mingyao Yang8c8bad82015-02-09 18:13:26 -080059 // No underflow.
60 return false;
61 }
62 return true;
63 }
64
Mingyao Yang0304e182015-01-30 16:41:29 -080065 static bool IsAddOrSubAConstant(HInstruction* instruction,
66 HInstruction** left_instruction,
67 int* right_constant) {
68 if (instruction->IsAdd() || instruction->IsSub()) {
69 HBinaryOperation* bin_op = instruction->AsBinaryOperation();
70 HInstruction* left = bin_op->GetLeft();
71 HInstruction* right = bin_op->GetRight();
72 if (right->IsIntConstant()) {
73 *left_instruction = left;
74 int32_t c = right->AsIntConstant()->GetValue();
75 *right_constant = instruction->IsAdd() ? c : -c;
76 return true;
77 }
78 }
79 *left_instruction = nullptr;
80 *right_constant = 0;
81 return false;
82 }
83
Mingyao Yang64197522014-12-05 15:56:23 -080084 // Try to detect useful value bound format from an instruction, e.g.
85 // a constant or array length related value.
86 static ValueBound DetectValueBoundFromValue(HInstruction* instruction, bool* found) {
87 DCHECK(instruction != nullptr);
Mingyao Yangf384f882014-10-22 16:08:18 -070088 if (instruction->IsIntConstant()) {
Mingyao Yang64197522014-12-05 15:56:23 -080089 *found = true;
90 return ValueBound(nullptr, instruction->AsIntConstant()->GetValue());
Mingyao Yangf384f882014-10-22 16:08:18 -070091 }
Mingyao Yang64197522014-12-05 15:56:23 -080092
93 if (instruction->IsArrayLength()) {
94 *found = true;
95 return ValueBound(instruction, 0);
96 }
97 // Try to detect (array.length + c) format.
Mingyao Yang0304e182015-01-30 16:41:29 -080098 HInstruction *left;
99 int32_t right;
100 if (IsAddOrSubAConstant(instruction, &left, &right)) {
101 if (left->IsArrayLength()) {
Mingyao Yang64197522014-12-05 15:56:23 -0800102 *found = true;
Mingyao Yang0304e182015-01-30 16:41:29 -0800103 return ValueBound(left, right);
Mingyao Yang64197522014-12-05 15:56:23 -0800104 }
105 }
106
107 // No useful bound detected.
108 *found = false;
109 return ValueBound::Max();
Mingyao Yangf384f882014-10-22 16:08:18 -0700110 }
111
112 HInstruction* GetInstruction() const { return instruction_; }
Mingyao Yang0304e182015-01-30 16:41:29 -0800113 int32_t GetConstant() const { return constant_; }
Mingyao Yangf384f882014-10-22 16:08:18 -0700114
Mingyao Yang0304e182015-01-30 16:41:29 -0800115 bool IsRelatedToArrayLength() const {
116 // Some bounds are created with HNewArray* as the instruction instead
117 // of HArrayLength*. They are treated the same.
118 return (instruction_ != nullptr) &&
119 (instruction_->IsArrayLength() || instruction_->IsNewArray());
Mingyao Yangf384f882014-10-22 16:08:18 -0700120 }
121
122 bool IsConstant() const {
123 return instruction_ == nullptr;
124 }
125
Aart Bikaab5b752015-09-23 11:18:57 -0700126 static ValueBound Min() { return ValueBound(nullptr, std::numeric_limits<int32_t>::min()); }
127 static ValueBound Max() { return ValueBound(nullptr, std::numeric_limits<int32_t>::max()); }
Mingyao Yangf384f882014-10-22 16:08:18 -0700128
129 bool Equals(ValueBound bound) const {
130 return instruction_ == bound.instruction_ && constant_ == bound.constant_;
131 }
132
Aart Bik22af3be2015-09-10 12:50:58 -0700133 /*
134 * Hunt "under the hood" of array lengths (leading to array references),
135 * null checks (also leading to array references), and new arrays
136 * (leading to the actual length). This makes it more likely related
137 * instructions become actually comparable.
138 */
139 static HInstruction* HuntForDeclaration(HInstruction* instruction) {
140 while (instruction->IsArrayLength() ||
141 instruction->IsNullCheck() ||
142 instruction->IsNewArray()) {
143 instruction = instruction->InputAt(0);
Mingyao Yang0304e182015-01-30 16:41:29 -0800144 }
145 return instruction;
146 }
147
148 static bool Equal(HInstruction* instruction1, HInstruction* instruction2) {
149 if (instruction1 == instruction2) {
150 return true;
151 }
Mingyao Yang0304e182015-01-30 16:41:29 -0800152 if (instruction1 == nullptr || instruction2 == nullptr) {
Mingyao Yangf384f882014-10-22 16:08:18 -0700153 return false;
154 }
Aart Bik22af3be2015-09-10 12:50:58 -0700155 instruction1 = HuntForDeclaration(instruction1);
156 instruction2 = HuntForDeclaration(instruction2);
Mingyao Yang0304e182015-01-30 16:41:29 -0800157 return instruction1 == instruction2;
158 }
159
160 // Returns if it's certain this->bound >= `bound`.
161 bool GreaterThanOrEqualTo(ValueBound bound) const {
162 if (Equal(instruction_, bound.instruction_)) {
163 return constant_ >= bound.constant_;
164 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700165 // Not comparable. Just return false.
166 return false;
167 }
168
Mingyao Yang0304e182015-01-30 16:41:29 -0800169 // Returns if it's certain this->bound <= `bound`.
170 bool LessThanOrEqualTo(ValueBound bound) const {
171 if (Equal(instruction_, bound.instruction_)) {
172 return constant_ <= bound.constant_;
Mingyao Yangf384f882014-10-22 16:08:18 -0700173 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700174 // Not comparable. Just return false.
175 return false;
176 }
177
178 // Try to narrow lower bound. Returns the greatest of the two if possible.
179 // Pick one if they are not comparable.
180 static ValueBound NarrowLowerBound(ValueBound bound1, ValueBound bound2) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800181 if (bound1.GreaterThanOrEqualTo(bound2)) {
182 return bound1;
183 }
184 if (bound2.GreaterThanOrEqualTo(bound1)) {
185 return bound2;
Mingyao Yangf384f882014-10-22 16:08:18 -0700186 }
187
188 // Not comparable. Just pick one. We may lose some info, but that's ok.
189 // Favor constant as lower bound.
190 return bound1.IsConstant() ? bound1 : bound2;
191 }
192
193 // Try to narrow upper bound. Returns the lowest of the two if possible.
194 // Pick one if they are not comparable.
195 static ValueBound NarrowUpperBound(ValueBound bound1, ValueBound bound2) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800196 if (bound1.LessThanOrEqualTo(bound2)) {
197 return bound1;
198 }
199 if (bound2.LessThanOrEqualTo(bound1)) {
200 return bound2;
Mingyao Yangf384f882014-10-22 16:08:18 -0700201 }
202
203 // Not comparable. Just pick one. We may lose some info, but that's ok.
204 // Favor array length as upper bound.
Mingyao Yang0304e182015-01-30 16:41:29 -0800205 return bound1.IsRelatedToArrayLength() ? bound1 : bound2;
Mingyao Yangf384f882014-10-22 16:08:18 -0700206 }
207
Mingyao Yang0304e182015-01-30 16:41:29 -0800208 // Add a constant to a ValueBound.
209 // `overflow` or `underflow` will return whether the resulting bound may
210 // overflow or underflow an int.
211 ValueBound Add(int32_t c, bool* overflow, bool* underflow) const {
212 *overflow = *underflow = false;
Mingyao Yangf384f882014-10-22 16:08:18 -0700213 if (c == 0) {
214 return *this;
215 }
216
Mingyao Yang0304e182015-01-30 16:41:29 -0800217 int32_t new_constant;
Mingyao Yangf384f882014-10-22 16:08:18 -0700218 if (c > 0) {
Aart Bikaab5b752015-09-23 11:18:57 -0700219 if (constant_ > (std::numeric_limits<int32_t>::max() - c)) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800220 *overflow = true;
Mingyao Yang64197522014-12-05 15:56:23 -0800221 return Max();
Mingyao Yangf384f882014-10-22 16:08:18 -0700222 }
Mingyao Yang0304e182015-01-30 16:41:29 -0800223
224 new_constant = constant_ + c;
225 // (array.length + non-positive-constant) won't overflow an int.
226 if (IsConstant() || (IsRelatedToArrayLength() && new_constant <= 0)) {
227 return ValueBound(instruction_, new_constant);
228 }
229 // Be conservative.
230 *overflow = true;
231 return Max();
Mingyao Yangf384f882014-10-22 16:08:18 -0700232 } else {
Aart Bikaab5b752015-09-23 11:18:57 -0700233 if (constant_ < (std::numeric_limits<int32_t>::min() - c)) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800234 *underflow = true;
235 return Min();
Mingyao Yangf384f882014-10-22 16:08:18 -0700236 }
Mingyao Yang0304e182015-01-30 16:41:29 -0800237
238 new_constant = constant_ + c;
239 // Regardless of the value new_constant, (array.length+new_constant) will
240 // never underflow since array.length is no less than 0.
241 if (IsConstant() || IsRelatedToArrayLength()) {
242 return ValueBound(instruction_, new_constant);
243 }
244 // Be conservative.
245 *underflow = true;
246 return Min();
Mingyao Yangf384f882014-10-22 16:08:18 -0700247 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700248 }
249
250 private:
Mingyao Yangf384f882014-10-22 16:08:18 -0700251 HInstruction* instruction_;
Mingyao Yang0304e182015-01-30 16:41:29 -0800252 int32_t constant_;
Mingyao Yangf384f882014-10-22 16:08:18 -0700253};
254
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700255// Collect array access data for a loop.
256// TODO: make it work for multiple arrays inside the loop.
257class ArrayAccessInsideLoopFinder : public ValueObject {
258 public:
259 explicit ArrayAccessInsideLoopFinder(HInstruction* induction_variable)
260 : induction_variable_(induction_variable),
261 found_array_length_(nullptr),
Aart Bikaab5b752015-09-23 11:18:57 -0700262 offset_low_(std::numeric_limits<int32_t>::max()),
263 offset_high_(std::numeric_limits<int32_t>::min()) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700264 Run();
265 }
266
267 HArrayLength* GetFoundArrayLength() const { return found_array_length_; }
268 bool HasFoundArrayLength() const { return found_array_length_ != nullptr; }
269 int32_t GetOffsetLow() const { return offset_low_; }
270 int32_t GetOffsetHigh() const { return offset_high_; }
271
Mingyao Yang9d750ef2015-04-26 18:15:30 -0700272 // Returns if `block` that is in loop_info may exit the loop, unless it's
273 // the loop header for loop_info.
274 static bool EarlyExit(HBasicBlock* block, HLoopInformation* loop_info) {
275 DCHECK(loop_info->Contains(*block));
276 if (block == loop_info->GetHeader()) {
277 // Loop header of loop_info. Exiting loop is normal.
278 return false;
279 }
Vladimir Marko60584552015-09-03 13:35:12 +0000280 for (HBasicBlock* successor : block->GetSuccessors()) {
281 if (!loop_info->Contains(*successor)) {
Mingyao Yang9d750ef2015-04-26 18:15:30 -0700282 // One of the successors exits the loop.
283 return true;
284 }
285 }
286 return false;
287 }
288
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100289 static bool DominatesAllBackEdges(HBasicBlock* block, HLoopInformation* loop_info) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100290 for (HBasicBlock* back_edge : loop_info->GetBackEdges()) {
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100291 if (!block->Dominates(back_edge)) {
292 return false;
293 }
294 }
295 return true;
296 }
297
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700298 void Run() {
299 HLoopInformation* loop_info = induction_variable_->GetBlock()->GetLoopInformation();
Mingyao Yang3584bce2015-05-19 16:01:59 -0700300 HBlocksInLoopReversePostOrderIterator it_loop(*loop_info);
301 HBasicBlock* block = it_loop.Current();
302 DCHECK(block == induction_variable_->GetBlock());
303 // Skip loop header. Since narrowed value range of a MonotonicValueRange only
304 // applies to the loop body (after the test at the end of the loop header).
305 it_loop.Advance();
306 for (; !it_loop.Done(); it_loop.Advance()) {
307 block = it_loop.Current();
Mingyao Yang9d750ef2015-04-26 18:15:30 -0700308 DCHECK(block->IsInLoop());
Nicolas Geoffraydb216f42015-05-05 17:02:20 +0100309 if (!DominatesAllBackEdges(block, loop_info)) {
Mingyao Yang9d750ef2015-04-26 18:15:30 -0700310 // In order not to trigger deoptimization unnecessarily, make sure
311 // that all array accesses collected are really executed in the loop.
312 // For array accesses in a branch inside the loop, don't collect the
313 // access. The bounds check in that branch might not be eliminated.
314 continue;
315 }
316 if (EarlyExit(block, loop_info)) {
317 // If the loop body can exit loop (like break, return, etc.), it's not guaranteed
318 // that the loop will loop through the full monotonic value range from
319 // initial_ to end_. So adding deoptimization might be too aggressive and can
320 // trigger deoptimization unnecessarily even if the loop won't actually throw
Mingyao Yang3584bce2015-05-19 16:01:59 -0700321 // AIOOBE.
Mingyao Yang9d750ef2015-04-26 18:15:30 -0700322 found_array_length_ = nullptr;
323 return;
324 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700325 for (HInstruction* instruction = block->GetFirstInstruction();
326 instruction != nullptr;
327 instruction = instruction->GetNext()) {
Mingyao Yang3584bce2015-05-19 16:01:59 -0700328 if (!instruction->IsBoundsCheck()) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700329 continue;
330 }
331
Mingyao Yang3584bce2015-05-19 16:01:59 -0700332 HInstruction* length_value = instruction->InputAt(1);
333 if (length_value->IsIntConstant()) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700334 // TODO: may optimize for constant case.
335 continue;
336 }
337
Mingyao Yang3584bce2015-05-19 16:01:59 -0700338 if (length_value->IsPhi()) {
Nicolas Geoffray3cde6222015-06-17 10:17:49 +0100339 // When adding deoptimizations in outer loops, we might create
340 // a phi for the array length, and update all uses of the
341 // length in the loop to that phi. Therefore, inner loops having
342 // bounds checks on the same array will use that phi.
343 // TODO: handle these cases.
Mingyao Yang3584bce2015-05-19 16:01:59 -0700344 continue;
345 }
346
347 DCHECK(length_value->IsArrayLength());
348 HArrayLength* array_length = length_value->AsArrayLength();
349
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700350 HInstruction* array = array_length->InputAt(0);
351 if (array->IsNullCheck()) {
352 array = array->AsNullCheck()->InputAt(0);
353 }
354 if (loop_info->Contains(*array->GetBlock())) {
355 // Array is defined inside the loop. Skip.
356 continue;
357 }
358
359 if (found_array_length_ != nullptr && found_array_length_ != array_length) {
360 // There is already access for another array recorded for the loop.
361 // TODO: handle multiple arrays.
362 continue;
363 }
364
Mingyao Yang3584bce2015-05-19 16:01:59 -0700365 HInstruction* index = instruction->AsBoundsCheck()->InputAt(0);
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700366 HInstruction* left = index;
367 int32_t right = 0;
368 if (left == induction_variable_ ||
369 (ValueBound::IsAddOrSubAConstant(index, &left, &right) &&
370 left == induction_variable_)) {
371 // For patterns like array[i] or array[i + 2].
372 if (right < offset_low_) {
373 offset_low_ = right;
374 }
375 if (right > offset_high_) {
376 offset_high_ = right;
377 }
378 } else {
379 // Access not in induction_variable/(induction_variable_ + constant)
380 // format. Skip.
381 continue;
382 }
383 // Record this array.
384 found_array_length_ = array_length;
385 }
386 }
387 }
388
389 private:
390 // The instruction that corresponds to a MonotonicValueRange.
391 HInstruction* induction_variable_;
392
Mingyao Yang3584bce2015-05-19 16:01:59 -0700393 // The array length of the array that's accessed inside the loop body.
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700394 HArrayLength* found_array_length_;
395
396 // The lowest and highest constant offsets relative to induction variable
397 // instruction_ in all array accesses.
398 // If array access are: array[i-1], array[i], array[i+1],
399 // offset_low_ is -1 and offset_high is 1.
400 int32_t offset_low_;
401 int32_t offset_high_;
402
403 DISALLOW_COPY_AND_ASSIGN(ArrayAccessInsideLoopFinder);
404};
405
Mingyao Yangf384f882014-10-22 16:08:18 -0700406/**
407 * Represent a range of lower bound and upper bound, both being inclusive.
408 * Currently a ValueRange may be generated as a result of the following:
409 * comparisons related to array bounds, array bounds check, add/sub on top
Mingyao Yang0304e182015-01-30 16:41:29 -0800410 * of an existing value range, NewArray or a loop phi corresponding to an
Mingyao Yangf384f882014-10-22 16:08:18 -0700411 * incrementing/decrementing array index (MonotonicValueRange).
412 */
Vladimir Marko5233f932015-09-29 19:01:15 +0100413class ValueRange : public ArenaObject<kArenaAllocBoundsCheckElimination> {
Mingyao Yangf384f882014-10-22 16:08:18 -0700414 public:
415 ValueRange(ArenaAllocator* allocator, ValueBound lower, ValueBound upper)
416 : allocator_(allocator), lower_(lower), upper_(upper) {}
417
418 virtual ~ValueRange() {}
419
Mingyao Yang57e04752015-02-09 18:13:26 -0800420 virtual MonotonicValueRange* AsMonotonicValueRange() { return nullptr; }
421 bool IsMonotonicValueRange() {
Mingyao Yangf384f882014-10-22 16:08:18 -0700422 return AsMonotonicValueRange() != nullptr;
423 }
424
425 ArenaAllocator* GetAllocator() const { return allocator_; }
426 ValueBound GetLower() const { return lower_; }
427 ValueBound GetUpper() const { return upper_; }
428
Mingyao Yang3584bce2015-05-19 16:01:59 -0700429 bool IsConstantValueRange() { return lower_.IsConstant() && upper_.IsConstant(); }
430
Mingyao Yangf384f882014-10-22 16:08:18 -0700431 // If it's certain that this value range fits in other_range.
432 virtual bool FitsIn(ValueRange* other_range) const {
433 if (other_range == nullptr) {
434 return true;
435 }
436 DCHECK(!other_range->IsMonotonicValueRange());
Mingyao Yang0304e182015-01-30 16:41:29 -0800437 return lower_.GreaterThanOrEqualTo(other_range->lower_) &&
438 upper_.LessThanOrEqualTo(other_range->upper_);
Mingyao Yangf384f882014-10-22 16:08:18 -0700439 }
440
441 // Returns the intersection of this and range.
442 // If it's not possible to do intersection because some
443 // bounds are not comparable, it's ok to pick either bound.
444 virtual ValueRange* Narrow(ValueRange* range) {
445 if (range == nullptr) {
446 return this;
447 }
448
449 if (range->IsMonotonicValueRange()) {
450 return this;
451 }
452
453 return new (allocator_) ValueRange(
454 allocator_,
455 ValueBound::NarrowLowerBound(lower_, range->lower_),
456 ValueBound::NarrowUpperBound(upper_, range->upper_));
457 }
458
Mingyao Yang0304e182015-01-30 16:41:29 -0800459 // Shift a range by a constant.
460 ValueRange* Add(int32_t constant) const {
461 bool overflow, underflow;
462 ValueBound lower = lower_.Add(constant, &overflow, &underflow);
463 if (underflow) {
464 // Lower bound underflow will wrap around to positive values
465 // and invalidate the upper bound.
466 return nullptr;
Mingyao Yangf384f882014-10-22 16:08:18 -0700467 }
Mingyao Yang0304e182015-01-30 16:41:29 -0800468 ValueBound upper = upper_.Add(constant, &overflow, &underflow);
469 if (overflow) {
470 // Upper bound overflow will wrap around to negative values
471 // and invalidate the lower bound.
472 return nullptr;
Mingyao Yangf384f882014-10-22 16:08:18 -0700473 }
474 return new (allocator_) ValueRange(allocator_, lower, upper);
475 }
476
Mingyao Yangf384f882014-10-22 16:08:18 -0700477 private:
478 ArenaAllocator* const allocator_;
479 const ValueBound lower_; // inclusive
480 const ValueBound upper_; // inclusive
481
482 DISALLOW_COPY_AND_ASSIGN(ValueRange);
483};
484
485/**
486 * A monotonically incrementing/decrementing value range, e.g.
487 * the variable i in "for (int i=0; i<array.length; i++)".
488 * Special care needs to be taken to account for overflow/underflow
489 * of such value ranges.
490 */
491class MonotonicValueRange : public ValueRange {
492 public:
Mingyao Yang64197522014-12-05 15:56:23 -0800493 MonotonicValueRange(ArenaAllocator* allocator,
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700494 HPhi* induction_variable,
Mingyao Yang64197522014-12-05 15:56:23 -0800495 HInstruction* initial,
Mingyao Yang0304e182015-01-30 16:41:29 -0800496 int32_t increment,
Mingyao Yang64197522014-12-05 15:56:23 -0800497 ValueBound bound)
Aart Bikaab5b752015-09-23 11:18:57 -0700498 // To be conservative, give it full range [Min(), Max()] in case it's
Mingyao Yang64197522014-12-05 15:56:23 -0800499 // used as a regular value range, due to possible overflow/underflow.
500 : ValueRange(allocator, ValueBound::Min(), ValueBound::Max()),
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700501 induction_variable_(induction_variable),
Mingyao Yang64197522014-12-05 15:56:23 -0800502 initial_(initial),
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700503 end_(nullptr),
504 inclusive_(false),
Mingyao Yang64197522014-12-05 15:56:23 -0800505 increment_(increment),
506 bound_(bound) {}
Mingyao Yangf384f882014-10-22 16:08:18 -0700507
508 virtual ~MonotonicValueRange() {}
509
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700510 HInstruction* GetInductionVariable() const { return induction_variable_; }
Mingyao Yang57e04752015-02-09 18:13:26 -0800511 int32_t GetIncrement() const { return increment_; }
Mingyao Yang57e04752015-02-09 18:13:26 -0800512 ValueBound GetBound() const { return bound_; }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700513 void SetEnd(HInstruction* end) { end_ = end; }
514 void SetInclusive(bool inclusive) { inclusive_ = inclusive; }
Mingyao Yang3584bce2015-05-19 16:01:59 -0700515 HBasicBlock* GetLoopHeader() const {
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700516 DCHECK(induction_variable_->GetBlock()->IsLoopHeader());
517 return induction_variable_->GetBlock();
518 }
Mingyao Yang57e04752015-02-09 18:13:26 -0800519
520 MonotonicValueRange* AsMonotonicValueRange() OVERRIDE { return this; }
Mingyao Yangf384f882014-10-22 16:08:18 -0700521
Mingyao Yang3584bce2015-05-19 16:01:59 -0700522 HBasicBlock* GetLoopHeaderSuccesorInLoop() {
523 HBasicBlock* header = GetLoopHeader();
524 HInstruction* instruction = header->GetLastInstruction();
525 DCHECK(instruction->IsIf());
526 HIf* h_if = instruction->AsIf();
527 HLoopInformation* loop_info = header->GetLoopInformation();
528 bool true_successor_in_loop = loop_info->Contains(*h_if->IfTrueSuccessor());
529 bool false_successor_in_loop = loop_info->Contains(*h_if->IfFalseSuccessor());
530
531 // Just in case it's some strange loop structure.
532 if (true_successor_in_loop && false_successor_in_loop) {
533 return nullptr;
534 }
535 DCHECK(true_successor_in_loop || false_successor_in_loop);
536 return false_successor_in_loop ? h_if->IfFalseSuccessor() : h_if->IfTrueSuccessor();
537 }
538
Mingyao Yangf384f882014-10-22 16:08:18 -0700539 // If it's certain that this value range fits in other_range.
540 bool FitsIn(ValueRange* other_range) const OVERRIDE {
541 if (other_range == nullptr) {
542 return true;
543 }
544 DCHECK(!other_range->IsMonotonicValueRange());
545 return false;
546 }
547
548 // Try to narrow this MonotonicValueRange given another range.
549 // Ideally it will return a normal ValueRange. But due to
550 // possible overflow/underflow, that may not be possible.
551 ValueRange* Narrow(ValueRange* range) OVERRIDE {
552 if (range == nullptr) {
553 return this;
554 }
555 DCHECK(!range->IsMonotonicValueRange());
556
557 if (increment_ > 0) {
558 // Monotonically increasing.
Mingyao Yang64197522014-12-05 15:56:23 -0800559 ValueBound lower = ValueBound::NarrowLowerBound(bound_, range->GetLower());
Aart Bikaab5b752015-09-23 11:18:57 -0700560 if (!lower.IsConstant() || lower.GetConstant() == std::numeric_limits<int32_t>::min()) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700561 // Lower bound isn't useful. Leave it to deoptimization.
562 return this;
563 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700564
Aart Bikaab5b752015-09-23 11:18:57 -0700565 // We currently conservatively assume max array length is Max().
566 // If we can make assumptions about the max array length, e.g. due to the max heap size,
Mingyao Yangf384f882014-10-22 16:08:18 -0700567 // divided by the element size (such as 4 bytes for each integer array), we can
568 // lower this number and rule out some possible overflows.
Aart Bikaab5b752015-09-23 11:18:57 -0700569 int32_t max_array_len = std::numeric_limits<int32_t>::max();
Mingyao Yangf384f882014-10-22 16:08:18 -0700570
Mingyao Yang0304e182015-01-30 16:41:29 -0800571 // max possible integer value of range's upper value.
Aart Bikaab5b752015-09-23 11:18:57 -0700572 int32_t upper = std::numeric_limits<int32_t>::max();
Mingyao Yang0304e182015-01-30 16:41:29 -0800573 // Try to lower upper.
574 ValueBound upper_bound = range->GetUpper();
575 if (upper_bound.IsConstant()) {
576 upper = upper_bound.GetConstant();
577 } else if (upper_bound.IsRelatedToArrayLength() && upper_bound.GetConstant() <= 0) {
578 // Normal case. e.g. <= array.length - 1.
579 upper = max_array_len + upper_bound.GetConstant();
Mingyao Yangf384f882014-10-22 16:08:18 -0700580 }
581
582 // If we can prove for the last number in sequence of initial_,
583 // initial_ + increment_, initial_ + 2 x increment_, ...
584 // that's <= upper, (last_num_in_sequence + increment_) doesn't trigger overflow,
585 // then this MonoticValueRange is narrowed to a normal value range.
586
587 // Be conservative first, assume last number in the sequence hits upper.
Mingyao Yang0304e182015-01-30 16:41:29 -0800588 int32_t last_num_in_sequence = upper;
Mingyao Yangf384f882014-10-22 16:08:18 -0700589 if (initial_->IsIntConstant()) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800590 int32_t initial_constant = initial_->AsIntConstant()->GetValue();
Mingyao Yangf384f882014-10-22 16:08:18 -0700591 if (upper <= initial_constant) {
592 last_num_in_sequence = upper;
593 } else {
Mingyao Yang0304e182015-01-30 16:41:29 -0800594 // Cast to int64_t for the substraction part to avoid int32_t overflow.
Mingyao Yangf384f882014-10-22 16:08:18 -0700595 last_num_in_sequence = initial_constant +
596 ((int64_t)upper - (int64_t)initial_constant) / increment_ * increment_;
597 }
598 }
Aart Bikaab5b752015-09-23 11:18:57 -0700599 if (last_num_in_sequence <= (std::numeric_limits<int32_t>::max() - increment_)) {
Mingyao Yangf384f882014-10-22 16:08:18 -0700600 // No overflow. The sequence will be stopped by the upper bound test as expected.
601 return new (GetAllocator()) ValueRange(GetAllocator(), lower, range->GetUpper());
602 }
603
604 // There might be overflow. Give up narrowing.
605 return this;
606 } else {
607 DCHECK_NE(increment_, 0);
608 // Monotonically decreasing.
Mingyao Yang64197522014-12-05 15:56:23 -0800609 ValueBound upper = ValueBound::NarrowUpperBound(bound_, range->GetUpper());
Aart Bikaab5b752015-09-23 11:18:57 -0700610 if ((!upper.IsConstant() || upper.GetConstant() == std::numeric_limits<int32_t>::max()) &&
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700611 !upper.IsRelatedToArrayLength()) {
612 // Upper bound isn't useful. Leave it to deoptimization.
613 return this;
614 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700615
616 // Need to take care of underflow. Try to prove underflow won't happen
Mingyao Yang0304e182015-01-30 16:41:29 -0800617 // for common cases.
Mingyao Yangf384f882014-10-22 16:08:18 -0700618 if (range->GetLower().IsConstant()) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800619 int32_t constant = range->GetLower().GetConstant();
Aart Bikaab5b752015-09-23 11:18:57 -0700620 if (constant >= (std::numeric_limits<int32_t>::min() - increment_)) {
Mingyao Yangf384f882014-10-22 16:08:18 -0700621 return new (GetAllocator()) ValueRange(GetAllocator(), range->GetLower(), upper);
622 }
623 }
624
Mingyao Yang0304e182015-01-30 16:41:29 -0800625 // For non-constant lower bound, just assume might be underflow. Give up narrowing.
Mingyao Yangf384f882014-10-22 16:08:18 -0700626 return this;
627 }
628 }
629
Mingyao Yang3584bce2015-05-19 16:01:59 -0700630 // Try to add HDeoptimize's in the loop pre-header first to narrow this range.
631 // For example, this loop:
632 //
633 // for (int i = start; i < end; i++) {
634 // array[i - 1] = array[i] + array[i + 1];
635 // }
636 //
637 // will be transformed to:
638 //
639 // int array_length_in_loop_body_if_needed;
640 // if (start >= end) {
641 // array_length_in_loop_body_if_needed = 0;
642 // } else {
643 // if (start < 1) deoptimize();
644 // if (array == null) deoptimize();
645 // array_length = array.length;
646 // if (end > array_length - 1) deoptimize;
647 // array_length_in_loop_body_if_needed = array_length;
648 // }
649 // for (int i = start; i < end; i++) {
650 // // No more null check and bounds check.
651 // // array.length value is replaced with array_length_in_loop_body_if_needed
652 // // in the loop body.
653 // array[i - 1] = array[i] + array[i + 1];
654 // }
655 //
656 // We basically first go through the loop body and find those array accesses whose
657 // index is at a constant offset from the induction variable ('i' in the above example),
658 // and update offset_low and offset_high along the way. We then add the following
659 // deoptimizations in the loop pre-header (suppose end is not inclusive).
660 // if (start < -offset_low) deoptimize();
661 // if (end >= array.length - offset_high) deoptimize();
662 // It might be necessary to first hoist array.length (and the null check on it) out of
663 // the loop with another deoptimization.
664 //
665 // In order not to trigger deoptimization unnecessarily, we want to make a strong
666 // guarantee that no deoptimization is triggered if the loop body itself doesn't
667 // throw AIOOBE. (It's the same as saying if deoptimization is triggered, the loop
668 // body must throw AIOOBE).
669 // This is achieved by the following:
670 // 1) We only process loops that iterate through the full monotonic range from
671 // initial_ to end_. We do the following checks to make sure that's the case:
672 // a) The loop doesn't have early exit (via break, return, etc.)
673 // b) The increment_ is 1/-1. An increment of 2, for example, may skip end_.
674 // 2) We only collect array accesses of blocks in the loop body that dominate
675 // all loop back edges, these array accesses are guaranteed to happen
676 // at each loop iteration.
677 // With 1) and 2), if the loop body doesn't throw AIOOBE, collected array accesses
678 // when the induction variable is at initial_ and end_ must be in a legal range.
679 // Since the added deoptimizations are basically checking the induction variable
680 // at initial_ and end_ values, no deoptimization will be triggered either.
681 //
682 // A special case is the loop body isn't entered at all. In that case, we may still
683 // add deoptimization due to the analysis described above. In order not to trigger
684 // deoptimization, we do a test between initial_ and end_ first and skip over
685 // the added deoptimization.
686 ValueRange* NarrowWithDeoptimization() {
687 if (increment_ != 1 && increment_ != -1) {
688 // In order not to trigger deoptimization unnecessarily, we want to
689 // make sure the loop iterates through the full range from initial_ to
690 // end_ so that boundaries are covered by the loop. An increment of 2,
691 // for example, may skip end_.
692 return this;
693 }
694
695 if (end_ == nullptr) {
696 // No full info to add deoptimization.
697 return this;
698 }
699
700 HBasicBlock* header = induction_variable_->GetBlock();
701 DCHECK(header->IsLoopHeader());
702 HBasicBlock* pre_header = header->GetLoopInformation()->GetPreHeader();
703 if (!initial_->GetBlock()->Dominates(pre_header) ||
704 !end_->GetBlock()->Dominates(pre_header)) {
705 // Can't add a check in loop pre-header if the value isn't available there.
706 return this;
707 }
708
709 ArrayAccessInsideLoopFinder finder(induction_variable_);
710
711 if (!finder.HasFoundArrayLength()) {
712 // No array access was found inside the loop that can benefit
713 // from deoptimization.
714 return this;
715 }
716
717 if (!AddDeoptimization(finder)) {
718 return this;
719 }
720
721 // After added deoptimizations, induction variable fits in
722 // [-offset_low, array.length-1-offset_high], adjusted with collected offsets.
723 ValueBound lower = ValueBound(0, -finder.GetOffsetLow());
724 ValueBound upper = ValueBound(finder.GetFoundArrayLength(), -1 - finder.GetOffsetHigh());
725 // We've narrowed the range after added deoptimizations.
726 return new (GetAllocator()) ValueRange(GetAllocator(), lower, upper);
727 }
728
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700729 // Returns true if adding a (constant >= value) check for deoptimization
730 // is allowed and will benefit compiled code.
Mingyao Yang3584bce2015-05-19 16:01:59 -0700731 bool CanAddDeoptimizationConstant(HInstruction* value, int32_t constant, bool* is_proven) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700732 *is_proven = false;
Mingyao Yang3584bce2015-05-19 16:01:59 -0700733 HBasicBlock* header = induction_variable_->GetBlock();
734 DCHECK(header->IsLoopHeader());
735 HBasicBlock* pre_header = header->GetLoopInformation()->GetPreHeader();
736 DCHECK(value->GetBlock()->Dominates(pre_header));
737
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700738 // See if we can prove the relationship first.
739 if (value->IsIntConstant()) {
740 if (value->AsIntConstant()->GetValue() >= constant) {
741 // Already true.
742 *is_proven = true;
743 return true;
744 } else {
745 // May throw exception. Don't add deoptimization.
746 // Keep bounds checks in the loops.
747 return false;
748 }
749 }
750 // Can benefit from deoptimization.
751 return true;
752 }
753
Mingyao Yang3584bce2015-05-19 16:01:59 -0700754 // Try to filter out cases that the loop entry test will never be true.
755 bool LoopEntryTestUseful() {
756 if (initial_->IsIntConstant() && end_->IsIntConstant()) {
757 int32_t initial_val = initial_->AsIntConstant()->GetValue();
758 int32_t end_val = end_->AsIntConstant()->GetValue();
759 if (increment_ == 1) {
760 if (inclusive_) {
761 return initial_val > end_val;
762 } else {
763 return initial_val >= end_val;
764 }
765 } else {
Andreas Gampe45d68f12015-06-10 18:33:26 -0700766 DCHECK_EQ(increment_, -1);
Mingyao Yang3584bce2015-05-19 16:01:59 -0700767 if (inclusive_) {
768 return initial_val < end_val;
769 } else {
770 return initial_val <= end_val;
771 }
772 }
773 }
774 return true;
775 }
776
777 // Returns the block for adding deoptimization.
778 HBasicBlock* TransformLoopForDeoptimizationIfNeeded() {
779 HBasicBlock* header = induction_variable_->GetBlock();
780 DCHECK(header->IsLoopHeader());
781 HBasicBlock* pre_header = header->GetLoopInformation()->GetPreHeader();
782 // Deoptimization is only added when both initial_ and end_ are defined
783 // before the loop.
784 DCHECK(initial_->GetBlock()->Dominates(pre_header));
785 DCHECK(end_->GetBlock()->Dominates(pre_header));
786
787 // If it can be proven the loop body is definitely entered (unless exception
788 // is thrown in the loop header for which triggering deoptimization is fine),
789 // there is no need for tranforming the loop. In that case, deoptimization
790 // will just be added in the loop pre-header.
791 if (!LoopEntryTestUseful()) {
792 return pre_header;
793 }
794
795 HGraph* graph = header->GetGraph();
796 graph->TransformLoopHeaderForBCE(header);
797 HBasicBlock* new_pre_header = header->GetDominator();
798 DCHECK(new_pre_header == header->GetLoopInformation()->GetPreHeader());
799 HBasicBlock* if_block = new_pre_header->GetDominator();
Vladimir Marko60584552015-09-03 13:35:12 +0000800 HBasicBlock* dummy_block = if_block->GetSuccessor(0); // True successor.
801 HBasicBlock* deopt_block = if_block->GetSuccessor(1); // False successor.
Mingyao Yang3584bce2015-05-19 16:01:59 -0700802
803 dummy_block->AddInstruction(new (graph->GetArena()) HGoto());
804 deopt_block->AddInstruction(new (graph->GetArena()) HGoto());
805 new_pre_header->AddInstruction(new (graph->GetArena()) HGoto());
806 return deopt_block;
807 }
808
809 // Adds a test between initial_ and end_ to see if the loop body is entered.
810 // If the loop body isn't entered at all, it jumps to the loop pre-header (after
811 // transformation) to avoid any deoptimization.
812 void AddLoopBodyEntryTest() {
813 HBasicBlock* header = induction_variable_->GetBlock();
814 DCHECK(header->IsLoopHeader());
815 HBasicBlock* pre_header = header->GetLoopInformation()->GetPreHeader();
816 HBasicBlock* if_block = pre_header->GetDominator();
817 HGraph* graph = header->GetGraph();
818
819 HCondition* cond;
820 if (increment_ == 1) {
821 if (inclusive_) {
822 cond = new (graph->GetArena()) HGreaterThan(initial_, end_);
823 } else {
824 cond = new (graph->GetArena()) HGreaterThanOrEqual(initial_, end_);
825 }
826 } else {
Andreas Gampe45d68f12015-06-10 18:33:26 -0700827 DCHECK_EQ(increment_, -1);
Mingyao Yang3584bce2015-05-19 16:01:59 -0700828 if (inclusive_) {
829 cond = new (graph->GetArena()) HLessThan(initial_, end_);
830 } else {
831 cond = new (graph->GetArena()) HLessThanOrEqual(initial_, end_);
832 }
833 }
834 HIf* h_if = new (graph->GetArena()) HIf(cond);
835 if_block->AddInstruction(cond);
836 if_block->AddInstruction(h_if);
837 }
838
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700839 // Adds a check that (value >= constant), and HDeoptimize otherwise.
840 void AddDeoptimizationConstant(HInstruction* value,
Mingyao Yang3584bce2015-05-19 16:01:59 -0700841 int32_t constant,
842 HBasicBlock* deopt_block,
843 bool loop_entry_test_block_added) {
844 HBasicBlock* header = induction_variable_->GetBlock();
845 DCHECK(header->IsLoopHeader());
846 HBasicBlock* pre_header = header->GetDominator();
847 if (loop_entry_test_block_added) {
Vladimir Marko60584552015-09-03 13:35:12 +0000848 DCHECK(deopt_block->GetSuccessor(0) == pre_header);
Mingyao Yang3584bce2015-05-19 16:01:59 -0700849 } else {
850 DCHECK(deopt_block == pre_header);
851 }
852 HGraph* graph = header->GetGraph();
853 HSuspendCheck* suspend_check = header->GetLoopInformation()->GetSuspendCheck();
854 if (loop_entry_test_block_added) {
Vladimir Marko60584552015-09-03 13:35:12 +0000855 DCHECK_EQ(deopt_block, header->GetDominator()->GetDominator()->GetSuccessor(1));
Mingyao Yang3584bce2015-05-19 16:01:59 -0700856 }
857
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700858 HIntConstant* const_instr = graph->GetIntConstant(constant);
859 HCondition* cond = new (graph->GetArena()) HLessThan(value, const_instr);
860 HDeoptimize* deoptimize = new (graph->GetArena())
861 HDeoptimize(cond, suspend_check->GetDexPc());
Mingyao Yang3584bce2015-05-19 16:01:59 -0700862 deopt_block->InsertInstructionBefore(cond, deopt_block->GetLastInstruction());
863 deopt_block->InsertInstructionBefore(deoptimize, deopt_block->GetLastInstruction());
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700864 deoptimize->CopyEnvironmentFromWithLoopPhiAdjustment(
Mingyao Yang3584bce2015-05-19 16:01:59 -0700865 suspend_check->GetEnvironment(), header);
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700866 }
867
868 // Returns true if adding a (value <= array_length + offset) check for deoptimization
869 // is allowed and will benefit compiled code.
870 bool CanAddDeoptimizationArrayLength(HInstruction* value,
871 HArrayLength* array_length,
872 int32_t offset,
873 bool* is_proven) {
874 *is_proven = false;
Mingyao Yang3584bce2015-05-19 16:01:59 -0700875 HBasicBlock* header = induction_variable_->GetBlock();
876 DCHECK(header->IsLoopHeader());
877 HBasicBlock* pre_header = header->GetLoopInformation()->GetPreHeader();
878 DCHECK(value->GetBlock()->Dominates(pre_header));
879
880 if (array_length->GetBlock() == header) {
881 // array_length_in_loop_body_if_needed only has correct value when the loop
882 // body is entered. We bail out in this case. Usually array_length defined
883 // in the loop header is already hoisted by licm.
884 return false;
885 } else {
886 // array_length is defined either before the loop header already, or in
887 // the loop body since it's used in the loop body. If it's defined in the loop body,
888 // a phi array_length_in_loop_body_if_needed is used to replace it. In that case,
889 // all the uses of array_length must be dominated by its definition in the loop
890 // body. array_length_in_loop_body_if_needed is guaranteed to be the same as
891 // array_length once the loop body is entered so all the uses of the phi will
892 // use the correct value.
893 }
894
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700895 if (offset > 0) {
896 // There might be overflow issue.
897 // TODO: handle this, possibly with some distance relationship between
898 // offset_low and offset_high, or using another deoptimization to make
899 // sure (array_length + offset) doesn't overflow.
900 return false;
901 }
902
903 // See if we can prove the relationship first.
904 if (value == array_length) {
905 if (offset >= 0) {
906 // Already true.
907 *is_proven = true;
908 return true;
909 } else {
910 // May throw exception. Don't add deoptimization.
911 // Keep bounds checks in the loops.
912 return false;
913 }
914 }
915 // Can benefit from deoptimization.
916 return true;
917 }
918
919 // Adds a check that (value <= array_length + offset), and HDeoptimize otherwise.
920 void AddDeoptimizationArrayLength(HInstruction* value,
921 HArrayLength* array_length,
Mingyao Yang3584bce2015-05-19 16:01:59 -0700922 int32_t offset,
923 HBasicBlock* deopt_block,
924 bool loop_entry_test_block_added) {
925 HBasicBlock* header = induction_variable_->GetBlock();
926 DCHECK(header->IsLoopHeader());
927 HBasicBlock* pre_header = header->GetDominator();
928 if (loop_entry_test_block_added) {
Vladimir Marko60584552015-09-03 13:35:12 +0000929 DCHECK(deopt_block->GetSuccessor(0) == pre_header);
Mingyao Yang3584bce2015-05-19 16:01:59 -0700930 } else {
931 DCHECK(deopt_block == pre_header);
932 }
933 HGraph* graph = header->GetGraph();
934 HSuspendCheck* suspend_check = header->GetLoopInformation()->GetSuspendCheck();
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700935
936 // We may need to hoist null-check and array_length out of loop first.
Mingyao Yang3584bce2015-05-19 16:01:59 -0700937 if (!array_length->GetBlock()->Dominates(deopt_block)) {
938 // array_length must be defined in the loop body.
939 DCHECK(header->GetLoopInformation()->Contains(*array_length->GetBlock()));
940 DCHECK(array_length->GetBlock() != header);
941
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700942 HInstruction* array = array_length->InputAt(0);
943 HNullCheck* null_check = array->AsNullCheck();
944 if (null_check != nullptr) {
945 array = null_check->InputAt(0);
946 }
Mingyao Yang3584bce2015-05-19 16:01:59 -0700947 // We've already made sure the array is defined before the loop when collecting
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700948 // array accesses for the loop.
Mingyao Yang3584bce2015-05-19 16:01:59 -0700949 DCHECK(array->GetBlock()->Dominates(deopt_block));
950 if (null_check != nullptr && !null_check->GetBlock()->Dominates(deopt_block)) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700951 // Hoist null check out of loop with a deoptimization.
952 HNullConstant* null_constant = graph->GetNullConstant();
953 HCondition* null_check_cond = new (graph->GetArena()) HEqual(array, null_constant);
954 // TODO: for one dex_pc, share the same deoptimization slow path.
955 HDeoptimize* null_check_deoptimize = new (graph->GetArena())
956 HDeoptimize(null_check_cond, suspend_check->GetDexPc());
Mingyao Yang3584bce2015-05-19 16:01:59 -0700957 deopt_block->InsertInstructionBefore(
958 null_check_cond, deopt_block->GetLastInstruction());
959 deopt_block->InsertInstructionBefore(
960 null_check_deoptimize, deopt_block->GetLastInstruction());
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700961 // Eliminate null check in the loop.
962 null_check->ReplaceWith(array);
963 null_check->GetBlock()->RemoveInstruction(null_check);
964 null_check_deoptimize->CopyEnvironmentFromWithLoopPhiAdjustment(
Mingyao Yang3584bce2015-05-19 16:01:59 -0700965 suspend_check->GetEnvironment(), header);
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700966 }
Mingyao Yang3584bce2015-05-19 16:01:59 -0700967
968 HArrayLength* new_array_length = new (graph->GetArena()) HArrayLength(array);
969 deopt_block->InsertInstructionBefore(new_array_length, deopt_block->GetLastInstruction());
970
971 if (loop_entry_test_block_added) {
972 // Replace array_length defined inside the loop body with a phi
973 // array_length_in_loop_body_if_needed. This is a synthetic phi so there is
974 // no vreg number for it.
975 HPhi* phi = new (graph->GetArena()) HPhi(
976 graph->GetArena(), kNoRegNumber, 2, Primitive::kPrimInt);
977 // Set to 0 if the loop body isn't entered.
978 phi->SetRawInputAt(0, graph->GetIntConstant(0));
979 // Set to array.length if the loop body is entered.
980 phi->SetRawInputAt(1, new_array_length);
981 pre_header->AddPhi(phi);
982 array_length->ReplaceWith(phi);
983 // Make sure phi is only used after the loop body is entered.
984 if (kIsDebugBuild) {
985 for (HUseIterator<HInstruction*> it(phi->GetUses());
986 !it.Done();
987 it.Advance()) {
988 HInstruction* user = it.Current()->GetUser();
989 DCHECK(GetLoopHeaderSuccesorInLoop()->Dominates(user->GetBlock()));
990 }
991 }
992 } else {
993 array_length->ReplaceWith(new_array_length);
994 }
995
996 array_length->GetBlock()->RemoveInstruction(array_length);
997 // Use new_array_length for deopt.
998 array_length = new_array_length;
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700999 }
1000
Mingyao Yang3584bce2015-05-19 16:01:59 -07001001 HInstruction* added = array_length;
1002 if (offset != 0) {
1003 HIntConstant* offset_instr = graph->GetIntConstant(offset);
1004 added = new (graph->GetArena()) HAdd(Primitive::kPrimInt, array_length, offset_instr);
1005 deopt_block->InsertInstructionBefore(added, deopt_block->GetLastInstruction());
1006 }
1007 HCondition* cond = new (graph->GetArena()) HGreaterThan(value, added);
1008 HDeoptimize* deopt = new (graph->GetArena()) HDeoptimize(cond, suspend_check->GetDexPc());
1009 deopt_block->InsertInstructionBefore(cond, deopt_block->GetLastInstruction());
1010 deopt_block->InsertInstructionBefore(deopt, deopt_block->GetLastInstruction());
1011 deopt->CopyEnvironmentFromWithLoopPhiAdjustment(suspend_check->GetEnvironment(), header);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001012 }
1013
Mingyao Yang3584bce2015-05-19 16:01:59 -07001014 // Adds deoptimizations in loop pre-header with the collected array access
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001015 // data so that value ranges can be established in loop body.
1016 // Returns true if deoptimizations are successfully added, or if it's proven
1017 // it's not necessary.
1018 bool AddDeoptimization(const ArrayAccessInsideLoopFinder& finder) {
1019 int32_t offset_low = finder.GetOffsetLow();
1020 int32_t offset_high = finder.GetOffsetHigh();
1021 HArrayLength* array_length = finder.GetFoundArrayLength();
1022
1023 HBasicBlock* pre_header =
1024 induction_variable_->GetBlock()->GetLoopInformation()->GetPreHeader();
1025 if (!initial_->GetBlock()->Dominates(pre_header) ||
1026 !end_->GetBlock()->Dominates(pre_header)) {
1027 // Can't move initial_ or end_ into pre_header for comparisons.
1028 return false;
1029 }
1030
Mingyao Yang3584bce2015-05-19 16:01:59 -07001031 HBasicBlock* deopt_block;
1032 bool loop_entry_test_block_added = false;
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001033 bool is_constant_proven, is_length_proven;
Mingyao Yang3584bce2015-05-19 16:01:59 -07001034
1035 HInstruction* const_comparing_instruction;
1036 int32_t const_compared_to;
1037 HInstruction* array_length_comparing_instruction;
1038 int32_t array_length_offset;
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001039 if (increment_ == 1) {
1040 // Increasing from initial_ to end_.
Mingyao Yang3584bce2015-05-19 16:01:59 -07001041 const_comparing_instruction = initial_;
1042 const_compared_to = -offset_low;
1043 array_length_comparing_instruction = end_;
1044 array_length_offset = inclusive_ ? -offset_high - 1 : -offset_high;
1045 } else {
1046 const_comparing_instruction = end_;
1047 const_compared_to = inclusive_ ? -offset_low : -offset_low - 1;
1048 array_length_comparing_instruction = initial_;
1049 array_length_offset = -offset_high - 1;
1050 }
1051
1052 if (CanAddDeoptimizationConstant(const_comparing_instruction,
1053 const_compared_to,
1054 &is_constant_proven) &&
1055 CanAddDeoptimizationArrayLength(array_length_comparing_instruction,
1056 array_length,
1057 array_length_offset,
1058 &is_length_proven)) {
1059 if (!is_constant_proven || !is_length_proven) {
1060 deopt_block = TransformLoopForDeoptimizationIfNeeded();
1061 loop_entry_test_block_added = (deopt_block != pre_header);
1062 if (loop_entry_test_block_added) {
1063 // Loop body may be entered.
1064 AddLoopBodyEntryTest();
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001065 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001066 }
Mingyao Yang3584bce2015-05-19 16:01:59 -07001067 if (!is_constant_proven) {
1068 AddDeoptimizationConstant(const_comparing_instruction,
1069 const_compared_to,
1070 deopt_block,
1071 loop_entry_test_block_added);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001072 }
Mingyao Yang3584bce2015-05-19 16:01:59 -07001073 if (!is_length_proven) {
1074 AddDeoptimizationArrayLength(array_length_comparing_instruction,
1075 array_length,
1076 array_length_offset,
1077 deopt_block,
1078 loop_entry_test_block_added);
1079 }
1080 return true;
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001081 }
1082 return false;
1083 }
1084
Mingyao Yangf384f882014-10-22 16:08:18 -07001085 private:
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001086 HPhi* const induction_variable_; // Induction variable for this monotonic value range.
1087 HInstruction* const initial_; // Initial value.
1088 HInstruction* end_; // End value.
1089 bool inclusive_; // Whether end value is inclusive.
1090 const int32_t increment_; // Increment for each loop iteration.
1091 const ValueBound bound_; // Additional value bound info for initial_.
Mingyao Yangf384f882014-10-22 16:08:18 -07001092
1093 DISALLOW_COPY_AND_ASSIGN(MonotonicValueRange);
1094};
1095
1096class BCEVisitor : public HGraphVisitor {
1097 public:
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001098 // The least number of bounds checks that should be eliminated by triggering
1099 // the deoptimization technique.
1100 static constexpr size_t kThresholdForAddingDeoptimize = 2;
1101
1102 // Very large constant index is considered as an anomaly. This is a threshold
1103 // beyond which we don't bother to apply the deoptimization technique since
1104 // it's likely some AIOOBE will be thrown.
Aart Bikaab5b752015-09-23 11:18:57 -07001105 static constexpr int32_t kMaxConstantForAddingDeoptimize =
1106 std::numeric_limits<int32_t>::max() - 1024 * 1024;
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001107
Mingyao Yang3584bce2015-05-19 16:01:59 -07001108 // Added blocks for loop body entry test.
1109 bool IsAddedBlock(HBasicBlock* block) const {
1110 return block->GetBlockId() >= initial_block_size_;
1111 }
1112
Aart Bik22af3be2015-09-10 12:50:58 -07001113 BCEVisitor(HGraph* graph, HInductionVarAnalysis* induction_analysis)
1114 : HGraphVisitor(graph),
Vladimir Marko5233f932015-09-29 19:01:15 +01001115 maps_(graph->GetBlocks().size(),
1116 ArenaSafeMap<int, ValueRange*>(
1117 std::less<int>(),
1118 graph->GetArena()->Adapter(kArenaAllocBoundsCheckElimination)),
1119 graph->GetArena()->Adapter(kArenaAllocBoundsCheckElimination)),
1120 first_constant_index_bounds_check_map_(
1121 std::less<int>(),
1122 graph->GetArena()->Adapter(kArenaAllocBoundsCheckElimination)),
Aart Bik22af3be2015-09-10 12:50:58 -07001123 need_to_revisit_block_(false),
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001124 initial_block_size_(graph->GetBlocks().size()),
Aart Bik22af3be2015-09-10 12:50:58 -07001125 induction_range_(induction_analysis) {}
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001126
1127 void VisitBasicBlock(HBasicBlock* block) OVERRIDE {
Mingyao Yang3584bce2015-05-19 16:01:59 -07001128 DCHECK(!IsAddedBlock(block));
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001129 first_constant_index_bounds_check_map_.clear();
1130 HGraphVisitor::VisitBasicBlock(block);
1131 if (need_to_revisit_block_) {
1132 AddComparesWithDeoptimization(block);
1133 need_to_revisit_block_ = false;
1134 first_constant_index_bounds_check_map_.clear();
1135 GetValueRangeMap(block)->clear();
1136 HGraphVisitor::VisitBasicBlock(block);
1137 }
1138 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001139
1140 private:
1141 // Return the map of proven value ranges at the beginning of a basic block.
1142 ArenaSafeMap<int, ValueRange*>* GetValueRangeMap(HBasicBlock* basic_block) {
Mingyao Yang3584bce2015-05-19 16:01:59 -07001143 if (IsAddedBlock(basic_block)) {
1144 // Added blocks don't keep value ranges.
1145 return nullptr;
1146 }
Vladimir Marko5233f932015-09-29 19:01:15 +01001147 uint32_t block_id = basic_block->GetBlockId();
1148 DCHECK_LT(block_id, maps_.size());
1149 return &maps_[block_id];
Mingyao Yangf384f882014-10-22 16:08:18 -07001150 }
1151
1152 // Traverse up the dominator tree to look for value range info.
1153 ValueRange* LookupValueRange(HInstruction* instruction, HBasicBlock* basic_block) {
1154 while (basic_block != nullptr) {
1155 ArenaSafeMap<int, ValueRange*>* map = GetValueRangeMap(basic_block);
Mingyao Yang3584bce2015-05-19 16:01:59 -07001156 if (map != nullptr) {
1157 if (map->find(instruction->GetId()) != map->end()) {
1158 return map->Get(instruction->GetId());
1159 }
1160 } else {
1161 DCHECK(IsAddedBlock(basic_block));
Mingyao Yangf384f882014-10-22 16:08:18 -07001162 }
1163 basic_block = basic_block->GetDominator();
1164 }
1165 // Didn't find any.
1166 return nullptr;
1167 }
1168
Aart Bik22af3be2015-09-10 12:50:58 -07001169 // Return the range resulting from induction variable analysis of "instruction" when the value
1170 // is used from "context", for example, an index used from a bounds-check inside a loop body.
1171 ValueRange* LookupInductionRange(HInstruction* context, HInstruction* instruction) {
1172 InductionVarRange::Value v1 = induction_range_.GetMinInduction(context, instruction);
1173 InductionVarRange::Value v2 = induction_range_.GetMaxInduction(context, instruction);
Aart Bikb3365e02015-09-21 14:45:05 -07001174 if (v1.is_known && (v1.a_constant == 0 || v1.a_constant == 1) &&
1175 v2.is_known && (v2.a_constant == 0 || v2.a_constant == 1)) {
Aart Bik22af3be2015-09-10 12:50:58 -07001176 DCHECK(v1.a_constant == 1 || v1.instruction == nullptr);
1177 DCHECK(v2.a_constant == 1 || v2.instruction == nullptr);
1178 ValueBound low = ValueBound(v1.instruction, v1.b_constant);
1179 ValueBound up = ValueBound(v2.instruction, v2.b_constant);
1180 return new (GetGraph()->GetArena()) ValueRange(GetGraph()->GetArena(), low, up);
1181 }
1182 // Didn't find anything useful.
1183 return nullptr;
1184 }
1185
Mingyao Yang0304e182015-01-30 16:41:29 -08001186 // Narrow the value range of `instruction` at the end of `basic_block` with `range`,
1187 // and push the narrowed value range to `successor`.
Mingyao Yangf384f882014-10-22 16:08:18 -07001188 void ApplyRangeFromComparison(HInstruction* instruction, HBasicBlock* basic_block,
Mingyao Yang8c8bad82015-02-09 18:13:26 -08001189 HBasicBlock* successor, ValueRange* range) {
Mingyao Yangf384f882014-10-22 16:08:18 -07001190 ValueRange* existing_range = LookupValueRange(instruction, basic_block);
Mingyao Yang8c8bad82015-02-09 18:13:26 -08001191 if (existing_range == nullptr) {
1192 if (range != nullptr) {
1193 GetValueRangeMap(successor)->Overwrite(instruction->GetId(), range);
1194 }
1195 return;
1196 }
1197 if (existing_range->IsMonotonicValueRange()) {
1198 DCHECK(instruction->IsLoopHeaderPhi());
1199 // Make sure the comparison is in the loop header so each increment is
1200 // checked with a comparison.
1201 if (instruction->GetBlock() != basic_block) {
1202 return;
1203 }
1204 }
1205 ValueRange* narrowed_range = existing_range->Narrow(range);
Nicolas Geoffraya09ff9c2015-06-24 10:38:27 +01001206 GetValueRangeMap(successor)->Overwrite(instruction->GetId(), narrowed_range);
Mingyao Yangf384f882014-10-22 16:08:18 -07001207 }
1208
Mingyao Yang57e04752015-02-09 18:13:26 -08001209 // Special case that we may simultaneously narrow two MonotonicValueRange's to
1210 // regular value ranges.
1211 void HandleIfBetweenTwoMonotonicValueRanges(HIf* instruction,
1212 HInstruction* left,
1213 HInstruction* right,
1214 IfCondition cond,
1215 MonotonicValueRange* left_range,
1216 MonotonicValueRange* right_range) {
1217 DCHECK(left->IsLoopHeaderPhi());
1218 DCHECK(right->IsLoopHeaderPhi());
1219 if (instruction->GetBlock() != left->GetBlock()) {
1220 // Comparison needs to be in loop header to make sure it's done after each
1221 // increment/decrement.
1222 return;
1223 }
1224
1225 // Handle common cases which also don't have overflow/underflow concerns.
1226 if (left_range->GetIncrement() == 1 &&
1227 left_range->GetBound().IsConstant() &&
1228 right_range->GetIncrement() == -1 &&
1229 right_range->GetBound().IsRelatedToArrayLength() &&
1230 right_range->GetBound().GetConstant() < 0) {
Mingyao Yang57e04752015-02-09 18:13:26 -08001231 HBasicBlock* successor = nullptr;
1232 int32_t left_compensation = 0;
1233 int32_t right_compensation = 0;
1234 if (cond == kCondLT) {
1235 left_compensation = -1;
1236 right_compensation = 1;
1237 successor = instruction->IfTrueSuccessor();
1238 } else if (cond == kCondLE) {
1239 successor = instruction->IfTrueSuccessor();
1240 } else if (cond == kCondGT) {
1241 successor = instruction->IfFalseSuccessor();
1242 } else if (cond == kCondGE) {
1243 left_compensation = -1;
1244 right_compensation = 1;
1245 successor = instruction->IfFalseSuccessor();
1246 } else {
1247 // We don't handle '=='/'!=' test in case left and right can cross and
1248 // miss each other.
1249 return;
1250 }
1251
1252 if (successor != nullptr) {
1253 bool overflow;
1254 bool underflow;
1255 ValueRange* new_left_range = new (GetGraph()->GetArena()) ValueRange(
1256 GetGraph()->GetArena(),
1257 left_range->GetBound(),
1258 right_range->GetBound().Add(left_compensation, &overflow, &underflow));
1259 if (!overflow && !underflow) {
1260 ApplyRangeFromComparison(left, instruction->GetBlock(), successor,
1261 new_left_range);
1262 }
1263
1264 ValueRange* new_right_range = new (GetGraph()->GetArena()) ValueRange(
1265 GetGraph()->GetArena(),
1266 left_range->GetBound().Add(right_compensation, &overflow, &underflow),
1267 right_range->GetBound());
1268 if (!overflow && !underflow) {
1269 ApplyRangeFromComparison(right, instruction->GetBlock(), successor,
1270 new_right_range);
1271 }
1272 }
1273 }
1274 }
1275
Mingyao Yangf384f882014-10-22 16:08:18 -07001276 // Handle "if (left cmp_cond right)".
1277 void HandleIf(HIf* instruction, HInstruction* left, HInstruction* right, IfCondition cond) {
1278 HBasicBlock* block = instruction->GetBlock();
1279
1280 HBasicBlock* true_successor = instruction->IfTrueSuccessor();
1281 // There should be no critical edge at this point.
Vladimir Marko60584552015-09-03 13:35:12 +00001282 DCHECK_EQ(true_successor->GetPredecessors().size(), 1u);
Mingyao Yangf384f882014-10-22 16:08:18 -07001283
1284 HBasicBlock* false_successor = instruction->IfFalseSuccessor();
1285 // There should be no critical edge at this point.
Vladimir Marko60584552015-09-03 13:35:12 +00001286 DCHECK_EQ(false_successor->GetPredecessors().size(), 1u);
Mingyao Yangf384f882014-10-22 16:08:18 -07001287
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001288 ValueRange* left_range = LookupValueRange(left, block);
1289 MonotonicValueRange* left_monotonic_range = nullptr;
1290 if (left_range != nullptr) {
1291 left_monotonic_range = left_range->AsMonotonicValueRange();
1292 if (left_monotonic_range != nullptr) {
Mingyao Yang3584bce2015-05-19 16:01:59 -07001293 HBasicBlock* loop_head = left_monotonic_range->GetLoopHeader();
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001294 if (instruction->GetBlock() != loop_head) {
1295 // For monotonic value range, don't handle `instruction`
1296 // if it's not defined in the loop header.
1297 return;
1298 }
1299 }
1300 }
1301
Mingyao Yang64197522014-12-05 15:56:23 -08001302 bool found;
1303 ValueBound bound = ValueBound::DetectValueBoundFromValue(right, &found);
Mingyao Yang0304e182015-01-30 16:41:29 -08001304 // Each comparison can establish a lower bound and an upper bound
1305 // for the left hand side.
Mingyao Yangf384f882014-10-22 16:08:18 -07001306 ValueBound lower = bound;
1307 ValueBound upper = bound;
1308 if (!found) {
Mingyao Yang0304e182015-01-30 16:41:29 -08001309 // No constant or array.length+c format bound found.
Mingyao Yangf384f882014-10-22 16:08:18 -07001310 // 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 -08001311 ValueRange* right_range = LookupValueRange(right, block);
1312 if (right_range != nullptr) {
1313 if (right_range->IsMonotonicValueRange()) {
Mingyao Yang57e04752015-02-09 18:13:26 -08001314 if (left_range != nullptr && left_range->IsMonotonicValueRange()) {
1315 HandleIfBetweenTwoMonotonicValueRanges(instruction, left, right, cond,
1316 left_range->AsMonotonicValueRange(),
1317 right_range->AsMonotonicValueRange());
1318 return;
1319 }
1320 }
1321 lower = right_range->GetLower();
1322 upper = right_range->GetUpper();
Mingyao Yangf384f882014-10-22 16:08:18 -07001323 } else {
1324 lower = ValueBound::Min();
1325 upper = ValueBound::Max();
1326 }
1327 }
1328
Mingyao Yang0304e182015-01-30 16:41:29 -08001329 bool overflow, underflow;
Mingyao Yangf384f882014-10-22 16:08:18 -07001330 if (cond == kCondLT || cond == kCondLE) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001331 if (left_monotonic_range != nullptr) {
1332 // Update the info for monotonic value range.
1333 if (left_monotonic_range->GetInductionVariable() == left &&
1334 left_monotonic_range->GetIncrement() < 0 &&
Mingyao Yang3584bce2015-05-19 16:01:59 -07001335 block == left_monotonic_range->GetLoopHeader() &&
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001336 instruction->IfFalseSuccessor()->GetLoopInformation() == block->GetLoopInformation()) {
1337 left_monotonic_range->SetEnd(right);
1338 left_monotonic_range->SetInclusive(cond == kCondLT);
1339 }
1340 }
1341
Mingyao Yangf384f882014-10-22 16:08:18 -07001342 if (!upper.Equals(ValueBound::Max())) {
Mingyao Yang0304e182015-01-30 16:41:29 -08001343 int32_t compensation = (cond == kCondLT) ? -1 : 0; // upper bound is inclusive
1344 ValueBound new_upper = upper.Add(compensation, &overflow, &underflow);
1345 if (overflow || underflow) {
1346 return;
Mingyao Yang64197522014-12-05 15:56:23 -08001347 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001348 ValueRange* new_range = new (GetGraph()->GetArena())
1349 ValueRange(GetGraph()->GetArena(), ValueBound::Min(), new_upper);
1350 ApplyRangeFromComparison(left, block, true_successor, new_range);
1351 }
1352
1353 // array.length as a lower bound isn't considered useful.
Mingyao Yang0304e182015-01-30 16:41:29 -08001354 if (!lower.Equals(ValueBound::Min()) && !lower.IsRelatedToArrayLength()) {
1355 int32_t compensation = (cond == kCondLE) ? 1 : 0; // lower bound is inclusive
1356 ValueBound new_lower = lower.Add(compensation, &overflow, &underflow);
1357 if (overflow || underflow) {
1358 return;
Mingyao Yang64197522014-12-05 15:56:23 -08001359 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001360 ValueRange* new_range = new (GetGraph()->GetArena())
1361 ValueRange(GetGraph()->GetArena(), new_lower, ValueBound::Max());
1362 ApplyRangeFromComparison(left, block, false_successor, new_range);
1363 }
1364 } else if (cond == kCondGT || cond == kCondGE) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001365 if (left_monotonic_range != nullptr) {
1366 // Update the info for monotonic value range.
1367 if (left_monotonic_range->GetInductionVariable() == left &&
1368 left_monotonic_range->GetIncrement() > 0 &&
Mingyao Yang3584bce2015-05-19 16:01:59 -07001369 block == left_monotonic_range->GetLoopHeader() &&
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001370 instruction->IfFalseSuccessor()->GetLoopInformation() == block->GetLoopInformation()) {
1371 left_monotonic_range->SetEnd(right);
1372 left_monotonic_range->SetInclusive(cond == kCondGT);
1373 }
1374 }
1375
Mingyao Yangf384f882014-10-22 16:08:18 -07001376 // array.length as a lower bound isn't considered useful.
Mingyao Yang0304e182015-01-30 16:41:29 -08001377 if (!lower.Equals(ValueBound::Min()) && !lower.IsRelatedToArrayLength()) {
1378 int32_t compensation = (cond == kCondGT) ? 1 : 0; // lower bound is inclusive
1379 ValueBound new_lower = lower.Add(compensation, &overflow, &underflow);
1380 if (overflow || underflow) {
1381 return;
Mingyao Yang64197522014-12-05 15:56:23 -08001382 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001383 ValueRange* new_range = new (GetGraph()->GetArena())
1384 ValueRange(GetGraph()->GetArena(), new_lower, ValueBound::Max());
1385 ApplyRangeFromComparison(left, block, true_successor, new_range);
1386 }
1387
1388 if (!upper.Equals(ValueBound::Max())) {
Mingyao Yang0304e182015-01-30 16:41:29 -08001389 int32_t compensation = (cond == kCondGE) ? -1 : 0; // upper bound is inclusive
1390 ValueBound new_upper = upper.Add(compensation, &overflow, &underflow);
1391 if (overflow || underflow) {
1392 return;
Mingyao Yang64197522014-12-05 15:56:23 -08001393 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001394 ValueRange* new_range = new (GetGraph()->GetArena())
1395 ValueRange(GetGraph()->GetArena(), ValueBound::Min(), new_upper);
1396 ApplyRangeFromComparison(left, block, false_successor, new_range);
1397 }
1398 }
1399 }
1400
1401 void VisitBoundsCheck(HBoundsCheck* bounds_check) {
1402 HBasicBlock* block = bounds_check->GetBlock();
1403 HInstruction* index = bounds_check->InputAt(0);
1404 HInstruction* array_length = bounds_check->InputAt(1);
Mingyao Yang3584bce2015-05-19 16:01:59 -07001405 DCHECK(array_length->IsIntConstant() ||
1406 array_length->IsArrayLength() ||
1407 array_length->IsPhi());
1408
1409 if (array_length->IsPhi()) {
1410 // Input 1 of the phi contains the real array.length once the loop body is
1411 // entered. That value will be used for bound analysis. The graph is still
Nicolas Geoffray8df886b2015-06-24 14:57:44 +01001412 // strictly in SSA form.
Mingyao Yang3584bce2015-05-19 16:01:59 -07001413 array_length = array_length->AsPhi()->InputAt(1)->AsArrayLength();
1414 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001415
Mingyao Yang0304e182015-01-30 16:41:29 -08001416 if (!index->IsIntConstant()) {
Aart Bik22af3be2015-09-10 12:50:58 -07001417 ValueBound lower = ValueBound(nullptr, 0); // constant 0
1418 ValueBound upper = ValueBound(array_length, -1); // array_length - 1
1419 ValueRange array_range(GetGraph()->GetArena(), lower, upper);
1420 // Try range obtained by local analysis.
Mingyao Yang0304e182015-01-30 16:41:29 -08001421 ValueRange* index_range = LookupValueRange(index, block);
Aart Bik22af3be2015-09-10 12:50:58 -07001422 if (index_range != nullptr && index_range->FitsIn(&array_range)) {
1423 ReplaceBoundsCheck(bounds_check, index);
1424 return;
1425 }
1426 // Try range obtained by induction variable analysis.
1427 index_range = LookupInductionRange(bounds_check, index);
1428 if (index_range != nullptr && index_range->FitsIn(&array_range)) {
1429 ReplaceBoundsCheck(bounds_check, index);
1430 return;
Mingyao Yangf384f882014-10-22 16:08:18 -07001431 }
Mingyao Yang0304e182015-01-30 16:41:29 -08001432 } else {
1433 int32_t constant = index->AsIntConstant()->GetValue();
1434 if (constant < 0) {
1435 // Will always throw exception.
1436 return;
1437 }
1438 if (array_length->IsIntConstant()) {
1439 if (constant < array_length->AsIntConstant()->GetValue()) {
1440 ReplaceBoundsCheck(bounds_check, index);
1441 }
1442 return;
1443 }
1444
1445 DCHECK(array_length->IsArrayLength());
1446 ValueRange* existing_range = LookupValueRange(array_length, block);
1447 if (existing_range != nullptr) {
1448 ValueBound lower = existing_range->GetLower();
1449 DCHECK(lower.IsConstant());
1450 if (constant < lower.GetConstant()) {
1451 ReplaceBoundsCheck(bounds_check, index);
1452 return;
1453 } else {
1454 // Existing range isn't strong enough to eliminate the bounds check.
1455 // Fall through to update the array_length range with info from this
1456 // bounds check.
1457 }
1458 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001459
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001460 if (first_constant_index_bounds_check_map_.find(array_length->GetId()) ==
1461 first_constant_index_bounds_check_map_.end()) {
1462 // Remember the first bounds check against array_length of a constant index.
1463 // That bounds check instruction has an associated HEnvironment where we
1464 // may add an HDeoptimize to eliminate bounds checks of constant indices
1465 // against array_length.
1466 first_constant_index_bounds_check_map_.Put(array_length->GetId(), bounds_check);
1467 } else {
1468 // We've seen it at least twice. It's beneficial to introduce a compare with
1469 // deoptimization fallback to eliminate the bounds checks.
1470 need_to_revisit_block_ = true;
1471 }
1472
Mingyao Yangf384f882014-10-22 16:08:18 -07001473 // Once we have an array access like 'array[5] = 1', we record array.length >= 6.
Mingyao Yang0304e182015-01-30 16:41:29 -08001474 // We currently don't do it for non-constant index since a valid array[i] can't prove
1475 // a valid array[i-1] yet due to the lower bound side.
Aart Bikaab5b752015-09-23 11:18:57 -07001476 if (constant == std::numeric_limits<int32_t>::max()) {
1477 // Max() as an index will definitely throw AIOOBE.
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001478 return;
1479 }
Mingyao Yang64197522014-12-05 15:56:23 -08001480 ValueBound lower = ValueBound(nullptr, constant + 1);
Mingyao Yangf384f882014-10-22 16:08:18 -07001481 ValueBound upper = ValueBound::Max();
1482 ValueRange* range = new (GetGraph()->GetArena())
1483 ValueRange(GetGraph()->GetArena(), lower, upper);
Mingyao Yang0304e182015-01-30 16:41:29 -08001484 GetValueRangeMap(block)->Overwrite(array_length->GetId(), range);
Mingyao Yangf384f882014-10-22 16:08:18 -07001485 }
1486 }
1487
1488 void ReplaceBoundsCheck(HInstruction* bounds_check, HInstruction* index) {
1489 bounds_check->ReplaceWith(index);
1490 bounds_check->GetBlock()->RemoveInstruction(bounds_check);
1491 }
1492
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01001493 static bool HasSameInputAtBackEdges(HPhi* phi) {
1494 DCHECK(phi->IsLoopHeaderPhi());
1495 // Start with input 1. Input 0 is from the incoming block.
1496 HInstruction* input1 = phi->InputAt(1);
1497 DCHECK(phi->GetBlock()->GetLoopInformation()->IsBackEdge(
Vladimir Marko60584552015-09-03 13:35:12 +00001498 *phi->GetBlock()->GetPredecessor(1)));
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01001499 for (size_t i = 2, e = phi->InputCount(); i < e; ++i) {
1500 DCHECK(phi->GetBlock()->GetLoopInformation()->IsBackEdge(
Vladimir Marko60584552015-09-03 13:35:12 +00001501 *phi->GetBlock()->GetPredecessor(i)));
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01001502 if (input1 != phi->InputAt(i)) {
1503 return false;
1504 }
1505 }
1506 return true;
1507 }
1508
Mingyao Yangf384f882014-10-22 16:08:18 -07001509 void VisitPhi(HPhi* phi) {
Nicolas Geoffraydb216f42015-05-05 17:02:20 +01001510 if (phi->IsLoopHeaderPhi()
1511 && (phi->GetType() == Primitive::kPrimInt)
1512 && HasSameInputAtBackEdges(phi)) {
Mingyao Yangf384f882014-10-22 16:08:18 -07001513 HInstruction* instruction = phi->InputAt(1);
Mingyao Yang0304e182015-01-30 16:41:29 -08001514 HInstruction *left;
1515 int32_t increment;
1516 if (ValueBound::IsAddOrSubAConstant(instruction, &left, &increment)) {
1517 if (left == phi) {
Mingyao Yangf384f882014-10-22 16:08:18 -07001518 HInstruction* initial_value = phi->InputAt(0);
1519 ValueRange* range = nullptr;
Mingyao Yang64197522014-12-05 15:56:23 -08001520 if (increment == 0) {
Mingyao Yangf384f882014-10-22 16:08:18 -07001521 // Add constant 0. It's really a fixed value.
1522 range = new (GetGraph()->GetArena()) ValueRange(
1523 GetGraph()->GetArena(),
Mingyao Yang64197522014-12-05 15:56:23 -08001524 ValueBound(initial_value, 0),
1525 ValueBound(initial_value, 0));
Mingyao Yangf384f882014-10-22 16:08:18 -07001526 } else {
1527 // Monotonically increasing/decreasing.
Mingyao Yang64197522014-12-05 15:56:23 -08001528 bool found;
1529 ValueBound bound = ValueBound::DetectValueBoundFromValue(
1530 initial_value, &found);
1531 if (!found) {
1532 // No constant or array.length+c bound found.
1533 // For i=j, we can still use j's upper bound as i's upper bound.
1534 // Same for lower.
1535 ValueRange* initial_range = LookupValueRange(initial_value, phi->GetBlock());
1536 if (initial_range != nullptr) {
1537 bound = increment > 0 ? initial_range->GetLower() :
1538 initial_range->GetUpper();
1539 } else {
1540 bound = increment > 0 ? ValueBound::Min() : ValueBound::Max();
1541 }
1542 }
1543 range = new (GetGraph()->GetArena()) MonotonicValueRange(
Mingyao Yangf384f882014-10-22 16:08:18 -07001544 GetGraph()->GetArena(),
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001545 phi,
Mingyao Yangf384f882014-10-22 16:08:18 -07001546 initial_value,
Mingyao Yang64197522014-12-05 15:56:23 -08001547 increment,
1548 bound);
Mingyao Yangf384f882014-10-22 16:08:18 -07001549 }
1550 GetValueRangeMap(phi->GetBlock())->Overwrite(phi->GetId(), range);
1551 }
1552 }
1553 }
1554 }
1555
1556 void VisitIf(HIf* instruction) {
1557 if (instruction->InputAt(0)->IsCondition()) {
1558 HCondition* cond = instruction->InputAt(0)->AsCondition();
1559 IfCondition cmp = cond->GetCondition();
1560 if (cmp == kCondGT || cmp == kCondGE ||
1561 cmp == kCondLT || cmp == kCondLE) {
1562 HInstruction* left = cond->GetLeft();
1563 HInstruction* right = cond->GetRight();
1564 HandleIf(instruction, left, right, cmp);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001565
1566 HBasicBlock* block = instruction->GetBlock();
1567 ValueRange* left_range = LookupValueRange(left, block);
1568 if (left_range == nullptr) {
1569 return;
1570 }
1571
1572 if (left_range->IsMonotonicValueRange() &&
Mingyao Yang3584bce2015-05-19 16:01:59 -07001573 block == left_range->AsMonotonicValueRange()->GetLoopHeader()) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001574 // The comparison is for an induction variable in the loop header.
1575 DCHECK(left == left_range->AsMonotonicValueRange()->GetInductionVariable());
Mingyao Yang3584bce2015-05-19 16:01:59 -07001576 HBasicBlock* loop_body_successor =
1577 left_range->AsMonotonicValueRange()->GetLoopHeaderSuccesorInLoop();
1578 if (loop_body_successor == nullptr) {
1579 // In case it's some strange loop structure.
1580 return;
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001581 }
1582 ValueRange* new_left_range = LookupValueRange(left, loop_body_successor);
Mingyao Yang3584bce2015-05-19 16:01:59 -07001583 if ((new_left_range == left_range) ||
1584 // Range narrowed with deoptimization is usually more useful than
1585 // a constant range.
1586 new_left_range->IsConstantValueRange()) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001587 // We are not successful in narrowing the monotonic value range to
1588 // a regular value range. Try using deoptimization.
1589 new_left_range = left_range->AsMonotonicValueRange()->
1590 NarrowWithDeoptimization();
1591 if (new_left_range != left_range) {
Mingyao Yang3584bce2015-05-19 16:01:59 -07001592 GetValueRangeMap(loop_body_successor)->Overwrite(left->GetId(), new_left_range);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001593 }
1594 }
1595 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001596 }
1597 }
1598 }
1599
1600 void VisitAdd(HAdd* add) {
1601 HInstruction* right = add->GetRight();
1602 if (right->IsIntConstant()) {
1603 ValueRange* left_range = LookupValueRange(add->GetLeft(), add->GetBlock());
1604 if (left_range == nullptr) {
1605 return;
1606 }
1607 ValueRange* range = left_range->Add(right->AsIntConstant()->GetValue());
1608 if (range != nullptr) {
1609 GetValueRangeMap(add->GetBlock())->Overwrite(add->GetId(), range);
1610 }
1611 }
1612 }
1613
1614 void VisitSub(HSub* sub) {
1615 HInstruction* left = sub->GetLeft();
1616 HInstruction* right = sub->GetRight();
1617 if (right->IsIntConstant()) {
1618 ValueRange* left_range = LookupValueRange(left, sub->GetBlock());
1619 if (left_range == nullptr) {
1620 return;
1621 }
1622 ValueRange* range = left_range->Add(-right->AsIntConstant()->GetValue());
1623 if (range != nullptr) {
1624 GetValueRangeMap(sub->GetBlock())->Overwrite(sub->GetId(), range);
1625 return;
1626 }
1627 }
1628
1629 // Here we are interested in the typical triangular case of nested loops,
1630 // such as the inner loop 'for (int j=0; j<array.length-i; j++)' where i
1631 // 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 -08001632
1633 // Try to handle (array.length - i) or (array.length + c - i) format.
1634 HInstruction* left_of_left; // left input of left.
1635 int32_t right_const = 0;
1636 if (ValueBound::IsAddOrSubAConstant(left, &left_of_left, &right_const)) {
1637 left = left_of_left;
1638 }
1639 // The value of left input of the sub equals (left + right_const).
1640
Mingyao Yangf384f882014-10-22 16:08:18 -07001641 if (left->IsArrayLength()) {
1642 HInstruction* array_length = left->AsArrayLength();
1643 ValueRange* right_range = LookupValueRange(right, sub->GetBlock());
1644 if (right_range != nullptr) {
1645 ValueBound lower = right_range->GetLower();
1646 ValueBound upper = right_range->GetUpper();
Mingyao Yang0304e182015-01-30 16:41:29 -08001647 if (lower.IsConstant() && upper.IsRelatedToArrayLength()) {
Mingyao Yangf384f882014-10-22 16:08:18 -07001648 HInstruction* upper_inst = upper.GetInstruction();
Mingyao Yang0304e182015-01-30 16:41:29 -08001649 // Make sure it's the same array.
1650 if (ValueBound::Equal(array_length, upper_inst)) {
Mingyao Yang8c8bad82015-02-09 18:13:26 -08001651 int32_t c0 = right_const;
1652 int32_t c1 = lower.GetConstant();
1653 int32_t c2 = upper.GetConstant();
1654 // (array.length + c0 - v) where v is in [c1, array.length + c2]
1655 // gets [c0 - c2, array.length + c0 - c1] as its value range.
1656 if (!ValueBound::WouldAddOverflowOrUnderflow(c0, -c2) &&
1657 !ValueBound::WouldAddOverflowOrUnderflow(c0, -c1)) {
1658 if ((c0 - c1) <= 0) {
1659 // array.length + (c0 - c1) won't overflow/underflow.
1660 ValueRange* range = new (GetGraph()->GetArena()) ValueRange(
1661 GetGraph()->GetArena(),
1662 ValueBound(nullptr, right_const - upper.GetConstant()),
1663 ValueBound(array_length, right_const - lower.GetConstant()));
1664 GetValueRangeMap(sub->GetBlock())->Overwrite(sub->GetId(), range);
1665 }
1666 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001667 }
1668 }
1669 }
1670 }
1671 }
1672
Mingyao Yang8c8bad82015-02-09 18:13:26 -08001673 void FindAndHandlePartialArrayLength(HBinaryOperation* instruction) {
1674 DCHECK(instruction->IsDiv() || instruction->IsShr() || instruction->IsUShr());
1675 HInstruction* right = instruction->GetRight();
1676 int32_t right_const;
1677 if (right->IsIntConstant()) {
1678 right_const = right->AsIntConstant()->GetValue();
1679 // Detect division by two or more.
1680 if ((instruction->IsDiv() && right_const <= 1) ||
1681 (instruction->IsShr() && right_const < 1) ||
1682 (instruction->IsUShr() && right_const < 1)) {
1683 return;
1684 }
1685 } else {
1686 return;
1687 }
1688
1689 // Try to handle array.length/2 or (array.length-1)/2 format.
1690 HInstruction* left = instruction->GetLeft();
1691 HInstruction* left_of_left; // left input of left.
1692 int32_t c = 0;
1693 if (ValueBound::IsAddOrSubAConstant(left, &left_of_left, &c)) {
1694 left = left_of_left;
1695 }
1696 // The value of left input of instruction equals (left + c).
1697
1698 // (array_length + 1) or smaller divided by two or more
Aart Bikaab5b752015-09-23 11:18:57 -07001699 // always generate a value in [Min(), array_length].
1700 // This is true even if array_length is Max().
Mingyao Yang8c8bad82015-02-09 18:13:26 -08001701 if (left->IsArrayLength() && c <= 1) {
1702 if (instruction->IsUShr() && c < 0) {
1703 // Make sure for unsigned shift, left side is not negative.
1704 // e.g. if array_length is 2, ((array_length - 3) >>> 2) is way bigger
1705 // than array_length.
1706 return;
1707 }
1708 ValueRange* range = new (GetGraph()->GetArena()) ValueRange(
1709 GetGraph()->GetArena(),
Aart Bikaab5b752015-09-23 11:18:57 -07001710 ValueBound(nullptr, std::numeric_limits<int32_t>::min()),
Mingyao Yang8c8bad82015-02-09 18:13:26 -08001711 ValueBound(left, 0));
1712 GetValueRangeMap(instruction->GetBlock())->Overwrite(instruction->GetId(), range);
1713 }
1714 }
1715
1716 void VisitDiv(HDiv* div) {
1717 FindAndHandlePartialArrayLength(div);
1718 }
1719
1720 void VisitShr(HShr* shr) {
1721 FindAndHandlePartialArrayLength(shr);
1722 }
1723
1724 void VisitUShr(HUShr* ushr) {
1725 FindAndHandlePartialArrayLength(ushr);
1726 }
1727
Mingyao Yang4559f002015-02-27 14:43:53 -08001728 void VisitAnd(HAnd* instruction) {
1729 if (instruction->GetRight()->IsIntConstant()) {
1730 int32_t constant = instruction->GetRight()->AsIntConstant()->GetValue();
1731 if (constant > 0) {
1732 // constant serves as a mask so any number masked with it
1733 // gets a [0, constant] value range.
1734 ValueRange* range = new (GetGraph()->GetArena()) ValueRange(
1735 GetGraph()->GetArena(),
1736 ValueBound(nullptr, 0),
1737 ValueBound(nullptr, constant));
1738 GetValueRangeMap(instruction->GetBlock())->Overwrite(instruction->GetId(), range);
1739 }
1740 }
1741 }
1742
Mingyao Yang0304e182015-01-30 16:41:29 -08001743 void VisitNewArray(HNewArray* new_array) {
1744 HInstruction* len = new_array->InputAt(0);
1745 if (!len->IsIntConstant()) {
1746 HInstruction *left;
1747 int32_t right_const;
1748 if (ValueBound::IsAddOrSubAConstant(len, &left, &right_const)) {
1749 // (left + right_const) is used as size to new the array.
1750 // We record "-right_const <= left <= new_array - right_const";
1751 ValueBound lower = ValueBound(nullptr, -right_const);
1752 // We use new_array for the bound instead of new_array.length,
1753 // which isn't available as an instruction yet. new_array will
1754 // be treated the same as new_array.length when it's used in a ValueBound.
1755 ValueBound upper = ValueBound(new_array, -right_const);
1756 ValueRange* range = new (GetGraph()->GetArena())
1757 ValueRange(GetGraph()->GetArena(), lower, upper);
Nicolas Geoffraya09ff9c2015-06-24 10:38:27 +01001758 ValueRange* existing_range = LookupValueRange(left, new_array->GetBlock());
1759 if (existing_range != nullptr) {
1760 range = existing_range->Narrow(range);
1761 }
Mingyao Yang0304e182015-01-30 16:41:29 -08001762 GetValueRangeMap(new_array->GetBlock())->Overwrite(left->GetId(), range);
1763 }
1764 }
1765 }
1766
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001767 void VisitDeoptimize(HDeoptimize* deoptimize) {
1768 // Right now it's only HLessThanOrEqual.
1769 DCHECK(deoptimize->InputAt(0)->IsLessThanOrEqual());
1770 HLessThanOrEqual* less_than_or_equal = deoptimize->InputAt(0)->AsLessThanOrEqual();
1771 HInstruction* instruction = less_than_or_equal->InputAt(0);
1772 if (instruction->IsArrayLength()) {
1773 HInstruction* constant = less_than_or_equal->InputAt(1);
1774 DCHECK(constant->IsIntConstant());
1775 DCHECK(constant->AsIntConstant()->GetValue() <= kMaxConstantForAddingDeoptimize);
1776 ValueBound lower = ValueBound(nullptr, constant->AsIntConstant()->GetValue() + 1);
1777 ValueRange* range = new (GetGraph()->GetArena())
1778 ValueRange(GetGraph()->GetArena(), lower, ValueBound::Max());
1779 GetValueRangeMap(deoptimize->GetBlock())->Overwrite(instruction->GetId(), range);
1780 }
1781 }
1782
1783 void AddCompareWithDeoptimization(HInstruction* array_length,
1784 HIntConstant* const_instr,
1785 HBasicBlock* block) {
1786 DCHECK(array_length->IsArrayLength());
1787 ValueRange* range = LookupValueRange(array_length, block);
1788 ValueBound lower_bound = range->GetLower();
1789 DCHECK(lower_bound.IsConstant());
1790 DCHECK(const_instr->GetValue() <= kMaxConstantForAddingDeoptimize);
Nicolas Geoffray8d82a0c2015-06-20 23:49:01 +01001791 // Note that the lower bound of the array length may have been refined
1792 // through other instructions (such as `HNewArray(length - 4)`).
1793 DCHECK_LE(const_instr->GetValue() + 1, lower_bound.GetConstant());
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001794
1795 // If array_length is less than lower_const, deoptimize.
1796 HBoundsCheck* bounds_check = first_constant_index_bounds_check_map_.Get(
1797 array_length->GetId())->AsBoundsCheck();
1798 HCondition* cond = new (GetGraph()->GetArena()) HLessThanOrEqual(array_length, const_instr);
1799 HDeoptimize* deoptimize = new (GetGraph()->GetArena())
1800 HDeoptimize(cond, bounds_check->GetDexPc());
1801 block->InsertInstructionBefore(cond, bounds_check);
1802 block->InsertInstructionBefore(deoptimize, bounds_check);
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001803 deoptimize->CopyEnvironmentFrom(bounds_check->GetEnvironment());
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001804 }
1805
1806 void AddComparesWithDeoptimization(HBasicBlock* block) {
1807 for (ArenaSafeMap<int, HBoundsCheck*>::iterator it =
1808 first_constant_index_bounds_check_map_.begin();
1809 it != first_constant_index_bounds_check_map_.end();
1810 ++it) {
1811 HBoundsCheck* bounds_check = it->second;
Nicolas Geoffray8df886b2015-06-24 14:57:44 +01001812 HInstruction* array_length = bounds_check->InputAt(1);
1813 if (!array_length->IsArrayLength()) {
1814 // Prior deoptimizations may have changed the array length to a phi.
1815 // TODO(mingyao): propagate the range to the phi?
1816 DCHECK(array_length->IsPhi()) << array_length->DebugName();
1817 continue;
1818 }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001819 HIntConstant* lower_bound_const_instr = nullptr;
Aart Bikaab5b752015-09-23 11:18:57 -07001820 int32_t lower_bound_const = std::numeric_limits<int32_t>::min();
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001821 size_t counter = 0;
1822 // Count the constant indexing for which bounds checks haven't
1823 // been removed yet.
1824 for (HUseIterator<HInstruction*> it2(array_length->GetUses());
1825 !it2.Done();
1826 it2.Advance()) {
1827 HInstruction* user = it2.Current()->GetUser();
1828 if (user->GetBlock() == block &&
1829 user->IsBoundsCheck() &&
1830 user->AsBoundsCheck()->InputAt(0)->IsIntConstant()) {
1831 DCHECK_EQ(array_length, user->AsBoundsCheck()->InputAt(1));
1832 HIntConstant* const_instr = user->AsBoundsCheck()->InputAt(0)->AsIntConstant();
1833 if (const_instr->GetValue() > lower_bound_const) {
1834 lower_bound_const = const_instr->GetValue();
1835 lower_bound_const_instr = const_instr;
1836 }
1837 counter++;
1838 }
1839 }
1840 if (counter >= kThresholdForAddingDeoptimize &&
1841 lower_bound_const_instr->GetValue() <= kMaxConstantForAddingDeoptimize) {
1842 AddCompareWithDeoptimization(array_length, lower_bound_const_instr, block);
1843 }
1844 }
1845 }
1846
Vladimir Marko5233f932015-09-29 19:01:15 +01001847 ArenaVector<ArenaSafeMap<int, ValueRange*>> maps_;
Mingyao Yangf384f882014-10-22 16:08:18 -07001848
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001849 // Map an HArrayLength instruction's id to the first HBoundsCheck instruction in
1850 // a block that checks a constant index against that HArrayLength.
Vladimir Marko5233f932015-09-29 19:01:15 +01001851 ArenaSafeMap<int, HBoundsCheck*> first_constant_index_bounds_check_map_;
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001852
1853 // For the block, there is at least one HArrayLength instruction for which there
1854 // is more than one bounds check instruction with constant indexing. And it's
1855 // beneficial to add a compare instruction that has deoptimization fallback and
1856 // eliminate those bounds checks.
1857 bool need_to_revisit_block_;
1858
Mingyao Yang3584bce2015-05-19 16:01:59 -07001859 // Initial number of blocks.
Vladimir Markofa6b93c2015-09-15 10:15:55 +01001860 uint32_t initial_block_size_;
Mingyao Yang3584bce2015-05-19 16:01:59 -07001861
Aart Bik22af3be2015-09-10 12:50:58 -07001862 // Range analysis based on induction variables.
1863 InductionVarRange induction_range_;
1864
Mingyao Yangf384f882014-10-22 16:08:18 -07001865 DISALLOW_COPY_AND_ASSIGN(BCEVisitor);
1866};
1867
1868void BoundsCheckElimination::Run() {
Mark Mendell1152c922015-04-24 17:06:35 -04001869 if (!graph_->HasBoundsChecks()) {
Mingyao Yange4335eb2015-03-02 15:14:13 -08001870 return;
1871 }
1872
Aart Bik22af3be2015-09-10 12:50:58 -07001873 BCEVisitor visitor(graph_, induction_analysis_);
Mingyao Yangf384f882014-10-22 16:08:18 -07001874 // Reverse post order guarantees a node's dominators are visited first.
1875 // We want to visit in the dominator-based order since if a value is known to
1876 // be bounded by a range at one instruction, it must be true that all uses of
1877 // that value dominated by that instruction fits in that range. Range of that
1878 // value can be narrowed further down in the dominator tree.
1879 //
1880 // TODO: only visit blocks that dominate some array accesses.
Mingyao Yang3584bce2015-05-19 16:01:59 -07001881 HBasicBlock* last_visited_block = nullptr;
1882 for (HReversePostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
1883 HBasicBlock* current = it.Current();
1884 if (current == last_visited_block) {
1885 // We may insert blocks into the reverse post order list when processing
1886 // a loop header. Don't process it again.
1887 DCHECK(current->IsLoopHeader());
1888 continue;
1889 }
1890 if (visitor.IsAddedBlock(current)) {
1891 // Skip added blocks. Their effects are already taken care of.
1892 continue;
1893 }
1894 visitor.VisitBasicBlock(current);
1895 last_visited_block = current;
1896 }
Mingyao Yangf384f882014-10-22 16:08:18 -07001897}
1898
1899} // namespace art