spirv-fuzz: Fix vector wrapping fuzzer pass (#4392)

The fuzzer pass was passing the type of a scalar where a vector type
was required, and was not checking whether synonyms could be made for
the operands to the scalar instruction.
diff --git a/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp b/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp
index 3f324df..5f1ae18 100644
--- a/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp
+++ b/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp
@@ -48,13 +48,6 @@
           return;
         }
 
-        // The transformation will not be applicable if the id of the scalar
-        // operation is irrelevant.
-        if (GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
-                instruction_iterator->result_id())) {
-          return;
-        }
-
         // It must be valid to insert an OpCompositeConstruct instruction
         // before |instruction_iterator|.
         if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
@@ -77,6 +70,25 @@
         uint32_t target_id1 = instruction_iterator->GetSingleWordInOperand(0);
         uint32_t target_id2 = instruction_iterator->GetSingleWordInOperand(1);
 
+        // We need to be able to make a synonym of the scalar operation's result
+        // id, as well as the operand ids (for example, they cannot be
+        // irrelevant).
+        if (!fuzzerutil::CanMakeSynonymOf(GetIRContext(),
+                                          *GetTransformationContext(),
+                                          &*instruction_iterator)) {
+          return;
+        }
+        if (!fuzzerutil::CanMakeSynonymOf(
+                GetIRContext(), *GetTransformationContext(),
+                GetIRContext()->get_def_use_mgr()->GetDef(target_id1))) {
+          return;
+        }
+        if (!fuzzerutil::CanMakeSynonymOf(
+                GetIRContext(), *GetTransformationContext(),
+                GetIRContext()->get_def_use_mgr()->GetDef(target_id2))) {
+          return;
+        }
+
         // Stores the ids of scalar constants.
         std::vector<uint32_t> vec1_components;
         std::vector<uint32_t> vec2_components;
@@ -95,19 +107,21 @@
         }
 
         // Add two OpCompositeConstruct to the module with result id returned.
+        const uint32_t vector_type_id =
+            FindOrCreateVectorType(operand_type_id, vector_size);
 
         // Add the first OpCompositeConstruct that wraps the id of the first
         // operand.
         uint32_t result_id1 = GetFuzzerContext()->GetFreshId();
         ApplyTransformation(TransformationCompositeConstruct(
-            operand_type_id, vec1_components, instruction_descriptor,
+            vector_type_id, vec1_components, instruction_descriptor,
             result_id1));
 
         // Add the second OpCompositeConstruct that wraps the id of the second
         // operand.
         uint32_t result_id2 = GetFuzzerContext()->GetFreshId();
         ApplyTransformation(TransformationCompositeConstruct(
-            operand_type_id, vec2_components, instruction_descriptor,
+            vector_type_id, vec2_components, instruction_descriptor,
             result_id2));
 
         // Apply transformation to do vector operation and add synonym between
diff --git a/source/fuzz/fuzzer_util.cpp b/source/fuzz/fuzzer_util.cpp
index 0e718e1..cae87a3 100644
--- a/source/fuzz/fuzzer_util.cpp
+++ b/source/fuzz/fuzzer_util.cpp
@@ -305,7 +305,7 @@
 
 bool CanMakeSynonymOf(opt::IRContext* ir_context,
                       const TransformationContext& transformation_context,
-                      opt::Instruction* inst) {
+                      const opt::Instruction* inst) {
   if (inst->opcode() == SpvOpSampledImage) {
     // The SPIR-V data rules say that only very specific instructions may
     // may consume the result id of an OpSampledImage, and this excludes the
diff --git a/source/fuzz/fuzzer_util.h b/source/fuzz/fuzzer_util.h
index a394661..40b51d5 100644
--- a/source/fuzz/fuzzer_util.h
+++ b/source/fuzz/fuzzer_util.h
@@ -118,7 +118,7 @@
 // does not participate in IdIsIrrelevant fact.
 bool CanMakeSynonymOf(opt::IRContext* ir_context,
                       const TransformationContext& transformation_context,
-                      opt::Instruction* inst);
+                      const opt::Instruction* inst);
 
 // Determines whether the given type is a composite; that is: an array, matrix,
 // struct or vector.
diff --git a/source/fuzz/transformation_wrap_vector_synonym.cpp b/source/fuzz/transformation_wrap_vector_synonym.cpp
index 86eb51c..4402589 100644
--- a/source/fuzz/transformation_wrap_vector_synonym.cpp
+++ b/source/fuzz/transformation_wrap_vector_synonym.cpp
@@ -55,9 +55,12 @@
     return false;
   }
 
-  assert(!transformation_context.GetFactManager()->IdIsIrrelevant(
-             instruction->result_id()) &&
-         "Result id of the scalar operation must be relevant.");
+  // It must be possible to make a synonym of the result id of the scalar
+  // operation
+  if (!fuzzerutil::CanMakeSynonymOf(ir_context, transformation_context,
+                                    instruction)) {
+    return false;
+  }
 
   // |vector_operand1| and |vector_operand2| must exist.
   auto vec1 = ir_context->get_def_use_mgr()->GetDef(message_.vector_operand1());