summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
author Aart Bik <ajcbik@google.com> 2017-09-08 16:46:50 -0700
committer Aart Bik <ajcbik@google.com> 2017-09-09 10:13:18 -0700
commit8e9090bd6e3ad7ebde47db9d01701733bbfeb89e (patch)
treede85515d5d57c5c335225287f636f432d0ae0ff5 /compiler/optimizing
parentd4d11822e349e7e4af0b43cb3fc69e14f1c95475 (diff)
Generalize range analysis.
Rationale: obvious case x+-1 vs x-1 was missing Test: test-art-host Bug: 63631713 Change-Id: I0a97548a509239bee34a099b1ce9856bac311dba
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/induction_var_range.cc9
-rw-r--r--compiler/optimizing/induction_var_range_test.cc23
2 files changed, 32 insertions, 0 deletions
diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc
index 089340e715..191d3d128c 100644
--- a/compiler/optimizing/induction_var_range.cc
+++ b/compiler/optimizing/induction_var_range.cc
@@ -670,6 +670,15 @@ InductionVarRange::Value InductionVarRange::GetFetch(HInstruction* instruction,
return AddValue(GetFetch(instruction->InputAt(0), trip, in_body, is_min),
Value(static_cast<int32_t>(value)));
}
+ } else if (instruction->IsSub()) {
+ // Incorporate suitable constants in the chased value.
+ if (IsInt64AndGet(instruction->InputAt(0), &value) && CanLongValueFitIntoInt(value)) {
+ return SubValue(Value(static_cast<int32_t>(value)),
+ GetFetch(instruction->InputAt(1), trip, in_body, !is_min));
+ } else if (IsInt64AndGet(instruction->InputAt(1), &value) && CanLongValueFitIntoInt(value)) {
+ return SubValue(GetFetch(instruction->InputAt(0), trip, in_body, is_min),
+ Value(static_cast<int32_t>(value)));
+ }
} else if (instruction->IsArrayLength()) {
// Exploit length properties when chasing constants or chase into a new array declaration.
if (chase_hint_ == nullptr) {
diff --git a/compiler/optimizing/induction_var_range_test.cc b/compiler/optimizing/induction_var_range_test.cc
index 2b82b336d7..9437014407 100644
--- a/compiler/optimizing/induction_var_range_test.cc
+++ b/compiler/optimizing/induction_var_range_test.cc
@@ -723,6 +723,29 @@ TEST_F(InductionVarRangeTest, ArrayLengthAndHints) {
ExpectEqual(Value(x_, 1, 0), GetMax(CreateFetch(array_length), nullptr));
}
+TEST_F(InductionVarRangeTest, AddOrSubAndConstant) {
+ HInstruction* add = new (&allocator_)
+ HAdd(Primitive::kPrimInt, x_, graph_->GetIntConstant(-1));
+ HInstruction* alt = new (&allocator_)
+ HAdd(Primitive::kPrimInt, graph_->GetIntConstant(-1), x_);
+ HInstruction* sub = new (&allocator_)
+ HSub(Primitive::kPrimInt, x_, graph_->GetIntConstant(1));
+ HInstruction* rev = new (&allocator_)
+ HSub(Primitive::kPrimInt, graph_->GetIntConstant(1), x_);
+ entry_block_->AddInstruction(add);
+ entry_block_->AddInstruction(alt);
+ entry_block_->AddInstruction(sub);
+ entry_block_->AddInstruction(rev);
+ ExpectEqual(Value(x_, 1, -1), GetMin(CreateFetch(add), nullptr));
+ ExpectEqual(Value(x_, 1, -1), GetMax(CreateFetch(add), nullptr));
+ ExpectEqual(Value(x_, 1, -1), GetMin(CreateFetch(alt), nullptr));
+ ExpectEqual(Value(x_, 1, -1), GetMax(CreateFetch(alt), nullptr));
+ ExpectEqual(Value(x_, 1, -1), GetMin(CreateFetch(sub), nullptr));
+ ExpectEqual(Value(x_, 1, -1), GetMax(CreateFetch(sub), nullptr));
+ ExpectEqual(Value(x_, -1, 1), GetMin(CreateFetch(rev), nullptr));
+ ExpectEqual(Value(x_, -1, 1), GetMax(CreateFetch(rev), nullptr));
+}
+
//
// Tests on public methods.
//