summaryrefslogtreecommitdiff
path: root/source/opt
diff options
context:
space:
mode:
authorArseny Kapoulkine <arseny.kapoulkine@gmail.com>2018-02-14 20:45:36 -0800
committerSteven Perron <31666470+s-perron@users.noreply.github.com>2018-02-15 10:03:22 -0500
commit32a8e04c7dd4dc7139d73b8e1081fd81e08cc66f (patch)
treecfa98206c5d3401dc3efbf29713113288b826dc1 /source/opt
parent0e9f2f948a50c02c1675765c6f847cb64139305a (diff)
downloadSPIRV-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.cpp34
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