spirv-fuzz: Rework id descriptors (#2959)

A refactoring that separates the identification of an instruction from
the identification of a use in an instruction, to enable the former to
be used independently of the latter.
This commit is contained in:
Alastair Donaldson 2019-10-11 10:13:06 +01:00 committed by GitHub
parent eba98c4eb7
commit 3eda1b9ff1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 392 additions and 232 deletions

View File

@ -50,6 +50,7 @@ if(SPIRV_BUILD_FUZZER)
fuzzer_pass_split_blocks.h
fuzzer_util.h
id_use_descriptor.h
instruction_descriptor.h
protobufs/spirvfuzz_protobufs.h
pseudo_random_generator.h
random_generator.h
@ -99,6 +100,7 @@ if(SPIRV_BUILD_FUZZER)
fuzzer_pass_split_blocks.cpp
fuzzer_util.cpp
id_use_descriptor.cpp
instruction_descriptor.cpp
pseudo_random_generator.cpp
random_generator.cpp
replayer.cpp

View File

@ -15,6 +15,7 @@
#include "source/fuzz/force_render_red.h"
#include "source/fuzz/fact_manager.h"
#include "source/fuzz/instruction_descriptor.h"
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/transformation_replace_constant_with_uniform.h"
#include "source/fuzz/uniform_buffer_element_descriptor.h"
@ -147,9 +148,10 @@ MakeConstantUniformReplacement(opt::IRContext* ir_context,
uint32_t greater_than_instruction,
uint32_t in_operand_index) {
return MakeUnique<TransformationReplaceConstantWithUniform>(
transformation::MakeIdUseDescriptor(constant_id, SpvOpFOrdGreaterThan,
in_operand_index,
greater_than_instruction, 0),
MakeIdUseDescriptor(constant_id,
MakeInstructionDescriptor(greater_than_instruction,
SpvOpFOrdGreaterThan, 0),
in_operand_index),
fact_manager.GetUniformDescriptorsForConstant(ir_context, constant_id)[0],
ir_context->TakeNextId(), ir_context->TakeNextId());
}

View File

@ -85,8 +85,8 @@ void FuzzerPassApplyIdSynonyms::Apply() {
: GetFuzzerContext()->GetFreshId();
TransformationReplaceIdWithSynonym replace_id_transformation(
transformation::MakeIdUseDescriptorFromUse(
GetIRContext(), use_inst, use_in_operand_index),
MakeIdUseDescriptorFromUse(GetIRContext(), use_inst,
use_in_operand_index),
*synonym_to_try, fresh_id_for_temporary);
// The transformation should be applicable by construction.

View File

@ -16,6 +16,7 @@
#include <cmath>
#include "source/fuzz/instruction_descriptor.h"
#include "source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h"
#include "source/fuzz/transformation_replace_constant_with_uniform.h"
#include "source/opt/ir_context.h"
@ -102,10 +103,11 @@ void FuzzerPassObfuscateConstants::ObfuscateBoolConstantViaConstantPair(
// We randomly decide, based on the current depth of obfuscation, whether
// to further obfuscate this operand.
if (GetFuzzerContext()->GoDeeperInConstantObfuscation(depth)) {
auto in_operand_use = transformation::MakeIdUseDescriptor(
auto in_operand_use = MakeIdUseDescriptor(
binary_operator_instruction->GetSingleWordInOperand(index),
binary_operator_instruction->opcode(), index,
binary_operator_instruction->result_id(), 0);
MakeInstructionDescriptor(binary_operator_instruction->result_id(),
binary_operator_instruction->opcode(), 0),
index);
ObfuscateConstant(depth + 1, in_operand_use);
}
}
@ -366,14 +368,17 @@ void FuzzerPassObfuscateConstants::MaybeAddConstantIdUse(
// it.
protobufs::IdUseDescriptor id_use_descriptor;
id_use_descriptor.set_id_of_interest(operand_id);
id_use_descriptor.set_target_instruction_opcode(inst.opcode());
id_use_descriptor.mutable_enclosing_instruction()
->set_target_instruction_opcode(inst.opcode());
id_use_descriptor.mutable_enclosing_instruction()
->set_base_instruction_result_id(base_instruction_result_id);
id_use_descriptor.mutable_enclosing_instruction()
->set_num_opcodes_to_ignore(
skipped_opcode_count.find(inst.opcode()) ==
skipped_opcode_count.end()
? 0
: skipped_opcode_count.at(inst.opcode()));
id_use_descriptor.set_in_operand_index(in_operand_index);
id_use_descriptor.set_base_instruction_result_id(
base_instruction_result_id);
id_use_descriptor.set_num_opcodes_to_ignore(
skipped_opcode_count.find(inst.opcode()) == skipped_opcode_count.end()
? 0
: skipped_opcode_count.at(inst.opcode()));
constant_uses->push_back(id_use_descriptor);
} break;
default:

View File

@ -14,71 +14,41 @@
#include "source/fuzz/id_use_descriptor.h"
#include "source/fuzz/instruction_descriptor.h"
namespace spvtools {
namespace fuzz {
opt::Instruction* transformation::FindInstruction(
const protobufs::IdUseDescriptor& descriptor,
spvtools::opt::IRContext* context) {
for (auto& function : *context->module()) {
for (auto& block : function) {
bool found_base = block.id() == descriptor.base_instruction_result_id();
uint32_t num_ignored = 0;
for (auto& instruction : block) {
if (instruction.HasResultId() &&
instruction.result_id() ==
descriptor.base_instruction_result_id()) {
assert(!found_base &&
"It should not be possible to find the base instruction "
"multiple times.");
found_base = true;
assert(num_ignored == 0 &&
"The skipped instruction count should only be incremented "
"after the instruction base has been found.");
}
if (found_base &&
instruction.opcode() == descriptor.target_instruction_opcode()) {
if (num_ignored == descriptor.num_opcodes_to_ignore()) {
if (descriptor.in_operand_index() >= instruction.NumInOperands()) {
return nullptr;
}
auto in_operand =
instruction.GetInOperand(descriptor.in_operand_index());
if (in_operand.type != SPV_OPERAND_TYPE_ID) {
return nullptr;
}
if (in_operand.words[0] != descriptor.id_of_interest()) {
return nullptr;
}
return &instruction;
}
num_ignored++;
}
}
if (found_base) {
// We found the base instruction, but did not find the target
// instruction in the same block.
return nullptr;
}
}
opt::Instruction* FindInstructionContainingUse(
const protobufs::IdUseDescriptor& id_use_descriptor,
opt::IRContext* context) {
auto result =
FindInstruction(id_use_descriptor.enclosing_instruction(), context);
if (!result) {
return nullptr;
}
if (id_use_descriptor.in_operand_index() >= result->NumInOperands()) {
return nullptr;
}
if (result->GetSingleWordInOperand(id_use_descriptor.in_operand_index()) !=
id_use_descriptor.id_of_interest()) {
return nullptr;
}
return nullptr;
}
protobufs::IdUseDescriptor transformation::MakeIdUseDescriptor(
uint32_t id_of_interest, SpvOp target_instruction_opcode,
uint32_t in_operand_index, uint32_t base_instruction_result_id,
uint32_t num_opcodes_to_ignore) {
protobufs::IdUseDescriptor result;
result.set_id_of_interest(id_of_interest);
result.set_target_instruction_opcode(target_instruction_opcode);
result.set_in_operand_index(in_operand_index);
result.set_base_instruction_result_id(base_instruction_result_id);
result.set_num_opcodes_to_ignore(num_opcodes_to_ignore);
return result;
}
protobufs::IdUseDescriptor transformation::MakeIdUseDescriptorFromUse(
protobufs::IdUseDescriptor MakeIdUseDescriptor(
uint32_t id_of_interest,
const protobufs::InstructionDescriptor& enclosing_instruction,
uint32_t in_operand_index) {
protobufs::IdUseDescriptor result;
result.set_id_of_interest(id_of_interest);
*result.mutable_enclosing_instruction() = enclosing_instruction;
result.set_in_operand_index(in_operand_index);
return result;
}
protobufs::IdUseDescriptor MakeIdUseDescriptorFromUse(
opt::IRContext* context, opt::Instruction* inst,
uint32_t in_operand_index) {
auto in_operand = inst->GetInOperand(in_operand_index);
@ -94,9 +64,11 @@ protobufs::IdUseDescriptor transformation::MakeIdUseDescriptorFromUse(
num_opcodes_to_ignore = 0;
}
if (&inst_in_block == inst) {
return MakeIdUseDescriptor(id_of_interest, inst->opcode(),
in_operand_index, base_instruction_result_id,
num_opcodes_to_ignore);
return MakeIdUseDescriptor(
id_of_interest,
MakeInstructionDescriptor(base_instruction_result_id, inst->opcode(),
num_opcodes_to_ignore),
in_operand_index);
}
if (inst_in_block.opcode() == inst->opcode()) {
num_opcodes_to_ignore++;

View File

@ -12,28 +12,28 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SOURCE_FUZZ_ID_USE_LOCATOR_H_
#define SOURCE_FUZZ_ID_USE_LOCATOR_H_
#ifndef SOURCE_FUZZ_ID_USE_DESCRIPTOR_H_
#define SOURCE_FUZZ_ID_USE_DESCRIPTOR_H_
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/opt/ir_context.h"
namespace spvtools {
namespace fuzz {
namespace transformation {
// Looks for an instruction in |context| such that the id use represented by
// |descriptor| is one of the operands to said instruction. Returns |nullptr|
// if no such instruction can be found.
opt::Instruction* FindInstruction(const protobufs::IdUseDescriptor& descriptor,
opt::IRContext* context);
// Looks for an instruction in |context| that contains a use
// identified by |id_use_descriptor|.
// Returns |nullptr| if no such instruction can be found.
opt::Instruction* FindInstructionContainingUse(
const protobufs::IdUseDescriptor& id_use_descriptor,
opt::IRContext* context);
// Creates an IdUseDescriptor protobuf message from the given components.
// See the protobuf definition for details of what these components mean.
protobufs::IdUseDescriptor MakeIdUseDescriptor(
uint32_t id_of_interest, SpvOp target_instruction_opcode,
uint32_t in_operand_index, uint32_t base_instruction_result_id,
uint32_t num_opcodes_to_ignore);
uint32_t id_of_interest,
const protobufs::InstructionDescriptor& enclosing_instruction,
uint32_t in_operand_index);
// Given an id use, represented by the instruction |inst| that uses the id, and
// the input operand index |in_operand_index| associated with the usage, returns
@ -41,8 +41,7 @@ protobufs::IdUseDescriptor MakeIdUseDescriptor(
protobufs::IdUseDescriptor MakeIdUseDescriptorFromUse(
opt::IRContext* context, opt::Instruction* inst, uint32_t in_operand_index);
} // namespace transformation
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_ID_USE_LOCATOR_H_
#endif // SOURCE_FUZZ_ID_USE_DESCRIPTOR_H_

View File

@ -0,0 +1,70 @@
// Copyright (c) 2019 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/instruction_descriptor.h"
namespace spvtools {
namespace fuzz {
opt::Instruction* FindInstruction(
const protobufs::InstructionDescriptor& instruction_descriptor,
spvtools::opt::IRContext* context) {
for (auto& function : *context->module()) {
for (auto& block : function) {
bool found_base =
block.id() == instruction_descriptor.base_instruction_result_id();
uint32_t num_ignored = 0;
for (auto& instruction : block) {
if (instruction.HasResultId() &&
instruction.result_id() ==
instruction_descriptor.base_instruction_result_id()) {
assert(!found_base &&
"It should not be possible to find the base instruction "
"multiple times.");
found_base = true;
assert(num_ignored == 0 &&
"The skipped instruction count should only be incremented "
"after the instruction base has been found.");
}
if (found_base &&
instruction.opcode() ==
instruction_descriptor.target_instruction_opcode()) {
if (num_ignored == instruction_descriptor.num_opcodes_to_ignore()) {
return &instruction;
}
num_ignored++;
}
}
if (found_base) {
// We found the base instruction, but did not find the target
// instruction in the same block.
return nullptr;
}
}
}
return nullptr;
}
protobufs::InstructionDescriptor MakeInstructionDescriptor(
uint32_t base_instruction_result_id, SpvOp target_instruction_opcode,
uint32_t num_opcodes_to_ignore) {
protobufs::InstructionDescriptor result;
result.set_base_instruction_result_id(base_instruction_result_id);
result.set_target_instruction_opcode(target_instruction_opcode);
result.set_num_opcodes_to_ignore(num_opcodes_to_ignore);
return result;
}
} // namespace fuzz
} // namespace spvtools

View File

@ -0,0 +1,40 @@
// Copyright (c) 2019 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_INSTRUCTION_DESCRIPTOR_H_
#define SOURCE_FUZZ_INSTRUCTION_DESCRIPTOR_H_
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/opt/ir_context.h"
namespace spvtools {
namespace fuzz {
// Looks for an instruction in |context| corresponding to |descriptor|.
// Returns |nullptr| if no such instruction can be found.
opt::Instruction* FindInstruction(
const protobufs::InstructionDescriptor& instruction_descriptor,
opt::IRContext* context);
// Creates an InstructionDescriptor protobuf message from the given
// components. See the protobuf definition for details of what these
// components mean.
protobufs::InstructionDescriptor MakeInstructionDescriptor(
uint32_t base_instruction_result_id, SpvOp target_instruction_opcode,
uint32_t num_opcodes_to_ignore);
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_INSTRUCTION_DESCRIPTOR_H_

View File

@ -21,6 +21,24 @@ syntax = "proto3";
package spvtools.fuzz.protobufs;
message InstructionDescriptor {
// Describes an instruction in some block of a function with respect to a
// base instruction.
// The id of an instruction after which the instruction being described is
// believed to be located. It might be the using instruction itself.
uint32 base_instruction_result_id = 1;
// The opcode for the instruction being described.
uint32 target_instruction_opcode = 2;
// The number of matching opcodes to skip over when searching from the base
// instruction to the instruction being described.
uint32 num_opcodes_to_ignore = 3;
}
message IdUseDescriptor {
// Describes a use of an id as an input operand to an instruction in some
@ -28,10 +46,12 @@ message IdUseDescriptor {
// Example:
// - id_of_interest = 42
// - target_instruction_opcode = OpStore
// - enclosing_instruction = (
// base_instruction_result_id = 50,
// target_instruction_opcode = OpStore
// num_opcodes_to_ignore = 7
// )
// - in_operand_index = 1
// - base_instruction_result_id = 50
// - num_opcodes_to_ignore = 7
// represents a use of id 42 as input operand 1 to an OpStore instruction,
// such that the OpStore instruction can be found in the same basic block as
// the instruction with result id 50, and in particular is the 8th OpStore
@ -41,20 +61,11 @@ message IdUseDescriptor {
// An id that we would like to be able to find a use of.
uint32 id_of_interest = 1;
// The opcode for the instruction that uses the id.
uint32 target_instruction_opcode = 2;
// The input operand index at which the use is expected.
InstructionDescriptor enclosing_instruction = 2;
uint32 in_operand_index = 3;
// The id of an instruction after which the instruction that contains the use
// is believed to occur; it might be the using instruction itself.
uint32 base_instruction_result_id = 4;
// The number of matching opcodes to skip over when searching for the using
// instruction from the base instruction.
uint32 num_opcodes_to_ignore = 5;
}
message DataDescriptor {

View File

@ -238,7 +238,7 @@ bool TransformationReplaceBooleanConstantWithConstantBinary::IsApplicable(
// The id use descriptor must identify some instruction
auto instruction =
transformation::FindInstruction(message_.id_use_descriptor(), context);
FindInstructionContainingUse(message_.id_use_descriptor(), context);
if (instruction == nullptr) {
return false;
}
@ -268,7 +268,7 @@ TransformationReplaceBooleanConstantWithConstantBinary::ApplyWithResult(
message_.fresh_id_for_binary_operation(), operands);
opt::Instruction* result = binary_instruction.get();
auto instruction_containing_constant_use =
transformation::FindInstruction(message_.id_use_descriptor(), context);
FindInstructionContainingUse(message_.id_use_descriptor(), context);
// We want to insert the new instruction before the instruction that contains
// the use of the boolean, but we need to go backwards one more instruction if

View File

@ -149,7 +149,7 @@ bool TransformationReplaceConstantWithUniform::IsApplicable(
// The id use descriptor must identify some instruction with respect to the
// module.
auto instruction_using_constant =
transformation::FindInstruction(message_.id_use_descriptor(), context);
FindInstructionContainingUse(message_.id_use_descriptor(), context);
if (!instruction_using_constant) {
return false;
}
@ -188,7 +188,7 @@ void TransformationReplaceConstantWithUniform::Apply(
spvtools::fuzz::FactManager* /*unused*/) const {
// Get the instruction that contains the id use we wish to replace.
auto instruction_containing_constant_use =
transformation::FindInstruction(message_.id_use_descriptor(), context);
FindInstructionContainingUse(message_.id_use_descriptor(), context);
assert(instruction_containing_constant_use &&
"Precondition requires that the id use can be found.");
assert(instruction_containing_constant_use->GetSingleWordInOperand(

View File

@ -62,7 +62,7 @@ bool TransformationReplaceIdWithSynonym::IsApplicable(
// Does the id use descriptor in the transformation identify an instruction?
auto use_instruction =
transformation::FindInstruction(message_.id_use_descriptor(), context);
FindInstructionContainingUse(message_.id_use_descriptor(), context);
if (!use_instruction) {
return false;
}
@ -101,7 +101,7 @@ void TransformationReplaceIdWithSynonym::Apply(
spvtools::opt::IRContext* context,
spvtools::fuzz::FactManager* /*unused*/) const {
auto instruction_to_change =
transformation::FindInstruction(message_.id_use_descriptor(), context);
FindInstructionContainingUse(message_.id_use_descriptor(), context);
// Ultimately we are going to replace the id use identified in the
// transformation with |replacement_id|, which will either be the synonym's

View File

@ -16,6 +16,7 @@
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/id_use_descriptor.h"
#include "source/fuzz/instruction_descriptor.h"
#include "test/fuzz/fuzz_test_util.h"
namespace spvtools {
@ -164,12 +165,14 @@ TEST(TransformationReplaceBooleanConstantWithConstantBinaryTest,
FactManager fact_manager;
std::vector<protobufs::IdUseDescriptor> uses_of_true = {
transformation::MakeIdUseDescriptor(41, SpvOpStore, 1, 44, 12),
transformation::MakeIdUseDescriptor(41, SpvOpLogicalOr, 0, 46, 0)};
MakeIdUseDescriptor(41, MakeInstructionDescriptor(44, SpvOpStore, 12), 1),
MakeIdUseDescriptor(41, MakeInstructionDescriptor(46, SpvOpLogicalOr, 0),
0)};
std::vector<protobufs::IdUseDescriptor> uses_of_false = {
transformation::MakeIdUseDescriptor(43, SpvOpStore, 1, 44, 13),
transformation::MakeIdUseDescriptor(43, SpvOpLogicalAnd, 1, 48, 0)};
MakeIdUseDescriptor(43, MakeInstructionDescriptor(44, SpvOpStore, 13), 1),
MakeIdUseDescriptor(43, MakeInstructionDescriptor(48, SpvOpLogicalAnd, 0),
1)};
const uint32_t fresh_id = 100;
@ -529,10 +532,10 @@ TEST(TransformationReplaceBooleanConstantWithConstantBinaryTest,
FactManager fact_manager;
auto use_of_true_in_if =
transformation::MakeIdUseDescriptor(13, SpvOpBranchConditional, 0, 10, 0);
auto use_of_false_in_while =
transformation::MakeIdUseDescriptor(21, SpvOpBranchConditional, 0, 16, 0);
auto use_of_true_in_if = MakeIdUseDescriptor(
13, MakeInstructionDescriptor(10, SpvOpBranchConditional, 0), 0);
auto use_of_false_in_while = MakeIdUseDescriptor(
21, MakeInstructionDescriptor(16, SpvOpBranchConditional, 0), 0);
auto replacement_1 = TransformationReplaceBooleanConstantWithConstantBinary(
use_of_true_in_if, 9, 11, SpvOpSLessThan, 100);
@ -641,8 +644,8 @@ TEST(TransformationReplaceBooleanConstantWithConstantBinaryTest, OpPhi) {
FactManager fact_manager;
auto replacement = TransformationReplaceBooleanConstantWithConstantBinary(
transformation::MakeIdUseDescriptor(9, SpvOpPhi, 0, 23, 0), 13, 15,
SpvOpSLessThan, 100);
MakeIdUseDescriptor(9, MakeInstructionDescriptor(23, SpvOpPhi, 0), 0), 13,
15, SpvOpSLessThan, 100);
ASSERT_FALSE(replacement.IsApplicable(context.get(), fact_manager));
}

View File

@ -13,6 +13,7 @@
// limitations under the License.
#include "source/fuzz/transformation_replace_constant_with_uniform.h"
#include "source/fuzz/instruction_descriptor.h"
#include "source/fuzz/uniform_buffer_element_descriptor.h"
#include "test/fuzz/fuzz_test_util.h"
@ -116,11 +117,11 @@ TEST(TransformationReplaceConstantWithUniformTest, BasicReplacements) {
// The constant ids are 9, 11 and 14, for 1, 2 and 3 respectively.
protobufs::IdUseDescriptor use_of_9_in_store =
transformation::MakeIdUseDescriptor(9, SpvOpStore, 1, 8, 0);
MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1);
protobufs::IdUseDescriptor use_of_11_in_add =
transformation::MakeIdUseDescriptor(11, SpvOpIAdd, 1, 12, 0);
MakeIdUseDescriptor(11, MakeInstructionDescriptor(12, SpvOpIAdd, 0), 1);
protobufs::IdUseDescriptor use_of_14_in_add =
transformation::MakeIdUseDescriptor(14, SpvOpIAdd, 0, 15, 0);
MakeIdUseDescriptor(14, MakeInstructionDescriptor(15, SpvOpIAdd, 0), 0);
// These transformations work: they match the facts.
auto transformation_use_of_9_in_store =
@ -167,7 +168,7 @@ TEST(TransformationReplaceConstantWithUniformTest, BasicReplacements) {
// The following transformation does not apply because the id descriptor is
// not sensible.
protobufs::IdUseDescriptor nonsense_id_use_descriptor =
transformation::MakeIdUseDescriptor(9, SpvOpIAdd, 0, 15, 0);
MakeIdUseDescriptor(9, MakeInstructionDescriptor(15, SpvOpIAdd, 0), 0);
ASSERT_FALSE(TransformationReplaceConstantWithUniform(
nonsense_id_use_descriptor, blockname_a, 101, 102)
.IsApplicable(context.get(), fact_manager));
@ -477,13 +478,13 @@ TEST(TransformationReplaceConstantWithUniformTest, NestedStruct) {
// The constant ids are 13, 15, 17 and 20, for 1, 2, 3 and 4 respectively.
protobufs::IdUseDescriptor use_of_13_in_store =
transformation::MakeIdUseDescriptor(13, SpvOpStore, 1, 21, 0);
MakeIdUseDescriptor(13, MakeInstructionDescriptor(21, SpvOpStore, 0), 1);
protobufs::IdUseDescriptor use_of_15_in_add =
transformation::MakeIdUseDescriptor(15, SpvOpIAdd, 1, 16, 0);
MakeIdUseDescriptor(15, MakeInstructionDescriptor(16, SpvOpIAdd, 0), 1);
protobufs::IdUseDescriptor use_of_17_in_add =
transformation::MakeIdUseDescriptor(17, SpvOpIAdd, 0, 19, 0);
MakeIdUseDescriptor(17, MakeInstructionDescriptor(19, SpvOpIAdd, 0), 0);
protobufs::IdUseDescriptor use_of_20_in_store =
transformation::MakeIdUseDescriptor(20, SpvOpStore, 1, 19, 1);
MakeIdUseDescriptor(20, MakeInstructionDescriptor(19, SpvOpStore, 1), 1);
// These transformations work: they match the facts.
auto transformation_use_of_13_in_store =
@ -703,7 +704,7 @@ TEST(TransformationReplaceConstantWithUniformTest, NoUniformIntPointerPresent) {
// The constant id is 9 for 0.
protobufs::IdUseDescriptor use_of_9_in_store =
transformation::MakeIdUseDescriptor(9, SpvOpStore, 1, 8, 0);
MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1);
// This transformation is not available because no uniform pointer to integer
// type is present:
@ -778,7 +779,7 @@ TEST(TransformationReplaceConstantWithUniformTest, NoConstantPresentForIndex) {
// The constant id is 9 for 9.
protobufs::IdUseDescriptor use_of_9_in_store =
transformation::MakeIdUseDescriptor(9, SpvOpStore, 1, 8, 0);
MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1);
// This transformation is not available because no constant is present for the
// index 1 required to index into the uniform buffer:
@ -852,7 +853,7 @@ TEST(TransformationReplaceConstantWithUniformTest,
// The constant id is 9 for 3.0.
protobufs::IdUseDescriptor use_of_9_in_store =
transformation::MakeIdUseDescriptor(9, SpvOpStore, 1, 8, 0);
MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1);
// This transformation is not available because no integer type is present to
// allow a constant index to be expressed:
@ -937,9 +938,9 @@ TEST(TransformationReplaceConstantWithUniformTest,
// The constant ids for 9 and 10 are 9 and 11 respectively
protobufs::IdUseDescriptor use_of_9_in_store =
transformation::MakeIdUseDescriptor(9, SpvOpStore, 1, 10, 0);
MakeIdUseDescriptor(9, MakeInstructionDescriptor(10, SpvOpStore, 0), 1);
protobufs::IdUseDescriptor use_of_11_in_store =
transformation::MakeIdUseDescriptor(11, SpvOpStore, 1, 10, 1);
MakeIdUseDescriptor(11, MakeInstructionDescriptor(10, SpvOpStore, 1), 1);
// These are right:
ASSERT_TRUE(TransformationReplaceConstantWithUniform(use_of_9_in_store,
@ -1220,58 +1221,58 @@ TEST(TransformationReplaceConstantWithUniformTest, ComplexReplacements) {
std::vector<TransformationReplaceConstantWithUniform> transformations;
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(18, SpvOpStore, 1, 20, 0),
MakeIdUseDescriptor(18, MakeInstructionDescriptor(20, SpvOpStore, 0), 1),
uniform_f_a_4, 200, 201));
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(22, SpvOpStore, 1, 23, 0),
MakeIdUseDescriptor(22, MakeInstructionDescriptor(23, SpvOpStore, 0), 1),
uniform_f_a_3, 202, 203));
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(25, SpvOpStore, 1, 26, 0),
MakeIdUseDescriptor(25, MakeInstructionDescriptor(26, SpvOpStore, 0), 1),
uniform_f_a_2, 204, 205));
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(28, SpvOpStore, 1, 29, 0),
MakeIdUseDescriptor(28, MakeInstructionDescriptor(29, SpvOpStore, 0), 1),
uniform_f_a_1, 206, 207));
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(31, SpvOpStore, 1, 32, 0),
MakeIdUseDescriptor(31, MakeInstructionDescriptor(32, SpvOpStore, 0), 1),
uniform_f_a_0, 208, 209));
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(30, SpvOpStore, 1, 35, 0),
MakeIdUseDescriptor(30, MakeInstructionDescriptor(35, SpvOpStore, 0), 1),
uniform_f_b_w, 210, 211));
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(27, SpvOpStore, 1, 37, 0),
MakeIdUseDescriptor(27, MakeInstructionDescriptor(37, SpvOpStore, 0), 1),
uniform_f_b_z, 212, 213));
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(24, SpvOpStore, 1, 39, 0),
MakeIdUseDescriptor(24, MakeInstructionDescriptor(39, SpvOpStore, 0), 1),
uniform_f_b_y, 214, 215));
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(21, SpvOpStore, 1, 41, 0),
MakeIdUseDescriptor(21, MakeInstructionDescriptor(41, SpvOpStore, 0), 1),
uniform_f_b_x, 216, 217));
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(44, SpvOpStore, 1, 45, 0),
MakeIdUseDescriptor(44, MakeInstructionDescriptor(45, SpvOpStore, 0), 1),
uniform_f_c_z, 220, 221));
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(46, SpvOpStore, 1, 47, 0),
MakeIdUseDescriptor(46, MakeInstructionDescriptor(47, SpvOpStore, 0), 1),
uniform_f_c_y, 222, 223));
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(48, SpvOpStore, 1, 49, 0),
MakeIdUseDescriptor(48, MakeInstructionDescriptor(49, SpvOpStore, 0), 1),
uniform_f_c_x, 224, 225));
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(50, SpvOpStore, 1, 52, 0),
MakeIdUseDescriptor(50, MakeInstructionDescriptor(52, SpvOpStore, 0), 1),
uniform_f_d, 226, 227));
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(53, SpvOpStore, 1, 54, 0),
MakeIdUseDescriptor(53, MakeInstructionDescriptor(54, SpvOpStore, 0), 1),
uniform_h_x, 228, 229));
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(55, SpvOpStore, 1, 56, 0),
MakeIdUseDescriptor(55, MakeInstructionDescriptor(56, SpvOpStore, 0), 1),
uniform_h_y, 230, 231));
transformations.emplace_back(TransformationReplaceConstantWithUniform(
transformation::MakeIdUseDescriptor(42, SpvOpStore, 1, 43, 0), uniform_g,
218, 219));
MakeIdUseDescriptor(42, MakeInstructionDescriptor(43, SpvOpStore, 0), 1),
uniform_g, 218, 219));
for (auto& transformation : transformations) {
ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));

View File

@ -15,6 +15,7 @@
#include "source/fuzz/transformation_replace_id_with_synonym.h"
#include "source/fuzz/data_descriptor.h"
#include "source/fuzz/id_use_descriptor.h"
#include "source/fuzz/instruction_descriptor.h"
#include "test/fuzz/fuzz_test_util.h"
namespace spvtools {
@ -226,7 +227,7 @@ TEST(TransformationReplaceIdWithSynonymTest, IllegalTransformations) {
// %202 cannot replace %15 as in-operand 0 of %300, since %202 does not
// dominate %300.
auto synonym_does_not_dominate_use = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(15, SpvOpIAdd, 0, 300, 0),
MakeIdUseDescriptor(15, MakeInstructionDescriptor(300, SpvOpIAdd, 0), 0),
MakeDataDescriptor(202, {}), 0);
ASSERT_FALSE(
synonym_does_not_dominate_use.IsApplicable(context.get(), fact_manager));
@ -235,28 +236,31 @@ TEST(TransformationReplaceIdWithSynonymTest, IllegalTransformations) {
// incoming value for block %72, and %202 does not dominate %72.
auto synonym_does_not_dominate_use_op_phi =
TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(15, SpvOpPhi, 2, 301, 0),
MakeIdUseDescriptor(15, MakeInstructionDescriptor(301, SpvOpPhi, 0),
2),
MakeDataDescriptor(202, {}), 0);
ASSERT_FALSE(synonym_does_not_dominate_use_op_phi.IsApplicable(context.get(),
fact_manager));
// %200 is not a synonym for %84
auto id_in_use_is_not_synonymous = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(84, SpvOpSGreaterThan, 0, 67, 0),
MakeIdUseDescriptor(
84, MakeInstructionDescriptor(67, SpvOpSGreaterThan, 0), 0),
MakeDataDescriptor(200, {}), 0);
ASSERT_FALSE(
id_in_use_is_not_synonymous.IsApplicable(context.get(), fact_manager));
// %86 is not a synonym for anything (and in particular not for %74)
auto id_has_no_synonyms = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(86, SpvOpPhi, 2, 84, 0),
MakeIdUseDescriptor(86, MakeInstructionDescriptor(84, SpvOpPhi, 0), 2),
MakeDataDescriptor(74, {}), 0);
ASSERT_FALSE(id_has_no_synonyms.IsApplicable(context.get(), fact_manager));
// This would lead to %207 = 'OpCopyObject %type %207' if it were allowed
auto synonym_use_is_in_synonym_definition =
TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(84, SpvOpCopyObject, 0, 207, 0),
MakeIdUseDescriptor(
84, MakeInstructionDescriptor(207, SpvOpCopyObject, 0), 0),
MakeDataDescriptor(207, {}), 0);
ASSERT_FALSE(synonym_use_is_in_synonym_definition.IsApplicable(context.get(),
fact_manager));
@ -264,14 +268,16 @@ TEST(TransformationReplaceIdWithSynonymTest, IllegalTransformations) {
// The id use descriptor does not lead to a use (%84 is not used in the
// definition of %207)
auto bad_id_use_descriptor = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(84, SpvOpCopyObject, 0, 200, 0),
MakeIdUseDescriptor(
84, MakeInstructionDescriptor(200, SpvOpCopyObject, 0), 0),
MakeDataDescriptor(207, {}), 0);
ASSERT_FALSE(bad_id_use_descriptor.IsApplicable(context.get(), fact_manager));
// This replacement would lead to an access chain into a struct using a
// non-constant index.
auto bad_access_chain = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(12, SpvOpAccessChain, 1, 14, 0),
MakeIdUseDescriptor(
12, MakeInstructionDescriptor(14, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(209, {}), 0);
ASSERT_FALSE(bad_access_chain.IsApplicable(context.get(), fact_manager));
}
@ -287,7 +293,7 @@ TEST(TransformationReplaceIdWithSynonymTest, LegalTransformations) {
SetUpIdSynonyms(&fact_manager, context.get());
auto global_constant_synonym = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(19, SpvOpStore, 1, 47, 0),
MakeIdUseDescriptor(19, MakeInstructionDescriptor(47, SpvOpStore, 0), 1),
MakeDataDescriptor(210, {}), 0);
ASSERT_TRUE(
global_constant_synonym.IsApplicable(context.get(), fact_manager));
@ -295,7 +301,8 @@ TEST(TransformationReplaceIdWithSynonymTest, LegalTransformations) {
ASSERT_TRUE(IsValid(env, context.get()));
auto replace_vector_access_chain_index = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(54, SpvOpAccessChain, 1, 55, 0),
MakeIdUseDescriptor(
54, MakeInstructionDescriptor(55, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(204, {}), 0);
ASSERT_TRUE(replace_vector_access_chain_index.IsApplicable(context.get(),
fact_manager));
@ -305,21 +312,22 @@ TEST(TransformationReplaceIdWithSynonymTest, LegalTransformations) {
// This is an interesting case because it replaces something that is being
// copied with something that is already a synonym.
auto regular_replacement = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(15, SpvOpCopyObject, 0, 202, 0),
MakeIdUseDescriptor(
15, MakeInstructionDescriptor(202, SpvOpCopyObject, 0), 0),
MakeDataDescriptor(201, {}), 0);
ASSERT_TRUE(regular_replacement.IsApplicable(context.get(), fact_manager));
regular_replacement.Apply(context.get(), &fact_manager);
ASSERT_TRUE(IsValid(env, context.get()));
auto regular_replacement2 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(55, SpvOpStore, 0, 203, 0),
MakeIdUseDescriptor(55, MakeInstructionDescriptor(203, SpvOpStore, 0), 0),
MakeDataDescriptor(203, {}), 0);
ASSERT_TRUE(regular_replacement2.IsApplicable(context.get(), fact_manager));
regular_replacement2.Apply(context.get(), &fact_manager);
ASSERT_TRUE(IsValid(env, context.get()));
auto good_op_phi = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(74, SpvOpPhi, 2, 86, 0),
MakeIdUseDescriptor(74, MakeInstructionDescriptor(86, SpvOpPhi, 0), 2),
MakeDataDescriptor(205, {}), 0);
ASSERT_TRUE(good_op_phi.IsApplicable(context.get(), fact_manager));
good_op_phi.Apply(context.get(), &fact_manager);
@ -503,7 +511,7 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfVariables) {
// Replace %10 with %100 in:
// %11 = OpLoad %6 %10
auto replacement1 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(10, SpvOpLoad, 0, 11, 0),
MakeIdUseDescriptor(10, MakeInstructionDescriptor(11, SpvOpLoad, 0), 0),
MakeDataDescriptor(100, {}), 0);
ASSERT_TRUE(replacement1.IsApplicable(context.get(), fact_manager));
replacement1.Apply(context.get(), &fact_manager);
@ -512,7 +520,7 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfVariables) {
// Replace %8 with %101 in:
// OpStore %8 %11
auto replacement2 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(8, SpvOpStore, 0, 11, 0),
MakeIdUseDescriptor(8, MakeInstructionDescriptor(11, SpvOpStore, 0), 0),
MakeDataDescriptor(101, {}), 0);
ASSERT_TRUE(replacement2.IsApplicable(context.get(), fact_manager));
replacement2.Apply(context.get(), &fact_manager);
@ -521,7 +529,7 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfVariables) {
// Replace %8 with %101 in:
// %12 = OpLoad %6 %8
auto replacement3 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(8, SpvOpLoad, 0, 12, 0),
MakeIdUseDescriptor(8, MakeInstructionDescriptor(12, SpvOpLoad, 0), 0),
MakeDataDescriptor(101, {}), 0);
ASSERT_TRUE(replacement3.IsApplicable(context.get(), fact_manager));
replacement3.Apply(context.get(), &fact_manager);
@ -530,7 +538,7 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfVariables) {
// Replace %10 with %100 in:
// OpStore %10 %12
auto replacement4 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(10, SpvOpStore, 0, 12, 0),
MakeIdUseDescriptor(10, MakeInstructionDescriptor(12, SpvOpStore, 0), 0),
MakeDataDescriptor(100, {}), 0);
ASSERT_TRUE(replacement4.IsApplicable(context.get(), fact_manager));
replacement4.Apply(context.get(), &fact_manager);
@ -631,7 +639,8 @@ TEST(TransformationReplaceIdWithSynonymTest,
// Replace %14 with %100 in:
// %16 = OpFunctionCall %2 %10 %14
auto replacement = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(14, SpvOpFunctionCall, 1, 16, 0),
MakeIdUseDescriptor(
14, MakeInstructionDescriptor(16, SpvOpFunctionCall, 0), 1),
MakeDataDescriptor(100, {}), 0);
ASSERT_FALSE(replacement.IsApplicable(context.get(), fact_manager));
}
@ -809,7 +818,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to d.*a*[2]
// The index %16 used for a cannot be replaced
auto replacement1 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(16, SpvOpAccessChain, 1, 20, 0),
MakeIdUseDescriptor(
16, MakeInstructionDescriptor(20, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(100, {}), 0);
ASSERT_FALSE(replacement1.IsApplicable(context.get(), fact_manager));
@ -817,7 +827,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to h.*f*
// The index %16 used for f cannot be replaced
auto replacement2 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(16, SpvOpAccessChain, 1, 39, 0),
MakeIdUseDescriptor(
16, MakeInstructionDescriptor(39, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(100, {}), 0);
ASSERT_FALSE(replacement2.IsApplicable(context.get(), fact_manager));
@ -825,7 +836,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to h.g.*a*[1]
// The index %16 used for a cannot be replaced
auto replacement3 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(16, SpvOpAccessChain, 2, 41, 0),
MakeIdUseDescriptor(
16, MakeInstructionDescriptor(41, SpvOpAccessChain, 0), 2),
MakeDataDescriptor(100, {}), 0);
ASSERT_FALSE(replacement3.IsApplicable(context.get(), fact_manager));
@ -833,7 +845,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to i[*0*].f
// The index %16 used for 0 *can* be replaced
auto replacement4 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(16, SpvOpAccessChain, 1, 52, 0),
MakeIdUseDescriptor(
16, MakeInstructionDescriptor(52, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(100, {}), 0);
ASSERT_TRUE(replacement4.IsApplicable(context.get(), fact_manager));
replacement4.Apply(context.get(), &fact_manager);
@ -843,7 +856,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to i[0].*f*
// The index %16 used for f cannot be replaced
auto replacement5 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(16, SpvOpAccessChain, 2, 52, 0),
MakeIdUseDescriptor(
16, MakeInstructionDescriptor(52, SpvOpAccessChain, 0), 2),
MakeDataDescriptor(100, {}), 0);
ASSERT_FALSE(replacement5.IsApplicable(context.get(), fact_manager));
@ -851,7 +865,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to i[1].g.*a*[0]
// The index %16 used for a cannot be replaced
auto replacement6 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(16, SpvOpAccessChain, 3, 53, 0),
MakeIdUseDescriptor(
16, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 3),
MakeDataDescriptor(100, {}), 0);
ASSERT_FALSE(replacement6.IsApplicable(context.get(), fact_manager));
@ -859,7 +874,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to i[1].g.a[*0*]
// The index %16 used for 0 *can* be replaced
auto replacement7 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(16, SpvOpAccessChain, 4, 53, 0),
MakeIdUseDescriptor(
16, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 4),
MakeDataDescriptor(100, {}), 0);
ASSERT_TRUE(replacement7.IsApplicable(context.get(), fact_manager));
replacement7.Apply(context.get(), &fact_manager);
@ -871,7 +887,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to d.*b*[3]
// The index %24 used for b cannot be replaced
auto replacement8 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(21, SpvOpAccessChain, 1, 24, 0),
MakeIdUseDescriptor(
21, MakeInstructionDescriptor(24, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(101, {}), 0);
ASSERT_FALSE(replacement8.IsApplicable(context.get(), fact_manager));
@ -879,7 +896,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to h.*g*.a[1]
// The index %24 used for g cannot be replaced
auto replacement9 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(21, SpvOpAccessChain, 1, 41, 0),
MakeIdUseDescriptor(
21, MakeInstructionDescriptor(41, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(101, {}), 0);
ASSERT_FALSE(replacement9.IsApplicable(context.get(), fact_manager));
@ -887,7 +905,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to h.g.a[*1*]
// The index %24 used for 1 *can* be replaced
auto replacement10 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(21, SpvOpAccessChain, 3, 41, 0),
MakeIdUseDescriptor(
21, MakeInstructionDescriptor(41, SpvOpAccessChain, 0), 3),
MakeDataDescriptor(101, {}), 0);
ASSERT_TRUE(replacement10.IsApplicable(context.get(), fact_manager));
replacement10.Apply(context.get(), &fact_manager);
@ -897,7 +916,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to h.*g*.b[0]
// The index %24 used for g cannot be replaced
auto replacement11 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(21, SpvOpAccessChain, 1, 44, 0),
MakeIdUseDescriptor(
21, MakeInstructionDescriptor(44, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(101, {}), 0);
ASSERT_FALSE(replacement11.IsApplicable(context.get(), fact_manager));
@ -905,7 +925,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to h.g.*b*[0]
// The index %24 used for b cannot be replaced
auto replacement12 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(21, SpvOpAccessChain, 2, 44, 0),
MakeIdUseDescriptor(
21, MakeInstructionDescriptor(44, SpvOpAccessChain, 0), 2),
MakeDataDescriptor(101, {}), 0);
ASSERT_FALSE(replacement12.IsApplicable(context.get(), fact_manager));
@ -913,7 +934,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to h.*g*.c
// The index %24 used for g cannot be replaced
auto replacement13 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(21, SpvOpAccessChain, 1, 46, 0),
MakeIdUseDescriptor(
21, MakeInstructionDescriptor(46, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(101, {}), 0);
ASSERT_FALSE(replacement13.IsApplicable(context.get(), fact_manager));
@ -921,7 +943,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to i[*1*].g.a[0]
// The index %24 used for 1 *can* be replaced
auto replacement14 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(21, SpvOpAccessChain, 1, 53, 0),
MakeIdUseDescriptor(
21, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(101, {}), 0);
ASSERT_TRUE(replacement14.IsApplicable(context.get(), fact_manager));
replacement14.Apply(context.get(), &fact_manager);
@ -931,7 +954,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to i[1].*g*.a[0]
// The index %24 used for g cannot be replaced
auto replacement15 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(21, SpvOpAccessChain, 2, 53, 0),
MakeIdUseDescriptor(
21, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 2),
MakeDataDescriptor(101, {}), 0);
ASSERT_FALSE(replacement15.IsApplicable(context.get(), fact_manager));
@ -939,7 +963,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to i[2].*g*.b[1]
// The index %24 used for g cannot be replaced
auto replacement16 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(21, SpvOpAccessChain, 2, 56, 0),
MakeIdUseDescriptor(
21, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 2),
MakeDataDescriptor(101, {}), 0);
ASSERT_FALSE(replacement16.IsApplicable(context.get(), fact_manager));
@ -947,7 +972,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to i[2].g.*b*[1]
// The index %24 used for b cannot be replaced
auto replacement17 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(21, SpvOpAccessChain, 3, 56, 0),
MakeIdUseDescriptor(
21, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 3),
MakeDataDescriptor(101, {}), 0);
ASSERT_FALSE(replacement17.IsApplicable(context.get(), fact_manager));
@ -955,7 +981,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to i[3].*g*.c
// The index %24 used for g cannot be replaced
auto replacement18 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(21, SpvOpAccessChain, 2, 58, 0),
MakeIdUseDescriptor(
21, MakeInstructionDescriptor(58, SpvOpAccessChain, 0), 2),
MakeDataDescriptor(101, {}), 0);
ASSERT_FALSE(replacement18.IsApplicable(context.get(), fact_manager));
@ -965,7 +992,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to d.a[*2*]
// The index %17 used for 2 *can* be replaced
auto replacement19 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(17, SpvOpAccessChain, 2, 20, 0),
MakeIdUseDescriptor(
17, MakeInstructionDescriptor(20, SpvOpAccessChain, 0), 2),
MakeDataDescriptor(102, {}), 0);
ASSERT_TRUE(replacement19.IsApplicable(context.get(), fact_manager));
replacement19.Apply(context.get(), &fact_manager);
@ -975,7 +1003,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to d.c
// The index %17 used for c cannot be replaced
auto replacement20 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(17, SpvOpAccessChain, 1, 27, 0),
MakeIdUseDescriptor(
17, MakeInstructionDescriptor(27, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(102, {}), 0);
ASSERT_FALSE(replacement20.IsApplicable(context.get(), fact_manager));
@ -983,7 +1012,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to h.g.*c*
// The index %17 used for c cannot be replaced
auto replacement21 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(17, SpvOpAccessChain, 2, 46, 0),
MakeIdUseDescriptor(
17, MakeInstructionDescriptor(46, SpvOpAccessChain, 0), 2),
MakeDataDescriptor(102, {}), 0);
ASSERT_FALSE(replacement21.IsApplicable(context.get(), fact_manager));
@ -991,7 +1021,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to i[*2*].g.b[1]
// The index %17 used for 2 *can* be replaced
auto replacement22 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(17, SpvOpAccessChain, 1, 56, 0),
MakeIdUseDescriptor(
17, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(102, {}), 0);
ASSERT_TRUE(replacement22.IsApplicable(context.get(), fact_manager));
replacement22.Apply(context.get(), &fact_manager);
@ -1001,7 +1032,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to i[3].g.*c*
// The index %17 used for c cannot be replaced
auto replacement23 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(17, SpvOpAccessChain, 3, 58, 0),
MakeIdUseDescriptor(
17, MakeInstructionDescriptor(58, SpvOpAccessChain, 0), 3),
MakeDataDescriptor(102, {}), 0);
ASSERT_FALSE(replacement23.IsApplicable(context.get(), fact_manager));
@ -1011,7 +1043,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to i[*3*].g.c
// The index %57 used for 3 *can* be replaced
auto replacement24 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(57, SpvOpAccessChain, 1, 58, 0),
MakeIdUseDescriptor(
57, MakeInstructionDescriptor(58, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(103, {}), 0);
ASSERT_TRUE(replacement24.IsApplicable(context.get(), fact_manager));
replacement24.Apply(context.get(), &fact_manager);
@ -1023,7 +1056,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to e[*17*]
// The index %32 used for 17 *can* be replaced
auto replacement25 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(32, SpvOpAccessChain, 1, 34, 0),
MakeIdUseDescriptor(
32, MakeInstructionDescriptor(34, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(106, {}), 0);
ASSERT_TRUE(replacement25.IsApplicable(context.get(), fact_manager));
replacement25.Apply(context.get(), &fact_manager);
@ -1035,7 +1069,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to h.g.b[*0*]
// The index %43 used for 0 *can* be replaced
auto replacement26 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(43, SpvOpAccessChain, 3, 44, 0),
MakeIdUseDescriptor(
43, MakeInstructionDescriptor(44, SpvOpAccessChain, 0), 3),
MakeDataDescriptor(107, {}), 0);
ASSERT_TRUE(replacement26.IsApplicable(context.get(), fact_manager));
replacement26.Apply(context.get(), &fact_manager);
@ -1047,7 +1082,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to i[2].g.b[*1*]
// The index %55 used for 1 *can* be replaced
auto replacement27 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(55, SpvOpAccessChain, 4, 56, 0),
MakeIdUseDescriptor(
55, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 4),
MakeDataDescriptor(108, {}), 0);
ASSERT_TRUE(replacement27.IsApplicable(context.get(), fact_manager));
replacement27.Apply(context.get(), &fact_manager);
@ -1059,7 +1095,8 @@ TEST(TransformationReplaceIdWithSynonymTest, SynonymsOfAccessChainIndices) {
// Corresponds to d.b[*3*]
// The index %8 used for 3 *can* be replaced
auto replacement28 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(8, SpvOpAccessChain, 2, 24, 0),
MakeIdUseDescriptor(8, MakeInstructionDescriptor(24, SpvOpAccessChain, 0),
2),
MakeDataDescriptor(109, {}), 0);
ASSERT_TRUE(replacement28.IsApplicable(context.get(), fact_manager));
replacement28.Apply(context.get(), &fact_manager);
@ -1267,11 +1304,13 @@ TEST(TransformationReplaceIdWithSynonymTest, ArrayCompositeSynonyms) {
// Replace %12 with %100[0] in '%25 = OpAccessChain %24 %20 %12'
auto good_replacement_1 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(12, SpvOpAccessChain, 1, 25, 0),
MakeIdUseDescriptor(
12, MakeInstructionDescriptor(25, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(100, {0}), 102);
// Bad: id already in use
auto bad_replacement_1 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(12, SpvOpAccessChain, 1, 25, 0),
MakeIdUseDescriptor(
12, MakeInstructionDescriptor(25, SpvOpAccessChain, 0), 1),
MakeDataDescriptor(100, {0}), 25);
ASSERT_TRUE(good_replacement_1.IsApplicable(context.get(), fact_manager));
ASSERT_FALSE(bad_replacement_1.IsApplicable(context.get(), fact_manager));
@ -1280,11 +1319,11 @@ TEST(TransformationReplaceIdWithSynonymTest, ArrayCompositeSynonyms) {
// Replace %13 with %100[1] in 'OpStore %15 %13'
auto good_replacement_2 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(13, SpvOpStore, 1, 100, 0),
MakeIdUseDescriptor(13, MakeInstructionDescriptor(100, SpvOpStore, 0), 1),
MakeDataDescriptor(100, {1}), 103);
// Bad: too many indices
auto bad_replacement_2 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(13, SpvOpStore, 1, 100, 0),
MakeIdUseDescriptor(13, MakeInstructionDescriptor(100, SpvOpStore, 0), 1),
MakeDataDescriptor(100, {1, 0}), 103);
ASSERT_TRUE(good_replacement_2.IsApplicable(context.get(), fact_manager));
ASSERT_FALSE(bad_replacement_2.IsApplicable(context.get(), fact_manager));
@ -1293,11 +1332,13 @@ TEST(TransformationReplaceIdWithSynonymTest, ArrayCompositeSynonyms) {
// Replace %22 with %100[2] in '%23 = OpConvertSToF %16 %22'
auto good_replacement_3 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(22, SpvOpConvertSToF, 0, 23, 0),
MakeIdUseDescriptor(
22, MakeInstructionDescriptor(23, SpvOpConvertSToF, 0), 0),
MakeDataDescriptor(100, {2}), 104);
// Bad: wrong input operand index
auto bad_replacement_3 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(22, SpvOpConvertSToF, 1, 23, 0),
MakeIdUseDescriptor(
22, MakeInstructionDescriptor(23, SpvOpConvertSToF, 0), 1),
MakeDataDescriptor(100, {2}), 104);
ASSERT_TRUE(good_replacement_3.IsApplicable(context.get(), fact_manager));
ASSERT_FALSE(bad_replacement_3.IsApplicable(context.get(), fact_manager));
@ -1306,11 +1347,12 @@ TEST(TransformationReplaceIdWithSynonymTest, ArrayCompositeSynonyms) {
// Replace %28 with %101[0] in 'OpStore %33 %28'
auto good_replacement_4 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(28, SpvOpStore, 1, 33, 0),
MakeIdUseDescriptor(28, MakeInstructionDescriptor(33, SpvOpStore, 0), 1),
MakeDataDescriptor(101, {0}), 105);
// Bad: id use descriptor does not identify an appropriate instruction
auto bad_replacement_4 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(28, SpvOpCopyObject, 1, 33, 0),
MakeIdUseDescriptor(28, MakeInstructionDescriptor(33, SpvOpCopyObject, 0),
1),
MakeDataDescriptor(101, {0}), 105);
ASSERT_TRUE(good_replacement_4.IsApplicable(context.get(), fact_manager));
ASSERT_FALSE(bad_replacement_4.IsApplicable(context.get(), fact_manager));
@ -1319,11 +1361,13 @@ TEST(TransformationReplaceIdWithSynonymTest, ArrayCompositeSynonyms) {
// Replace %23 with %101[1] in '%50 = OpCopyObject %16 %23'
auto good_replacement_5 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(23, SpvOpCopyObject, 0, 50, 0),
MakeIdUseDescriptor(23, MakeInstructionDescriptor(50, SpvOpCopyObject, 0),
0),
MakeDataDescriptor(101, {1}), 106);
// Bad: wrong synonym fact being used
auto bad_replacement_5 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(23, SpvOpCopyObject, 0, 50, 0),
MakeIdUseDescriptor(23, MakeInstructionDescriptor(50, SpvOpCopyObject, 0),
0),
MakeDataDescriptor(101, {0}), 106);
ASSERT_TRUE(good_replacement_5.IsApplicable(context.get(), fact_manager));
ASSERT_FALSE(bad_replacement_5.IsApplicable(context.get(), fact_manager));
@ -1332,11 +1376,11 @@ TEST(TransformationReplaceIdWithSynonymTest, ArrayCompositeSynonyms) {
// Replace %32 with %101[2] in 'OpStore %33 %32'
auto good_replacement_6 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(32, SpvOpStore, 1, 33, 1),
MakeIdUseDescriptor(32, MakeInstructionDescriptor(33, SpvOpStore, 1), 1),
MakeDataDescriptor(101, {2}), 107);
// Bad: id 1001 does not exist
auto bad_replacement_6 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(32, SpvOpStore, 1, 33, 1),
MakeIdUseDescriptor(32, MakeInstructionDescriptor(33, SpvOpStore, 1), 1),
MakeDataDescriptor(1001, {2}), 107);
ASSERT_TRUE(good_replacement_6.IsApplicable(context.get(), fact_manager));
ASSERT_FALSE(bad_replacement_6.IsApplicable(context.get(), fact_manager));
@ -1345,11 +1389,13 @@ TEST(TransformationReplaceIdWithSynonymTest, ArrayCompositeSynonyms) {
// Replace %23 with %101[3] in '%51 = OpCopyObject %16 %23'
auto good_replacement_7 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(23, SpvOpCopyObject, 0, 51, 0),
MakeIdUseDescriptor(23, MakeInstructionDescriptor(51, SpvOpCopyObject, 0),
0),
MakeDataDescriptor(101, {3}), 108);
// Bad: id 0 is invalid
auto bad_replacement_7 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(0, SpvOpCopyObject, 0, 51, 0),
MakeIdUseDescriptor(0, MakeInstructionDescriptor(51, SpvOpCopyObject, 0),
0),
MakeDataDescriptor(101, {3}), 108);
ASSERT_TRUE(good_replacement_7.IsApplicable(context.get(), fact_manager));
ASSERT_FALSE(bad_replacement_7.IsApplicable(context.get(), fact_manager));
@ -1498,7 +1544,7 @@ TEST(TransformationReplaceIdWithSynonymTest, MatrixCompositeSynonyms) {
// Replace %23 with %100[0] in '%26 = OpFAdd %7 %23 %25'
auto replacement_1 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(23, SpvOpFAdd, 0, 26, 0),
MakeIdUseDescriptor(23, MakeInstructionDescriptor(26, SpvOpFAdd, 0), 0),
MakeDataDescriptor(100, {0}), 101);
ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager));
replacement_1.Apply(context.get(), &fact_manager);
@ -1506,7 +1552,7 @@ TEST(TransformationReplaceIdWithSynonymTest, MatrixCompositeSynonyms) {
// Replace %25 with %100[1] in '%26 = OpFAdd %7 %23 %25'
auto replacement_2 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(25, SpvOpFAdd, 1, 26, 0),
MakeIdUseDescriptor(25, MakeInstructionDescriptor(26, SpvOpFAdd, 0), 1),
MakeDataDescriptor(100, {1}), 102);
ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager));
replacement_2.Apply(context.get(), &fact_manager);
@ -1656,8 +1702,8 @@ TEST(TransformationReplaceIdWithSynonymTest, StructCompositeSynonyms) {
// Replace %45 with %100[1] in '%46 = OpCompositeConstruct %32 %35 %45'
auto replacement_1 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(45, SpvOpCompositeConstruct, 1, 46,
0),
MakeIdUseDescriptor(
45, MakeInstructionDescriptor(46, SpvOpCompositeConstruct, 0), 1),
MakeDataDescriptor(100, {1}), 201);
ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager));
replacement_1.Apply(context.get(), &fact_manager);
@ -1666,8 +1712,8 @@ TEST(TransformationReplaceIdWithSynonymTest, StructCompositeSynonyms) {
// Replace second occurrence of %27 with %101[0] in '%28 =
// OpCompositeConstruct %8 %27 %27'
auto replacement_2 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(27, SpvOpCompositeConstruct, 1, 28,
0),
MakeIdUseDescriptor(
27, MakeInstructionDescriptor(28, SpvOpCompositeConstruct, 0), 1),
MakeDataDescriptor(101, {0}), 202);
ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager));
replacement_2.Apply(context.get(), &fact_manager);
@ -1675,8 +1721,8 @@ TEST(TransformationReplaceIdWithSynonymTest, StructCompositeSynonyms) {
// Replace %36 with %101[1] in '%45 = OpCompositeConstruct %31 %36 %41 %44'
auto replacement_3 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(36, SpvOpCompositeConstruct, 0, 45,
0),
MakeIdUseDescriptor(
36, MakeInstructionDescriptor(45, SpvOpCompositeConstruct, 0), 0),
MakeDataDescriptor(101, {1}), 203);
ASSERT_TRUE(replacement_3.IsApplicable(context.get(), fact_manager));
replacement_3.Apply(context.get(), &fact_manager);
@ -1685,8 +1731,8 @@ TEST(TransformationReplaceIdWithSynonymTest, StructCompositeSynonyms) {
// Replace first occurrence of %27 with %101[2] in '%28 = OpCompositeConstruct
// %8 %27 %27'
auto replacement_4 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(27, SpvOpCompositeConstruct, 0, 28,
0),
MakeIdUseDescriptor(
27, MakeInstructionDescriptor(28, SpvOpCompositeConstruct, 0), 0),
MakeDataDescriptor(101, {2}), 204);
ASSERT_TRUE(replacement_4.IsApplicable(context.get(), fact_manager));
replacement_4.Apply(context.get(), &fact_manager);
@ -1694,7 +1740,7 @@ TEST(TransformationReplaceIdWithSynonymTest, StructCompositeSynonyms) {
// Replace %22 with %102[0] in 'OpStore %23 %22'
auto replacement_5 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(22, SpvOpStore, 1, 23, 0),
MakeIdUseDescriptor(22, MakeInstructionDescriptor(23, SpvOpStore, 0), 1),
MakeDataDescriptor(102, {0}), 205);
ASSERT_TRUE(replacement_5.IsApplicable(context.get(), fact_manager));
replacement_5.Apply(context.get(), &fact_manager);
@ -1915,7 +1961,8 @@ TEST(TransformationReplaceIdWithSynonymTest, VectorCompositeSynonyms) {
// Replace %20 with %100[0] in '%80 = OpCopyObject %16 %20'
auto replacement_1 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(20, SpvOpCopyObject, 0, 80, 0),
MakeIdUseDescriptor(20, MakeInstructionDescriptor(80, SpvOpCopyObject, 0),
0),
MakeDataDescriptor(100, {0}), 200);
ASSERT_TRUE(replacement_1.IsApplicable(context.get(), fact_manager));
replacement_1.Apply(context.get(), &fact_manager);
@ -1923,7 +1970,8 @@ TEST(TransformationReplaceIdWithSynonymTest, VectorCompositeSynonyms) {
// Replace %54 with %100[3] in '%56 = OpFOrdNotEqual %30 %54 %55'
auto replacement_2 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(54, SpvOpFOrdNotEqual, 0, 56, 0),
MakeIdUseDescriptor(
54, MakeInstructionDescriptor(56, SpvOpFOrdNotEqual, 0), 0),
MakeDataDescriptor(100, {3}), 201);
ASSERT_TRUE(replacement_2.IsApplicable(context.get(), fact_manager));
replacement_2.Apply(context.get(), &fact_manager);
@ -1931,7 +1979,7 @@ TEST(TransformationReplaceIdWithSynonymTest, VectorCompositeSynonyms) {
// Replace %15 with %101[0] in 'OpStore %12 %15'
auto replacement_3 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(15, SpvOpStore, 1, 64, 0),
MakeIdUseDescriptor(15, MakeInstructionDescriptor(64, SpvOpStore, 0), 1),
MakeDataDescriptor(101, {0}), 202);
ASSERT_TRUE(replacement_3.IsApplicable(context.get(), fact_manager));
replacement_3.Apply(context.get(), &fact_manager);
@ -1939,7 +1987,8 @@ TEST(TransformationReplaceIdWithSynonymTest, VectorCompositeSynonyms) {
// Replace %19 with %101[2] in '%81 = OpVectorShuffle %16 %19 %19 0 0 1'
auto replacement_4 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(19, SpvOpVectorShuffle, 0, 81, 0),
MakeIdUseDescriptor(
19, MakeInstructionDescriptor(81, SpvOpVectorShuffle, 0), 0),
MakeDataDescriptor(101, {2}), 203);
ASSERT_TRUE(replacement_4.IsApplicable(context.get(), fact_manager));
replacement_4.Apply(context.get(), &fact_manager);
@ -1948,8 +1997,8 @@ TEST(TransformationReplaceIdWithSynonymTest, VectorCompositeSynonyms) {
// Replace %27 with %102[0] in '%82 = OpCompositeConstruct %21 %26 %27 %28
// %25'
auto replacement_5 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(27, SpvOpCompositeConstruct, 1, 82,
0),
MakeIdUseDescriptor(
27, MakeInstructionDescriptor(82, SpvOpCompositeConstruct, 0), 1),
MakeDataDescriptor(102, {0}), 204);
ASSERT_TRUE(replacement_5.IsApplicable(context.get(), fact_manager));
replacement_5.Apply(context.get(), &fact_manager);
@ -1957,7 +2006,8 @@ TEST(TransformationReplaceIdWithSynonymTest, VectorCompositeSynonyms) {
// Replace %15 with %102[1] in '%83 = OpCopyObject %10 %15'
auto replacement_6 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(15, SpvOpCopyObject, 0, 83, 0),
MakeIdUseDescriptor(15, MakeInstructionDescriptor(83, SpvOpCopyObject, 0),
0),
MakeDataDescriptor(102, {1}), 205);
ASSERT_TRUE(replacement_6.IsApplicable(context.get(), fact_manager));
replacement_6.Apply(context.get(), &fact_manager);
@ -1965,7 +2015,8 @@ TEST(TransformationReplaceIdWithSynonymTest, VectorCompositeSynonyms) {
// Replace %33 with %103[0] in '%86 = OpCopyObject %30 %33'
auto replacement_7 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(33, SpvOpCopyObject, 0, 86, 0),
MakeIdUseDescriptor(33, MakeInstructionDescriptor(86, SpvOpCopyObject, 0),
0),
MakeDataDescriptor(103, {0}), 206);
ASSERT_TRUE(replacement_7.IsApplicable(context.get(), fact_manager));
replacement_7.Apply(context.get(), &fact_manager);
@ -1973,7 +2024,8 @@ TEST(TransformationReplaceIdWithSynonymTest, VectorCompositeSynonyms) {
// Replace %47 with %103[1] in '%84 = OpCopyObject %39 %47'
auto replacement_8 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(47, SpvOpCopyObject, 0, 84, 0),
MakeIdUseDescriptor(47, MakeInstructionDescriptor(84, SpvOpCopyObject, 0),
0),
MakeDataDescriptor(103, {1}), 207);
ASSERT_TRUE(replacement_8.IsApplicable(context.get(), fact_manager));
replacement_8.Apply(context.get(), &fact_manager);
@ -1981,7 +2033,8 @@ TEST(TransformationReplaceIdWithSynonymTest, VectorCompositeSynonyms) {
// Replace %42 with %104[0] in '%85 = OpCopyObject %30 %42'
auto replacement_9 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(42, SpvOpCopyObject, 0, 85, 0),
MakeIdUseDescriptor(42, MakeInstructionDescriptor(85, SpvOpCopyObject, 0),
0),
MakeDataDescriptor(104, {0}), 208);
ASSERT_TRUE(replacement_9.IsApplicable(context.get(), fact_manager));
replacement_9.Apply(context.get(), &fact_manager);
@ -1989,7 +2042,8 @@ TEST(TransformationReplaceIdWithSynonymTest, VectorCompositeSynonyms) {
// Replace %45 with %104[1] in '%63 = OpLogicalOr %30 %45 %46'
auto replacement_10 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(45, SpvOpLogicalOr, 0, 63, 0),
MakeIdUseDescriptor(45, MakeInstructionDescriptor(63, SpvOpLogicalOr, 0),
0),
MakeDataDescriptor(104, {1}), 209);
ASSERT_TRUE(replacement_10.IsApplicable(context.get(), fact_manager));
replacement_10.Apply(context.get(), &fact_manager);
@ -1997,7 +2051,7 @@ TEST(TransformationReplaceIdWithSynonymTest, VectorCompositeSynonyms) {
// Replace %38 with %105[0] in 'OpStore %36 %38'
auto replacement_11 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(38, SpvOpStore, 1, 85, 0),
MakeIdUseDescriptor(38, MakeInstructionDescriptor(85, SpvOpStore, 0), 1),
MakeDataDescriptor(105, {0}), 210);
ASSERT_TRUE(replacement_11.IsApplicable(context.get(), fact_manager));
replacement_11.Apply(context.get(), &fact_manager);
@ -2005,7 +2059,8 @@ TEST(TransformationReplaceIdWithSynonymTest, VectorCompositeSynonyms) {
// Replace %46 with %105[2] in '%62 = OpLogicalAnd %30 %45 %46'
auto replacement_12 = TransformationReplaceIdWithSynonym(
transformation::MakeIdUseDescriptor(46, SpvOpLogicalAnd, 1, 62, 0),
MakeIdUseDescriptor(46, MakeInstructionDescriptor(62, SpvOpLogicalAnd, 0),
1),
MakeDataDescriptor(105, {2}), 211);
ASSERT_TRUE(replacement_12.IsApplicable(context.get(), fact_manager));
replacement_12.Apply(context.get(), &fact_manager);