diff options
author | 2023-09-19 16:24:59 +0100 | |
---|---|---|
committer | 2023-10-02 12:33:46 +0000 | |
commit | 317ab9e551f867476769ec5a6adbbafc6a8d1896 (patch) | |
tree | d226d7e410e699861d462e921b5c0a78e3c6fd35 /compiler | |
parent | ee83f167e5041ea43439617e4b5985cad4a34210 (diff) |
Optimize Select instructions regarding equality
* Select[a, b, EQ(a,b)] / Select[a, b, EQ(b,a)] into a
* Select[a, b, NE(a,b)] / Select[a, b, NE(b,a)] into b
Test: art/test/testrunner/testrunner.py --host --64 -b --optimizing
Change-Id: I5a32af63dc9fb27868d0ffb313324cb1772cff64
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 95 |
1 files changed, 52 insertions, 43 deletions
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 4a1813266e..0e2a62226f 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -1050,51 +1050,60 @@ void InstructionSimplifierVisitor::VisitSelect(HSelect* select) { HInstruction* b = condition->InputAt(1); DataType::Type t_type = true_value->GetType(); DataType::Type f_type = false_value->GetType(); - // Here we have a <cmp> b ? true_value : false_value. - // Test if both values are compatible integral types (resulting MIN/MAX/ABS - // type will be int or long, like the condition). Replacements are general, - // but assume conditions prefer constants on the right. if (DataType::IsIntegralType(t_type) && DataType::Kind(t_type) == DataType::Kind(f_type)) { - // Allow a < 100 ? max(a, -100) : .. - // or a > -100 ? min(a, 100) : .. - // to use min/max instead of a to detect nested min/max expressions. - HInstruction* new_a = AllowInMinMax(cmp, a, b, true_value); - if (new_a != nullptr) { - a = new_a; - } - // Try to replace typical integral MIN/MAX/ABS constructs. - if ((cmp == kCondLT || cmp == kCondLE || cmp == kCondGT || cmp == kCondGE) && - ((a == true_value && b == false_value) || - (b == true_value && a == false_value))) { - // Found a < b ? a : b (MIN) or a < b ? b : a (MAX) - // or a > b ? a : b (MAX) or a > b ? b : a (MIN). - bool is_min = (cmp == kCondLT || cmp == kCondLE) == (a == true_value); - replace_with = NewIntegralMinMax(GetGraph()->GetAllocator(), a, b, select, is_min); - } else if (((cmp == kCondLT || cmp == kCondLE) && true_value->IsNeg()) || - ((cmp == kCondGT || cmp == kCondGE) && false_value->IsNeg())) { - bool negLeft = (cmp == kCondLT || cmp == kCondLE); - HInstruction* the_negated = negLeft ? true_value->InputAt(0) : false_value->InputAt(0); - HInstruction* not_negated = negLeft ? false_value : true_value; - if (a == the_negated && a == not_negated && IsInt64Value(b, 0)) { - // Found a < 0 ? -a : a - // or a > 0 ? a : -a - // which can be replaced by ABS(a). - replace_with = NewIntegralAbs(GetGraph()->GetAllocator(), a, select); + if (cmp == kCondEQ || cmp == kCondNE) { + // Turns + // * Select[a, b, EQ(a,b)] / Select[a, b, EQ(b,a)] into a + // * Select[a, b, NE(a,b)] / Select[a, b, NE(b,a)] into b + // Note that the order in EQ/NE is irrelevant. + if ((a == true_value && b == false_value) || (a == false_value && b == true_value)) { + replace_with = cmp == kCondEQ ? false_value : true_value; + } + } else { + // Test if both values are compatible integral types (resulting MIN/MAX/ABS + // type will be int or long, like the condition). Replacements are general, + // but assume conditions prefer constants on the right. + + // Allow a < 100 ? max(a, -100) : .. + // or a > -100 ? min(a, 100) : .. + // to use min/max instead of a to detect nested min/max expressions. + HInstruction* new_a = AllowInMinMax(cmp, a, b, true_value); + if (new_a != nullptr) { + a = new_a; } - } else if (true_value->IsSub() && false_value->IsSub()) { - HInstruction* true_sub1 = true_value->InputAt(0); - HInstruction* true_sub2 = true_value->InputAt(1); - HInstruction* false_sub1 = false_value->InputAt(0); - HInstruction* false_sub2 = false_value->InputAt(1); - if ((((cmp == kCondGT || cmp == kCondGE) && - (a == true_sub1 && b == true_sub2 && a == false_sub2 && b == false_sub1)) || - ((cmp == kCondLT || cmp == kCondLE) && - (a == true_sub2 && b == true_sub1 && a == false_sub1 && b == false_sub2))) && - AreLowerPrecisionArgs(t_type, a, b)) { - // Found a > b ? a - b : b - a - // or a < b ? b - a : a - b - // which can be replaced by ABS(a - b) for lower precision operands a, b. - replace_with = NewIntegralAbs(GetGraph()->GetAllocator(), true_value, select); + // Try to replace typical integral MIN/MAX/ABS constructs. + if ((cmp == kCondLT || cmp == kCondLE || cmp == kCondGT || cmp == kCondGE) && + ((a == true_value && b == false_value) || (b == true_value && a == false_value))) { + // Found a < b ? a : b (MIN) or a < b ? b : a (MAX) + // or a > b ? a : b (MAX) or a > b ? b : a (MIN). + bool is_min = (cmp == kCondLT || cmp == kCondLE) == (a == true_value); + replace_with = NewIntegralMinMax(GetGraph()->GetAllocator(), a, b, select, is_min); + } else if (((cmp == kCondLT || cmp == kCondLE) && true_value->IsNeg()) || + ((cmp == kCondGT || cmp == kCondGE) && false_value->IsNeg())) { + bool negLeft = (cmp == kCondLT || cmp == kCondLE); + HInstruction* the_negated = negLeft ? true_value->InputAt(0) : false_value->InputAt(0); + HInstruction* not_negated = negLeft ? false_value : true_value; + if (a == the_negated && a == not_negated && IsInt64Value(b, 0)) { + // Found a < 0 ? -a : a + // or a > 0 ? a : -a + // which can be replaced by ABS(a). + replace_with = NewIntegralAbs(GetGraph()->GetAllocator(), a, select); + } + } else if (true_value->IsSub() && false_value->IsSub()) { + HInstruction* true_sub1 = true_value->InputAt(0); + HInstruction* true_sub2 = true_value->InputAt(1); + HInstruction* false_sub1 = false_value->InputAt(0); + HInstruction* false_sub2 = false_value->InputAt(1); + if ((((cmp == kCondGT || cmp == kCondGE) && + (a == true_sub1 && b == true_sub2 && a == false_sub2 && b == false_sub1)) || + ((cmp == kCondLT || cmp == kCondLE) && + (a == true_sub2 && b == true_sub1 && a == false_sub1 && b == false_sub2))) && + AreLowerPrecisionArgs(t_type, a, b)) { + // Found a > b ? a - b : b - a + // or a < b ? b - a : a - b + // which can be replaced by ABS(a - b) for lower precision operands a, b. + replace_with = NewIntegralAbs(GetGraph()->GetAllocator(), true_value, select); + } } } } |