mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-24 00:40:14 +00:00
spirv-fuzz: Add bit instruction synonym transformation (#3775)
This PR implements part of the add bit instruction synonym transformation. For now, the implementation covers the OpBitwiseOr, OpBitwiseXor and OpBitwiseAnd cases.
This commit is contained in:
parent
e7c84feda0
commit
e8ce4355ae
@ -52,6 +52,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||
fuzzer_context.h
|
||||
fuzzer_pass.h
|
||||
fuzzer_pass_add_access_chains.h
|
||||
fuzzer_pass_add_bit_instruction_synonyms.h
|
||||
fuzzer_pass_add_composite_inserts.h
|
||||
fuzzer_pass_add_composite_types.h
|
||||
fuzzer_pass_add_copy_memory.h
|
||||
@ -124,6 +125,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||
shrinker.h
|
||||
transformation.h
|
||||
transformation_access_chain.h
|
||||
transformation_add_bit_instruction_synonym.h
|
||||
transformation_add_constant_boolean.h
|
||||
transformation_add_constant_composite.h
|
||||
transformation_add_constant_null.h
|
||||
@ -217,6 +219,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||
fuzzer_context.cpp
|
||||
fuzzer_pass.cpp
|
||||
fuzzer_pass_add_access_chains.cpp
|
||||
fuzzer_pass_add_bit_instruction_synonyms.cpp
|
||||
fuzzer_pass_add_composite_inserts.cpp
|
||||
fuzzer_pass_add_composite_types.cpp
|
||||
fuzzer_pass_add_copy_memory.cpp
|
||||
@ -288,6 +291,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||
shrinker.cpp
|
||||
transformation.cpp
|
||||
transformation_access_chain.cpp
|
||||
transformation_add_bit_instruction_synonym.cpp
|
||||
transformation_add_constant_boolean.cpp
|
||||
transformation_add_constant_composite.cpp
|
||||
transformation_add_constant_null.cpp
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "source/fuzz/fact_manager/fact_manager.h"
|
||||
#include "source/fuzz/fuzzer_context.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_access_chains.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_bit_instruction_synonyms.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_composite_inserts.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_composite_types.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_copy_memory.h"
|
||||
@ -205,6 +206,9 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run(
|
||||
MaybeAddPass<FuzzerPassAddAccessChains>(
|
||||
&passes, ir_context.get(), &transformation_context, &fuzzer_context,
|
||||
transformation_sequence_out);
|
||||
MaybeAddPass<FuzzerPassAddBitInstructionSynonyms>(
|
||||
&passes, ir_context.get(), &transformation_context, &fuzzer_context,
|
||||
transformation_sequence_out);
|
||||
MaybeAddPass<FuzzerPassAddCompositeInserts>(
|
||||
&passes, ir_context.get(), &transformation_context, &fuzzer_context,
|
||||
transformation_sequence_out);
|
||||
|
@ -27,6 +27,8 @@ const std::pair<uint32_t, uint32_t> kChanceOfAddingAccessChain = {5, 50};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfAddingAnotherStructField = {20,
|
||||
90};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfAddingArrayOrStructType = {20, 90};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfAddingBitInstructionSynonym = {20,
|
||||
90};
|
||||
const std::pair<uint32_t, uint32_t>
|
||||
kChanceOfAddingBothBranchesWhenReplacingOpSelect = {40, 60};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfAddingCompositeInsert = {20, 50};
|
||||
@ -172,6 +174,8 @@ FuzzerContext::FuzzerContext(RandomGenerator* random_generator,
|
||||
ChooseBetweenMinAndMax(kChanceOfAddingAnotherStructField);
|
||||
chance_of_adding_array_or_struct_type_ =
|
||||
ChooseBetweenMinAndMax(kChanceOfAddingArrayOrStructType);
|
||||
chance_of_adding_bit_instruction_synonym_ =
|
||||
ChooseBetweenMinAndMax(kChanceOfAddingBitInstructionSynonym);
|
||||
chance_of_adding_both_branches_when_replacing_opselect_ =
|
||||
ChooseBetweenMinAndMax(kChanceOfAddingBothBranchesWhenReplacingOpSelect);
|
||||
chance_of_adding_composite_insert_ =
|
||||
|
@ -115,6 +115,9 @@ class FuzzerContext {
|
||||
uint32_t GetChanceOfAddingArrayOrStructType() {
|
||||
return chance_of_adding_array_or_struct_type_;
|
||||
}
|
||||
uint32_t GetChanceOfAddingBitInstructionSynonym() {
|
||||
return chance_of_adding_bit_instruction_synonym_;
|
||||
}
|
||||
uint32_t GetChanceOfAddingBothBranchesWhenReplacingOpSelect() {
|
||||
return chance_of_adding_both_branches_when_replacing_opselect_;
|
||||
}
|
||||
@ -379,6 +382,7 @@ class FuzzerContext {
|
||||
uint32_t chance_of_adding_access_chain_;
|
||||
uint32_t chance_of_adding_another_struct_field_;
|
||||
uint32_t chance_of_adding_array_or_struct_type_;
|
||||
uint32_t chance_of_adding_bit_instruction_synonym_;
|
||||
uint32_t chance_of_adding_both_branches_when_replacing_opselect_;
|
||||
uint32_t chance_of_adding_composite_insert_;
|
||||
uint32_t chance_of_adding_copy_memory_;
|
||||
|
84
source/fuzz/fuzzer_pass_add_bit_instruction_synonyms.cpp
Normal file
84
source/fuzz/fuzzer_pass_add_bit_instruction_synonyms.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2020 André Perez Maselco
|
||||
//
|
||||
// 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/fuzzer_pass_add_bit_instruction_synonyms.h"
|
||||
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
#include "source/fuzz/instruction_descriptor.h"
|
||||
#include "source/fuzz/transformation_add_bit_instruction_synonym.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
FuzzerPassAddBitInstructionSynonyms::FuzzerPassAddBitInstructionSynonyms(
|
||||
opt::IRContext* ir_context, TransformationContext* transformation_context,
|
||||
FuzzerContext* fuzzer_context,
|
||||
protobufs::TransformationSequence* transformations)
|
||||
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
|
||||
transformations) {}
|
||||
|
||||
FuzzerPassAddBitInstructionSynonyms::~FuzzerPassAddBitInstructionSynonyms() =
|
||||
default;
|
||||
|
||||
void FuzzerPassAddBitInstructionSynonyms::Apply() {
|
||||
for (auto& function : *GetIRContext()->module()) {
|
||||
for (auto& block : function) {
|
||||
for (auto& instruction : block) {
|
||||
// Randomly decides whether the transformation will be applied.
|
||||
if (!GetFuzzerContext()->ChoosePercentage(
|
||||
GetFuzzerContext()->GetChanceOfAddingBitInstructionSynonym())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3557):
|
||||
// Right now we only support certain operations. When this issue is
|
||||
// addressed the following conditional can use the function
|
||||
// |spvOpcodeIsBit|.
|
||||
if (instruction.opcode() != SpvOpBitwiseOr &&
|
||||
instruction.opcode() != SpvOpBitwiseXor &&
|
||||
instruction.opcode() != SpvOpBitwiseAnd) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Right now, only integer operands are supported.
|
||||
if (GetIRContext()
|
||||
->get_type_mgr()
|
||||
->GetType(instruction.type_id())
|
||||
->AsVector()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure all bit indexes are defined as 32-bit unsigned integers.
|
||||
uint32_t width = GetIRContext()
|
||||
->get_type_mgr()
|
||||
->GetType(instruction.type_id())
|
||||
->AsInteger()
|
||||
->width();
|
||||
for (uint32_t i = 0; i < width; i++) {
|
||||
FindOrCreateIntegerConstant({i}, 32, false, false);
|
||||
}
|
||||
|
||||
// Applies the add bit instruction synonym transformation.
|
||||
ApplyTransformation(TransformationAddBitInstructionSynonym(
|
||||
instruction.result_id(),
|
||||
GetFuzzerContext()->GetFreshIds(
|
||||
TransformationAddBitInstructionSynonym::GetRequiredFreshIdCount(
|
||||
GetIRContext(), &instruction))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
41
source/fuzz/fuzzer_pass_add_bit_instruction_synonyms.h
Normal file
41
source/fuzz/fuzzer_pass_add_bit_instruction_synonyms.h
Normal file
@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2020 André Perez Maselco
|
||||
//
|
||||
// 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_FUZZER_PASS_ADD_BIT_INSTRUCTION_SYNONYMS_H_
|
||||
#define SOURCE_FUZZ_FUZZER_PASS_ADD_BIT_INSTRUCTION_SYNONYMS_H_
|
||||
|
||||
#include "source/fuzz/fuzzer_pass.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
// This fuzzer pass adds synonyms for bit instructions. It iterates over the
|
||||
// module instructions, checks if they are bit instructions and randomly applies
|
||||
// the transformation.
|
||||
class FuzzerPassAddBitInstructionSynonyms : public FuzzerPass {
|
||||
public:
|
||||
FuzzerPassAddBitInstructionSynonyms(
|
||||
opt::IRContext* ir_context, TransformationContext* transformation_context,
|
||||
FuzzerContext* fuzzer_context,
|
||||
protobufs::TransformationSequence* transformations);
|
||||
|
||||
~FuzzerPassAddBitInstructionSynonyms();
|
||||
|
||||
void Apply() override;
|
||||
};
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SOURCE_FUZZ_FUZZER_PASS_ADD_BIT_INSTRUCTION_SYNONYMS_H_
|
@ -496,6 +496,7 @@ message Transformation {
|
||||
TransformationReplaceOpSelectWithConditionalBranch replace_opselect_with_conditional_branch = 74;
|
||||
TransformationDuplicateRegionWithSelection duplicate_region_with_selection = 75;
|
||||
TransformationFlattenConditionalBranch flatten_conditional_branch = 76;
|
||||
TransformationAddBitInstructionSynonym add_bit_instruction_synonym = 77;
|
||||
// Add additional option using the next available number.
|
||||
}
|
||||
}
|
||||
@ -532,6 +533,33 @@ message TransformationAccessChain {
|
||||
|
||||
}
|
||||
|
||||
message TransformationAddBitInstructionSynonym {
|
||||
|
||||
// A transformation that adds synonyms for bit instructions by evaluating
|
||||
// each bit with the corresponding operation. There is a SPIR-V code example in the
|
||||
// header file of the transformation class that can help understand the transformation.
|
||||
|
||||
// This transformation is only applicable if the described instruction has one of the following opcodes.
|
||||
// Supported:
|
||||
// OpBitwiseOr
|
||||
// OpBitwiseXor
|
||||
// OpBitwiseAnd
|
||||
// To be supported in the future:
|
||||
// OpShiftRightLogical
|
||||
// OpShiftRightArithmetic
|
||||
// OpShiftLeftLogical
|
||||
// OpNot
|
||||
// OpBitReverse
|
||||
// OpBitCount
|
||||
|
||||
// The bit instruction result id.
|
||||
uint32 instruction_result_id = 1;
|
||||
|
||||
// The fresh ids required to apply the transformation.
|
||||
repeated uint32 fresh_ids = 2;
|
||||
|
||||
}
|
||||
|
||||
message TransformationAddConstantBoolean {
|
||||
|
||||
// Supports adding the constants true and false to a module, which may be
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
#include "source/fuzz/transformation_access_chain.h"
|
||||
#include "source/fuzz/transformation_add_bit_instruction_synonym.h"
|
||||
#include "source/fuzz/transformation_add_constant_boolean.h"
|
||||
#include "source/fuzz/transformation_add_constant_composite.h"
|
||||
#include "source/fuzz/transformation_add_constant_null.h"
|
||||
@ -105,6 +106,10 @@ std::unique_ptr<Transformation> Transformation::FromMessage(
|
||||
switch (message.transformation_case()) {
|
||||
case protobufs::Transformation::TransformationCase::kAccessChain:
|
||||
return MakeUnique<TransformationAccessChain>(message.access_chain());
|
||||
case protobufs::Transformation::TransformationCase::
|
||||
kAddBitInstructionSynonym:
|
||||
return MakeUnique<TransformationAddBitInstructionSynonym>(
|
||||
message.add_bit_instruction_synonym());
|
||||
case protobufs::Transformation::TransformationCase::kAddConstantBoolean:
|
||||
return MakeUnique<TransformationAddConstantBoolean>(
|
||||
message.add_constant_boolean());
|
||||
|
228
source/fuzz/transformation_add_bit_instruction_synonym.cpp
Normal file
228
source/fuzz/transformation_add_bit_instruction_synonym.cpp
Normal file
@ -0,0 +1,228 @@
|
||||
// Copyright (c) 2020 André Perez Maselco
|
||||
//
|
||||
// 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_add_bit_instruction_synonym.h"
|
||||
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
#include "source/fuzz/instruction_descriptor.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
TransformationAddBitInstructionSynonym::TransformationAddBitInstructionSynonym(
|
||||
const spvtools::fuzz::protobufs::TransformationAddBitInstructionSynonym&
|
||||
message)
|
||||
: message_(message) {}
|
||||
|
||||
TransformationAddBitInstructionSynonym::TransformationAddBitInstructionSynonym(
|
||||
const uint32_t instruction_result_id,
|
||||
const std::vector<uint32_t>& fresh_ids) {
|
||||
message_.set_instruction_result_id(instruction_result_id);
|
||||
*message_.mutable_fresh_ids() =
|
||||
google::protobuf::RepeatedField<google::protobuf::uint32>(
|
||||
fresh_ids.begin(), fresh_ids.end());
|
||||
}
|
||||
|
||||
bool TransformationAddBitInstructionSynonym::IsApplicable(
|
||||
opt::IRContext* ir_context,
|
||||
const TransformationContext& transformation_context) const {
|
||||
auto instruction =
|
||||
ir_context->get_def_use_mgr()->GetDef(message_.instruction_result_id());
|
||||
|
||||
// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3557):
|
||||
// Right now we only support certain operations. When this issue is addressed
|
||||
// the following conditional can use the function |spvOpcodeIsBit|.
|
||||
// |instruction| must be defined and must be a supported bit instruction.
|
||||
if (!instruction || (instruction->opcode() != SpvOpBitwiseOr &&
|
||||
instruction->opcode() != SpvOpBitwiseXor &&
|
||||
instruction->opcode() != SpvOpBitwiseAnd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3792):
|
||||
// Right now, only integer operands are supported.
|
||||
if (ir_context->get_type_mgr()->GetType(instruction->type_id())->AsVector()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3791):
|
||||
// This condition could be relaxed if the index exists as another integer
|
||||
// type.
|
||||
// All bit indexes must be defined as 32-bit unsigned integers.
|
||||
uint32_t width = ir_context->get_type_mgr()
|
||||
->GetType(instruction->type_id())
|
||||
->AsInteger()
|
||||
->width();
|
||||
for (uint32_t i = 0; i < width; i++) {
|
||||
if (!fuzzerutil::MaybeGetIntegerConstant(ir_context, transformation_context,
|
||||
{i}, 32, false, false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// |message_.fresh_ids.size| must have the exact number of fresh ids required
|
||||
// to apply the transformation.
|
||||
if (static_cast<uint32_t>(message_.fresh_ids().size()) !=
|
||||
GetRequiredFreshIdCount(ir_context, instruction)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// All ids in |message_.fresh_ids| must be fresh.
|
||||
for (uint32_t fresh_id : message_.fresh_ids()) {
|
||||
if (!fuzzerutil::IsFreshId(ir_context, fresh_id)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TransformationAddBitInstructionSynonym::Apply(
|
||||
opt::IRContext* ir_context,
|
||||
TransformationContext* transformation_context) const {
|
||||
auto bit_instruction =
|
||||
ir_context->get_def_use_mgr()->GetDef(message_.instruction_result_id());
|
||||
|
||||
switch (bit_instruction->opcode()) {
|
||||
case SpvOpBitwiseOr:
|
||||
case SpvOpBitwiseXor:
|
||||
case SpvOpBitwiseAnd:
|
||||
AddBitwiseSynonym(ir_context, transformation_context, bit_instruction);
|
||||
break;
|
||||
default:
|
||||
assert(false && "Should be unreachable.");
|
||||
break;
|
||||
}
|
||||
|
||||
ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
|
||||
}
|
||||
|
||||
protobufs::Transformation TransformationAddBitInstructionSynonym::ToMessage()
|
||||
const {
|
||||
protobufs::Transformation result;
|
||||
*result.mutable_add_bit_instruction_synonym() = message_;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t TransformationAddBitInstructionSynonym::GetRequiredFreshIdCount(
|
||||
opt::IRContext* ir_context, opt::Instruction* bit_instruction) {
|
||||
// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3557):
|
||||
// Right now, only certain operations are supported.
|
||||
switch (bit_instruction->opcode()) {
|
||||
case SpvOpBitwiseOr:
|
||||
case SpvOpBitwiseXor:
|
||||
case SpvOpBitwiseAnd:
|
||||
return 4 * ir_context->get_type_mgr()
|
||||
->GetType(bit_instruction->type_id())
|
||||
->AsInteger()
|
||||
->width() -
|
||||
1;
|
||||
default:
|
||||
assert(false && "Unsupported bit instruction.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TransformationAddBitInstructionSynonym::AddBitwiseSynonym(
|
||||
opt::IRContext* ir_context, TransformationContext* transformation_context,
|
||||
opt::Instruction* bit_instruction) const {
|
||||
// Fresh id iterator.
|
||||
auto fresh_id = message_.fresh_ids().begin();
|
||||
|
||||
// |width| is the bit width of operands (8, 16, 32 or 64).
|
||||
const uint32_t width = ir_context->get_type_mgr()
|
||||
->GetType(bit_instruction->type_id())
|
||||
->AsInteger()
|
||||
->width();
|
||||
|
||||
// |count| is the number of bits to be extracted and inserted at a time.
|
||||
const uint32_t count = fuzzerutil::MaybeGetIntegerConstant(
|
||||
ir_context, *transformation_context, {1}, 32, false, false);
|
||||
|
||||
// |bitwise_ids| is the collection of OpBiwise* instructions that evaluate a
|
||||
// pair of extracted bits. Those ids will be used to insert the result bits.
|
||||
std::vector<uint32_t> bitwise_ids(width);
|
||||
|
||||
for (uint32_t i = 0; i < width; i++) {
|
||||
// |offset| is the current bit index.
|
||||
uint32_t offset = fuzzerutil::MaybeGetIntegerConstant(
|
||||
ir_context, *transformation_context, {i}, 32, false, false);
|
||||
|
||||
// |bit_extract_ids| are the two extracted bits from the operands.
|
||||
std::vector<uint32_t> bit_extract_ids;
|
||||
|
||||
// Extracts the i-th bit from operands.
|
||||
for (auto operand = bit_instruction->begin() + 2;
|
||||
operand != bit_instruction->end(); operand++) {
|
||||
auto bit_extract =
|
||||
opt::Instruction(ir_context, SpvOpBitFieldUExtract,
|
||||
bit_instruction->type_id(), *fresh_id++,
|
||||
{{SPV_OPERAND_TYPE_ID, operand->words},
|
||||
{SPV_OPERAND_TYPE_ID, {offset}},
|
||||
{SPV_OPERAND_TYPE_ID, {count}}});
|
||||
bit_instruction->InsertBefore(MakeUnique<opt::Instruction>(bit_extract));
|
||||
fuzzerutil::UpdateModuleIdBound(ir_context, bit_extract.result_id());
|
||||
bit_extract_ids.push_back(bit_extract.result_id());
|
||||
}
|
||||
|
||||
// Applies |bit_instruction| to the pair of extracted bits.
|
||||
auto bitwise =
|
||||
opt::Instruction(ir_context, bit_instruction->opcode(),
|
||||
bit_instruction->type_id(), *fresh_id++,
|
||||
{{SPV_OPERAND_TYPE_ID, {bit_extract_ids[0]}},
|
||||
{SPV_OPERAND_TYPE_ID, {bit_extract_ids[1]}}});
|
||||
bit_instruction->InsertBefore(MakeUnique<opt::Instruction>(bitwise));
|
||||
fuzzerutil::UpdateModuleIdBound(ir_context, bitwise.result_id());
|
||||
bitwise_ids[i] = bitwise.result_id();
|
||||
}
|
||||
|
||||
// The first two ids in |bitwise_ids| are used to insert the first two bits of
|
||||
// the result.
|
||||
uint32_t offset = fuzzerutil::MaybeGetIntegerConstant(
|
||||
ir_context, *transformation_context, {1}, 32, false, false);
|
||||
auto bit_insert = opt::Instruction(ir_context, SpvOpBitFieldInsert,
|
||||
bit_instruction->type_id(), *fresh_id++,
|
||||
{{SPV_OPERAND_TYPE_ID, {bitwise_ids[0]}},
|
||||
{SPV_OPERAND_TYPE_ID, {bitwise_ids[1]}},
|
||||
{SPV_OPERAND_TYPE_ID, {offset}},
|
||||
{SPV_OPERAND_TYPE_ID, {count}}});
|
||||
bit_instruction->InsertBefore(MakeUnique<opt::Instruction>(bit_insert));
|
||||
fuzzerutil::UpdateModuleIdBound(ir_context, bit_insert.result_id());
|
||||
|
||||
// Inserts the remaining bits.
|
||||
for (uint32_t i = 2; i < width; i++) {
|
||||
offset = fuzzerutil::MaybeGetIntegerConstant(
|
||||
ir_context, *transformation_context, {i}, 32, false, false);
|
||||
bit_insert =
|
||||
opt::Instruction(ir_context, SpvOpBitFieldInsert,
|
||||
bit_instruction->type_id(), *fresh_id++,
|
||||
{{SPV_OPERAND_TYPE_ID, {bit_insert.result_id()}},
|
||||
{SPV_OPERAND_TYPE_ID, {bitwise_ids[i]}},
|
||||
{SPV_OPERAND_TYPE_ID, {offset}},
|
||||
{SPV_OPERAND_TYPE_ID, {count}}});
|
||||
bit_instruction->InsertBefore(MakeUnique<opt::Instruction>(bit_insert));
|
||||
fuzzerutil::UpdateModuleIdBound(ir_context, bit_insert.result_id());
|
||||
}
|
||||
|
||||
ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
|
||||
|
||||
// Adds the fact that the last |bit_insert| instruction is synonymous of
|
||||
// |bit_instruction|.
|
||||
transformation_context->GetFactManager()->AddFactDataSynonym(
|
||||
MakeDataDescriptor(bit_insert.result_id(), {}),
|
||||
MakeDataDescriptor(bit_instruction->result_id(), {}), ir_context);
|
||||
}
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
141
source/fuzz/transformation_add_bit_instruction_synonym.h
Normal file
141
source/fuzz/transformation_add_bit_instruction_synonym.h
Normal file
@ -0,0 +1,141 @@
|
||||
// Copyright (c) 2020 André Perez Maselco
|
||||
//
|
||||
// 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_ADD_BIT_INSTRUCTION_SYNONYM_H_
|
||||
#define SOURCE_FUZZ_TRANSFORMATION_ADD_BIT_INSTRUCTION_SYNONYM_H_
|
||||
|
||||
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
|
||||
#include "source/fuzz/transformation.h"
|
||||
#include "source/fuzz/transformation_context.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
// clang-format off
|
||||
// SPIR-V code to help understand the transformation.
|
||||
//
|
||||
// ----------------------------------------------------------------------------------------------------------------
|
||||
// | Reference shader | Variant shader |
|
||||
// ----------------------------------------------------------------------------------------------------------------
|
||||
// | OpCapability Shader | OpCapability Shader |
|
||||
// | OpCapability Int8 | OpCapability Int8 |
|
||||
// | %1 = OpExtInstImport "GLSL.std.450" | %1 = OpExtInstImport "GLSL.std.450" |
|
||||
// | OpMemoryModel Logical GLSL450 | OpMemoryModel Logical GLSL450 |
|
||||
// | OpEntryPoint Vertex %7 "main" | OpEntryPoint Vertex %7 "main" |
|
||||
// | | |
|
||||
// | ; Types | ; Types |
|
||||
// | %2 = OpTypeInt 8 0 | %2 = OpTypeInt 8 0 |
|
||||
// | %3 = OpTypeVoid | %3 = OpTypeVoid |
|
||||
// | %4 = OpTypeFunction %3 | %4 = OpTypeFunction %3 |
|
||||
// | | |
|
||||
// | ; Constants | ; Constants |
|
||||
// | %5 = OpConstant %2 0 | %5 = OpConstant %2 0 |
|
||||
// | %6 = OpConstant %2 1 | %6 = OpConstant %2 1 |
|
||||
// | | %10 = OpConstant %2 2 |
|
||||
// | ; main function | %11 = OpConstant %2 3 |
|
||||
// | %7 = OpFunction %3 None %4 | %12 = OpConstant %2 4 |
|
||||
// | %8 = OpLabel | %13 = OpConstant %2 5 |
|
||||
// | %9 = OpBitwiseOr %2 %5 %6 ; bit instruction | %14 = OpConstant %2 6 |
|
||||
// | OpReturn | %15 = OpConstant %2 7 |
|
||||
// | OpFunctionEnd | |
|
||||
// | | ; main function |
|
||||
// | | %7 = OpFunction %3 None %4 |
|
||||
// | | %8 = OpLabel |
|
||||
// | | |
|
||||
// | | %16 = OpBitFieldUExtract %2 %5 %5 %6 ; extracts bit 0 from %5 |
|
||||
// | | %17 = OpBitFieldUExtract %2 %6 %5 %6 ; extracts bit 0 from %6 |
|
||||
// | | %18 = OpBitwiseOr %2 %16 %17 |
|
||||
// | | |
|
||||
// | | %19 = OpBitFieldUExtract %2 %5 %6 %6 ; extracts bit 1 from %5 |
|
||||
// | | %20 = OpBitFieldUExtract %2 %6 %6 %6 ; extracts bit 1 from %6 |
|
||||
// | | %21 = OpBitwiseOr %2 %19 %20 |
|
||||
// | | |
|
||||
// | | %22 = OpBitFieldUExtract %2 %5 %10 %6 ; extracts bit 2 from %5 |
|
||||
// | | %23 = OpBitFieldUExtract %2 %6 %10 %6 ; extracts bit 2 from %6 |
|
||||
// | | %24 = OpBitwiseOr %2 %22 %23 |
|
||||
// | | |
|
||||
// | | %25 = OpBitFieldUExtract %2 %5 %11 %6 ; extracts bit 3 from %5 |
|
||||
// | | %26 = OpBitFieldUExtract %2 %6 %11 %6 ; extracts bit 3 from %6 |
|
||||
// | | %27 = OpBitwiseOr %2 %25 %26 |
|
||||
// | | |
|
||||
// | | %28 = OpBitFieldUExtract %2 %5 %12 %6 ; extracts bit 4 from %5 |
|
||||
// | | %29 = OpBitFieldUExtract %2 %6 %12 %6 ; extracts bit 4 from %6 |
|
||||
// | | %30 = OpBitwiseOr %2 %28 %29 |
|
||||
// | | |
|
||||
// | | %31 = OpBitFieldUExtract %2 %5 %13 %6 ; extracts bit 5 from %5 |
|
||||
// | | %32 = OpBitFieldUExtract %2 %6 %13 %6 ; extracts bit 5 from %6 |
|
||||
// | | %33 = OpBitwiseOr %2 %31 %32 |
|
||||
// | | |
|
||||
// | | %34 = OpBitFieldUExtract %2 %5 %14 %6 ; extracts bit 6 from %5 |
|
||||
// | | %35 = OpBitFieldUExtract %2 %6 %14 %6 ; extracts bit 6 from %6 |
|
||||
// | | %36 = OpBitwiseOr %2 %34 %35 |
|
||||
// | | |
|
||||
// | | %37 = OpBitFieldUExtract %2 %5 %15 %6 ; extracts bit 7 from %5 |
|
||||
// | | %38 = OpBitFieldUExtract %2 %6 %15 %6 ; extracts bit 7 from %6 |
|
||||
// | | %39 = OpBitwiseOr %2 %37 %38 |
|
||||
// | | |
|
||||
// | | %40 = OpBitFieldInsert %2 %18 %21 %6 %6 ; inserts bit 1 |
|
||||
// | | %41 = OpBitFieldInsert %2 %40 %24 %10 %6 ; inserts bit 2 |
|
||||
// | | %42 = OpBitFieldInsert %2 %41 %27 %11 %6 ; inserts bit 3 |
|
||||
// | | %43 = OpBitFieldInsert %2 %42 %30 %12 %6 ; inserts bit 4 |
|
||||
// | | %44 = OpBitFieldInsert %2 %43 %33 %13 %6 ; inserts bit 5 |
|
||||
// | | %45 = OpBitFieldInsert %2 %44 %36 %14 %6 ; inserts bit 6 |
|
||||
// | | %46 = OpBitFieldInsert %2 %45 %39 %15 %6 ; inserts bit 7 |
|
||||
// | | %9 = OpBitwiseOr %2 %5 %6 ; bit instruction |
|
||||
// | | OpReturn |
|
||||
// | | OpFunctionEnd |
|
||||
// ----------------------------------------------------------------------------------------------------------------
|
||||
//
|
||||
// After the transformation, %9 and %46 will be synonymous.
|
||||
// clang-format on
|
||||
class TransformationAddBitInstructionSynonym : public Transformation {
|
||||
public:
|
||||
explicit TransformationAddBitInstructionSynonym(
|
||||
const protobufs::TransformationAddBitInstructionSynonym& message);
|
||||
|
||||
TransformationAddBitInstructionSynonym(
|
||||
const uint32_t instruction_result_id,
|
||||
const std::vector<uint32_t>& fresh_ids);
|
||||
|
||||
// - |message_.instruction_result_id| must be a bit instruction.
|
||||
// - |message_.fresh_ids| must be fresh ids needed to apply the
|
||||
// transformation.
|
||||
bool IsApplicable(
|
||||
opt::IRContext* ir_context,
|
||||
const TransformationContext& transformation_context) const override;
|
||||
|
||||
// Adds a bit instruction synonym.
|
||||
void Apply(opt::IRContext* ir_context,
|
||||
TransformationContext* transformation_context) const override;
|
||||
|
||||
protobufs::Transformation ToMessage() const override;
|
||||
|
||||
// Returns the number of fresh ids required to apply the transformation.
|
||||
static uint32_t GetRequiredFreshIdCount(opt::IRContext* ir_context,
|
||||
opt::Instruction* bit_instruction);
|
||||
|
||||
private:
|
||||
protobufs::TransformationAddBitInstructionSynonym message_;
|
||||
|
||||
// Adds an OpBitwise* synonym.
|
||||
void AddBitwiseSynonym(opt::IRContext* ir_context,
|
||||
TransformationContext* transformation_context,
|
||||
opt::Instruction* bitwise_instruction) const;
|
||||
};
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SOURCE_FUZZ_TRANSFORMATION_ADD_BIT_INSTRUCTION_SYNONYM_H_
|
@ -731,3 +731,20 @@ bool spvOpcodeIsAccessChain(SpvOp opcode) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool spvOpcodeIsBit(SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpShiftRightLogical:
|
||||
case SpvOpShiftRightArithmetic:
|
||||
case SpvOpShiftLeftLogical:
|
||||
case SpvOpBitwiseOr:
|
||||
case SpvOpBitwiseXor:
|
||||
case SpvOpBitwiseAnd:
|
||||
case SpvOpNot:
|
||||
case SpvOpBitReverse:
|
||||
case SpvOpBitCount:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -134,17 +134,20 @@ bool spvOpcodeIsDebug(SpvOp opcode);
|
||||
// where the order of the operands is irrelevant.
|
||||
bool spvOpcodeIsCommutativeBinaryOperator(SpvOp opcode);
|
||||
|
||||
// Returns true for opcodes that represents linear algebra instructions.
|
||||
// Returns true for opcodes that represent linear algebra instructions.
|
||||
bool spvOpcodeIsLinearAlgebra(SpvOp opcode);
|
||||
|
||||
// Returns true for opcodes that represents an image sample instruction.
|
||||
// Returns true for opcodes that represent image sample instructions.
|
||||
bool spvOpcodeIsImageSample(SpvOp opcode);
|
||||
|
||||
// Returns a vector containing the indices of the memory semantics <id>
|
||||
// operands for |opcode|.
|
||||
std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode);
|
||||
|
||||
// Returns true for opcodes that represents access chain instructions.
|
||||
// Returns true for opcodes that represent access chain instructions.
|
||||
bool spvOpcodeIsAccessChain(SpvOp opcode);
|
||||
|
||||
// Returns true for opcodes that represent bit instructions.
|
||||
bool spvOpcodeIsBit(SpvOp opcode);
|
||||
|
||||
#endif // SOURCE_OPCODE_H_
|
||||
|
@ -31,6 +31,7 @@ if (${SPIRV_BUILD_FUZZER})
|
||||
fuzzer_pass_test.cpp
|
||||
replayer_test.cpp
|
||||
transformation_access_chain_test.cpp
|
||||
transformation_add_bit_instruction_synonym_test.cpp
|
||||
transformation_add_constant_boolean_test.cpp
|
||||
transformation_add_constant_composite_test.cpp
|
||||
transformation_add_constant_null_test.cpp
|
||||
|
463
test/fuzz/transformation_add_bit_instruction_synonym_test.cpp
Normal file
463
test/fuzz/transformation_add_bit_instruction_synonym_test.cpp
Normal file
@ -0,0 +1,463 @@
|
||||
// Copyright (c) 2020 André Perez Maselco
|
||||
//
|
||||
// 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_add_bit_instruction_synonym.h"
|
||||
#include "source/fuzz/instruction_descriptor.h"
|
||||
#include "test/fuzz/fuzz_test_util.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
namespace {
|
||||
|
||||
TEST(TransformationAddBitInstructionSynonymTest, IsApplicable) {
|
||||
std::string reference_shader = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %37 "main"
|
||||
|
||||
; Types
|
||||
%2 = OpTypeInt 32 0
|
||||
%3 = OpTypeVoid
|
||||
%4 = OpTypeFunction %3
|
||||
|
||||
; Constants
|
||||
%5 = OpConstant %2 0
|
||||
%6 = OpConstant %2 1
|
||||
%7 = OpConstant %2 2
|
||||
%8 = OpConstant %2 3
|
||||
%9 = OpConstant %2 4
|
||||
%10 = OpConstant %2 5
|
||||
%11 = OpConstant %2 6
|
||||
%12 = OpConstant %2 7
|
||||
%13 = OpConstant %2 8
|
||||
%14 = OpConstant %2 9
|
||||
%15 = OpConstant %2 10
|
||||
%16 = OpConstant %2 11
|
||||
%17 = OpConstant %2 12
|
||||
%18 = OpConstant %2 13
|
||||
%19 = OpConstant %2 14
|
||||
%20 = OpConstant %2 15
|
||||
%21 = OpConstant %2 16
|
||||
%22 = OpConstant %2 17
|
||||
%23 = OpConstant %2 18
|
||||
%24 = OpConstant %2 19
|
||||
%25 = OpConstant %2 20
|
||||
%26 = OpConstant %2 21
|
||||
%27 = OpConstant %2 22
|
||||
%28 = OpConstant %2 23
|
||||
%29 = OpConstant %2 24
|
||||
%30 = OpConstant %2 25
|
||||
%31 = OpConstant %2 26
|
||||
%32 = OpConstant %2 27
|
||||
%33 = OpConstant %2 28
|
||||
%34 = OpConstant %2 29
|
||||
%35 = OpConstant %2 30
|
||||
%36 = OpConstant %2 31
|
||||
|
||||
; main function
|
||||
%37 = OpFunction %3 None %4
|
||||
%38 = OpLabel
|
||||
%39 = OpBitwiseOr %2 %5 %6
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const auto env = SPV_ENV_UNIVERSAL_1_5;
|
||||
const auto consumer = nullptr;
|
||||
const auto context =
|
||||
BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
FactManager fact_manager;
|
||||
spvtools::ValidatorOptions validator_options;
|
||||
TransformationContext transformation_context(&fact_manager,
|
||||
validator_options);
|
||||
|
||||
// Tests undefined bit instruction.
|
||||
auto transformation = TransformationAddBitInstructionSynonym(
|
||||
40, {41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
|
||||
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
|
||||
67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
|
||||
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
|
||||
93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
|
||||
106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
|
||||
119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
|
||||
132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
|
||||
145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
|
||||
158, 159, 160, 161, 162, 163, 164, 165, 166, 167});
|
||||
ASSERT_FALSE(
|
||||
transformation.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Tests false bit instruction.
|
||||
transformation = TransformationAddBitInstructionSynonym(
|
||||
38, {40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
|
||||
53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
|
||||
66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
|
||||
79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
|
||||
92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
|
||||
105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
|
||||
118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
|
||||
131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
|
||||
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
|
||||
157, 158, 159, 160, 161, 162, 163, 164, 165, 166});
|
||||
ASSERT_FALSE(
|
||||
transformation.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Tests the number of fresh ids being different than the necessary.
|
||||
transformation = TransformationAddBitInstructionSynonym(
|
||||
39,
|
||||
{40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
|
||||
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
|
||||
68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
|
||||
82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
|
||||
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
||||
110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
|
||||
124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137,
|
||||
138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
|
||||
152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165});
|
||||
ASSERT_FALSE(
|
||||
transformation.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Tests non-fresh ids.
|
||||
transformation = TransformationAddBitInstructionSynonym(
|
||||
39, {38, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
|
||||
78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
|
||||
91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103,
|
||||
104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
|
||||
117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
|
||||
130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
|
||||
143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155,
|
||||
156, 157, 158, 159, 160, 161, 162, 163, 164, 165});
|
||||
ASSERT_FALSE(
|
||||
transformation.IsApplicable(context.get(), transformation_context));
|
||||
|
||||
// Tests applicable transformation.
|
||||
transformation = TransformationAddBitInstructionSynonym(
|
||||
39, {40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
|
||||
53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
|
||||
66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
|
||||
79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
|
||||
92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
|
||||
105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
|
||||
118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
|
||||
131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
|
||||
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
|
||||
157, 158, 159, 160, 161, 162, 163, 164, 165, 166});
|
||||
ASSERT_TRUE(
|
||||
transformation.IsApplicable(context.get(), transformation_context));
|
||||
}
|
||||
|
||||
TEST(TransformationAddBitInstructionSynonymTest, AddBitwiseSynonym) {
|
||||
std::string reference_shader = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %37 "main"
|
||||
|
||||
; Types
|
||||
%2 = OpTypeInt 32 0
|
||||
%3 = OpTypeVoid
|
||||
%4 = OpTypeFunction %3
|
||||
|
||||
; Constants
|
||||
%5 = OpConstant %2 0
|
||||
%6 = OpConstant %2 1
|
||||
%7 = OpConstant %2 2
|
||||
%8 = OpConstant %2 3
|
||||
%9 = OpConstant %2 4
|
||||
%10 = OpConstant %2 5
|
||||
%11 = OpConstant %2 6
|
||||
%12 = OpConstant %2 7
|
||||
%13 = OpConstant %2 8
|
||||
%14 = OpConstant %2 9
|
||||
%15 = OpConstant %2 10
|
||||
%16 = OpConstant %2 11
|
||||
%17 = OpConstant %2 12
|
||||
%18 = OpConstant %2 13
|
||||
%19 = OpConstant %2 14
|
||||
%20 = OpConstant %2 15
|
||||
%21 = OpConstant %2 16
|
||||
%22 = OpConstant %2 17
|
||||
%23 = OpConstant %2 18
|
||||
%24 = OpConstant %2 19
|
||||
%25 = OpConstant %2 20
|
||||
%26 = OpConstant %2 21
|
||||
%27 = OpConstant %2 22
|
||||
%28 = OpConstant %2 23
|
||||
%29 = OpConstant %2 24
|
||||
%30 = OpConstant %2 25
|
||||
%31 = OpConstant %2 26
|
||||
%32 = OpConstant %2 27
|
||||
%33 = OpConstant %2 28
|
||||
%34 = OpConstant %2 29
|
||||
%35 = OpConstant %2 30
|
||||
%36 = OpConstant %2 31
|
||||
|
||||
; main function
|
||||
%37 = OpFunction %3 None %4
|
||||
%38 = OpLabel
|
||||
%39 = OpBitwiseOr %2 %5 %6
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const auto env = SPV_ENV_UNIVERSAL_1_5;
|
||||
const auto consumer = nullptr;
|
||||
const auto context =
|
||||
BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
|
||||
FactManager fact_manager;
|
||||
spvtools::ValidatorOptions validator_options;
|
||||
TransformationContext transformation_context(&fact_manager,
|
||||
validator_options);
|
||||
|
||||
auto transformation = TransformationAddBitInstructionSynonym(
|
||||
39, {40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
|
||||
53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
|
||||
66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
|
||||
79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
|
||||
92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104,
|
||||
105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
|
||||
118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130,
|
||||
131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
|
||||
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
|
||||
157, 158, 159, 160, 161, 162, 163, 164, 165, 166});
|
||||
transformation.Apply(context.get(), &transformation_context);
|
||||
|
||||
std::string variant_shader = R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %37 "main"
|
||||
|
||||
; Types
|
||||
%2 = OpTypeInt 32 0
|
||||
%3 = OpTypeVoid
|
||||
%4 = OpTypeFunction %3
|
||||
|
||||
; Constants
|
||||
%5 = OpConstant %2 0
|
||||
%6 = OpConstant %2 1
|
||||
%7 = OpConstant %2 2
|
||||
%8 = OpConstant %2 3
|
||||
%9 = OpConstant %2 4
|
||||
%10 = OpConstant %2 5
|
||||
%11 = OpConstant %2 6
|
||||
%12 = OpConstant %2 7
|
||||
%13 = OpConstant %2 8
|
||||
%14 = OpConstant %2 9
|
||||
%15 = OpConstant %2 10
|
||||
%16 = OpConstant %2 11
|
||||
%17 = OpConstant %2 12
|
||||
%18 = OpConstant %2 13
|
||||
%19 = OpConstant %2 14
|
||||
%20 = OpConstant %2 15
|
||||
%21 = OpConstant %2 16
|
||||
%22 = OpConstant %2 17
|
||||
%23 = OpConstant %2 18
|
||||
%24 = OpConstant %2 19
|
||||
%25 = OpConstant %2 20
|
||||
%26 = OpConstant %2 21
|
||||
%27 = OpConstant %2 22
|
||||
%28 = OpConstant %2 23
|
||||
%29 = OpConstant %2 24
|
||||
%30 = OpConstant %2 25
|
||||
%31 = OpConstant %2 26
|
||||
%32 = OpConstant %2 27
|
||||
%33 = OpConstant %2 28
|
||||
%34 = OpConstant %2 29
|
||||
%35 = OpConstant %2 30
|
||||
%36 = OpConstant %2 31
|
||||
|
||||
; main function
|
||||
%37 = OpFunction %3 None %4
|
||||
%38 = OpLabel
|
||||
|
||||
%40 = OpBitFieldUExtract %2 %5 %5 %6 ; extracts bit 0 from %5
|
||||
%41 = OpBitFieldUExtract %2 %6 %5 %6 ; extracts bit 0 from %6
|
||||
%42 = OpBitwiseOr %2 %40 %41
|
||||
|
||||
%43 = OpBitFieldUExtract %2 %5 %6 %6 ; extracts bit 1 from %5
|
||||
%44 = OpBitFieldUExtract %2 %6 %6 %6 ; extracts bit 1 from %6
|
||||
%45 = OpBitwiseOr %2 %43 %44
|
||||
|
||||
%46 = OpBitFieldUExtract %2 %5 %7 %6 ; extracts bit 2 from %5
|
||||
%47 = OpBitFieldUExtract %2 %6 %7 %6 ; extracts bit 2 from %6
|
||||
%48 = OpBitwiseOr %2 %46 %47
|
||||
|
||||
%49 = OpBitFieldUExtract %2 %5 %8 %6 ; extracts bit 3 from %5
|
||||
%50 = OpBitFieldUExtract %2 %6 %8 %6 ; extracts bit 3 from %6
|
||||
%51 = OpBitwiseOr %2 %49 %50
|
||||
|
||||
%52 = OpBitFieldUExtract %2 %5 %9 %6 ; extracts bit 4 from %5
|
||||
%53 = OpBitFieldUExtract %2 %6 %9 %6 ; extracts bit 4 from %6
|
||||
%54 = OpBitwiseOr %2 %52 %53
|
||||
|
||||
%55 = OpBitFieldUExtract %2 %5 %10 %6 ; extracts bit 5 from %5
|
||||
%56 = OpBitFieldUExtract %2 %6 %10 %6 ; extracts bit 5 from %6
|
||||
%57 = OpBitwiseOr %2 %55 %56
|
||||
|
||||
%58 = OpBitFieldUExtract %2 %5 %11 %6 ; extracts bit 6 from %5
|
||||
%59 = OpBitFieldUExtract %2 %6 %11 %6 ; extracts bit 6 from %6
|
||||
%60 = OpBitwiseOr %2 %58 %59
|
||||
|
||||
%61 = OpBitFieldUExtract %2 %5 %12 %6 ; extracts bit 7 from %5
|
||||
%62 = OpBitFieldUExtract %2 %6 %12 %6 ; extracts bit 7 from %6
|
||||
%63 = OpBitwiseOr %2 %61 %62
|
||||
|
||||
%64 = OpBitFieldUExtract %2 %5 %13 %6 ; extracts bit 8 from %5
|
||||
%65 = OpBitFieldUExtract %2 %6 %13 %6 ; extracts bit 8 from %6
|
||||
%66 = OpBitwiseOr %2 %64 %65
|
||||
|
||||
%67 = OpBitFieldUExtract %2 %5 %14 %6 ; extracts bit 9 from %5
|
||||
%68 = OpBitFieldUExtract %2 %6 %14 %6 ; extracts bit 9 from %6
|
||||
%69 = OpBitwiseOr %2 %67 %68
|
||||
|
||||
%70 = OpBitFieldUExtract %2 %5 %15 %6 ; extracts bit 10 from %5
|
||||
%71 = OpBitFieldUExtract %2 %6 %15 %6 ; extracts bit 10 from %6
|
||||
%72 = OpBitwiseOr %2 %70 %71
|
||||
|
||||
%73 = OpBitFieldUExtract %2 %5 %16 %6 ; extracts bit 11 from %5
|
||||
%74 = OpBitFieldUExtract %2 %6 %16 %6 ; extracts bit 11 from %6
|
||||
%75 = OpBitwiseOr %2 %73 %74
|
||||
|
||||
%76 = OpBitFieldUExtract %2 %5 %17 %6 ; extracts bit 12 from %5
|
||||
%77 = OpBitFieldUExtract %2 %6 %17 %6 ; extracts bit 12 from %6
|
||||
%78 = OpBitwiseOr %2 %76 %77
|
||||
|
||||
%79 = OpBitFieldUExtract %2 %5 %18 %6 ; extracts bit 13 from %5
|
||||
%80 = OpBitFieldUExtract %2 %6 %18 %6 ; extracts bit 13 from %6
|
||||
%81 = OpBitwiseOr %2 %79 %80
|
||||
|
||||
%82 = OpBitFieldUExtract %2 %5 %19 %6 ; extracts bit 14 from %5
|
||||
%83 = OpBitFieldUExtract %2 %6 %19 %6 ; extracts bit 14 from %6
|
||||
%84 = OpBitwiseOr %2 %82 %83
|
||||
|
||||
%85 = OpBitFieldUExtract %2 %5 %20 %6 ; extracts bit 15 from %5
|
||||
%86 = OpBitFieldUExtract %2 %6 %20 %6 ; extracts bit 15 from %6
|
||||
%87 = OpBitwiseOr %2 %85 %86
|
||||
|
||||
%88 = OpBitFieldUExtract %2 %5 %21 %6 ; extracts bit 16 from %5
|
||||
%89 = OpBitFieldUExtract %2 %6 %21 %6 ; extracts bit 16 from %6
|
||||
%90 = OpBitwiseOr %2 %88 %89
|
||||
|
||||
%91 = OpBitFieldUExtract %2 %5 %22 %6 ; extracts bit 17 from %5
|
||||
%92 = OpBitFieldUExtract %2 %6 %22 %6 ; extracts bit 17 from %6
|
||||
%93 = OpBitwiseOr %2 %91 %92
|
||||
|
||||
%94 = OpBitFieldUExtract %2 %5 %23 %6 ; extracts bit 18 from %5
|
||||
%95 = OpBitFieldUExtract %2 %6 %23 %6 ; extracts bit 18 from %6
|
||||
%96 = OpBitwiseOr %2 %94 %95
|
||||
|
||||
%97 = OpBitFieldUExtract %2 %5 %24 %6 ; extracts bit 19 from %5
|
||||
%98 = OpBitFieldUExtract %2 %6 %24 %6 ; extracts bit 19 from %6
|
||||
%99 = OpBitwiseOr %2 %97 %98
|
||||
|
||||
%100 = OpBitFieldUExtract %2 %5 %25 %6 ; extracts bit 20 from %5
|
||||
%101 = OpBitFieldUExtract %2 %6 %25 %6 ; extracts bit 20 from %6
|
||||
%102 = OpBitwiseOr %2 %100 %101
|
||||
|
||||
%103 = OpBitFieldUExtract %2 %5 %26 %6 ; extracts bit 21 from %5
|
||||
%104 = OpBitFieldUExtract %2 %6 %26 %6 ; extracts bit 21 from %6
|
||||
%105 = OpBitwiseOr %2 %103 %104
|
||||
|
||||
%106 = OpBitFieldUExtract %2 %5 %27 %6 ; extracts bit 22 from %5
|
||||
%107 = OpBitFieldUExtract %2 %6 %27 %6 ; extracts bit 22 from %6
|
||||
%108 = OpBitwiseOr %2 %106 %107
|
||||
|
||||
%109 = OpBitFieldUExtract %2 %5 %28 %6 ; extracts bit 23 from %5
|
||||
%110 = OpBitFieldUExtract %2 %6 %28 %6 ; extracts bit 23 from %6
|
||||
%111 = OpBitwiseOr %2 %109 %110
|
||||
|
||||
%112 = OpBitFieldUExtract %2 %5 %29 %6 ; extracts bit 24 from %5
|
||||
%113 = OpBitFieldUExtract %2 %6 %29 %6 ; extracts bit 24 from %6
|
||||
%114 = OpBitwiseOr %2 %112 %113
|
||||
|
||||
%115 = OpBitFieldUExtract %2 %5 %30 %6 ; extracts bit 25 from %5
|
||||
%116 = OpBitFieldUExtract %2 %6 %30 %6 ; extracts bit 25 from %6
|
||||
%117 = OpBitwiseOr %2 %115 %116
|
||||
|
||||
%118 = OpBitFieldUExtract %2 %5 %31 %6 ; extracts bit 26 from %5
|
||||
%119 = OpBitFieldUExtract %2 %6 %31 %6 ; extracts bit 26 from %6
|
||||
%120 = OpBitwiseOr %2 %118 %119
|
||||
|
||||
%121 = OpBitFieldUExtract %2 %5 %32 %6 ; extracts bit 27 from %5
|
||||
%122 = OpBitFieldUExtract %2 %6 %32 %6 ; extracts bit 27 from %6
|
||||
%123 = OpBitwiseOr %2 %121 %122
|
||||
|
||||
%124 = OpBitFieldUExtract %2 %5 %33 %6 ; extracts bit 28 from %5
|
||||
%125 = OpBitFieldUExtract %2 %6 %33 %6 ; extracts bit 28 from %6
|
||||
%126 = OpBitwiseOr %2 %124 %125
|
||||
|
||||
%127 = OpBitFieldUExtract %2 %5 %34 %6 ; extracts bit 29 from %5
|
||||
%128 = OpBitFieldUExtract %2 %6 %34 %6 ; extracts bit 29 from %6
|
||||
%129 = OpBitwiseOr %2 %127 %128
|
||||
|
||||
%130 = OpBitFieldUExtract %2 %5 %35 %6 ; extracts bit 30 from %5
|
||||
%131 = OpBitFieldUExtract %2 %6 %35 %6 ; extracts bit 30 from %6
|
||||
%132 = OpBitwiseOr %2 %130 %131
|
||||
|
||||
%133 = OpBitFieldUExtract %2 %5 %36 %6 ; extracts bit 31 from %5
|
||||
%134 = OpBitFieldUExtract %2 %6 %36 %6 ; extracts bit 31 from %6
|
||||
%135 = OpBitwiseOr %2 %133 %134
|
||||
|
||||
%136 = OpBitFieldInsert %2 %42 %45 %6 %6 ; inserts bit 1
|
||||
%137 = OpBitFieldInsert %2 %136 %48 %7 %6 ; inserts bit 2
|
||||
%138 = OpBitFieldInsert %2 %137 %51 %8 %6 ; inserts bit 3
|
||||
%139 = OpBitFieldInsert %2 %138 %54 %9 %6 ; inserts bit 4
|
||||
%140 = OpBitFieldInsert %2 %139 %57 %10 %6 ; inserts bit 5
|
||||
%141 = OpBitFieldInsert %2 %140 %60 %11 %6 ; inserts bit 6
|
||||
%142 = OpBitFieldInsert %2 %141 %63 %12 %6 ; inserts bit 7
|
||||
%143 = OpBitFieldInsert %2 %142 %66 %13 %6 ; inserts bit 8
|
||||
%144 = OpBitFieldInsert %2 %143 %69 %14 %6 ; inserts bit 9
|
||||
%145 = OpBitFieldInsert %2 %144 %72 %15 %6 ; inserts bit 10
|
||||
%146 = OpBitFieldInsert %2 %145 %75 %16 %6 ; inserts bit 11
|
||||
%147 = OpBitFieldInsert %2 %146 %78 %17 %6 ; inserts bit 12
|
||||
%148 = OpBitFieldInsert %2 %147 %81 %18 %6 ; inserts bit 13
|
||||
%149 = OpBitFieldInsert %2 %148 %84 %19 %6 ; inserts bit 14
|
||||
%150 = OpBitFieldInsert %2 %149 %87 %20 %6 ; inserts bit 15
|
||||
%151 = OpBitFieldInsert %2 %150 %90 %21 %6 ; inserts bit 16
|
||||
%152 = OpBitFieldInsert %2 %151 %93 %22 %6 ; inserts bit 17
|
||||
%153 = OpBitFieldInsert %2 %152 %96 %23 %6 ; inserts bit 18
|
||||
%154 = OpBitFieldInsert %2 %153 %99 %24 %6 ; inserts bit 19
|
||||
%155 = OpBitFieldInsert %2 %154 %102 %25 %6 ; inserts bit 20
|
||||
%156 = OpBitFieldInsert %2 %155 %105 %26 %6 ; inserts bit 21
|
||||
%157 = OpBitFieldInsert %2 %156 %108 %27 %6 ; inserts bit 22
|
||||
%158 = OpBitFieldInsert %2 %157 %111 %28 %6 ; inserts bit 23
|
||||
%159 = OpBitFieldInsert %2 %158 %114 %29 %6 ; inserts bit 24
|
||||
%160 = OpBitFieldInsert %2 %159 %117 %30 %6 ; inserts bit 25
|
||||
%161 = OpBitFieldInsert %2 %160 %120 %31 %6 ; inserts bit 26
|
||||
%162 = OpBitFieldInsert %2 %161 %123 %32 %6 ; inserts bit 27
|
||||
%163 = OpBitFieldInsert %2 %162 %126 %33 %6 ; inserts bit 28
|
||||
%164 = OpBitFieldInsert %2 %163 %129 %34 %6 ; inserts bit 29
|
||||
%165 = OpBitFieldInsert %2 %164 %132 %35 %6 ; inserts bit 30
|
||||
%166 = OpBitFieldInsert %2 %165 %135 %36 %6 ; inserts bit 31
|
||||
%39 = OpBitwiseOr %2 %5 %6
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
ASSERT_TRUE(IsValid(env, context.get()));
|
||||
ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
|
||||
ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(166, {}),
|
||||
MakeDataDescriptor(39, {})));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
Loading…
Reference in New Issue
Block a user