spirv-fuzz: Fix to TransformationDuplicateRegionWithSelection (#3941)
Also incorporates a few style fixes.
Fixes #3940.
diff --git a/source/fuzz/fuzzer_pass_duplicate_regions_with_selections.cpp b/source/fuzz/fuzzer_pass_duplicate_regions_with_selections.cpp
index db83daf..1651a9d 100644
--- a/source/fuzz/fuzzer_pass_duplicate_regions_with_selections.cpp
+++ b/source/fuzz/fuzzer_pass_duplicate_regions_with_selections.cpp
@@ -124,9 +124,8 @@
TransformationDuplicateRegionWithSelection(
GetFuzzerContext()->GetFreshId(), condition_id,
GetFuzzerContext()->GetFreshId(), entry_block->id(),
- exit_block->id(), std::move(original_label_to_duplicate_label),
- std::move(original_id_to_duplicate_id),
- std::move(original_id_to_phi_id));
+ exit_block->id(), original_label_to_duplicate_label,
+ original_id_to_duplicate_id, original_id_to_phi_id);
MaybeApplyTransformation(transformation);
}
}
diff --git a/source/fuzz/transformation_duplicate_region_with_selection.cpp b/source/fuzz/transformation_duplicate_region_with_selection.cpp
index 2bce558..ba701a1 100644
--- a/source/fuzz/transformation_duplicate_region_with_selection.cpp
+++ b/source/fuzz/transformation_duplicate_region_with_selection.cpp
@@ -589,6 +589,21 @@
}
});
+ opt::Instruction* merge_block_terminator = merge_block->terminator();
+ switch (merge_block_terminator->opcode()) {
+ case SpvOpReturnValue:
+ case SpvOpBranchConditional: {
+ uint32_t operand = merge_block_terminator->GetSingleWordInOperand(0);
+ if (original_id_to_phi_id.count(operand)) {
+ merge_block_terminator->SetInOperand(
+ 0, {original_id_to_phi_id.at(operand)});
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
// Insert the merge block after the |duplicated_exit_block| (the
// last duplicated block).
enclosing_function->InsertBasicBlockAfter(std::move(merge_block),
diff --git a/source/fuzz/transformation_merge_function_returns.cpp b/source/fuzz/transformation_merge_function_returns.cpp
index bdaec04..c693444 100644
--- a/source/fuzz/transformation_merge_function_returns.cpp
+++ b/source/fuzz/transformation_merge_function_returns.cpp
@@ -509,7 +509,7 @@
{SPV_OPERAND_TYPE_LOOP_CONTROL, {SpvLoopControlMaskNone}}}));
// Add conditional branch:
- // OpBranchConditional %true %block_after_entry %outer_header_id
+ // OpBranchConditional %true %block_after_entry %outer_header_id
// This will always branch to %block_after_entry, but it also creates a back
// edge for the loop (which is never traversed).
outer_loop_header->AddInstruction(MakeUnique<opt::Instruction>(
diff --git a/test/fuzz/fuzzer_replayer_test.cpp b/test/fuzz/fuzzer_replayer_test.cpp
index 43bc0b5..dc90574 100644
--- a/test/fuzz/fuzzer_replayer_test.cpp
+++ b/test/fuzz/fuzzer_replayer_test.cpp
@@ -1590,7 +1590,7 @@
%2 = OpFunction %132 None %133
%164 = OpLabel
%184 = OpLoad %15 %40
- %213 = OpLoad %38 %41
+ %213 = OpLoad %38 %41
%216 = OpSampledImage %45 %184 %213
%217 = OpImageSampleImplicitLod %76 %216 %112 Bias %55
OpReturn
diff --git a/test/fuzz/transformation_compute_data_synonym_fact_closure_test.cpp b/test/fuzz/transformation_compute_data_synonym_fact_closure_test.cpp
index 7a36c5c..995b260 100644
--- a/test/fuzz/transformation_compute_data_synonym_fact_closure_test.cpp
+++ b/test/fuzz/transformation_compute_data_synonym_fact_closure_test.cpp
@@ -45,7 +45,7 @@
// void main() {
// T myT = T(bool[5](true, false, true, false, true),
// mat4x2(vec2(1.0, 2.0), vec2(3.0, 4.0),
- // vec2(5.0, 6.0), vec2(7.0, 8.0)),
+ // vec2(5.0, 6.0), vec2(7.0, 8.0)),
// S(10, uvec2(100u, 200u)));
// }
diff --git a/test/fuzz/transformation_duplicate_region_with_selection_test.cpp b/test/fuzz/transformation_duplicate_region_with_selection_test.cpp
index 98b81f8..d4850ce 100644
--- a/test/fuzz/transformation_duplicate_region_with_selection_test.cpp
+++ b/test/fuzz/transformation_duplicate_region_with_selection_test.cpp
@@ -1904,7 +1904,7 @@
%9 = OpConstant %6 0
%16 = OpConstant %6 100
%17 = OpTypeBool
- %50 = OpConstantTrue %17
+ %50 = OpConstantTrue %17
%20 = OpConstant %6 1
%4 = OpFunction %2 None %3
%5 = OpLabel
@@ -1971,7 +1971,7 @@
%9 = OpConstant %6 0
%16 = OpConstant %6 100
%17 = OpTypeBool
- %50 = OpConstantTrue %17
+ %50 = OpConstantTrue %17
%20 = OpConstant %6 1
%4 = OpFunction %2 None %3
%5 = OpLabel
@@ -2015,6 +2015,230 @@
ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
}
+TEST(TransformationDuplicateRegionWithSelectionTest,
+ RegionExitIsOpBranchConditionalUsingBooleanDefinedInBlock) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ OpName %4 "main"
+ OpName %8 "i"
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %7 = OpTypePointer Function %6
+ %9 = OpConstant %6 0
+ %16 = OpConstant %6 100
+ %17 = OpTypeBool
+ %50 = OpConstantTrue %17
+ %20 = OpConstant %6 1
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %8 = OpVariable %7 Function
+ OpStore %8 %9
+ OpBranch %10
+ %10 = OpLabel
+ OpLoopMerge %12 %13 None
+ OpBranch %14
+ %14 = OpLabel
+ %15 = OpLoad %6 %8
+ %18 = OpSLessThan %17 %15 %16
+ OpBranchConditional %18 %11 %12
+ %11 = OpLabel
+ %19 = OpLoad %6 %8
+ %21 = OpIAdd %6 %19 %20
+ %70 = OpCopyObject %17 %50
+ OpStore %8 %21
+ OpBranchConditional %70 %13 %12
+ %13 = OpLabel
+ %22 = OpLoad %6 %8
+ %23 = OpIAdd %6 %22 %20
+ OpStore %8 %23
+ OpBranch %10
+ %12 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_4;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+
+ TransformationDuplicateRegionWithSelection transformation_good_1 =
+ TransformationDuplicateRegionWithSelection(
+ 600, 50, 601, 11, 11, {{11, 602}}, {{19, 603}, {21, 604}, {70, 608}},
+ {{19, 605}, {21, 606}, {70, 607}});
+ ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
+ transformation_context));
+ ApplyAndCheckFreshIds(transformation_good_1, context.get(),
+ &transformation_context);
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+
+ std::string expected_shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ OpName %4 "main"
+ OpName %8 "i"
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %7 = OpTypePointer Function %6
+ %9 = OpConstant %6 0
+ %16 = OpConstant %6 100
+ %17 = OpTypeBool
+ %50 = OpConstantTrue %17
+ %20 = OpConstant %6 1
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %8 = OpVariable %7 Function
+ OpStore %8 %9
+ OpBranch %10
+ %10 = OpLabel
+ OpLoopMerge %12 %13 None
+ OpBranch %14
+ %14 = OpLabel
+ %15 = OpLoad %6 %8
+ %18 = OpSLessThan %17 %15 %16
+ OpBranchConditional %18 %600 %12
+ %600 = OpLabel
+ OpSelectionMerge %601 None
+ OpBranchConditional %50 %11 %602
+ %11 = OpLabel
+ %19 = OpLoad %6 %8
+ %21 = OpIAdd %6 %19 %20
+ %70 = OpCopyObject %17 %50
+ OpStore %8 %21
+ OpBranch %601
+ %602 = OpLabel
+ %603 = OpLoad %6 %8
+ %604 = OpIAdd %6 %603 %20
+ %608 = OpCopyObject %17 %50
+ OpStore %8 %604
+ OpBranch %601
+ %601 = OpLabel
+ %605 = OpPhi %6 %19 %11 %603 %602
+ %606 = OpPhi %6 %21 %11 %604 %602
+ %607 = OpPhi %17 %70 %11 %608 %602
+ OpBranchConditional %607 %13 %12
+ %13 = OpLabel
+ %22 = OpLoad %6 %8
+ %23 = OpIAdd %6 %22 %20
+ OpStore %8 %23
+ OpBranch %10
+ %12 = OpLabel
+ OpReturn
+ OpFunctionEnd
+ )";
+
+ ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
+}
+
+TEST(TransformationDuplicateRegionWithSelectionTest,
+ RegionExitUsesOpReturnValueWithIdDefinedInRegion) {
+ std::string shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %7 = OpTypeFunction %6
+ %10 = OpConstant %6 2
+ %30 = OpTypeBool
+ %31 = OpConstantTrue %30
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %13 = OpFunctionCall %6 %8
+ OpReturn
+ OpFunctionEnd
+ %8 = OpFunction %6 None %7
+ %9 = OpLabel
+ OpBranch %20
+ %20 = OpLabel
+ %21 = OpCopyObject %6 %10
+ OpReturnValue %21
+ OpFunctionEnd
+ )";
+
+ const auto env = SPV_ENV_UNIVERSAL_1_4;
+ const auto consumer = nullptr;
+ const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
+ spvtools::ValidatorOptions validator_options;
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+ TransformationContext transformation_context(
+ MakeUnique<FactManager>(context.get()), validator_options);
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+
+ TransformationDuplicateRegionWithSelection transformation_good_1 =
+ TransformationDuplicateRegionWithSelection(
+ 600, 31, 601, 20, 20, {{20, 602}}, {{21, 603}}, {{21, 605}});
+ ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
+ transformation_context));
+ ApplyAndCheckFreshIds(transformation_good_1, context.get(),
+ &transformation_context);
+ ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
+ kConsoleMessageConsumer));
+
+ std::string expected_shader = R"(
+ OpCapability Shader
+ %1 = OpExtInstImport "GLSL.std.450"
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint Fragment %4 "main"
+ OpExecutionMode %4 OriginUpperLeft
+ OpSource ESSL 320
+ %2 = OpTypeVoid
+ %3 = OpTypeFunction %2
+ %6 = OpTypeInt 32 1
+ %7 = OpTypeFunction %6
+ %10 = OpConstant %6 2
+ %30 = OpTypeBool
+ %31 = OpConstantTrue %30
+ %4 = OpFunction %2 None %3
+ %5 = OpLabel
+ %13 = OpFunctionCall %6 %8
+ OpReturn
+ OpFunctionEnd
+ %8 = OpFunction %6 None %7
+ %9 = OpLabel
+ OpBranch %600
+ %600 = OpLabel
+ OpSelectionMerge %601 None
+ OpBranchConditional %31 %20 %602
+ %20 = OpLabel
+ %21 = OpCopyObject %6 %10
+ OpBranch %601
+ %602 = OpLabel
+ %603 = OpCopyObject %6 %10
+ OpBranch %601
+ %601 = OpLabel
+ %605 = OpPhi %6 %21 %20 %603 %602
+ OpReturnValue %605
+ OpFunctionEnd
+ )";
+
+ ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
+}
+
} // namespace
} // namespace fuzz
} // namespace spvtools