mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-25 01:01:04 +00:00
Implement transformation to record synonymous constants. (#3494)
Adds a fact-only transformation that records that two constants in the module are synonymous.
This commit is contained in:
parent
94667fbf66
commit
5f8cdd8b45
@ -128,6 +128,7 @@ if(SPIRV_BUILD_FUZZER)
|
|||||||
transformation_permute_function_parameters.h
|
transformation_permute_function_parameters.h
|
||||||
transformation_permute_phi_operands.h
|
transformation_permute_phi_operands.h
|
||||||
transformation_push_id_through_variable.h
|
transformation_push_id_through_variable.h
|
||||||
|
transformation_record_synonymous_constants.h
|
||||||
transformation_replace_boolean_constant_with_constant_binary.h
|
transformation_replace_boolean_constant_with_constant_binary.h
|
||||||
transformation_replace_constant_with_uniform.h
|
transformation_replace_constant_with_uniform.h
|
||||||
transformation_replace_id_with_synonym.h
|
transformation_replace_id_with_synonym.h
|
||||||
@ -243,6 +244,7 @@ if(SPIRV_BUILD_FUZZER)
|
|||||||
transformation_permute_function_parameters.cpp
|
transformation_permute_function_parameters.cpp
|
||||||
transformation_permute_phi_operands.cpp
|
transformation_permute_phi_operands.cpp
|
||||||
transformation_push_id_through_variable.cpp
|
transformation_push_id_through_variable.cpp
|
||||||
|
transformation_record_synonymous_constants.cpp
|
||||||
transformation_replace_boolean_constant_with_constant_binary.cpp
|
transformation_replace_boolean_constant_with_constant_binary.cpp
|
||||||
transformation_replace_constant_with_uniform.cpp
|
transformation_replace_constant_with_uniform.cpp
|
||||||
transformation_replace_id_with_synonym.cpp
|
transformation_replace_id_with_synonym.cpp
|
||||||
|
@ -385,6 +385,7 @@ message Transformation {
|
|||||||
TransformationInvertComparisonOperator invert_comparison_operator = 54;
|
TransformationInvertComparisonOperator invert_comparison_operator = 54;
|
||||||
TransformationAddImageSampleUnusedComponents add_image_sample_unused_components = 55;
|
TransformationAddImageSampleUnusedComponents add_image_sample_unused_components = 55;
|
||||||
TransformationReplaceParameterWithGlobal replace_parameter_with_global = 56;
|
TransformationReplaceParameterWithGlobal replace_parameter_with_global = 56;
|
||||||
|
TransformationRecordSynonymousConstants record_synonymous_constants = 57;
|
||||||
// Add additional option using the next available number.
|
// Add additional option using the next available number.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1123,6 +1124,26 @@ message TransformationPushIdThroughVariable {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message TransformationRecordSynonymousConstants {
|
||||||
|
|
||||||
|
// A transformation that, given the IDs to two synonymous constants,
|
||||||
|
// records the fact that they are synonymous. The module is not changed.
|
||||||
|
// Two constants are synonymous if:
|
||||||
|
// - they have the same type (ignoring the presence of integer sign)
|
||||||
|
// - they have the same opcode (one of OpConstant, OpConstantTrue,
|
||||||
|
// OpConstantFalse, OpConstantNull)
|
||||||
|
// - they have the same value
|
||||||
|
// If the types are the same, OpConstantNull is equivalent to
|
||||||
|
// OpConstantFalse or OpConstant with value zero.
|
||||||
|
|
||||||
|
// The id of a constant
|
||||||
|
uint32 constant1_id = 1;
|
||||||
|
|
||||||
|
// The id of the synonym
|
||||||
|
uint32 constant2_id = 2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
message TransformationReplaceParameterWithGlobal {
|
message TransformationReplaceParameterWithGlobal {
|
||||||
|
|
||||||
// Removes parameter with result id |parameter_id| from its function
|
// Removes parameter with result id |parameter_id| from its function
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
#include "source/fuzz/transformation_permute_function_parameters.h"
|
#include "source/fuzz/transformation_permute_function_parameters.h"
|
||||||
#include "source/fuzz/transformation_permute_phi_operands.h"
|
#include "source/fuzz/transformation_permute_phi_operands.h"
|
||||||
#include "source/fuzz/transformation_push_id_through_variable.h"
|
#include "source/fuzz/transformation_push_id_through_variable.h"
|
||||||
|
#include "source/fuzz/transformation_record_synonymous_constants.h"
|
||||||
#include "source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h"
|
#include "source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h"
|
||||||
#include "source/fuzz/transformation_replace_constant_with_uniform.h"
|
#include "source/fuzz/transformation_replace_constant_with_uniform.h"
|
||||||
#include "source/fuzz/transformation_replace_id_with_synonym.h"
|
#include "source/fuzz/transformation_replace_id_with_synonym.h"
|
||||||
@ -194,6 +195,10 @@ std::unique_ptr<Transformation> Transformation::FromMessage(
|
|||||||
case protobufs::Transformation::TransformationCase::kPushIdThroughVariable:
|
case protobufs::Transformation::TransformationCase::kPushIdThroughVariable:
|
||||||
return MakeUnique<TransformationPushIdThroughVariable>(
|
return MakeUnique<TransformationPushIdThroughVariable>(
|
||||||
message.push_id_through_variable());
|
message.push_id_through_variable());
|
||||||
|
case protobufs::Transformation::TransformationCase::
|
||||||
|
kRecordSynonymousConstants:
|
||||||
|
return MakeUnique<TransformationRecordSynonymousConstants>(
|
||||||
|
message.record_synonymous_constants());
|
||||||
case protobufs::Transformation::TransformationCase::
|
case protobufs::Transformation::TransformationCase::
|
||||||
kReplaceParameterWithGlobal:
|
kReplaceParameterWithGlobal:
|
||||||
return MakeUnique<TransformationReplaceParameterWithGlobal>(
|
return MakeUnique<TransformationReplaceParameterWithGlobal>(
|
||||||
|
107
source/fuzz/transformation_record_synonymous_constants.cpp
Normal file
107
source/fuzz/transformation_record_synonymous_constants.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// Copyright (c) 2020 Stefano Milizia
|
||||||
|
// Copyright (c) 2020 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "transformation_record_synonymous_constants.h"
|
||||||
|
|
||||||
|
namespace spvtools {
|
||||||
|
namespace fuzz {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
bool IsScalarZeroConstant(const opt::analysis::Constant* constant) {
|
||||||
|
return constant->AsScalarConstant() && constant->IsZero();
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TransformationRecordSynonymousConstants::
|
||||||
|
TransformationRecordSynonymousConstants(
|
||||||
|
const protobufs::TransformationRecordSynonymousConstants& message)
|
||||||
|
: message_(message) {}
|
||||||
|
|
||||||
|
TransformationRecordSynonymousConstants::
|
||||||
|
TransformationRecordSynonymousConstants(uint32_t constant1_id,
|
||||||
|
uint32_t constant2_id) {
|
||||||
|
message_.set_constant1_id(constant1_id);
|
||||||
|
message_.set_constant2_id(constant2_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TransformationRecordSynonymousConstants::IsApplicable(
|
||||||
|
opt::IRContext* ir_context,
|
||||||
|
const TransformationContext& /* unused */) const {
|
||||||
|
// The ids must be different
|
||||||
|
if (message_.constant1_id() == message_.constant2_id()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto constant1 = ir_context->get_constant_mgr()->FindDeclaredConstant(
|
||||||
|
message_.constant1_id());
|
||||||
|
auto constant2 = ir_context->get_constant_mgr()->FindDeclaredConstant(
|
||||||
|
message_.constant2_id());
|
||||||
|
|
||||||
|
// The constants must exist
|
||||||
|
if (constant1 == nullptr || constant2 == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the constants are equal, then they are equivalent
|
||||||
|
if (constant1 == constant2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the constants are two integers (signed or unsigned), they are equal
|
||||||
|
// if they have the same width and the same data words.
|
||||||
|
if (constant1->AsIntConstant() && constant2->AsIntConstant() &&
|
||||||
|
constant1->type()->AsInteger()->width() ==
|
||||||
|
constant2->type()->AsInteger()->width() &&
|
||||||
|
constant1->AsIntConstant()->words() ==
|
||||||
|
constant2->AsIntConstant()->words()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The types must be the same
|
||||||
|
if (!constant1->type()->IsSame(constant2->type())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The constants are equivalent if one is null and the other is a static
|
||||||
|
// constant with value 0.
|
||||||
|
return (constant1->AsNullConstant() && IsScalarZeroConstant(constant2)) ||
|
||||||
|
(IsScalarZeroConstant(constant1) && constant2->AsNullConstant());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransformationRecordSynonymousConstants::Apply(
|
||||||
|
opt::IRContext* ir_context,
|
||||||
|
TransformationContext* transformation_context) const {
|
||||||
|
protobufs::FactDataSynonym fact_data_synonym;
|
||||||
|
// Define the two equivalent data descriptors (just containing the ids)
|
||||||
|
*fact_data_synonym.mutable_data1() =
|
||||||
|
MakeDataDescriptor(message_.constant1_id(), {});
|
||||||
|
*fact_data_synonym.mutable_data2() =
|
||||||
|
MakeDataDescriptor(message_.constant2_id(), {});
|
||||||
|
protobufs::Fact fact;
|
||||||
|
*fact.mutable_data_synonym_fact() = fact_data_synonym;
|
||||||
|
|
||||||
|
// Add the fact to the fact manager
|
||||||
|
transformation_context->GetFactManager()->AddFact(fact, ir_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
protobufs::Transformation TransformationRecordSynonymousConstants::ToMessage()
|
||||||
|
const {
|
||||||
|
protobufs::Transformation result;
|
||||||
|
*result.mutable_record_synonymous_constants() = message_;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace fuzz
|
||||||
|
} // namespace spvtools
|
59
source/fuzz/transformation_record_synonymous_constants.h
Normal file
59
source/fuzz/transformation_record_synonymous_constants.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// Copyright (c) 2020 Stefano Milizia
|
||||||
|
// Copyright (c) 2020 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef SOURCE_FUZZ_TRANSFORMATION_RECORD_SYNONYMOUS_CONSTANTS_H
|
||||||
|
#define SOURCE_FUZZ_TRANSFORMATION_RECORD_SYNONYMOUS_CONSTANTS_H
|
||||||
|
|
||||||
|
#include "source/fuzz/transformation.h"
|
||||||
|
|
||||||
|
namespace spvtools {
|
||||||
|
namespace fuzz {
|
||||||
|
|
||||||
|
class TransformationRecordSynonymousConstants : public Transformation {
|
||||||
|
public:
|
||||||
|
explicit TransformationRecordSynonymousConstants(
|
||||||
|
const protobufs::TransformationRecordSynonymousConstants& message);
|
||||||
|
|
||||||
|
TransformationRecordSynonymousConstants(uint32_t constant1_id,
|
||||||
|
uint32_t constant2_id);
|
||||||
|
|
||||||
|
// - |message_.constant_id| and |message_.synonym_id| are distinct ids
|
||||||
|
// of constants
|
||||||
|
// - |message_.constant_id| and |message_.synonym_id| refer to constants
|
||||||
|
// that are equal or equivalent.
|
||||||
|
// Two integers with the same width and value are equal, even if one is
|
||||||
|
// signed and the other is not.
|
||||||
|
// Constants are equivalent if both of them represent zero-like scalar
|
||||||
|
// values of the same type (for example OpConstant of type int and value
|
||||||
|
// 0 and OpConstantNull of type int).
|
||||||
|
bool IsApplicable(
|
||||||
|
opt::IRContext* ir_context,
|
||||||
|
const TransformationContext& transformation_context) const override;
|
||||||
|
|
||||||
|
// Adds the fact that |message_.constant_id| and |message_.synonym_id|
|
||||||
|
// are synonyms to the fact manager. The module is not changed.
|
||||||
|
void Apply(opt::IRContext* ir_context,
|
||||||
|
TransformationContext* transformation_context) const override;
|
||||||
|
|
||||||
|
protobufs::Transformation ToMessage() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
protobufs::TransformationRecordSynonymousConstants message_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace fuzz
|
||||||
|
} // namespace spvtools
|
||||||
|
|
||||||
|
#endif // SOURCE_FUZZ_TRANSFORMATION_RECORD_SYNONYMOUS_CONSTANTS
|
@ -78,6 +78,7 @@ if (${SPIRV_BUILD_FUZZER})
|
|||||||
transformation_swap_commutable_operands_test.cpp
|
transformation_swap_commutable_operands_test.cpp
|
||||||
transformation_swap_conditional_branch_operands_test.cpp
|
transformation_swap_conditional_branch_operands_test.cpp
|
||||||
transformation_toggle_access_chain_instruction_test.cpp
|
transformation_toggle_access_chain_instruction_test.cpp
|
||||||
|
transformation_record_synonymous_constants_test.cpp
|
||||||
transformation_vector_shuffle_test.cpp
|
transformation_vector_shuffle_test.cpp
|
||||||
uniform_buffer_element_descriptor_test.cpp)
|
uniform_buffer_element_descriptor_test.cpp)
|
||||||
|
|
||||||
|
325
test/fuzz/transformation_record_synonymous_constants_test.cpp
Normal file
325
test/fuzz/transformation_record_synonymous_constants_test.cpp
Normal file
@ -0,0 +1,325 @@
|
|||||||
|
// Copyright (c) 2020 Stefano Milizia
|
||||||
|
// Copyright (c) 2020 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "source/fuzz/transformation_record_synonymous_constants.h"
|
||||||
|
|
||||||
|
#include "test/fuzz/fuzz_test_util.h"
|
||||||
|
|
||||||
|
namespace spvtools {
|
||||||
|
namespace fuzz {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Apply the TransformationRecordSynonymousConstants defined by the given
|
||||||
|
// constant1_id and constant2_id and check that the fact that the two
|
||||||
|
// constants are synonym is recorded.
|
||||||
|
void ApplyTransformationAndCheckFactManager(
|
||||||
|
uint32_t constant1_id, uint32_t constant2_id, opt::IRContext* ir_context,
|
||||||
|
TransformationContext* transformation_context) {
|
||||||
|
TransformationRecordSynonymousConstants(constant1_id, constant2_id)
|
||||||
|
.Apply(ir_context, transformation_context);
|
||||||
|
|
||||||
|
ASSERT_TRUE(transformation_context->GetFactManager()->IsSynonymous(
|
||||||
|
MakeDataDescriptor(constant1_id, {}),
|
||||||
|
MakeDataDescriptor(constant2_id, {})));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TransformationRecordSynonymousConstantsTest, IntConstants) {
|
||||||
|
std::string shader = R"(
|
||||||
|
OpCapability Shader
|
||||||
|
%1 = OpExtInstImport "GLSL.std.450"
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %4 "main" %17
|
||||||
|
OpExecutionMode %4 OriginUpperLeft
|
||||||
|
OpSource ESSL 310
|
||||||
|
OpName %4 "main"
|
||||||
|
OpName %8 "a"
|
||||||
|
OpName %10 "b"
|
||||||
|
OpName %12 "c"
|
||||||
|
OpName %17 "color"
|
||||||
|
OpDecorate %8 RelaxedPrecision
|
||||||
|
OpDecorate %10 RelaxedPrecision
|
||||||
|
OpDecorate %12 RelaxedPrecision
|
||||||
|
OpDecorate %17 Location 0
|
||||||
|
%2 = OpTypeVoid
|
||||||
|
%3 = OpTypeFunction %2
|
||||||
|
%6 = OpTypeInt 32 0
|
||||||
|
%19 = OpTypeInt 32 1
|
||||||
|
%7 = OpTypePointer Function %6
|
||||||
|
%9 = OpConstant %6 0
|
||||||
|
%18 = OpConstant %6 0
|
||||||
|
%11 = OpConstantNull %6
|
||||||
|
%13 = OpConstant %6 1
|
||||||
|
%20 = OpConstant %19 1
|
||||||
|
%21 = OpConstant %19 -1
|
||||||
|
%22 = OpConstant %6 1
|
||||||
|
%14 = OpTypeFloat 32
|
||||||
|
%15 = OpTypeVector %14 4
|
||||||
|
%16 = OpTypePointer Output %15
|
||||||
|
%17 = OpVariable %16 Output
|
||||||
|
%4 = OpFunction %2 None %3
|
||||||
|
%5 = OpLabel
|
||||||
|
%8 = OpVariable %7 Function
|
||||||
|
%10 = OpVariable %7 Function
|
||||||
|
%12 = OpVariable %7 Function
|
||||||
|
OpStore %8 %9
|
||||||
|
OpStore %10 %11
|
||||||
|
OpStore %12 %13
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
|
||||||
|
const auto env = SPV_ENV_UNIVERSAL_1_4;
|
||||||
|
const auto consumer = nullptr;
|
||||||
|
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
||||||
|
|
||||||
|
FactManager fact_manager;
|
||||||
|
spvtools::ValidatorOptions validator_options;
|
||||||
|
TransformationContext transformation_context(&fact_manager,
|
||||||
|
validator_options);
|
||||||
|
ASSERT_TRUE(IsValid(env, context.get()));
|
||||||
|
|
||||||
|
// %3 is not a constant declaration
|
||||||
|
ASSERT_FALSE(TransformationRecordSynonymousConstants(3, 9).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
// Swapping the ids gives the same result
|
||||||
|
ASSERT_FALSE(TransformationRecordSynonymousConstants(9, 3).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
// The two constants must be different
|
||||||
|
ASSERT_FALSE(TransformationRecordSynonymousConstants(9, 9).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
// %9 and %13 are not equivalent
|
||||||
|
ASSERT_FALSE(TransformationRecordSynonymousConstants(9, 13).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
// Swapping the ids gives the same result
|
||||||
|
ASSERT_FALSE(TransformationRecordSynonymousConstants(13, 9).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
// %11 and %13 are not equivalent
|
||||||
|
ASSERT_FALSE(TransformationRecordSynonymousConstants(11, 13).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
// Swapping the ids gives the same result
|
||||||
|
ASSERT_FALSE(TransformationRecordSynonymousConstants(13, 11).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
// %20 and %21 have different values
|
||||||
|
ASSERT_FALSE(TransformationRecordSynonymousConstants(20, 21).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
// %13 and %22 are equal and thus equivalent (having the same value and type)
|
||||||
|
ASSERT_TRUE(TransformationRecordSynonymousConstants(13, 22).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
ApplyTransformationAndCheckFactManager(13, 22, context.get(),
|
||||||
|
&transformation_context);
|
||||||
|
|
||||||
|
// %13 and %20 are equal even if %13 is signed and %20 is unsigned
|
||||||
|
ASSERT_TRUE(TransformationRecordSynonymousConstants(13, 20).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
ApplyTransformationAndCheckFactManager(13, 20, context.get(),
|
||||||
|
&transformation_context);
|
||||||
|
|
||||||
|
// %9 and %11 are equivalent (OpConstant with value 0 and OpConstantNull)
|
||||||
|
ASSERT_TRUE(TransformationRecordSynonymousConstants(9, 11).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
ApplyTransformationAndCheckFactManager(9, 11, context.get(),
|
||||||
|
&transformation_context);
|
||||||
|
|
||||||
|
// Swapping the ids gives the same result
|
||||||
|
ASSERT_TRUE(TransformationRecordSynonymousConstants(11, 9).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
ApplyTransformationAndCheckFactManager(11, 9, context.get(),
|
||||||
|
&transformation_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TransformationRecordSynonymousConstantsTest, BoolConstants) {
|
||||||
|
std::string shader = R"(
|
||||||
|
OpCapability Shader
|
||||||
|
%1 = OpExtInstImport "GLSL.std.450"
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %4 "main" %19
|
||||||
|
OpExecutionMode %4 OriginUpperLeft
|
||||||
|
OpSource ESSL 310
|
||||||
|
OpName %4 "main"
|
||||||
|
OpName %8 "b"
|
||||||
|
OpName %19 "color"
|
||||||
|
OpDecorate %19 Location 0
|
||||||
|
%2 = OpTypeVoid
|
||||||
|
%3 = OpTypeFunction %2
|
||||||
|
%6 = OpTypeBool
|
||||||
|
%7 = OpTypePointer Function %6
|
||||||
|
%9 = OpConstantFalse %6
|
||||||
|
%20 = OpConstantNull %6
|
||||||
|
%11 = OpConstantTrue %6
|
||||||
|
%21 = OpConstantFalse %6
|
||||||
|
%22 = OpConstantTrue %6
|
||||||
|
%16 = OpTypeFloat 32
|
||||||
|
%17 = OpTypeVector %16 4
|
||||||
|
%18 = OpTypePointer Output %17
|
||||||
|
%19 = OpVariable %18 Output
|
||||||
|
%4 = OpFunction %2 None %3
|
||||||
|
%5 = OpLabel
|
||||||
|
%8 = OpVariable %7 Function
|
||||||
|
OpStore %8 %9
|
||||||
|
%10 = OpLoad %6 %8
|
||||||
|
%12 = OpLogicalEqual %6 %10 %11
|
||||||
|
OpSelectionMerge %14 None
|
||||||
|
OpBranchConditional %12 %13 %14
|
||||||
|
%13 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
%14 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
|
||||||
|
const auto env = SPV_ENV_UNIVERSAL_1_4;
|
||||||
|
const auto consumer = nullptr;
|
||||||
|
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
||||||
|
|
||||||
|
FactManager fact_manager;
|
||||||
|
spvtools::ValidatorOptions validator_options;
|
||||||
|
TransformationContext transformation_context(&fact_manager,
|
||||||
|
validator_options);
|
||||||
|
ASSERT_TRUE(IsValid(env, context.get()));
|
||||||
|
|
||||||
|
// %9 and %11 are not equivalent
|
||||||
|
ASSERT_FALSE(TransformationRecordSynonymousConstants(9, 11).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
// %20 and %11 are not equivalent
|
||||||
|
ASSERT_FALSE(TransformationRecordSynonymousConstants(20, 11).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
// %9 and %21 are equivalent (both OpConstantFalse)
|
||||||
|
ASSERT_TRUE(TransformationRecordSynonymousConstants(9, 21).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
ApplyTransformationAndCheckFactManager(9, 21, context.get(),
|
||||||
|
&transformation_context);
|
||||||
|
|
||||||
|
// %11 and %22 are equivalent (both OpConstantTrue)
|
||||||
|
ASSERT_TRUE(TransformationRecordSynonymousConstants(11, 22).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
ApplyTransformationAndCheckFactManager(11, 22, context.get(),
|
||||||
|
&transformation_context);
|
||||||
|
|
||||||
|
// %9 and %20 are equivalent (OpConstantFalse and boolean OpConstantNull)
|
||||||
|
ASSERT_TRUE(TransformationRecordSynonymousConstants(9, 20).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
ApplyTransformationAndCheckFactManager(9, 20, context.get(),
|
||||||
|
&transformation_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(TransformationRecordSynonymousConstantsTest, FloatConstants) {
|
||||||
|
std::string shader = R"(
|
||||||
|
OpCapability Shader
|
||||||
|
%1 = OpExtInstImport "GLSL.std.450"
|
||||||
|
OpMemoryModel Logical GLSL450
|
||||||
|
OpEntryPoint Fragment %4 "main" %22
|
||||||
|
OpExecutionMode %4 OriginUpperLeft
|
||||||
|
OpSource ESSL 310
|
||||||
|
OpName %4 "main"
|
||||||
|
OpName %8 "a"
|
||||||
|
OpName %10 "b"
|
||||||
|
OpName %12 "c"
|
||||||
|
OpName %22 "color"
|
||||||
|
OpDecorate %22 Location 0
|
||||||
|
%2 = OpTypeVoid
|
||||||
|
%3 = OpTypeFunction %2
|
||||||
|
%6 = OpTypeFloat 32
|
||||||
|
%7 = OpTypePointer Function %6
|
||||||
|
%9 = OpConstant %6 0
|
||||||
|
%11 = OpConstantNull %6
|
||||||
|
%13 = OpConstant %6 2
|
||||||
|
%26 = OpConstant %6 2
|
||||||
|
%16 = OpTypeBool
|
||||||
|
%20 = OpTypeVector %6 4
|
||||||
|
%21 = OpTypePointer Output %20
|
||||||
|
%22 = OpVariable %21 Output
|
||||||
|
%23 = OpConstantComposite %20 %9 %11 %9 %11
|
||||||
|
%25 = OpConstantComposite %20 %11 %9 %9 %11
|
||||||
|
%4 = OpFunction %2 None %3
|
||||||
|
%5 = OpLabel
|
||||||
|
%8 = OpVariable %7 Function
|
||||||
|
%10 = OpVariable %7 Function
|
||||||
|
%12 = OpVariable %7 Function
|
||||||
|
OpStore %8 %9
|
||||||
|
OpStore %10 %11
|
||||||
|
OpStore %12 %13
|
||||||
|
%14 = OpLoad %6 %8
|
||||||
|
%15 = OpLoad %6 %10
|
||||||
|
%17 = OpFOrdEqual %16 %14 %15
|
||||||
|
OpSelectionMerge %19 None
|
||||||
|
OpBranchConditional %17 %18 %24
|
||||||
|
%18 = OpLabel
|
||||||
|
OpStore %22 %23
|
||||||
|
OpBranch %19
|
||||||
|
%24 = OpLabel
|
||||||
|
OpStore %22 %25
|
||||||
|
OpBranch %19
|
||||||
|
%19 = OpLabel
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
|
||||||
|
const auto env = SPV_ENV_UNIVERSAL_1_4;
|
||||||
|
const auto consumer = nullptr;
|
||||||
|
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
||||||
|
|
||||||
|
FactManager fact_manager;
|
||||||
|
spvtools::ValidatorOptions validator_options;
|
||||||
|
TransformationContext transformation_context(&fact_manager,
|
||||||
|
validator_options);
|
||||||
|
ASSERT_TRUE(IsValid(env, context.get()));
|
||||||
|
|
||||||
|
// %9 and %13 are not equivalent
|
||||||
|
ASSERT_FALSE(TransformationRecordSynonymousConstants(9, 13).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
// %11 and %13 are not equivalent
|
||||||
|
ASSERT_FALSE(TransformationRecordSynonymousConstants(11, 13).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
// %13 and %23 are not equivalent
|
||||||
|
ASSERT_FALSE(TransformationRecordSynonymousConstants(13, 23).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
// %13 and %26 are identical float constants
|
||||||
|
ASSERT_TRUE(TransformationRecordSynonymousConstants(13, 26).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
ApplyTransformationAndCheckFactManager(13, 26, context.get(),
|
||||||
|
&transformation_context);
|
||||||
|
|
||||||
|
// %9 and %11 are equivalent ()
|
||||||
|
ASSERT_TRUE(TransformationRecordSynonymousConstants(9, 11).IsApplicable(
|
||||||
|
context.get(), transformation_context));
|
||||||
|
|
||||||
|
ApplyTransformationAndCheckFactManager(9, 11, context.get(),
|
||||||
|
&transformation_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace fuzz
|
||||||
|
} // namespace spvtools
|
@ -35,7 +35,8 @@ AUTHORS = ['The Khronos Group Inc.',
|
|||||||
'Samsung Inc',
|
'Samsung Inc',
|
||||||
'André Perez Maselco',
|
'André Perez Maselco',
|
||||||
'Vasyl Teliman',
|
'Vasyl Teliman',
|
||||||
'Advanced Micro Devices, Inc.']
|
'Advanced Micro Devices, Inc.',
|
||||||
|
'Stefano Milizia']
|
||||||
CURRENT_YEAR='2020'
|
CURRENT_YEAR='2020'
|
||||||
|
|
||||||
YEARS = '(2014-2016|2015-2016|2015-2020|2016|2016-2017|2017|2017-2019|2018|2019|2020)'
|
YEARS = '(2014-2016|2015-2016|2015-2020|2016|2016-2017|2017|2017-2019|2018|2019|2020)'
|
||||||
|
Loading…
Reference in New Issue
Block a user