spirv-fuzz: Allow OpPhi operand to be replaced with a composite synonym (#3221)

In this PR, the class FuzzerPassApplyIdSynonyms was updated to allow OpPhi operand to be replaced with a composite synonym.

Fixes #3209.
diff --git a/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp b/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
index e7e9976..5711f35 100644
--- a/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
+++ b/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
@@ -81,9 +81,8 @@
         synonyms_to_try.push_back(data_descriptor);
       }
       while (!synonyms_to_try.empty()) {
-        auto synonym_index = GetFuzzerContext()->RandomIndex(synonyms_to_try);
-        auto synonym_to_try = synonyms_to_try[synonym_index];
-        synonyms_to_try.erase(synonyms_to_try.begin() + synonym_index);
+        auto synonym_to_try =
+            GetFuzzerContext()->RemoveAtRandomIndex(&synonyms_to_try);
 
         // If the synonym's |index_size| is zero, the synonym represents an id.
         // Otherwise it represents some element of a composite structure, in
@@ -91,12 +90,10 @@
         // that element out.
         if (synonym_to_try->index_size() > 0 &&
             !fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCompositeExtract,
-                                                          use_inst)) {
+                                                          use_inst) &&
+            use_inst->opcode() != SpvOpPhi) {
           // We cannot insert an extract before this instruction, so this
           // synonym is no good.
-          //
-          // TODO(afd): In the case of an OpPhi, we could consider inserting the
-          //  extract instruction into the relevant parent block of the OpPhi.
           continue;
         }
 
@@ -115,8 +112,26 @@
           id_with_which_to_replace_use = synonym_to_try->object();
         } else {
           id_with_which_to_replace_use = GetFuzzerContext()->GetFreshId();
+          opt::Instruction* instruction_to_insert_before = nullptr;
+
+          if (use_inst->opcode() != SpvOpPhi) {
+            instruction_to_insert_before = use_inst;
+          } else {
+            auto parent_block_id =
+                use_inst->GetSingleWordInOperand(use_in_operand_index + 1);
+            auto parent_block_instruction =
+                GetIRContext()->get_def_use_mgr()->GetDef(parent_block_id);
+            auto parent_block =
+                GetIRContext()->get_instr_block(parent_block_instruction);
+
+            instruction_to_insert_before = parent_block->GetMergeInst()
+                                               ? parent_block->GetMergeInst()
+                                               : parent_block->terminator();
+          }
+
           ApplyTransformation(TransformationCompositeExtract(
-              MakeInstructionDescriptor(GetIRContext(), use_inst),
+              MakeInstructionDescriptor(GetIRContext(),
+                                        instruction_to_insert_before),
               id_with_which_to_replace_use, synonym_to_try->object(),
               fuzzerutil::RepeatedFieldToVector(synonym_to_try->index())));
         }