#include "source/fuzz/transformation_permute_phi_operands.h"
#include <vector>
#include "source/fuzz/fuzzer_util.h"
namespace spvtools {
namespace fuzz {
TransformationPermutePhiOperands::TransformationPermutePhiOperands(
protobufs::TransformationPermutePhiOperands message)
: message_(std::move(message)) {}
TransformationPermutePhiOperands::TransformationPermutePhiOperands(
uint32_t result_id, const std::vector<uint32_t>& permutation) {
message_.set_result_id(result_id);
for (auto index : permutation) {
message_.add_permutation(index);
}
}
bool TransformationPermutePhiOperands::IsApplicable(
opt::IRContext* ir_context, const TransformationContext& ) const {
const auto* inst =
ir_context->get_def_use_mgr()->GetDef(message_.result_id());
if (!inst || inst->opcode() != spv::Op::OpPhi) {
return false;
}
auto expected_permutation_size = inst->NumInOperands() / 2;
if (static_cast<uint32_t>(message_.permutation().size()) !=
expected_permutation_size) {
return false;
}
std::vector<uint32_t> permutation(message_.permutation().begin(),
message_.permutation().end());
assert(!fuzzerutil::HasDuplicates(permutation) &&
"Permutation has duplicates");
return permutation.empty() ||
fuzzerutil::IsPermutationOfRange(permutation, 0,
expected_permutation_size - 1);
}
void TransformationPermutePhiOperands::Apply(
opt::IRContext* ir_context, TransformationContext* ) const {
auto* inst = ir_context->get_def_use_mgr()->GetDef(message_.result_id());
assert(inst);
opt::Instruction::OperandList permuted_operands;
permuted_operands.reserve(inst->NumInOperands());
for (auto index : message_.permutation()) {
permuted_operands.push_back(std::move(inst->GetInOperand(2 * index)));
permuted_operands.push_back(std::move(inst->GetInOperand(2 * index + 1)));
}
inst->SetInOperands(std::move(permuted_operands));
ir_context->UpdateDefUse(inst);
}
protobufs::Transformation TransformationPermutePhiOperands::ToMessage() const {
protobufs::Transformation result;
*result.mutable_permute_phi_operands() = message_;
return result;
}
std::unordered_set<uint32_t> TransformationPermutePhiOperands::GetFreshIds()
const {
return std::unordered_set<uint32_t>();
}
}
}