mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-18 11:10:05 +00:00
spirv-fuzz: Fix to transformation that adds a synonym via a loop (#3898)
Fixes #3897.
This commit is contained in:
parent
4b884928db
commit
2e6cf706ee
@ -932,7 +932,7 @@ message TransformationAddLoopToCreateIntConstantSynonym {
|
||||
// A transformation that uses a loop to create a synonym for an integer
|
||||
// constant C (scalar or vector) using an initial value I, a step value S and
|
||||
// a number of iterations N such that C = I - N * S. For each iteration, S is
|
||||
// added to the total.
|
||||
// subtracted from the total.
|
||||
// The loop can be made up of one or two blocks, and it is inserted before a
|
||||
// block with a single predecessor. In the one-block case, it is of the form:
|
||||
//
|
||||
@ -942,7 +942,7 @@ message TransformationAddLoopToCreateIntConstantSynonym {
|
||||
// %eventual_syn_id = OpISub %type_of_I %temp_id %step_val_id
|
||||
// %incremented_ctr_id = OpIAdd %int %ctr_id %int_1
|
||||
// %cond_id = OpSLessThan %bool %incremented_ctr_id %num_iterations_id
|
||||
// OpLoopMerge %block_after_loop_id %loop_id %none
|
||||
// OpLoopMerge %block_after_loop_id %loop_id None
|
||||
// OpBranchConditional %cond_id %loop_id %block_after_loop_id
|
||||
//
|
||||
// A new OpPhi instruction is then added to %block_after_loop_id, as follows:
|
||||
|
@ -387,12 +387,12 @@ void TransformationAddLoopToCreateIntConstantSynonym::Apply(
|
||||
[this](opt::Instruction* instruction, uint32_t operand_index) {
|
||||
assert(instruction->opcode() != SpvOpLoopMerge &&
|
||||
instruction->opcode() != SpvOpSelectionMerge &&
|
||||
instruction->opcode() != SpvOpSwitch &&
|
||||
"The block should not be referenced by OpLoopMerge, "
|
||||
"OpSelectionMerge or OpSwitch instructions, by construction.");
|
||||
"The block should not be referenced by OpLoopMerge or "
|
||||
"OpSelectionMerge, by construction.");
|
||||
// Replace all uses of the label inside branch instructions.
|
||||
if (instruction->opcode() == SpvOpBranch ||
|
||||
instruction->opcode() == SpvOpBranchConditional) {
|
||||
instruction->opcode() == SpvOpBranchConditional ||
|
||||
instruction->opcode() == SpvOpSwitch) {
|
||||
instruction->SetOperand(operand_index, {message_.loop_id()});
|
||||
}
|
||||
});
|
||||
|
@ -1021,6 +1021,113 @@ TEST(TransformationAddLoopToCreateIntConstantSynonymTest,
|
||||
.IsApplicable(context.get(), transformation_context));
|
||||
}
|
||||
|
||||
TEST(TransformationAddLoopToCreateIntConstantSynonymTest, InserBeforeOpSwitch) {
|
||||
// Checks that it is acceptable for a loop to be added before a target of an
|
||||
// OpSwitch instruction.
|
||||
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 = OpConstant %6 0
|
||||
%20 = OpConstant %6 1
|
||||
%21 = OpConstant %6 2
|
||||
%22 = OpTypeBool
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
OpSelectionMerge %10 None
|
||||
OpSwitch %7 %9 0 %8
|
||||
%9 = OpLabel
|
||||
OpBranch %10
|
||||
%8 = OpLabel
|
||||
OpBranch %10
|
||||
%10 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const auto env = SPV_ENV_UNIVERSAL_1_5;
|
||||
const auto consumer = nullptr;
|
||||
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
spvtools::ValidatorOptions validator_options;
|
||||
TransformationContext transformation_context(
|
||||
MakeUnique<FactManager>(context.get()), validator_options);
|
||||
|
||||
auto transformation1 = TransformationAddLoopToCreateIntConstantSynonym(
|
||||
20, 21, 20, 20, 9, 100, 101, 102, 103, 104, 105, 106, 0);
|
||||
ASSERT_TRUE(
|
||||
transformation1.IsApplicable(context.get(), transformation_context));
|
||||
ApplyAndCheckFreshIds(transformation1, context.get(),
|
||||
&transformation_context);
|
||||
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
|
||||
MakeDataDescriptor(20, {}), MakeDataDescriptor(100, {})));
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
auto transformation2 = TransformationAddLoopToCreateIntConstantSynonym(
|
||||
20, 21, 20, 20, 8, 200, 201, 202, 203, 204, 205, 206, 0);
|
||||
ASSERT_TRUE(
|
||||
transformation2.IsApplicable(context.get(), transformation_context));
|
||||
ApplyAndCheckFreshIds(transformation2, context.get(),
|
||||
&transformation_context);
|
||||
ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
|
||||
MakeDataDescriptor(20, {}), MakeDataDescriptor(200, {})));
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
std::string after_transformations = 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 = OpConstant %6 0
|
||||
%20 = OpConstant %6 1
|
||||
%21 = OpConstant %6 2
|
||||
%22 = OpTypeBool
|
||||
%4 = OpFunction %2 None %3
|
||||
%5 = OpLabel
|
||||
OpSelectionMerge %10 None
|
||||
OpSwitch %7 %101 0 %201
|
||||
%101 = OpLabel
|
||||
%102 = OpPhi %6 %7 %5 %105 %101
|
||||
%103 = OpPhi %6 %21 %5 %104 %101
|
||||
%104 = OpISub %6 %103 %20
|
||||
%105 = OpIAdd %6 %102 %20
|
||||
%106 = OpSLessThan %22 %105 %20
|
||||
OpLoopMerge %9 %101 None
|
||||
OpBranchConditional %106 %101 %9
|
||||
%9 = OpLabel
|
||||
%100 = OpPhi %6 %104 %101
|
||||
OpBranch %10
|
||||
%201 = OpLabel
|
||||
%202 = OpPhi %6 %7 %5 %205 %201
|
||||
%203 = OpPhi %6 %21 %5 %204 %201
|
||||
%204 = OpISub %6 %203 %20
|
||||
%205 = OpIAdd %6 %202 %20
|
||||
%206 = OpSLessThan %22 %205 %20
|
||||
OpLoopMerge %8 %201 None
|
||||
OpBranchConditional %206 %201 %8
|
||||
%8 = OpLabel
|
||||
%200 = OpPhi %6 %204 %201
|
||||
OpBranch %10
|
||||
%10 = OpLabel
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
ASSERT_TRUE(IsEqual(env, after_transformations, context.get()));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
Loading…
Reference in New Issue
Block a user