diff options
author | Arseny Kapoulkine <arseny.kapoulkine@gmail.com> | 2018-02-14 20:45:36 -0800 |
---|---|---|
committer | Steven Perron <31666470+s-perron@users.noreply.github.com> | 2018-02-15 10:03:22 -0500 |
commit | 32a8e04c7dd4dc7139d73b8e1081fd81e08cc66f (patch) | |
tree | cfa98206c5d3401dc3efbf29713113288b826dc1 /source/opt | |
parent | 0e9f2f948a50c02c1675765c6f847cb64139305a (diff) | |
download | SPIRV-Tools-32a8e04c7dd4dc7139d73b8e1081fd81e08cc66f.tar.gz SPIRV-Tools-32a8e04c7dd4dc7139d73b8e1081fd81e08cc66f.tar.bz2 SPIRV-Tools-32a8e04c7dd4dc7139d73b8e1081fd81e08cc66f.zip |
Add folding of redundant OpSelect insns
We can fold OpSelect into one of the operands in two cases:
- condition is constant
- both results are the same
Even if the original shader doesn't have either of these, if-conversion
pass sometimes ends up generating instructions like
%7127 = OpSelect %int %3220 %7058 %7058
And this optimization cleans them up.
Diffstat (limited to 'source/opt')
-rw-r--r-- | source/opt/folding_rules.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/source/opt/folding_rules.cpp b/source/opt/folding_rules.cpp index 4762e750..10208bdb 100644 --- a/source/opt/folding_rules.cpp +++ b/source/opt/folding_rules.cpp @@ -294,6 +294,38 @@ FoldingRule RedundantPhi() { return true; }; } + +FoldingRule RedundantSelect() { + // An OpSelect instruction where both values are the same or the condition is + // constant can be replaced by one of the values + return [](ir::Instruction* inst, + const std::vector<const analysis::Constant*>& constants) { + assert(inst->opcode() == SpvOpSelect && + "Wrong opcode. Should be OpSelect."); + assert(inst->NumInOperands() == 3); + assert(constants.size() == 3); + + const analysis::BoolConstant* bc = + constants[0] ? constants[0]->AsBoolConstant() : nullptr; + uint32_t true_id = inst->GetSingleWordInOperand(1); + uint32_t false_id = inst->GetSingleWordInOperand(2); + + if (bc) { + // Select condition is constant, result is known + inst->SetOpcode(SpvOpCopyObject); + inst->SetInOperands( + {{SPV_OPERAND_TYPE_ID, {bc->value() ? true_id : false_id}}}); + return true; + } else if (true_id == false_id) { + // Both results are the same, condition doesn't matter + inst->SetOpcode(SpvOpCopyObject); + inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {true_id}}}); + return true; + } else { + return false; + } + }; +} } // namespace spvtools::opt::FoldingRules::FoldingRules() { @@ -310,6 +342,8 @@ spvtools::opt::FoldingRules::FoldingRules() { rules_[SpvOpIMul].push_back(IntMultipleBy1()); rules_[SpvOpPhi].push_back(RedundantPhi()); + + rules_[SpvOpSelect].push_back(RedundantSelect()); } } // namespace opt } // namespace spvtools |