spirv-fuzz: Improve transformation test oracles (#4207)

To help ensure that optimizations that do less cautious invalidation
of analyses are implemented correctly, this change adds checks to the
tests of various transformations to ensure that analyses such as
def-use are up to date.
diff --git a/test/fuzz/transformation_add_type_array_test.cpp b/test/fuzz/transformation_add_type_array_test.cpp
index ab4ed9a..2ef8200 100644
--- a/test/fuzz/transformation_add_type_array_test.cpp
+++ b/test/fuzz/transformation_add_type_array_test.cpp
@@ -90,19 +90,34 @@
   ASSERT_FALSE(TransformationAddTypeArray(100, 11, 17)
                    .IsApplicable(context.get(), transformation_context));
 
-  TransformationAddTypeArray transformations[] = {
-      // %100 = OpTypeArray %10 %16
-      TransformationAddTypeArray(100, 10, 16),
-
-      // %101 = OpTypeArray %7 %12
-      TransformationAddTypeArray(101, 7, 12)};
-
-  for (auto& transformation : transformations) {
+  {
+    // %100 = OpTypeArray %10 %16
+    TransformationAddTypeArray transformation(100, 10, 16);
+    ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
+    ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(100));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
+    ASSERT_EQ(SpvOpTypeArray,
+              context->get_def_use_mgr()->GetDef(100)->opcode());
+    ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsArray());
   }
+
+  {
+    // %101 = OpTypeArray %7 %12
+    TransformationAddTypeArray transformation(101, 7, 12);
+    ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(101));
+    ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(101));
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    ApplyAndCheckFreshIds(transformation, context.get(),
+                          &transformation_context);
+    ASSERT_EQ(SpvOpTypeArray,
+              context->get_def_use_mgr()->GetDef(100)->opcode());
+    ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsArray());
+  }
+
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
 
diff --git a/test/fuzz/transformation_add_type_boolean_test.cpp b/test/fuzz/transformation_add_type_boolean_test.cpp
index 88d9f5b..a8e657b 100644
--- a/test/fuzz/transformation_add_type_boolean_test.cpp
+++ b/test/fuzz/transformation_add_type_boolean_test.cpp
@@ -52,9 +52,13 @@
       context.get(), transformation_context));
 
   auto add_type_bool = TransformationAddTypeBoolean(100);
+  ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
+  ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(100));
   ASSERT_TRUE(
       add_type_bool.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(add_type_bool, context.get(), &transformation_context);
+  ASSERT_EQ(SpvOpTypeBool, context->get_def_use_mgr()->GetDef(100)->opcode());
+  ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsBool());
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
 
diff --git a/test/fuzz/transformation_add_type_float_test.cpp b/test/fuzz/transformation_add_type_float_test.cpp
index 235d61b..dc57ccd 100644
--- a/test/fuzz/transformation_add_type_float_test.cpp
+++ b/test/fuzz/transformation_add_type_float_test.cpp
@@ -103,15 +103,27 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Adds 16-bit float type.
   auto transformation = TransformationAddTypeFloat(6, 16);
+  ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(6));
+  ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(6));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+  ASSERT_EQ(SpvOpTypeFloat, context->get_def_use_mgr()->GetDef(6)->opcode());
+  ASSERT_NE(nullptr, context->get_type_mgr()->GetType(6)->AsFloat());
 
   // Adds 32-bit float type.
   transformation = TransformationAddTypeFloat(7, 32);
+  ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(7));
+  ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(7));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+  ASSERT_EQ(SpvOpTypeFloat, context->get_def_use_mgr()->GetDef(7)->opcode());
+  ASSERT_NE(nullptr, context->get_type_mgr()->GetType(7)->AsFloat());
 
   // Adds 64-bit float type.
   transformation = TransformationAddTypeFloat(8, 64);
+  ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(8));
+  ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(8));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+  ASSERT_EQ(SpvOpTypeFloat, context->get_def_use_mgr()->GetDef(8)->opcode());
+  ASSERT_NE(nullptr, context->get_type_mgr()->GetType(8)->AsFloat());
 
   std::string variant_shader = R"(
          OpCapability Shader
diff --git a/test/fuzz/transformation_add_type_int_test.cpp b/test/fuzz/transformation_add_type_int_test.cpp
index ee4e799..273420c 100644
--- a/test/fuzz/transformation_add_type_int_test.cpp
+++ b/test/fuzz/transformation_add_type_int_test.cpp
@@ -118,8 +118,14 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // Adds signed 8-bit integer type.
+  // For this transformation we also check that the def-use manager and type
+  // manager are updated appropriately.
   auto transformation = TransformationAddTypeInt(6, 8, true);
+  ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(6));
+  ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(6));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+  ASSERT_EQ(SpvOpTypeInt, context->get_def_use_mgr()->GetDef(6)->opcode());
+  ASSERT_NE(nullptr, context->get_type_mgr()->GetType(6)->AsInteger());
 
   // Adds signed 16-bit integer type.
   transformation = TransformationAddTypeInt(7, 16, true);
diff --git a/test/fuzz/transformation_add_type_matrix_test.cpp b/test/fuzz/transformation_add_type_matrix_test.cpp
index 926e983..df0111e 100644
--- a/test/fuzz/transformation_add_type_matrix_test.cpp
+++ b/test/fuzz/transformation_add_type_matrix_test.cpp
@@ -63,10 +63,21 @@
   ASSERT_FALSE(TransformationAddTypeMatrix(100, 11, 2)
                    .IsApplicable(context.get(), transformation_context));
 
-  TransformationAddTypeMatrix transformations[] = {
-      // %100 = OpTypeMatrix %8 2
-      TransformationAddTypeMatrix(100, 8, 2),
+  {
+    // %100 = OpTypeMatrix %8 2
+    TransformationAddTypeMatrix transformation(100, 8, 2);
+    ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
+    ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(100));
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    ApplyAndCheckFreshIds(transformation, context.get(),
+                          &transformation_context);
+    ASSERT_EQ(SpvOpTypeMatrix,
+              context->get_def_use_mgr()->GetDef(100)->opcode());
+    ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsMatrix());
+  }
 
+  TransformationAddTypeMatrix transformations[] = {
       // %101 = OpTypeMatrix %8 3
       TransformationAddTypeMatrix(101, 8, 3),
 
diff --git a/test/fuzz/transformation_add_type_pointer_test.cpp b/test/fuzz/transformation_add_type_pointer_test.cpp
index 985e904..b9072e3 100644
--- a/test/fuzz/transformation_add_type_pointer_test.cpp
+++ b/test/fuzz/transformation_add_type_pointer_test.cpp
@@ -133,10 +133,24 @@
   ASSERT_FALSE(bad_result_id_is_not_fresh.IsApplicable(context.get(),
                                                        transformation_context));
 
+  {
+    auto& transformation = good_new_private_pointer_to_t;
+    ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(101));
+    ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(101));
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    ApplyAndCheckFreshIds(transformation, context.get(),
+                          &transformation_context);
+    ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
+        context.get(), validator_options, kConsoleMessageConsumer));
+    ASSERT_EQ(SpvOpTypePointer,
+              context->get_def_use_mgr()->GetDef(101)->opcode());
+    ASSERT_NE(nullptr, context->get_type_mgr()->GetType(101)->AsPointer());
+  }
+
   for (auto& transformation :
-       {good_new_private_pointer_to_t, good_new_uniform_pointer_to_t,
-        good_another_function_pointer_to_s, good_new_uniform_pointer_to_s,
-        good_another_private_pointer_to_float,
+       {good_new_uniform_pointer_to_t, good_another_function_pointer_to_s,
+        good_new_uniform_pointer_to_s, good_another_private_pointer_to_float,
         good_new_private_pointer_to_private_pointer_to_float,
         good_new_uniform_pointer_to_vec2,
         good_new_private_pointer_to_uniform_pointer_to_vec2}) {
diff --git a/test/fuzz/transformation_add_type_struct_test.cpp b/test/fuzz/transformation_add_type_struct_test.cpp
index b57bab2..7fb91ab 100644
--- a/test/fuzz/transformation_add_type_struct_test.cpp
+++ b/test/fuzz/transformation_add_type_struct_test.cpp
@@ -63,10 +63,21 @@
   ASSERT_FALSE(TransformationAddTypeStruct(100, {3}).IsApplicable(
       context.get(), transformation_context));
 
-  TransformationAddTypeStruct transformations[] = {
-      // %100 = OpTypeStruct %6 %7 %8 %9 %10 %11
-      TransformationAddTypeStruct(100, {6, 7, 8, 9, 10, 11}),
+  {
+    // %100 = OpTypeStruct %6 %7 %8 %9 %10 %11
+    TransformationAddTypeStruct transformation(100, {6, 7, 8, 9, 10, 11});
+    ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
+    ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(100));
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    ApplyAndCheckFreshIds(transformation, context.get(),
+                          &transformation_context);
+    ASSERT_EQ(SpvOpTypeStruct,
+              context->get_def_use_mgr()->GetDef(100)->opcode());
+    ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsStruct());
+  }
 
+  TransformationAddTypeStruct transformations[] = {
       // %101 = OpTypeStruct
       TransformationAddTypeStruct(101, {}),
 
diff --git a/test/fuzz/transformation_add_type_vector_test.cpp b/test/fuzz/transformation_add_type_vector_test.cpp
index a49ba6e..755bc4a 100644
--- a/test/fuzz/transformation_add_type_vector_test.cpp
+++ b/test/fuzz/transformation_add_type_vector_test.cpp
@@ -57,10 +57,21 @@
   ASSERT_FALSE(TransformationAddTypeVector(100, 1, 2).IsApplicable(
       context.get(), transformation_context));
 
-  TransformationAddTypeVector transformations[] = {
-      // %100 = OpTypeVector %6 2
-      TransformationAddTypeVector(100, 6, 2),
+  {
+    // %100 = OpTypeVector %6 2
+    TransformationAddTypeVector transformation(100, 6, 2);
+    ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
+    ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(100));
+    ASSERT_TRUE(
+        transformation.IsApplicable(context.get(), transformation_context));
+    ApplyAndCheckFreshIds(transformation, context.get(),
+                          &transformation_context);
+    ASSERT_EQ(SpvOpTypeVector,
+              context->get_def_use_mgr()->GetDef(100)->opcode());
+    ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsVector());
+  }
 
+  TransformationAddTypeVector transformations[] = {
       // %101 = OpTypeVector %7 3
       TransformationAddTypeVector(101, 7, 3),
 
diff --git a/test/fuzz/transformation_composite_construct_test.cpp b/test/fuzz/transformation_composite_construct_test.cpp
index edbfe3b..9b68721 100644
--- a/test/fuzz/transformation_composite_construct_test.cpp
+++ b/test/fuzz/transformation_composite_construct_test.cpp
@@ -146,8 +146,19 @@
                                                     transformation_context));
   ASSERT_FALSE(make_vec2_array_length_3_bad.IsApplicable(
       context.get(), transformation_context));
+  ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(200));
+  ASSERT_EQ(nullptr, context->get_instr_block(200));
+  uint32_t num_uses_of_41_before = context->get_def_use_mgr()->NumUses(41);
+  uint32_t num_uses_of_45_before = context->get_def_use_mgr()->NumUses(45);
+  uint32_t num_uses_of_27_before = context->get_def_use_mgr()->NumUses(27);
   ApplyAndCheckFreshIds(make_vec2_array_length_3, context.get(),
                         &transformation_context);
+  ASSERT_EQ(SpvOpCompositeConstruct,
+            context->get_def_use_mgr()->GetDef(200)->opcode());
+  ASSERT_EQ(34, context->get_instr_block(200)->id());
+  ASSERT_EQ(num_uses_of_41_before + 1, context->get_def_use_mgr()->NumUses(41));
+  ASSERT_EQ(num_uses_of_45_before + 1, context->get_def_use_mgr()->NumUses(45));
+  ASSERT_EQ(num_uses_of_27_before + 1, context->get_def_use_mgr()->NumUses(27));
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
   ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
diff --git a/test/fuzz/transformation_composite_extract_test.cpp b/test/fuzz/transformation_composite_extract_test.cpp
index 383a4db..1df5591 100644
--- a/test/fuzz/transformation_composite_extract_test.cpp
+++ b/test/fuzz/transformation_composite_extract_test.cpp
@@ -143,10 +143,18 @@
 
   TransformationCompositeExtract transformation_1(
       MakeInstructionDescriptor(36, SpvOpConvertFToS, 0), 201, 100, {2});
+  ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(201));
+  ASSERT_EQ(nullptr, context->get_instr_block(201));
+  uint32_t num_uses_of_100_before = context->get_def_use_mgr()->NumUses(100);
   ASSERT_TRUE(
       transformation_1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_1, context.get(),
                         &transformation_context);
+  ASSERT_EQ(SpvOpCompositeExtract,
+            context->get_def_use_mgr()->GetDef(201)->opcode());
+  ASSERT_EQ(15, context->get_instr_block(201)->id());
+  ASSERT_EQ(num_uses_of_100_before + 1,
+            context->get_def_use_mgr()->NumUses(100));
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
 
diff --git a/test/fuzz/transformation_equation_instruction_test.cpp b/test/fuzz/transformation_equation_instruction_test.cpp
index 654fffc..5b5033d 100644
--- a/test/fuzz/transformation_equation_instruction_test.cpp
+++ b/test/fuzz/transformation_equation_instruction_test.cpp
@@ -102,8 +102,12 @@
       14, SpvOpSNegate, {7}, return_instruction);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
+  ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(14));
+  ASSERT_EQ(nullptr, context->get_instr_block(14));
   ApplyAndCheckFreshIds(transformation1, context.get(),
                         &transformation_context);
+  ASSERT_EQ(SpvOpSNegate, context->get_def_use_mgr()->GetDef(14)->opcode());
+  ASSERT_EQ(13, context->get_instr_block(14)->id());
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
 
diff --git a/test/fuzz/transformation_permute_phi_operands_test.cpp b/test/fuzz/transformation_permute_phi_operands_test.cpp
index 2843cfc..3df399a 100644
--- a/test/fuzz/transformation_permute_phi_operands_test.cpp
+++ b/test/fuzz/transformation_permute_phi_operands_test.cpp
@@ -105,6 +105,23 @@
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
+  // Check that the def-use manager knows that the phi instruction's ids have
+  // been permuted.
+  std::vector<std::pair<uint32_t, uint32_t>> phi_operand_to_new_operand_index =
+      {{20, 4}, {16, 5}, {24, 2}, {21, 3}};
+  for (std::pair<uint32_t, uint32_t>& entry :
+       phi_operand_to_new_operand_index) {
+    context->get_def_use_mgr()->WhileEachUse(
+        entry.first,
+        [&entry](opt::Instruction* inst, uint32_t operand_index) -> bool {
+          if (inst->result_id() == 25) {
+            EXPECT_EQ(entry.second, operand_index);
+            return false;
+          }
+          return true;
+        });
+  }
+
   std::string after_transformation = R"(
                OpCapability Shader
           %1 = OpExtInstImport "GLSL.std.450"
diff --git a/test/fuzz/transformation_replace_id_with_synonym_test.cpp b/test/fuzz/transformation_replace_id_with_synonym_test.cpp
index 5c10fc5..629a00e 100644
--- a/test/fuzz/transformation_replace_id_with_synonym_test.cpp
+++ b/test/fuzz/transformation_replace_id_with_synonym_test.cpp
@@ -303,10 +303,18 @@
   auto global_constant_synonym = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(19, MakeInstructionDescriptor(47, SpvOpStore, 0), 1),
       210);
+  uint32_t num_uses_of_original_id_before_replacement =
+      context->get_def_use_mgr()->NumUses(19);
+  uint32_t num_uses_of_synonym_before_replacement =
+      context->get_def_use_mgr()->NumUses(210);
   ASSERT_TRUE(global_constant_synonym.IsApplicable(context.get(),
                                                    transformation_context));
   ApplyAndCheckFreshIds(global_constant_synonym, context.get(),
                         &transformation_context);
+  ASSERT_EQ(num_uses_of_original_id_before_replacement - 1,
+            context->get_def_use_mgr()->NumUses(19));
+  ASSERT_EQ(num_uses_of_synonym_before_replacement + 1,
+            context->get_def_use_mgr()->NumUses(210));
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
 
diff --git a/test/fuzz/transformation_set_loop_control_test.cpp b/test/fuzz/transformation_set_loop_control_test.cpp
index 5c95ccc..88b4aab 100644
--- a/test/fuzz/transformation_set_loop_control_test.cpp
+++ b/test/fuzz/transformation_set_loop_control_test.cpp
@@ -958,8 +958,8 @@
         context.get(), validator_options, kConsoleMessageConsumer));
     TransformationContext transformation_context(
         MakeUnique<FactManager>(context.get()), validator_options);
-    TransformationSetLoopControl peel_count(
-        10, SpvLoopControlPeelCountMask, 4, 0);
+    TransformationSetLoopControl peel_count(10, SpvLoopControlPeelCountMask, 4,
+                                            0);
     TransformationSetLoopControl partial_count(
         10, SpvLoopControlPartialCountMask, 0, 4);
 
diff --git a/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp b/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp
index e7a8732..6133a7a 100644
--- a/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp
+++ b/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp
@@ -91,9 +91,31 @@
 
   TransformationSwapConditionalBranchOperands transformation(
       MakeInstructionDescriptor(15, SpvOpBranchConditional, 0), 26);
+  ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(26));
+  ASSERT_EQ(nullptr, context->get_instr_block(26));
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+  ASSERT_EQ(SpvOpLogicalNot, context->get_def_use_mgr()->GetDef(26)->opcode());
+  ASSERT_EQ(5, context->get_instr_block(26)->id());
+  ASSERT_EQ(1, context->get_def_use_mgr()->NumUses(26));
+
+  // Check that the def-use manager knows that the conditional branch operands
+  // have been swapped.
+  std::vector<std::pair<uint32_t, uint32_t>> phi_operand_to_new_operand_index =
+      {{16, 2}, {21, 1}};
+  for (std::pair<uint32_t, uint32_t>& entry :
+       phi_operand_to_new_operand_index) {
+    context->get_def_use_mgr()->WhileEachUse(
+        entry.first,
+        [&entry](opt::Instruction* inst, uint32_t operand_index) -> bool {
+          if (inst->opcode() == SpvOpBranchConditional) {
+            EXPECT_EQ(entry.second, operand_index);
+            return false;
+          }
+          return true;
+        });
+  }
 
   std::string after_transformation = R"(
                OpCapability Shader