summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
author Santiago Aboy Solanes <solanes@google.com> 2023-09-19 16:24:59 +0100
committer Santiago Aboy Solanes <solanes@google.com> 2023-10-02 12:33:46 +0000
commit317ab9e551f867476769ec5a6adbbafc6a8d1896 (patch)
treed226d7e410e699861d462e921b5c0a78e3c6fd35 /compiler
parentee83f167e5041ea43439617e4b5985cad4a34210 (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.cc95
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);
+ }
}
}
}