diff options
author | 2018-03-28 16:30:02 -0700 | |
---|---|---|
committer | 2018-03-30 11:05:01 -0700 | |
commit | 1d746def1cca72979fa18ce900b248502f7cdcef (patch) | |
tree | 0123e62bd4c0a776f1ff94f6dea617485dde1b24 /compiler/optimizing/select_generator.cc | |
parent | dd43fe71d956ca16aecf3a12d12a02dde72cfe82 (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.cc | 17 |
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()); |