Minor cleanup of saturation arithmetic code.
Rationale:
Changes requested by Artem and Vladimir.
Bug: b/74026074
Test: test-art-host,target
Change-Id: If99dd2345369d4260e3b514bb212f81d433420a3
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index abd644a..e1fb7ac 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -36,10 +36,6 @@
// No loop unrolling factor (just one copy of the loop-body).
static constexpr uint32_t kNoUnrollingFactor = 1;
-// Values that indicate unbounded end.
-static constexpr int64_t kNoLo = std::numeric_limits<int64_t>::min();
-static constexpr int64_t kNoHi = std::numeric_limits<int64_t>::max();
-
//
// Static helpers.
//
@@ -338,33 +334,28 @@
// Detect clipped [lo, hi] range for nested MIN-MAX operations on a clippee,
// such as MIN(hi, MAX(lo, clippee)) for an arbitrary clippee expression.
// Example: MIN(10, MIN(20, MAX(0, x))) yields [0, 10] with clippee x.
-static bool IsClipped(HInstruction* instruction,
- /*out*/ int64_t* lo,
- /*out*/ int64_t* hi,
- /*out*/ HInstruction** clippee) {
- // Recurse into MIN-MAX expressions and 'tighten' the range [lo, hi].
- if (instruction->IsMin() || instruction->IsMax()) {
- // Find MIN-MAX(const, ..) or MIN-MAX(.., const).
- for (int i = 0; i < 2; i++) {
- int64_t c = 0;
- if (IsInt64AndGet(instruction->InputAt(i), &c)) {
- if (instruction->IsMin()) {
- *hi = std::min(*hi, c);
- } else {
- *lo = std::max(*lo, c);
- }
- return IsClipped(instruction->InputAt(1 - i), lo, hi, clippee);
- }
+static HInstruction* FindClippee(HInstruction* instruction,
+ /*out*/ int64_t* lo,
+ /*out*/ int64_t* hi) {
+ // Iterate into MIN(.., c)-MAX(.., c) expressions and 'tighten' the range [lo, hi].
+ while (instruction->IsMin() || instruction->IsMax()) {
+ HBinaryOperation* min_max = instruction->AsBinaryOperation();
+ DCHECK(min_max->GetType() == DataType::Type::kInt32 ||
+ min_max->GetType() == DataType::Type::kInt64);
+ // Process the constant.
+ HConstant* right = min_max->GetConstantRight();
+ if (right == nullptr) {
+ break;
+ } else if (instruction->IsMin()) {
+ *hi = std::min(*hi, Int64FromConstant(right));
+ } else {
+ *lo = std::max(*lo, Int64FromConstant(right));
}
- // Recursion fails at any MIN/MAX that does not have one constant
- // argument, e.g. MIN(x, y) or MAX(2 * x, f()).
- return false;
+ instruction = min_max->GetLeastConstantLeft();
}
- // Recursion ends in any other expression. At this point we record the leaf
- // expression as the clippee and report success on the range [lo, hi].
- DCHECK(*clippee == nullptr);
- *clippee = instruction;
- return true;
+ // Iteration ends in any other expression (possibly MIN/MAX without constant).
+ // This leaf expression is the clippee with range [lo, hi].
+ return instruction;
}
// Accept various saturated addition forms.
@@ -1896,15 +1887,15 @@
if (HasVectorRestrictions(restrictions, kNoSaturation)) {
return false;
}
- // Search for clipping of a clippee.
- int64_t lo = kNoLo;
- int64_t hi = kNoHi;
- HInstruction* clippee = nullptr;
- if (!IsClipped(instruction, &lo, &hi, &clippee)) {
+ // Restrict type (generalize if one day we generalize allowed MIN/MAX integral types).
+ if (instruction->GetType() != DataType::Type::kInt32 &&
+ instruction->GetType() != DataType::Type::kInt64) {
return false;
}
- CHECK(clippee != nullptr);
// Clipped addition or subtraction?
+ int64_t lo = std::numeric_limits<int64_t>::min();
+ int64_t hi = std::numeric_limits<int64_t>::max();
+ HInstruction* clippee = FindClippee(instruction, &lo, &hi);
bool is_add = true;
if (clippee->IsAdd()) {
is_add = true;