summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/3rdparty/spirv-tools/source/opt/folding_rules.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/bgfx/3rdparty/spirv-tools/source/opt/folding_rules.cpp')
-rw-r--r--3rdparty/bgfx/3rdparty/spirv-tools/source/opt/folding_rules.cpp131
1 files changed, 116 insertions, 15 deletions
diff --git a/3rdparty/bgfx/3rdparty/spirv-tools/source/opt/folding_rules.cpp b/3rdparty/bgfx/3rdparty/spirv-tools/source/opt/folding_rules.cpp
index d2d029d73e5..eea723820e7 100644
--- a/3rdparty/bgfx/3rdparty/spirv-tools/source/opt/folding_rules.cpp
+++ b/3rdparty/bgfx/3rdparty/spirv-tools/source/opt/folding_rules.cpp
@@ -18,6 +18,7 @@
#include <memory>
#include <utility>
+#include "ir_builder.h"
#include "source/latest_version_glsl_std_450_header.h"
#include "source/opt/ir_context.h"
@@ -1239,6 +1240,117 @@ FoldingRule MergeSubSubArithmetic() {
};
}
+// Helper function for MergeGenericAddSubArithmetic. If |addend| and
+// subtrahend of |sub| is the same, merge to copy of minuend of |sub|.
+bool MergeGenericAddendSub(uint32_t addend, uint32_t sub, Instruction* inst) {
+ IRContext* context = inst->context();
+ analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
+ Instruction* sub_inst = def_use_mgr->GetDef(sub);
+ if (sub_inst->opcode() != SpvOpFSub && sub_inst->opcode() != SpvOpISub)
+ return false;
+ if (sub_inst->opcode() == SpvOpFSub &&
+ !sub_inst->IsFloatingPointFoldingAllowed())
+ return false;
+ if (addend != sub_inst->GetSingleWordInOperand(1)) return false;
+ inst->SetOpcode(SpvOpCopyObject);
+ inst->SetInOperands(
+ {{SPV_OPERAND_TYPE_ID, {sub_inst->GetSingleWordInOperand(0)}}});
+ context->UpdateDefUse(inst);
+ return true;
+}
+
+// Folds addition of a subtraction where the subtrahend is equal to the
+// other addend. Return a copy of the minuend. Accepts generic (const and
+// non-const) operands.
+// Cases:
+// (a - b) + b = a
+// b + (a - b) = a
+FoldingRule MergeGenericAddSubArithmetic() {
+ return [](IRContext* context, Instruction* inst,
+ const std::vector<const analysis::Constant*>&) {
+ assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd);
+ const analysis::Type* type =
+ context->get_type_mgr()->GetType(inst->type_id());
+ bool uses_float = HasFloatingPoint(type);
+ if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false;
+
+ uint32_t width = ElementWidth(type);
+ if (width != 32 && width != 64) return false;
+
+ uint32_t add_op0 = inst->GetSingleWordInOperand(0);
+ uint32_t add_op1 = inst->GetSingleWordInOperand(1);
+ if (MergeGenericAddendSub(add_op0, add_op1, inst)) return true;
+ return MergeGenericAddendSub(add_op1, add_op0, inst);
+ };
+}
+
+// Helper function for FactorAddMuls. If |factor0_0| is the same as |factor1_0|,
+// generate |factor0_0| * (|factor0_1| + |factor1_1|).
+bool FactorAddMulsOpnds(uint32_t factor0_0, uint32_t factor0_1,
+ uint32_t factor1_0, uint32_t factor1_1,
+ Instruction* inst) {
+ IRContext* context = inst->context();
+ if (factor0_0 != factor1_0) return false;
+ InstructionBuilder ir_builder(
+ context, inst,
+ IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
+ Instruction* new_add_inst = ir_builder.AddBinaryOp(
+ inst->type_id(), inst->opcode(), factor0_1, factor1_1);
+ inst->SetOpcode(inst->opcode() == SpvOpFAdd ? SpvOpFMul : SpvOpIMul);
+ inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {factor0_0}},
+ {SPV_OPERAND_TYPE_ID, {new_add_inst->result_id()}}});
+ context->UpdateDefUse(inst);
+ return true;
+}
+
+// Perform the following factoring identity, handling all operand order
+// combinations: (a * b) + (a * c) = a * (b + c)
+FoldingRule FactorAddMuls() {
+ return [](IRContext* context, Instruction* inst,
+ const std::vector<const analysis::Constant*>&) {
+ assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd);
+ const analysis::Type* type =
+ context->get_type_mgr()->GetType(inst->type_id());
+ bool uses_float = HasFloatingPoint(type);
+ if (uses_float && !inst->IsFloatingPointFoldingAllowed()) return false;
+
+ analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
+ uint32_t add_op0 = inst->GetSingleWordInOperand(0);
+ Instruction* add_op0_inst = def_use_mgr->GetDef(add_op0);
+ if (add_op0_inst->opcode() != SpvOpFMul &&
+ add_op0_inst->opcode() != SpvOpIMul)
+ return false;
+ uint32_t add_op1 = inst->GetSingleWordInOperand(1);
+ Instruction* add_op1_inst = def_use_mgr->GetDef(add_op1);
+ if (add_op1_inst->opcode() != SpvOpFMul &&
+ add_op1_inst->opcode() != SpvOpIMul)
+ return false;
+
+ // Only perform this optimization if both of the muls only have one use.
+ // Otherwise this is a deoptimization in size and performance.
+ if (def_use_mgr->NumUses(add_op0_inst) > 1) return false;
+ if (def_use_mgr->NumUses(add_op1_inst) > 1) return false;
+
+ if (add_op0_inst->opcode() == SpvOpFMul &&
+ (!add_op0_inst->IsFloatingPointFoldingAllowed() ||
+ !add_op1_inst->IsFloatingPointFoldingAllowed()))
+ return false;
+
+ for (int i = 0; i < 2; i++) {
+ for (int j = 0; j < 2; j++) {
+ // Check if operand i in add_op0_inst matches operand j in add_op1_inst.
+ if (FactorAddMulsOpnds(add_op0_inst->GetSingleWordInOperand(i),
+ add_op0_inst->GetSingleWordInOperand(1 - i),
+ add_op1_inst->GetSingleWordInOperand(j),
+ add_op1_inst->GetSingleWordInOperand(1 - j),
+ inst))
+ return true;
+ }
+ }
+ return false;
+ };
+}
+
FoldingRule IntMultipleBy1() {
return [](IRContext*, Instruction* inst,
const std::vector<const analysis::Constant*>& constants) {
@@ -1407,20 +1519,6 @@ FoldingRule CompositeExtractFeedingConstruct() {
};
}
-// Folds an OpCompositeExtract instruction with no indexes into an OpCopyObject.
-bool ExtractWithNoIndexes(IRContext*, Instruction* inst,
- const std::vector<const analysis::Constant*>&) {
- assert(inst->opcode() == SpvOpCompositeExtract &&
- "Wrong opcode. Should be OpCompositeExtract.");
-
- if (inst->NumInOperands() > 1) {
- return false;
- }
-
- inst->SetOpcode(SpvOpCopyObject);
- return true;
-}
-
FoldingRule InsertFeedingExtract() {
return [](IRContext* context, Instruction* inst,
const std::vector<const analysis::Constant*>&) {
@@ -2227,7 +2325,6 @@ void FoldingRules::AddFoldingRules() {
// Take that into consideration.
rules_[SpvOpCompositeConstruct].push_back(CompositeExtractFeedingConstruct());
- rules_[SpvOpCompositeExtract].push_back(ExtractWithNoIndexes);
rules_[SpvOpCompositeExtract].push_back(InsertFeedingExtract());
rules_[SpvOpCompositeExtract].push_back(CompositeConstructFeedingExtract());
rules_[SpvOpCompositeExtract].push_back(VectorShuffleFeedingExtract());
@@ -2241,6 +2338,8 @@ void FoldingRules::AddFoldingRules() {
rules_[SpvOpFAdd].push_back(MergeAddNegateArithmetic());
rules_[SpvOpFAdd].push_back(MergeAddAddArithmetic());
rules_[SpvOpFAdd].push_back(MergeAddSubArithmetic());
+ rules_[SpvOpFAdd].push_back(MergeGenericAddSubArithmetic());
+ rules_[SpvOpFAdd].push_back(FactorAddMuls());
rules_[SpvOpFDiv].push_back(RedundantFDiv());
rules_[SpvOpFDiv].push_back(ReciprocalFDiv());
@@ -2266,6 +2365,8 @@ void FoldingRules::AddFoldingRules() {
rules_[SpvOpIAdd].push_back(MergeAddNegateArithmetic());
rules_[SpvOpIAdd].push_back(MergeAddAddArithmetic());
rules_[SpvOpIAdd].push_back(MergeAddSubArithmetic());
+ rules_[SpvOpIAdd].push_back(MergeGenericAddSubArithmetic());
+ rules_[SpvOpIAdd].push_back(FactorAddMuls());
rules_[SpvOpIMul].push_back(IntMultipleBy1());
rules_[SpvOpIMul].push_back(MergeMulMulArithmetic());