summaryrefslogtreecommitdiff
path: root/compiler/optimizing/select_generator.cc
diff options
context:
space:
mode:
author Aart Bik <ajcbik@google.com> 2018-03-28 16:30:02 -0700
committer Aart Bik <ajcbik@google.com> 2018-03-30 11:05:01 -0700
commit1d746def1cca72979fa18ce900b248502f7cdcef (patch)
tree0123e62bd4c0a776f1ff94f6dea617485dde1b24 /compiler/optimizing/select_generator.cc
parentdd43fe71d956ca16aecf3a12d12a02dde72cfe82 (diff)
Recognize nested MIN-MAX operations.
Rationale: Prior to this CL, select optimizer and instruction simplifier were unable to deal with more than one select. This CLs improves MIN-MAX recognition by allowing select diamonds to nest deeper and by recognizing constant clipping operations. This yields better optimizable code, as shown with more saturation idioms. Bug: b/74026074 Test: test-art-host,target Change-Id: I8a616a19475f1ae87c2b5210afc76b14265bd571
Diffstat (limited to 'compiler/optimizing/select_generator.cc')
-rw-r--r--compiler/optimizing/select_generator.cc17
1 files changed, 11 insertions, 6 deletions
diff --git a/compiler/optimizing/select_generator.cc b/compiler/optimizing/select_generator.cc
index 66e51421ca..3f52bdd13c 100644
--- a/compiler/optimizing/select_generator.cc
+++ b/compiler/optimizing/select_generator.cc
@@ -43,12 +43,16 @@ static bool IsSimpleBlock(HBasicBlock* block) {
for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
HInstruction* instruction = it.Current();
if (instruction->IsControlFlow()) {
- if (num_instructions > kMaxInstructionsInBranch) {
- return false;
- }
return instruction->IsGoto() || instruction->IsReturn();
} else if (instruction->CanBeMoved() && !instruction->HasSideEffects()) {
- num_instructions++;
+ if (instruction->IsSelect() &&
+ instruction->AsSelect()->GetCondition()->GetBlock() == block) {
+ // Count one HCondition and HSelect in the same block as a single instruction.
+ // This enables finding nested selects.
+ continue;
+ } else if (++num_instructions > kMaxInstructionsInBranch) {
+ return false; // bail as soon as we exceed number of allowed instructions
+ }
} else {
return false;
}
@@ -97,6 +101,7 @@ void HSelectGenerator::Run() {
HBasicBlock* true_block = if_instruction->IfTrueSuccessor();
HBasicBlock* false_block = if_instruction->IfFalseSuccessor();
DCHECK_NE(true_block, false_block);
+
if (!IsSimpleBlock(true_block) ||
!IsSimpleBlock(false_block) ||
!BlocksMergeTogether(true_block, false_block)) {
@@ -107,10 +112,10 @@ void HSelectGenerator::Run() {
// If the branches are not empty, move instructions in front of the If.
// TODO(dbrazdil): This puts an instruction between If and its condition.
// Implement moving of conditions to first users if possible.
- if (!true_block->IsSingleGoto() && !true_block->IsSingleReturn()) {
+ while (!true_block->IsSingleGoto() && !true_block->IsSingleReturn()) {
true_block->GetFirstInstruction()->MoveBefore(if_instruction);
}
- if (!false_block->IsSingleGoto() && !false_block->IsSingleReturn()) {
+ while (!false_block->IsSingleGoto() && !false_block->IsSingleReturn()) {
false_block->GetFirstInstruction()->MoveBefore(if_instruction);
}
DCHECK(true_block->IsSingleGoto() || true_block->IsSingleReturn());