diff options
author | 2017-04-12 17:09:20 -0700 | |
---|---|---|
committer | 2017-04-19 10:30:57 -0700 | |
commit | f3e61ee363fe7f82ef56704f06d753e2034a67dd (patch) | |
tree | a00f1fce4a2e284b0a03f941f530afc5b5c56b59 /compiler/optimizing/induction_var_range.cc | |
parent | 741a81af441cbcb7255229bf250bc009d2894e92 (diff) |
Implement halving add idiom (with checker tests).
Rationale:
First of several idioms that map to very efficient SIMD instructions.
Note that the is-zero-ext and is-sign-ext are general-purpose utilities
that will be widely used in the vectorizer to detect low precision
idioms, so expect that code to be shared with many CLs to come.
Test: test-art-host, test-art-target
Change-Id: If7dc2926c72a2e4b5cea15c44ef68cf5503e9be9
Diffstat (limited to 'compiler/optimizing/induction_var_range.cc')
-rw-r--r-- | compiler/optimizing/induction_var_range.cc | 28 |
1 files changed, 8 insertions, 20 deletions
diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc index 1c8674d522..7c833cf70c 100644 --- a/compiler/optimizing/induction_var_range.cc +++ b/compiler/optimizing/induction_var_range.cc @@ -45,18 +45,6 @@ static bool IsSafeDiv(int32_t c1, int32_t c2) { return c2 != 0 && CanLongValueFitIntoInt(static_cast<int64_t>(c1) / static_cast<int64_t>(c2)); } -/** Returns true for 32/64-bit constant instruction. */ -static bool IsIntAndGet(HInstruction* instruction, int64_t* value) { - if (instruction->IsIntConstant()) { - *value = instruction->AsIntConstant()->GetValue(); - return true; - } else if (instruction->IsLongConstant()) { - *value = instruction->AsLongConstant()->GetValue(); - return true; - } - return false; -} - /** Computes a * b for a,b > 0 (at least until first overflow happens). */ static int64_t SafeMul(int64_t a, int64_t b, /*out*/ bool* overflow) { if (a > 0 && b > 0 && a > (std::numeric_limits<int64_t>::max() / b)) { @@ -106,7 +94,7 @@ static bool IsGEZero(HInstruction* instruction) { } } int64_t value = -1; - return IsIntAndGet(instruction, &value) && value >= 0; + return IsInt64AndGet(instruction, &value) && value >= 0; } /** Hunts "under the hood" for a suitable instruction at the hint. */ @@ -149,7 +137,7 @@ static InductionVarRange::Value SimplifyMax(InductionVarRange::Value v, HInstruc int64_t value; if (v.instruction->IsDiv() && v.instruction->InputAt(0)->IsArrayLength() && - IsIntAndGet(v.instruction->InputAt(1), &value) && v.a_constant == value) { + IsInt64AndGet(v.instruction->InputAt(1), &value) && v.a_constant == value) { return InductionVarRange::Value(v.instruction->InputAt(0), 1, v.b_constant); } // If a == 1, the most suitable one suffices as maximum value. @@ -444,7 +432,7 @@ bool InductionVarRange::IsConstant(HInductionVarAnalysis::InductionInfo* info, // any of the three requests (kExact, kAtMost, and KAtLeast). if (info->induction_class == HInductionVarAnalysis::kInvariant && info->operation == HInductionVarAnalysis::kFetch) { - if (IsIntAndGet(info->fetch, value)) { + if (IsInt64AndGet(info->fetch, value)) { return true; } } @@ -635,7 +623,7 @@ InductionVarRange::Value InductionVarRange::GetGeometric(HInductionVarAnalysis:: int64_t f = 0; if (IsConstant(info->op_a, kExact, &a) && CanLongValueFitIntoInt(a) && - IsIntAndGet(info->fetch, &f) && f >= 1) { + IsInt64AndGet(info->fetch, &f) && f >= 1) { // Conservative bounds on a * f^-i + b with f >= 1 can be computed without // trip count. Other forms would require a much more elaborate evaluation. const bool is_min_a = a >= 0 ? is_min : !is_min; @@ -663,7 +651,7 @@ InductionVarRange::Value InductionVarRange::GetFetch(HInstruction* instruction, // Unless at a constant or hint, chase the instruction a bit deeper into the HIR tree, so that // it becomes more likely range analysis will compare the same instructions as terminal nodes. int64_t value; - if (IsIntAndGet(instruction, &value) && CanLongValueFitIntoInt(value)) { + if (IsInt64AndGet(instruction, &value) && CanLongValueFitIntoInt(value)) { // Proper constant reveals best information. return Value(static_cast<int32_t>(value)); } else if (instruction == chase_hint_) { @@ -671,10 +659,10 @@ InductionVarRange::Value InductionVarRange::GetFetch(HInstruction* instruction, return Value(instruction, 1, 0); } else if (instruction->IsAdd()) { // Incorporate suitable constants in the chased value. - if (IsIntAndGet(instruction->InputAt(0), &value) && CanLongValueFitIntoInt(value)) { + if (IsInt64AndGet(instruction->InputAt(0), &value) && CanLongValueFitIntoInt(value)) { return AddValue(Value(static_cast<int32_t>(value)), GetFetch(instruction->InputAt(1), trip, in_body, is_min)); - } else if (IsIntAndGet(instruction->InputAt(1), &value) && CanLongValueFitIntoInt(value)) { + } else if (IsInt64AndGet(instruction->InputAt(1), &value) && CanLongValueFitIntoInt(value)) { return AddValue(GetFetch(instruction->InputAt(0), trip, in_body, is_min), Value(static_cast<int32_t>(value))); } @@ -1074,7 +1062,7 @@ bool InductionVarRange::GenerateLastValueGeometric(HInductionVarAnalysis::Induct // Detect known base and trip count (always taken). int64_t f = 0; int64_t m = 0; - if (IsIntAndGet(info->fetch, &f) && f >= 1 && IsConstant(trip->op_a, kExact, &m) && m >= 1) { + if (IsInt64AndGet(info->fetch, &f) && f >= 1 && IsConstant(trip->op_a, kExact, &m) && m >= 1) { HInstruction* opa = nullptr; HInstruction* opb = nullptr; if (GenerateCode(info->op_a, nullptr, graph, block, &opa, false, false) && |