diff options
author | 2023-09-25 10:22:06 +0100 | |
---|---|---|
committer | 2023-09-26 12:50:06 +0000 | |
commit | b320a4d6edb6ab0824934700d706cb5e7cf19c56 (patch) | |
tree | 068d536878babd30ed9c52e498d96feca49beb53 /compiler/optimizing/instruction_simplifier.cc | |
parent | 11957a6dd52ea45eef7324225204fd06a6c983cf (diff) |
Optimize Sub/Sub and Sub/Add operations
Handles cases like:
* y - (x + y) = -x
* x - (x + y) = -y.
* (x - y) - x = -y.
* x - (x - y) = y.
Bug: 301612598
Fixes: 301612598
Test: art/test/testrunner/testrunner.py --host --64 -b --optimizing
Change-Id: I2f506b4a4903774baf39e8d2c681db6a59efeb2c
Diffstat (limited to 'compiler/optimizing/instruction_simplifier.cc')
-rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 70 |
1 files changed, 66 insertions, 4 deletions
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index e13c8eafaf..4a1813266e 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -2242,6 +2242,7 @@ void InstructionSimplifierVisitor::VisitSub(HSub* instruction) { } if (left->IsAdd()) { + // Cases (x + y) - y = x, and (x + y) - x = y. // Replace code patterns looking like // ADD dst1, x, y ADD dst1, x, y // SUB dst2, dst1, y SUB dst2, dst1, x @@ -2250,14 +2251,75 @@ void InstructionSimplifierVisitor::VisitSub(HSub* instruction) { // SUB instruction is not needed in this case, we may use // one of inputs of ADD instead. // It is applicable to integral types only. + HAdd* add = left->AsAdd(); DCHECK(DataType::IsIntegralType(type)); - if (left->InputAt(1) == right) { - instruction->ReplaceWith(left->InputAt(0)); + if (add->GetRight() == right) { + instruction->ReplaceWith(add->GetLeft()); + RecordSimplification(); + instruction->GetBlock()->RemoveInstruction(instruction); + return; + } else if (add->GetLeft() == right) { + instruction->ReplaceWith(add->GetRight()); RecordSimplification(); instruction->GetBlock()->RemoveInstruction(instruction); return; - } else if (left->InputAt(0) == right) { - instruction->ReplaceWith(left->InputAt(1)); + } + } else if (right->IsAdd()) { + // Cases y - (x + y) = -x, and x - (x + y) = -y. + // Replace code patterns looking like + // ADD dst1, x, y ADD dst1, x, y + // SUB dst2, y, dst1 SUB dst2, x, dst1 + // with + // ADD dst1, x, y ADD dst1, x, y + // NEG x NEG y + // SUB instruction is not needed in this case, we may use + // one of inputs of ADD instead with a NEG. + // It is applicable to integral types only. + HAdd* add = right->AsAdd(); + DCHECK(DataType::IsIntegralType(type)); + if (add->GetRight() == left) { + HNeg* neg = new (GetGraph()->GetAllocator()) HNeg(add->GetType(), add->GetLeft()); + instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, neg); + RecordSimplification(); + return; + } else if (add->GetLeft() == left) { + HNeg* neg = new (GetGraph()->GetAllocator()) HNeg(add->GetType(), add->GetRight()); + instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, neg); + RecordSimplification(); + return; + } + } else if (left->IsSub()) { + // Case (x - y) - x = -y. + // Replace code patterns looking like + // SUB dst1, x, y + // SUB dst2, dst1, x + // with + // SUB dst1, x, y + // NEG y + // The second SUB is not needed in this case, we may use the second input of the first SUB + // instead with a NEG. + // It is applicable to integral types only. + HSub* sub = left->AsSub(); + DCHECK(DataType::IsIntegralType(type)); + if (sub->GetLeft() == right) { + HNeg* neg = new (GetGraph()->GetAllocator()) HNeg(sub->GetType(), sub->GetRight()); + instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, neg); + RecordSimplification(); + return; + } + } else if (right->IsSub()) { + // Case x - (x - y) = y. + // Replace code patterns looking like + // SUB dst1, x, y + // SUB dst2, x, dst1 + // with + // SUB dst1, x, y + // The second SUB is not needed in this case, we may use the second input of the first SUB. + // It is applicable to integral types only. + HSub* sub = right->AsSub(); + DCHECK(DataType::IsIntegralType(type)); + if (sub->GetLeft() == left) { + instruction->ReplaceWith(sub->GetRight()); RecordSimplification(); instruction->GetBlock()->RemoveInstruction(instruction); return; |