blob: 65111207949be4967e1bf7ec0afa5900df0f4b44 [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 Yang0304e182015-01-30 16:41:29 -0800129 static HInstruction* FromArrayLengthToNewArrayIfPossible(HInstruction* instruction) {
130 // Null check on the NewArray should have been eliminated by instruction
131 // simplifier already.
132 if (instruction->IsArrayLength() && instruction->InputAt(0)->IsNewArray()) {
133 return instruction->InputAt(0)->AsNewArray();
134 }
135 return instruction;
136 }
137
138 static bool Equal(HInstruction* instruction1, HInstruction* instruction2) {
139 if (instruction1 == instruction2) {
140 return true;
141 }
142
143 if (instruction1 == nullptr || instruction2 == nullptr) {
Mingyao Yangf384f882014-10-22 16:08:18 -0700144 return false;
145 }
Mingyao Yang0304e182015-01-30 16:41:29 -0800146
147 // Some bounds are created with HNewArray* as the instruction instead
148 // of HArrayLength*. They are treated the same.
149 instruction1 = FromArrayLengthToNewArrayIfPossible(instruction1);
150 instruction2 = FromArrayLengthToNewArrayIfPossible(instruction2);
151 return instruction1 == instruction2;
152 }
153
154 // Returns if it's certain this->bound >= `bound`.
155 bool GreaterThanOrEqualTo(ValueBound bound) const {
156 if (Equal(instruction_, bound.instruction_)) {
157 return constant_ >= bound.constant_;
158 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700159 // Not comparable. Just return false.
160 return false;
161 }
162
Mingyao Yang0304e182015-01-30 16:41:29 -0800163 // Returns if it's certain this->bound <= `bound`.
164 bool LessThanOrEqualTo(ValueBound bound) const {
165 if (Equal(instruction_, bound.instruction_)) {
166 return constant_ <= bound.constant_;
Mingyao Yangf384f882014-10-22 16:08:18 -0700167 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700168 // Not comparable. Just return false.
169 return false;
170 }
171
172 // Try to narrow lower bound. Returns the greatest of the two if possible.
173 // Pick one if they are not comparable.
174 static ValueBound NarrowLowerBound(ValueBound bound1, ValueBound bound2) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800175 if (bound1.GreaterThanOrEqualTo(bound2)) {
176 return bound1;
177 }
178 if (bound2.GreaterThanOrEqualTo(bound1)) {
179 return bound2;
Mingyao Yangf384f882014-10-22 16:08:18 -0700180 }
181
182 // Not comparable. Just pick one. We may lose some info, but that's ok.
183 // Favor constant as lower bound.
184 return bound1.IsConstant() ? bound1 : bound2;
185 }
186
187 // Try to narrow upper bound. Returns the lowest of the two if possible.
188 // Pick one if they are not comparable.
189 static ValueBound NarrowUpperBound(ValueBound bound1, ValueBound bound2) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800190 if (bound1.LessThanOrEqualTo(bound2)) {
191 return bound1;
192 }
193 if (bound2.LessThanOrEqualTo(bound1)) {
194 return bound2;
Mingyao Yangf384f882014-10-22 16:08:18 -0700195 }
196
197 // Not comparable. Just pick one. We may lose some info, but that's ok.
198 // Favor array length as upper bound.
Mingyao Yang0304e182015-01-30 16:41:29 -0800199 return bound1.IsRelatedToArrayLength() ? bound1 : bound2;
Mingyao Yangf384f882014-10-22 16:08:18 -0700200 }
201
Mingyao Yang0304e182015-01-30 16:41:29 -0800202 // Add a constant to a ValueBound.
203 // `overflow` or `underflow` will return whether the resulting bound may
204 // overflow or underflow an int.
205 ValueBound Add(int32_t c, bool* overflow, bool* underflow) const {
206 *overflow = *underflow = false;
Mingyao Yangf384f882014-10-22 16:08:18 -0700207 if (c == 0) {
208 return *this;
209 }
210
Mingyao Yang0304e182015-01-30 16:41:29 -0800211 int32_t new_constant;
Mingyao Yangf384f882014-10-22 16:08:18 -0700212 if (c > 0) {
213 if (constant_ > INT_MAX - c) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800214 *overflow = true;
Mingyao Yang64197522014-12-05 15:56:23 -0800215 return Max();
Mingyao Yangf384f882014-10-22 16:08:18 -0700216 }
Mingyao Yang0304e182015-01-30 16:41:29 -0800217
218 new_constant = constant_ + c;
219 // (array.length + non-positive-constant) won't overflow an int.
220 if (IsConstant() || (IsRelatedToArrayLength() && new_constant <= 0)) {
221 return ValueBound(instruction_, new_constant);
222 }
223 // Be conservative.
224 *overflow = true;
225 return Max();
Mingyao Yangf384f882014-10-22 16:08:18 -0700226 } else {
227 if (constant_ < INT_MIN - c) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800228 *underflow = true;
229 return Min();
Mingyao Yangf384f882014-10-22 16:08:18 -0700230 }
Mingyao Yang0304e182015-01-30 16:41:29 -0800231
232 new_constant = constant_ + c;
233 // Regardless of the value new_constant, (array.length+new_constant) will
234 // never underflow since array.length is no less than 0.
235 if (IsConstant() || IsRelatedToArrayLength()) {
236 return ValueBound(instruction_, new_constant);
237 }
238 // Be conservative.
239 *underflow = true;
240 return Min();
Mingyao Yangf384f882014-10-22 16:08:18 -0700241 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700242 }
243
244 private:
Mingyao Yangf384f882014-10-22 16:08:18 -0700245 HInstruction* instruction_;
Mingyao Yang0304e182015-01-30 16:41:29 -0800246 int32_t constant_;
Mingyao Yangf384f882014-10-22 16:08:18 -0700247};
248
249/**
250 * Represent a range of lower bound and upper bound, both being inclusive.
251 * Currently a ValueRange may be generated as a result of the following:
252 * comparisons related to array bounds, array bounds check, add/sub on top
Mingyao Yang0304e182015-01-30 16:41:29 -0800253 * of an existing value range, NewArray or a loop phi corresponding to an
Mingyao Yangf384f882014-10-22 16:08:18 -0700254 * incrementing/decrementing array index (MonotonicValueRange).
255 */
256class ValueRange : public ArenaObject<kArenaAllocMisc> {
257 public:
258 ValueRange(ArenaAllocator* allocator, ValueBound lower, ValueBound upper)
259 : allocator_(allocator), lower_(lower), upper_(upper) {}
260
261 virtual ~ValueRange() {}
262
Mingyao Yang57e04752015-02-09 18:13:26 -0800263 virtual MonotonicValueRange* AsMonotonicValueRange() { return nullptr; }
264 bool IsMonotonicValueRange() {
Mingyao Yangf384f882014-10-22 16:08:18 -0700265 return AsMonotonicValueRange() != nullptr;
266 }
267
268 ArenaAllocator* GetAllocator() const { return allocator_; }
269 ValueBound GetLower() const { return lower_; }
270 ValueBound GetUpper() const { return upper_; }
271
272 // If it's certain that this value range fits in other_range.
273 virtual bool FitsIn(ValueRange* other_range) const {
274 if (other_range == nullptr) {
275 return true;
276 }
277 DCHECK(!other_range->IsMonotonicValueRange());
Mingyao Yang0304e182015-01-30 16:41:29 -0800278 return lower_.GreaterThanOrEqualTo(other_range->lower_) &&
279 upper_.LessThanOrEqualTo(other_range->upper_);
Mingyao Yangf384f882014-10-22 16:08:18 -0700280 }
281
282 // Returns the intersection of this and range.
283 // If it's not possible to do intersection because some
284 // bounds are not comparable, it's ok to pick either bound.
285 virtual ValueRange* Narrow(ValueRange* range) {
286 if (range == nullptr) {
287 return this;
288 }
289
290 if (range->IsMonotonicValueRange()) {
291 return this;
292 }
293
294 return new (allocator_) ValueRange(
295 allocator_,
296 ValueBound::NarrowLowerBound(lower_, range->lower_),
297 ValueBound::NarrowUpperBound(upper_, range->upper_));
298 }
299
Mingyao Yang0304e182015-01-30 16:41:29 -0800300 // Shift a range by a constant.
301 ValueRange* Add(int32_t constant) const {
302 bool overflow, underflow;
303 ValueBound lower = lower_.Add(constant, &overflow, &underflow);
304 if (underflow) {
305 // Lower bound underflow will wrap around to positive values
306 // and invalidate the upper bound.
307 return nullptr;
Mingyao Yangf384f882014-10-22 16:08:18 -0700308 }
Mingyao Yang0304e182015-01-30 16:41:29 -0800309 ValueBound upper = upper_.Add(constant, &overflow, &underflow);
310 if (overflow) {
311 // Upper bound overflow will wrap around to negative values
312 // and invalidate the lower bound.
313 return nullptr;
Mingyao Yangf384f882014-10-22 16:08:18 -0700314 }
315 return new (allocator_) ValueRange(allocator_, lower, upper);
316 }
317
Mingyao Yangf384f882014-10-22 16:08:18 -0700318 private:
319 ArenaAllocator* const allocator_;
320 const ValueBound lower_; // inclusive
321 const ValueBound upper_; // inclusive
322
323 DISALLOW_COPY_AND_ASSIGN(ValueRange);
324};
325
326/**
327 * A monotonically incrementing/decrementing value range, e.g.
328 * the variable i in "for (int i=0; i<array.length; i++)".
329 * Special care needs to be taken to account for overflow/underflow
330 * of such value ranges.
331 */
332class MonotonicValueRange : public ValueRange {
333 public:
Mingyao Yang64197522014-12-05 15:56:23 -0800334 MonotonicValueRange(ArenaAllocator* allocator,
335 HInstruction* initial,
Mingyao Yang0304e182015-01-30 16:41:29 -0800336 int32_t increment,
Mingyao Yang64197522014-12-05 15:56:23 -0800337 ValueBound bound)
338 // To be conservative, give it full range [INT_MIN, INT_MAX] in case it's
339 // used as a regular value range, due to possible overflow/underflow.
340 : ValueRange(allocator, ValueBound::Min(), ValueBound::Max()),
341 initial_(initial),
342 increment_(increment),
343 bound_(bound) {}
Mingyao Yangf384f882014-10-22 16:08:18 -0700344
345 virtual ~MonotonicValueRange() {}
346
Mingyao Yang57e04752015-02-09 18:13:26 -0800347 int32_t GetIncrement() const { return increment_; }
348
349 ValueBound GetBound() const { return bound_; }
350
351 MonotonicValueRange* AsMonotonicValueRange() OVERRIDE { return this; }
Mingyao Yangf384f882014-10-22 16:08:18 -0700352
353 // If it's certain that this value range fits in other_range.
354 bool FitsIn(ValueRange* other_range) const OVERRIDE {
355 if (other_range == nullptr) {
356 return true;
357 }
358 DCHECK(!other_range->IsMonotonicValueRange());
359 return false;
360 }
361
362 // Try to narrow this MonotonicValueRange given another range.
363 // Ideally it will return a normal ValueRange. But due to
364 // possible overflow/underflow, that may not be possible.
365 ValueRange* Narrow(ValueRange* range) OVERRIDE {
366 if (range == nullptr) {
367 return this;
368 }
369 DCHECK(!range->IsMonotonicValueRange());
370
371 if (increment_ > 0) {
372 // Monotonically increasing.
Mingyao Yang64197522014-12-05 15:56:23 -0800373 ValueBound lower = ValueBound::NarrowLowerBound(bound_, range->GetLower());
Mingyao Yangf384f882014-10-22 16:08:18 -0700374
375 // We currently conservatively assume max array length is INT_MAX. If we can
376 // make assumptions about the max array length, e.g. due to the max heap size,
377 // divided by the element size (such as 4 bytes for each integer array), we can
378 // lower this number and rule out some possible overflows.
Mingyao Yang0304e182015-01-30 16:41:29 -0800379 int32_t max_array_len = INT_MAX;
Mingyao Yangf384f882014-10-22 16:08:18 -0700380
Mingyao Yang0304e182015-01-30 16:41:29 -0800381 // max possible integer value of range's upper value.
382 int32_t upper = INT_MAX;
383 // Try to lower upper.
384 ValueBound upper_bound = range->GetUpper();
385 if (upper_bound.IsConstant()) {
386 upper = upper_bound.GetConstant();
387 } else if (upper_bound.IsRelatedToArrayLength() && upper_bound.GetConstant() <= 0) {
388 // Normal case. e.g. <= array.length - 1.
389 upper = max_array_len + upper_bound.GetConstant();
Mingyao Yangf384f882014-10-22 16:08:18 -0700390 }
391
392 // If we can prove for the last number in sequence of initial_,
393 // initial_ + increment_, initial_ + 2 x increment_, ...
394 // that's <= upper, (last_num_in_sequence + increment_) doesn't trigger overflow,
395 // then this MonoticValueRange is narrowed to a normal value range.
396
397 // Be conservative first, assume last number in the sequence hits upper.
Mingyao Yang0304e182015-01-30 16:41:29 -0800398 int32_t last_num_in_sequence = upper;
Mingyao Yangf384f882014-10-22 16:08:18 -0700399 if (initial_->IsIntConstant()) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800400 int32_t initial_constant = initial_->AsIntConstant()->GetValue();
Mingyao Yangf384f882014-10-22 16:08:18 -0700401 if (upper <= initial_constant) {
402 last_num_in_sequence = upper;
403 } else {
Mingyao Yang0304e182015-01-30 16:41:29 -0800404 // Cast to int64_t for the substraction part to avoid int32_t overflow.
Mingyao Yangf384f882014-10-22 16:08:18 -0700405 last_num_in_sequence = initial_constant +
406 ((int64_t)upper - (int64_t)initial_constant) / increment_ * increment_;
407 }
408 }
409 if (last_num_in_sequence <= INT_MAX - increment_) {
410 // No overflow. The sequence will be stopped by the upper bound test as expected.
411 return new (GetAllocator()) ValueRange(GetAllocator(), lower, range->GetUpper());
412 }
413
414 // There might be overflow. Give up narrowing.
415 return this;
416 } else {
417 DCHECK_NE(increment_, 0);
418 // Monotonically decreasing.
Mingyao Yang64197522014-12-05 15:56:23 -0800419 ValueBound upper = ValueBound::NarrowUpperBound(bound_, range->GetUpper());
Mingyao Yangf384f882014-10-22 16:08:18 -0700420
421 // Need to take care of underflow. Try to prove underflow won't happen
Mingyao Yang0304e182015-01-30 16:41:29 -0800422 // for common cases.
Mingyao Yangf384f882014-10-22 16:08:18 -0700423 if (range->GetLower().IsConstant()) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800424 int32_t constant = range->GetLower().GetConstant();
Mingyao Yangf384f882014-10-22 16:08:18 -0700425 if (constant >= INT_MIN - increment_) {
426 return new (GetAllocator()) ValueRange(GetAllocator(), range->GetLower(), upper);
427 }
428 }
429
Mingyao Yang0304e182015-01-30 16:41:29 -0800430 // For non-constant lower bound, just assume might be underflow. Give up narrowing.
Mingyao Yangf384f882014-10-22 16:08:18 -0700431 return this;
432 }
433 }
434
435 private:
Mingyao Yangf384f882014-10-22 16:08:18 -0700436 HInstruction* const initial_;
Mingyao Yang0304e182015-01-30 16:41:29 -0800437 const int32_t increment_;
Mingyao Yang64197522014-12-05 15:56:23 -0800438 ValueBound bound_; // Additional value bound info for initial_;
Mingyao Yangf384f882014-10-22 16:08:18 -0700439
440 DISALLOW_COPY_AND_ASSIGN(MonotonicValueRange);
441};
442
443class BCEVisitor : public HGraphVisitor {
444 public:
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700445 // The least number of bounds checks that should be eliminated by triggering
446 // the deoptimization technique.
447 static constexpr size_t kThresholdForAddingDeoptimize = 2;
448
449 // Very large constant index is considered as an anomaly. This is a threshold
450 // beyond which we don't bother to apply the deoptimization technique since
451 // it's likely some AIOOBE will be thrown.
452 static constexpr int32_t kMaxConstantForAddingDeoptimize = INT_MAX - 1024 * 1024;
453
Andreas Gampe0418b5b2014-12-04 17:24:50 -0800454 explicit BCEVisitor(HGraph* graph)
Mingyao Yangf384f882014-10-22 16:08:18 -0700455 : HGraphVisitor(graph),
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700456 maps_(graph->GetBlocks().Size()),
457 need_to_revisit_block_(false) {}
458
459 void VisitBasicBlock(HBasicBlock* block) OVERRIDE {
460 first_constant_index_bounds_check_map_.clear();
461 HGraphVisitor::VisitBasicBlock(block);
462 if (need_to_revisit_block_) {
463 AddComparesWithDeoptimization(block);
464 need_to_revisit_block_ = false;
465 first_constant_index_bounds_check_map_.clear();
466 GetValueRangeMap(block)->clear();
467 HGraphVisitor::VisitBasicBlock(block);
468 }
469 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700470
471 private:
472 // Return the map of proven value ranges at the beginning of a basic block.
473 ArenaSafeMap<int, ValueRange*>* GetValueRangeMap(HBasicBlock* basic_block) {
474 int block_id = basic_block->GetBlockId();
475 if (maps_.at(block_id) == nullptr) {
476 std::unique_ptr<ArenaSafeMap<int, ValueRange*>> map(
477 new ArenaSafeMap<int, ValueRange*>(
478 std::less<int>(), GetGraph()->GetArena()->Adapter()));
479 maps_.at(block_id) = std::move(map);
480 }
481 return maps_.at(block_id).get();
482 }
483
484 // Traverse up the dominator tree to look for value range info.
485 ValueRange* LookupValueRange(HInstruction* instruction, HBasicBlock* basic_block) {
486 while (basic_block != nullptr) {
487 ArenaSafeMap<int, ValueRange*>* map = GetValueRangeMap(basic_block);
488 if (map->find(instruction->GetId()) != map->end()) {
489 return map->Get(instruction->GetId());
490 }
491 basic_block = basic_block->GetDominator();
492 }
493 // Didn't find any.
494 return nullptr;
495 }
496
Mingyao Yang0304e182015-01-30 16:41:29 -0800497 // Narrow the value range of `instruction` at the end of `basic_block` with `range`,
498 // and push the narrowed value range to `successor`.
Mingyao Yangf384f882014-10-22 16:08:18 -0700499 void ApplyRangeFromComparison(HInstruction* instruction, HBasicBlock* basic_block,
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800500 HBasicBlock* successor, ValueRange* range) {
Mingyao Yangf384f882014-10-22 16:08:18 -0700501 ValueRange* existing_range = LookupValueRange(instruction, basic_block);
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800502 if (existing_range == nullptr) {
503 if (range != nullptr) {
504 GetValueRangeMap(successor)->Overwrite(instruction->GetId(), range);
505 }
506 return;
507 }
508 if (existing_range->IsMonotonicValueRange()) {
509 DCHECK(instruction->IsLoopHeaderPhi());
510 // Make sure the comparison is in the loop header so each increment is
511 // checked with a comparison.
512 if (instruction->GetBlock() != basic_block) {
513 return;
514 }
515 }
516 ValueRange* narrowed_range = existing_range->Narrow(range);
Mingyao Yangf384f882014-10-22 16:08:18 -0700517 if (narrowed_range != nullptr) {
518 GetValueRangeMap(successor)->Overwrite(instruction->GetId(), narrowed_range);
519 }
520 }
521
Mingyao Yang57e04752015-02-09 18:13:26 -0800522 // Special case that we may simultaneously narrow two MonotonicValueRange's to
523 // regular value ranges.
524 void HandleIfBetweenTwoMonotonicValueRanges(HIf* instruction,
525 HInstruction* left,
526 HInstruction* right,
527 IfCondition cond,
528 MonotonicValueRange* left_range,
529 MonotonicValueRange* right_range) {
530 DCHECK(left->IsLoopHeaderPhi());
531 DCHECK(right->IsLoopHeaderPhi());
532 if (instruction->GetBlock() != left->GetBlock()) {
533 // Comparison needs to be in loop header to make sure it's done after each
534 // increment/decrement.
535 return;
536 }
537
538 // Handle common cases which also don't have overflow/underflow concerns.
539 if (left_range->GetIncrement() == 1 &&
540 left_range->GetBound().IsConstant() &&
541 right_range->GetIncrement() == -1 &&
542 right_range->GetBound().IsRelatedToArrayLength() &&
543 right_range->GetBound().GetConstant() < 0) {
Mingyao Yang57e04752015-02-09 18:13:26 -0800544 HBasicBlock* successor = nullptr;
545 int32_t left_compensation = 0;
546 int32_t right_compensation = 0;
547 if (cond == kCondLT) {
548 left_compensation = -1;
549 right_compensation = 1;
550 successor = instruction->IfTrueSuccessor();
551 } else if (cond == kCondLE) {
552 successor = instruction->IfTrueSuccessor();
553 } else if (cond == kCondGT) {
554 successor = instruction->IfFalseSuccessor();
555 } else if (cond == kCondGE) {
556 left_compensation = -1;
557 right_compensation = 1;
558 successor = instruction->IfFalseSuccessor();
559 } else {
560 // We don't handle '=='/'!=' test in case left and right can cross and
561 // miss each other.
562 return;
563 }
564
565 if (successor != nullptr) {
566 bool overflow;
567 bool underflow;
568 ValueRange* new_left_range = new (GetGraph()->GetArena()) ValueRange(
569 GetGraph()->GetArena(),
570 left_range->GetBound(),
571 right_range->GetBound().Add(left_compensation, &overflow, &underflow));
572 if (!overflow && !underflow) {
573 ApplyRangeFromComparison(left, instruction->GetBlock(), successor,
574 new_left_range);
575 }
576
577 ValueRange* new_right_range = new (GetGraph()->GetArena()) ValueRange(
578 GetGraph()->GetArena(),
579 left_range->GetBound().Add(right_compensation, &overflow, &underflow),
580 right_range->GetBound());
581 if (!overflow && !underflow) {
582 ApplyRangeFromComparison(right, instruction->GetBlock(), successor,
583 new_right_range);
584 }
585 }
586 }
587 }
588
Mingyao Yangf384f882014-10-22 16:08:18 -0700589 // Handle "if (left cmp_cond right)".
590 void HandleIf(HIf* instruction, HInstruction* left, HInstruction* right, IfCondition cond) {
591 HBasicBlock* block = instruction->GetBlock();
592
593 HBasicBlock* true_successor = instruction->IfTrueSuccessor();
594 // There should be no critical edge at this point.
595 DCHECK_EQ(true_successor->GetPredecessors().Size(), 1u);
596
597 HBasicBlock* false_successor = instruction->IfFalseSuccessor();
598 // There should be no critical edge at this point.
599 DCHECK_EQ(false_successor->GetPredecessors().Size(), 1u);
600
Mingyao Yang64197522014-12-05 15:56:23 -0800601 bool found;
602 ValueBound bound = ValueBound::DetectValueBoundFromValue(right, &found);
Mingyao Yang0304e182015-01-30 16:41:29 -0800603 // Each comparison can establish a lower bound and an upper bound
604 // for the left hand side.
Mingyao Yangf384f882014-10-22 16:08:18 -0700605 ValueBound lower = bound;
606 ValueBound upper = bound;
607 if (!found) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800608 // No constant or array.length+c format bound found.
Mingyao Yangf384f882014-10-22 16:08:18 -0700609 // 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 -0800610 ValueRange* right_range = LookupValueRange(right, block);
611 if (right_range != nullptr) {
612 if (right_range->IsMonotonicValueRange()) {
613 ValueRange* left_range = LookupValueRange(left, block);
614 if (left_range != nullptr && left_range->IsMonotonicValueRange()) {
615 HandleIfBetweenTwoMonotonicValueRanges(instruction, left, right, cond,
616 left_range->AsMonotonicValueRange(),
617 right_range->AsMonotonicValueRange());
618 return;
619 }
620 }
621 lower = right_range->GetLower();
622 upper = right_range->GetUpper();
Mingyao Yangf384f882014-10-22 16:08:18 -0700623 } else {
624 lower = ValueBound::Min();
625 upper = ValueBound::Max();
626 }
627 }
628
Mingyao Yang0304e182015-01-30 16:41:29 -0800629 bool overflow, underflow;
Mingyao Yangf384f882014-10-22 16:08:18 -0700630 if (cond == kCondLT || cond == kCondLE) {
631 if (!upper.Equals(ValueBound::Max())) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800632 int32_t compensation = (cond == kCondLT) ? -1 : 0; // upper bound is inclusive
633 ValueBound new_upper = upper.Add(compensation, &overflow, &underflow);
634 if (overflow || underflow) {
635 return;
Mingyao Yang64197522014-12-05 15:56:23 -0800636 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700637 ValueRange* new_range = new (GetGraph()->GetArena())
638 ValueRange(GetGraph()->GetArena(), ValueBound::Min(), new_upper);
639 ApplyRangeFromComparison(left, block, true_successor, new_range);
640 }
641
642 // array.length as a lower bound isn't considered useful.
Mingyao Yang0304e182015-01-30 16:41:29 -0800643 if (!lower.Equals(ValueBound::Min()) && !lower.IsRelatedToArrayLength()) {
644 int32_t compensation = (cond == kCondLE) ? 1 : 0; // lower bound is inclusive
645 ValueBound new_lower = lower.Add(compensation, &overflow, &underflow);
646 if (overflow || underflow) {
647 return;
Mingyao Yang64197522014-12-05 15:56:23 -0800648 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700649 ValueRange* new_range = new (GetGraph()->GetArena())
650 ValueRange(GetGraph()->GetArena(), new_lower, ValueBound::Max());
651 ApplyRangeFromComparison(left, block, false_successor, new_range);
652 }
653 } else if (cond == kCondGT || cond == kCondGE) {
654 // array.length as a lower bound isn't considered useful.
Mingyao Yang0304e182015-01-30 16:41:29 -0800655 if (!lower.Equals(ValueBound::Min()) && !lower.IsRelatedToArrayLength()) {
656 int32_t compensation = (cond == kCondGT) ? 1 : 0; // lower bound is inclusive
657 ValueBound new_lower = lower.Add(compensation, &overflow, &underflow);
658 if (overflow || underflow) {
659 return;
Mingyao Yang64197522014-12-05 15:56:23 -0800660 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700661 ValueRange* new_range = new (GetGraph()->GetArena())
662 ValueRange(GetGraph()->GetArena(), new_lower, ValueBound::Max());
663 ApplyRangeFromComparison(left, block, true_successor, new_range);
664 }
665
666 if (!upper.Equals(ValueBound::Max())) {
Mingyao Yang0304e182015-01-30 16:41:29 -0800667 int32_t compensation = (cond == kCondGE) ? -1 : 0; // upper bound is inclusive
668 ValueBound new_upper = upper.Add(compensation, &overflow, &underflow);
669 if (overflow || underflow) {
670 return;
Mingyao Yang64197522014-12-05 15:56:23 -0800671 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700672 ValueRange* new_range = new (GetGraph()->GetArena())
673 ValueRange(GetGraph()->GetArena(), ValueBound::Min(), new_upper);
674 ApplyRangeFromComparison(left, block, false_successor, new_range);
675 }
676 }
677 }
678
679 void VisitBoundsCheck(HBoundsCheck* bounds_check) {
680 HBasicBlock* block = bounds_check->GetBlock();
681 HInstruction* index = bounds_check->InputAt(0);
682 HInstruction* array_length = bounds_check->InputAt(1);
Mingyao Yang0304e182015-01-30 16:41:29 -0800683 DCHECK(array_length->IsIntConstant() || array_length->IsArrayLength());
Mingyao Yangf384f882014-10-22 16:08:18 -0700684
Mingyao Yang0304e182015-01-30 16:41:29 -0800685 if (!index->IsIntConstant()) {
686 ValueRange* index_range = LookupValueRange(index, block);
687 if (index_range != nullptr) {
688 ValueBound lower = ValueBound(nullptr, 0); // constant 0
689 ValueBound upper = ValueBound(array_length, -1); // array_length - 1
690 ValueRange* array_range = new (GetGraph()->GetArena())
691 ValueRange(GetGraph()->GetArena(), lower, upper);
692 if (index_range->FitsIn(array_range)) {
Mingyao Yangf384f882014-10-22 16:08:18 -0700693 ReplaceBoundsCheck(bounds_check, index);
694 return;
695 }
696 }
Mingyao Yang0304e182015-01-30 16:41:29 -0800697 } else {
698 int32_t constant = index->AsIntConstant()->GetValue();
699 if (constant < 0) {
700 // Will always throw exception.
701 return;
702 }
703 if (array_length->IsIntConstant()) {
704 if (constant < array_length->AsIntConstant()->GetValue()) {
705 ReplaceBoundsCheck(bounds_check, index);
706 }
707 return;
708 }
709
710 DCHECK(array_length->IsArrayLength());
711 ValueRange* existing_range = LookupValueRange(array_length, block);
712 if (existing_range != nullptr) {
713 ValueBound lower = existing_range->GetLower();
714 DCHECK(lower.IsConstant());
715 if (constant < lower.GetConstant()) {
716 ReplaceBoundsCheck(bounds_check, index);
717 return;
718 } else {
719 // Existing range isn't strong enough to eliminate the bounds check.
720 // Fall through to update the array_length range with info from this
721 // bounds check.
722 }
723 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700724
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700725 if (first_constant_index_bounds_check_map_.find(array_length->GetId()) ==
726 first_constant_index_bounds_check_map_.end()) {
727 // Remember the first bounds check against array_length of a constant index.
728 // That bounds check instruction has an associated HEnvironment where we
729 // may add an HDeoptimize to eliminate bounds checks of constant indices
730 // against array_length.
731 first_constant_index_bounds_check_map_.Put(array_length->GetId(), bounds_check);
732 } else {
733 // We've seen it at least twice. It's beneficial to introduce a compare with
734 // deoptimization fallback to eliminate the bounds checks.
735 need_to_revisit_block_ = true;
736 }
737
Mingyao Yangf384f882014-10-22 16:08:18 -0700738 // Once we have an array access like 'array[5] = 1', we record array.length >= 6.
Mingyao Yang0304e182015-01-30 16:41:29 -0800739 // We currently don't do it for non-constant index since a valid array[i] can't prove
740 // a valid array[i-1] yet due to the lower bound side.
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700741 if (constant == INT_MAX) {
742 // INT_MAX as an index will definitely throw AIOOBE.
743 return;
744 }
Mingyao Yang64197522014-12-05 15:56:23 -0800745 ValueBound lower = ValueBound(nullptr, constant + 1);
Mingyao Yangf384f882014-10-22 16:08:18 -0700746 ValueBound upper = ValueBound::Max();
747 ValueRange* range = new (GetGraph()->GetArena())
748 ValueRange(GetGraph()->GetArena(), lower, upper);
Mingyao Yang0304e182015-01-30 16:41:29 -0800749 GetValueRangeMap(block)->Overwrite(array_length->GetId(), range);
Mingyao Yangf384f882014-10-22 16:08:18 -0700750 }
751 }
752
753 void ReplaceBoundsCheck(HInstruction* bounds_check, HInstruction* index) {
754 bounds_check->ReplaceWith(index);
755 bounds_check->GetBlock()->RemoveInstruction(bounds_check);
756 }
757
758 void VisitPhi(HPhi* phi) {
759 if (phi->IsLoopHeaderPhi() && phi->GetType() == Primitive::kPrimInt) {
Andreas Gampe0418b5b2014-12-04 17:24:50 -0800760 DCHECK_EQ(phi->InputCount(), 2U);
Mingyao Yangf384f882014-10-22 16:08:18 -0700761 HInstruction* instruction = phi->InputAt(1);
Mingyao Yang0304e182015-01-30 16:41:29 -0800762 HInstruction *left;
763 int32_t increment;
764 if (ValueBound::IsAddOrSubAConstant(instruction, &left, &increment)) {
765 if (left == phi) {
Mingyao Yangf384f882014-10-22 16:08:18 -0700766 HInstruction* initial_value = phi->InputAt(0);
767 ValueRange* range = nullptr;
Mingyao Yang64197522014-12-05 15:56:23 -0800768 if (increment == 0) {
Mingyao Yangf384f882014-10-22 16:08:18 -0700769 // Add constant 0. It's really a fixed value.
770 range = new (GetGraph()->GetArena()) ValueRange(
771 GetGraph()->GetArena(),
Mingyao Yang64197522014-12-05 15:56:23 -0800772 ValueBound(initial_value, 0),
773 ValueBound(initial_value, 0));
Mingyao Yangf384f882014-10-22 16:08:18 -0700774 } else {
775 // Monotonically increasing/decreasing.
Mingyao Yang64197522014-12-05 15:56:23 -0800776 bool found;
777 ValueBound bound = ValueBound::DetectValueBoundFromValue(
778 initial_value, &found);
779 if (!found) {
780 // No constant or array.length+c bound found.
781 // For i=j, we can still use j's upper bound as i's upper bound.
782 // Same for lower.
783 ValueRange* initial_range = LookupValueRange(initial_value, phi->GetBlock());
784 if (initial_range != nullptr) {
785 bound = increment > 0 ? initial_range->GetLower() :
786 initial_range->GetUpper();
787 } else {
788 bound = increment > 0 ? ValueBound::Min() : ValueBound::Max();
789 }
790 }
791 range = new (GetGraph()->GetArena()) MonotonicValueRange(
Mingyao Yangf384f882014-10-22 16:08:18 -0700792 GetGraph()->GetArena(),
793 initial_value,
Mingyao Yang64197522014-12-05 15:56:23 -0800794 increment,
795 bound);
Mingyao Yangf384f882014-10-22 16:08:18 -0700796 }
797 GetValueRangeMap(phi->GetBlock())->Overwrite(phi->GetId(), range);
798 }
799 }
800 }
801 }
802
803 void VisitIf(HIf* instruction) {
804 if (instruction->InputAt(0)->IsCondition()) {
805 HCondition* cond = instruction->InputAt(0)->AsCondition();
806 IfCondition cmp = cond->GetCondition();
807 if (cmp == kCondGT || cmp == kCondGE ||
808 cmp == kCondLT || cmp == kCondLE) {
809 HInstruction* left = cond->GetLeft();
810 HInstruction* right = cond->GetRight();
811 HandleIf(instruction, left, right, cmp);
812 }
813 }
814 }
815
816 void VisitAdd(HAdd* add) {
817 HInstruction* right = add->GetRight();
818 if (right->IsIntConstant()) {
819 ValueRange* left_range = LookupValueRange(add->GetLeft(), add->GetBlock());
820 if (left_range == nullptr) {
821 return;
822 }
823 ValueRange* range = left_range->Add(right->AsIntConstant()->GetValue());
824 if (range != nullptr) {
825 GetValueRangeMap(add->GetBlock())->Overwrite(add->GetId(), range);
826 }
827 }
828 }
829
830 void VisitSub(HSub* sub) {
831 HInstruction* left = sub->GetLeft();
832 HInstruction* right = sub->GetRight();
833 if (right->IsIntConstant()) {
834 ValueRange* left_range = LookupValueRange(left, sub->GetBlock());
835 if (left_range == nullptr) {
836 return;
837 }
838 ValueRange* range = left_range->Add(-right->AsIntConstant()->GetValue());
839 if (range != nullptr) {
840 GetValueRangeMap(sub->GetBlock())->Overwrite(sub->GetId(), range);
841 return;
842 }
843 }
844
845 // Here we are interested in the typical triangular case of nested loops,
846 // such as the inner loop 'for (int j=0; j<array.length-i; j++)' where i
847 // 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 -0800848
849 // Try to handle (array.length - i) or (array.length + c - i) format.
850 HInstruction* left_of_left; // left input of left.
851 int32_t right_const = 0;
852 if (ValueBound::IsAddOrSubAConstant(left, &left_of_left, &right_const)) {
853 left = left_of_left;
854 }
855 // The value of left input of the sub equals (left + right_const).
856
Mingyao Yangf384f882014-10-22 16:08:18 -0700857 if (left->IsArrayLength()) {
858 HInstruction* array_length = left->AsArrayLength();
859 ValueRange* right_range = LookupValueRange(right, sub->GetBlock());
860 if (right_range != nullptr) {
861 ValueBound lower = right_range->GetLower();
862 ValueBound upper = right_range->GetUpper();
Mingyao Yang0304e182015-01-30 16:41:29 -0800863 if (lower.IsConstant() && upper.IsRelatedToArrayLength()) {
Mingyao Yangf384f882014-10-22 16:08:18 -0700864 HInstruction* upper_inst = upper.GetInstruction();
Mingyao Yang0304e182015-01-30 16:41:29 -0800865 // Make sure it's the same array.
866 if (ValueBound::Equal(array_length, upper_inst)) {
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800867 int32_t c0 = right_const;
868 int32_t c1 = lower.GetConstant();
869 int32_t c2 = upper.GetConstant();
870 // (array.length + c0 - v) where v is in [c1, array.length + c2]
871 // gets [c0 - c2, array.length + c0 - c1] as its value range.
872 if (!ValueBound::WouldAddOverflowOrUnderflow(c0, -c2) &&
873 !ValueBound::WouldAddOverflowOrUnderflow(c0, -c1)) {
874 if ((c0 - c1) <= 0) {
875 // array.length + (c0 - c1) won't overflow/underflow.
876 ValueRange* range = new (GetGraph()->GetArena()) ValueRange(
877 GetGraph()->GetArena(),
878 ValueBound(nullptr, right_const - upper.GetConstant()),
879 ValueBound(array_length, right_const - lower.GetConstant()));
880 GetValueRangeMap(sub->GetBlock())->Overwrite(sub->GetId(), range);
881 }
882 }
Mingyao Yangf384f882014-10-22 16:08:18 -0700883 }
884 }
885 }
886 }
887 }
888
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800889 void FindAndHandlePartialArrayLength(HBinaryOperation* instruction) {
890 DCHECK(instruction->IsDiv() || instruction->IsShr() || instruction->IsUShr());
891 HInstruction* right = instruction->GetRight();
892 int32_t right_const;
893 if (right->IsIntConstant()) {
894 right_const = right->AsIntConstant()->GetValue();
895 // Detect division by two or more.
896 if ((instruction->IsDiv() && right_const <= 1) ||
897 (instruction->IsShr() && right_const < 1) ||
898 (instruction->IsUShr() && right_const < 1)) {
899 return;
900 }
901 } else {
902 return;
903 }
904
905 // Try to handle array.length/2 or (array.length-1)/2 format.
906 HInstruction* left = instruction->GetLeft();
907 HInstruction* left_of_left; // left input of left.
908 int32_t c = 0;
909 if (ValueBound::IsAddOrSubAConstant(left, &left_of_left, &c)) {
910 left = left_of_left;
911 }
912 // The value of left input of instruction equals (left + c).
913
914 // (array_length + 1) or smaller divided by two or more
915 // always generate a value in [INT_MIN, array_length].
916 // This is true even if array_length is INT_MAX.
917 if (left->IsArrayLength() && c <= 1) {
918 if (instruction->IsUShr() && c < 0) {
919 // Make sure for unsigned shift, left side is not negative.
920 // e.g. if array_length is 2, ((array_length - 3) >>> 2) is way bigger
921 // than array_length.
922 return;
923 }
924 ValueRange* range = new (GetGraph()->GetArena()) ValueRange(
925 GetGraph()->GetArena(),
926 ValueBound(nullptr, INT_MIN),
927 ValueBound(left, 0));
928 GetValueRangeMap(instruction->GetBlock())->Overwrite(instruction->GetId(), range);
929 }
930 }
931
932 void VisitDiv(HDiv* div) {
933 FindAndHandlePartialArrayLength(div);
934 }
935
936 void VisitShr(HShr* shr) {
937 FindAndHandlePartialArrayLength(shr);
938 }
939
940 void VisitUShr(HUShr* ushr) {
941 FindAndHandlePartialArrayLength(ushr);
942 }
943
Mingyao Yang4559f002015-02-27 14:43:53 -0800944 void VisitAnd(HAnd* instruction) {
945 if (instruction->GetRight()->IsIntConstant()) {
946 int32_t constant = instruction->GetRight()->AsIntConstant()->GetValue();
947 if (constant > 0) {
948 // constant serves as a mask so any number masked with it
949 // gets a [0, constant] value range.
950 ValueRange* range = new (GetGraph()->GetArena()) ValueRange(
951 GetGraph()->GetArena(),
952 ValueBound(nullptr, 0),
953 ValueBound(nullptr, constant));
954 GetValueRangeMap(instruction->GetBlock())->Overwrite(instruction->GetId(), range);
955 }
956 }
957 }
958
Mingyao Yang0304e182015-01-30 16:41:29 -0800959 void VisitNewArray(HNewArray* new_array) {
960 HInstruction* len = new_array->InputAt(0);
961 if (!len->IsIntConstant()) {
962 HInstruction *left;
963 int32_t right_const;
964 if (ValueBound::IsAddOrSubAConstant(len, &left, &right_const)) {
965 // (left + right_const) is used as size to new the array.
966 // We record "-right_const <= left <= new_array - right_const";
967 ValueBound lower = ValueBound(nullptr, -right_const);
968 // We use new_array for the bound instead of new_array.length,
969 // which isn't available as an instruction yet. new_array will
970 // be treated the same as new_array.length when it's used in a ValueBound.
971 ValueBound upper = ValueBound(new_array, -right_const);
972 ValueRange* range = new (GetGraph()->GetArena())
973 ValueRange(GetGraph()->GetArena(), lower, upper);
974 GetValueRangeMap(new_array->GetBlock())->Overwrite(left->GetId(), range);
975 }
976 }
977 }
978
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700979 void VisitDeoptimize(HDeoptimize* deoptimize) {
980 // Right now it's only HLessThanOrEqual.
981 DCHECK(deoptimize->InputAt(0)->IsLessThanOrEqual());
982 HLessThanOrEqual* less_than_or_equal = deoptimize->InputAt(0)->AsLessThanOrEqual();
983 HInstruction* instruction = less_than_or_equal->InputAt(0);
984 if (instruction->IsArrayLength()) {
985 HInstruction* constant = less_than_or_equal->InputAt(1);
986 DCHECK(constant->IsIntConstant());
987 DCHECK(constant->AsIntConstant()->GetValue() <= kMaxConstantForAddingDeoptimize);
988 ValueBound lower = ValueBound(nullptr, constant->AsIntConstant()->GetValue() + 1);
989 ValueRange* range = new (GetGraph()->GetArena())
990 ValueRange(GetGraph()->GetArena(), lower, ValueBound::Max());
991 GetValueRangeMap(deoptimize->GetBlock())->Overwrite(instruction->GetId(), range);
992 }
993 }
994
995 void AddCompareWithDeoptimization(HInstruction* array_length,
996 HIntConstant* const_instr,
997 HBasicBlock* block) {
998 DCHECK(array_length->IsArrayLength());
999 ValueRange* range = LookupValueRange(array_length, block);
1000 ValueBound lower_bound = range->GetLower();
1001 DCHECK(lower_bound.IsConstant());
1002 DCHECK(const_instr->GetValue() <= kMaxConstantForAddingDeoptimize);
1003 DCHECK_EQ(lower_bound.GetConstant(), const_instr->GetValue() + 1);
1004
1005 // If array_length is less than lower_const, deoptimize.
1006 HBoundsCheck* bounds_check = first_constant_index_bounds_check_map_.Get(
1007 array_length->GetId())->AsBoundsCheck();
1008 HCondition* cond = new (GetGraph()->GetArena()) HLessThanOrEqual(array_length, const_instr);
1009 HDeoptimize* deoptimize = new (GetGraph()->GetArena())
1010 HDeoptimize(cond, bounds_check->GetDexPc());
1011 block->InsertInstructionBefore(cond, bounds_check);
1012 block->InsertInstructionBefore(deoptimize, bounds_check);
Nicolas Geoffray3dcd58c2015-04-03 11:02:38 +01001013 deoptimize->CopyEnvironmentFrom(bounds_check->GetEnvironment());
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001014 }
1015
1016 void AddComparesWithDeoptimization(HBasicBlock* block) {
1017 for (ArenaSafeMap<int, HBoundsCheck*>::iterator it =
1018 first_constant_index_bounds_check_map_.begin();
1019 it != first_constant_index_bounds_check_map_.end();
1020 ++it) {
1021 HBoundsCheck* bounds_check = it->second;
1022 HArrayLength* array_length = bounds_check->InputAt(1)->AsArrayLength();
1023 HIntConstant* lower_bound_const_instr = nullptr;
1024 int32_t lower_bound_const = INT_MIN;
1025 size_t counter = 0;
1026 // Count the constant indexing for which bounds checks haven't
1027 // been removed yet.
1028 for (HUseIterator<HInstruction*> it2(array_length->GetUses());
1029 !it2.Done();
1030 it2.Advance()) {
1031 HInstruction* user = it2.Current()->GetUser();
1032 if (user->GetBlock() == block &&
1033 user->IsBoundsCheck() &&
1034 user->AsBoundsCheck()->InputAt(0)->IsIntConstant()) {
1035 DCHECK_EQ(array_length, user->AsBoundsCheck()->InputAt(1));
1036 HIntConstant* const_instr = user->AsBoundsCheck()->InputAt(0)->AsIntConstant();
1037 if (const_instr->GetValue() > lower_bound_const) {
1038 lower_bound_const = const_instr->GetValue();
1039 lower_bound_const_instr = const_instr;
1040 }
1041 counter++;
1042 }
1043 }
1044 if (counter >= kThresholdForAddingDeoptimize &&
1045 lower_bound_const_instr->GetValue() <= kMaxConstantForAddingDeoptimize) {
1046 AddCompareWithDeoptimization(array_length, lower_bound_const_instr, block);
1047 }
1048 }
1049 }
1050
Mingyao Yangf384f882014-10-22 16:08:18 -07001051 std::vector<std::unique_ptr<ArenaSafeMap<int, ValueRange*>>> maps_;
1052
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001053 // Map an HArrayLength instruction's id to the first HBoundsCheck instruction in
1054 // a block that checks a constant index against that HArrayLength.
1055 SafeMap<int, HBoundsCheck*> first_constant_index_bounds_check_map_;
1056
1057 // For the block, there is at least one HArrayLength instruction for which there
1058 // is more than one bounds check instruction with constant indexing. And it's
1059 // beneficial to add a compare instruction that has deoptimization fallback and
1060 // eliminate those bounds checks.
1061 bool need_to_revisit_block_;
1062
Mingyao Yangf384f882014-10-22 16:08:18 -07001063 DISALLOW_COPY_AND_ASSIGN(BCEVisitor);
1064};
1065
1066void BoundsCheckElimination::Run() {
Mingyao Yange4335eb2015-03-02 15:14:13 -08001067 if (!graph_->HasArrayAccesses()) {
1068 return;
1069 }
1070
Mingyao Yangf384f882014-10-22 16:08:18 -07001071 BCEVisitor visitor(graph_);
1072 // Reverse post order guarantees a node's dominators are visited first.
1073 // We want to visit in the dominator-based order since if a value is known to
1074 // be bounded by a range at one instruction, it must be true that all uses of
1075 // that value dominated by that instruction fits in that range. Range of that
1076 // value can be narrowed further down in the dominator tree.
1077 //
1078 // TODO: only visit blocks that dominate some array accesses.
1079 visitor.VisitReversePostOrder();
1080}
1081
1082} // namespace art