Merge changes I988caf15,I62185327
* changes:
Update SPIR-V Tools to b930e734e
Squashed 'third_party/SPIRV-Tools/' changes from 82d91083c..b930e734e
diff --git a/third_party/SPIRV-Tools/CHANGES b/third_party/SPIRV-Tools/CHANGES
index 7984461..f5e91cb 100644
--- a/third_party/SPIRV-Tools/CHANGES
+++ b/third_party/SPIRV-Tools/CHANGES
@@ -1,7 +1,20 @@
Revision history for SPIRV-Tools
-v2022.3-dev 2022-04-07
- - Start v2022.3-dev
+v2022.3-dev 2022-05-31
+ - General
+ - Add SPV_KHR_fragment_shader_barycentric support (#4805)
+ - Add support for SPV_KHR_subgroup_rotate (#4786)
+ - Optimizer
+ - Fold multiply and subtraction into FMA with negation (#4808)
+ - Add more folding for composite instructions (#4802)
+ - spirv-opt: add pass for interface variable scalar replacement (#4779)
+ - Don't try to unroll loop with step count 0. (#4769)
+ - Validator
+ - spirv-val: Add PerVertexKHR (#4807)
+ - spirv-opt : Add FixFuncCallArgumentsPass (#4775)
+ - spirv-val: Add CullMaskKHR support (#4792)
+ - Linker
+ - linker: Recalculate interface variables (#4784)
v2022.2 2022-04-07
- General
diff --git a/third_party/SPIRV-Tools/DEPS b/third_party/SPIRV-Tools/DEPS
index abc3a76..808ef6c 100644
--- a/third_party/SPIRV-Tools/DEPS
+++ b/third_party/SPIRV-Tools/DEPS
@@ -4,9 +4,9 @@
'github': 'https://github.com',
'effcee_revision': 'ddf5e2bb92957dc8a12c5392f8495333d6844133',
- 'googletest_revision': '25dcdc7e8bfac8967f20fb2c0a628f5cf442188d',
- 're2_revision': '0c5616df9c0aaa44c9440d87422012423d91c7d1',
- 'spirv_headers_revision': 'b765c355f488837ca4c77980ba69484f3ff277f5',
+ 'googletest_revision': '548b13dc3c02b93f60eeff9a0cc6e11c1ea722ca',
+ 're2_revision': '5723bb8950318135ed9cf4fc76bed988a087f536',
+ 'spirv_headers_revision': '5a121866927a16ab9d49bed4788b532c7fcea766',
}
deps = {
diff --git a/third_party/SPIRV-Tools/source/opt/folding_rules.cpp b/third_party/SPIRV-Tools/source/opt/folding_rules.cpp
index ab7a20e..0d8f7c8 100644
--- a/third_party/SPIRV-Tools/source/opt/folding_rules.cpp
+++ b/third_party/SPIRV-Tools/source/opt/folding_rules.cpp
@@ -1488,6 +1488,74 @@
return false;
}
+// Replaces |sub| inplace with an FMA instruction |(x*y)+a| where |a| first gets
+// negated if |negate_addition| is true, otherwise |x| gets negated.
+void ReplaceWithFmaAndNegate(Instruction* sub, uint32_t x, uint32_t y,
+ uint32_t a, bool negate_addition) {
+ uint32_t ext =
+ sub->context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450();
+
+ if (ext == 0) {
+ sub->context()->AddExtInstImport("GLSL.std.450");
+ ext = sub->context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450();
+ assert(ext != 0 &&
+ "Could not add the GLSL.std.450 extended instruction set");
+ }
+
+ InstructionBuilder ir_builder(
+ sub->context(), sub,
+ IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
+
+ Instruction* neg = ir_builder.AddUnaryOp(sub->type_id(), SpvOpFNegate,
+ negate_addition ? a : x);
+ uint32_t neg_op = neg->result_id(); // -a : -x
+
+ std::vector<Operand> operands;
+ operands.push_back({SPV_OPERAND_TYPE_ID, {ext}});
+ operands.push_back({SPV_OPERAND_TYPE_LITERAL_INTEGER, {GLSLstd450Fma}});
+ operands.push_back({SPV_OPERAND_TYPE_ID, {negate_addition ? x : neg_op}});
+ operands.push_back({SPV_OPERAND_TYPE_ID, {y}});
+ operands.push_back({SPV_OPERAND_TYPE_ID, {negate_addition ? neg_op : a}});
+
+ sub->SetOpcode(SpvOpExtInst);
+ sub->SetInOperands(std::move(operands));
+}
+
+// Folds a multiply and subtract into an Fma and negation.
+//
+// Cases:
+// (x * y) - a = Fma x y -a
+// a - (x * y) = Fma -x y a
+bool MergeMulSubArithmetic(IRContext* context, Instruction* sub,
+ const std::vector<const analysis::Constant*>&) {
+ assert(sub->opcode() == SpvOpFSub);
+
+ if (!sub->IsFloatingPointFoldingAllowed()) {
+ return false;
+ }
+
+ analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
+ for (int i = 0; i < 2; i++) {
+ uint32_t op_id = sub->GetSingleWordInOperand(i);
+ Instruction* mul = def_use_mgr->GetDef(op_id);
+
+ if (mul->opcode() != SpvOpFMul) {
+ continue;
+ }
+
+ if (!mul->IsFloatingPointFoldingAllowed()) {
+ continue;
+ }
+
+ uint32_t x = mul->GetSingleWordInOperand(0);
+ uint32_t y = mul->GetSingleWordInOperand(1);
+ uint32_t a = sub->GetSingleWordInOperand((i + 1) % 2);
+ ReplaceWithFmaAndNegate(sub, x, y, a, i == 0);
+ return true;
+ }
+ return false;
+}
+
FoldingRule IntMultipleBy1() {
return [](IRContext*, Instruction* inst,
const std::vector<const analysis::Constant*>& constants) {
@@ -2831,6 +2899,7 @@
rules_[SpvOpFSub].push_back(MergeSubNegateArithmetic());
rules_[SpvOpFSub].push_back(MergeSubAddArithmetic());
rules_[SpvOpFSub].push_back(MergeSubSubArithmetic());
+ rules_[SpvOpFSub].push_back(MergeMulSubArithmetic);
rules_[SpvOpIAdd].push_back(RedundantIAdd());
rules_[SpvOpIAdd].push_back(MergeAddNegateArithmetic());
diff --git a/third_party/SPIRV-Tools/test/opt/fold_test.cpp b/third_party/SPIRV-Tools/test/opt/fold_test.cpp
index e2240b8..8ee14a9 100644
--- a/third_party/SPIRV-Tools/test/opt/fold_test.cpp
+++ b/third_party/SPIRV-Tools/test/opt/fold_test.cpp
@@ -7359,7 +7359,7 @@
"OpReturn\n" +
"OpFunctionEnd",
3, true),
- // Test 5: that the OpExtInstImport instruction is generated if it is missing.
+ // Test 4: that the OpExtInstImport instruction is generated if it is missing.
InstructionFoldingCase<bool>(
std::string() +
"; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
@@ -7454,7 +7454,63 @@
"OpStore %a %3\n" +
"OpReturn\n" +
"OpFunctionEnd",
- 3, false)
+ 3, false),
+ // Test case 7: (x * y) - a = Fma(x, y, -a)
+ InstructionFoldingCase<bool>(
+ Header() +
+ "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
+ "; CHECK: OpFunction\n" +
+ "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
+ "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
+ "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
+ "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
+ "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
+ "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
+ "; CHECK: [[na:%\\w+]] = OpFNegate {{%\\w+}} [[la]]\n" +
+ "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[lx]] [[ly]] [[na]]\n" +
+ "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
+ "%main = OpFunction %void None %void_func\n" +
+ "%main_lab = OpLabel\n" +
+ "%x = OpVariable %_ptr_float Function\n" +
+ "%y = OpVariable %_ptr_float Function\n" +
+ "%a = OpVariable %_ptr_float Function\n" +
+ "%lx = OpLoad %float %x\n" +
+ "%ly = OpLoad %float %y\n" +
+ "%mul = OpFMul %float %lx %ly\n" +
+ "%la = OpLoad %float %a\n" +
+ "%3 = OpFSub %float %mul %la\n" +
+ "OpStore %a %3\n" +
+ "OpReturn\n" +
+ "OpFunctionEnd",
+ 3, true),
+ // Test case 8: a - (x * y) = Fma(-x, y, a)
+ InstructionFoldingCase<bool>(
+ Header() +
+ "; CHECK: [[ext:%\\w+]] = OpExtInstImport \"GLSL.std.450\"\n" +
+ "; CHECK: OpFunction\n" +
+ "; CHECK: [[x:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
+ "; CHECK: [[y:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
+ "; CHECK: [[a:%\\w+]] = OpVariable {{%\\w+}} Function\n" +
+ "; CHECK: [[lx:%\\w+]] = OpLoad {{%\\w+}} [[x]]\n" +
+ "; CHECK: [[ly:%\\w+]] = OpLoad {{%\\w+}} [[y]]\n" +
+ "; CHECK: [[la:%\\w+]] = OpLoad {{%\\w+}} [[a]]\n" +
+ "; CHECK: [[nx:%\\w+]] = OpFNegate {{%\\w+}} [[lx]]\n" +
+ "; CHECK: [[fma:%\\w+]] = OpExtInst {{%\\w+}} [[ext]] Fma [[nx]] [[ly]] [[la]]\n" +
+ "; CHECK: OpStore {{%\\w+}} [[fma]]\n" +
+ "%main = OpFunction %void None %void_func\n" +
+ "%main_lab = OpLabel\n" +
+ "%x = OpVariable %_ptr_float Function\n" +
+ "%y = OpVariable %_ptr_float Function\n" +
+ "%a = OpVariable %_ptr_float Function\n" +
+ "%lx = OpLoad %float %x\n" +
+ "%ly = OpLoad %float %y\n" +
+ "%mul = OpFMul %float %lx %ly\n" +
+ "%la = OpLoad %float %a\n" +
+ "%3 = OpFSub %float %la %mul\n" +
+ "OpStore %a %3\n" +
+ "OpReturn\n" +
+ "OpFunctionEnd",
+ 3, true)
));
using MatchingInstructionWithNoResultFoldingTest =