Invalidate analyses (#4260)

Some reduction opportunities don't invalidate all analyses. This PR
fixes the situation (although we might invalidate more analyses than
required).
diff --git a/source/reduce/change_operand_reduction_opportunity.cpp b/source/reduce/change_operand_reduction_opportunity.cpp
index c3f6fd7..18e340b 100644
--- a/source/reduce/change_operand_reduction_opportunity.cpp
+++ b/source/reduce/change_operand_reduction_opportunity.cpp
@@ -14,6 +14,8 @@
 
 #include "source/reduce/change_operand_reduction_opportunity.h"
 
+#include "source/opt/ir_context.h"
+
 namespace spvtools {
 namespace reduce {
 
@@ -26,6 +28,7 @@
 
 void ChangeOperandReductionOpportunity::Apply() {
   inst_->SetOperand(operand_index_, {new_id_});
+  inst_->context()->get_def_use_mgr()->UpdateDefUse(inst_);
 }
 
 }  // namespace reduce
diff --git a/source/reduce/remove_block_reduction_opportunity.cpp b/source/reduce/remove_block_reduction_opportunity.cpp
index aa48105..55e9576 100644
--- a/source/reduce/remove_block_reduction_opportunity.cpp
+++ b/source/reduce/remove_block_reduction_opportunity.cpp
@@ -20,12 +20,11 @@
 namespace reduce {
 
 RemoveBlockReductionOpportunity::RemoveBlockReductionOpportunity(
-    opt::Function* function, opt::BasicBlock* block)
-    : function_(function), block_(block) {
+    opt::IRContext* context, opt::Function* function, opt::BasicBlock* block)
+    : context_(context), function_(function), block_(block) {
   // precondition:
   assert(block_->begin() != block_->end() &&
-         block_->begin()->context()->get_def_use_mgr()->NumUsers(
-             block_->id()) == 0 &&
+         context_->get_def_use_mgr()->NumUsers(block_->id()) == 0 &&
          "RemoveBlockReductionOpportunity block must have 0 references");
 }
 
@@ -38,10 +37,8 @@
   // We need an iterator pointing to the block, hence the loop.
   for (auto bi = function_->begin(); bi != function_->end(); ++bi) {
     if (bi->id() == block_->id()) {
-      bi->KillAllInsts(true);
       bi.Erase();
-      // Block removal changes the function, but we don't use analyses, so no
-      // need to invalidate them.
+      context_->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
       return;
     }
   }
diff --git a/source/reduce/remove_block_reduction_opportunity.h b/source/reduce/remove_block_reduction_opportunity.h
index 4b358ab..03fede5 100644
--- a/source/reduce/remove_block_reduction_opportunity.h
+++ b/source/reduce/remove_block_reduction_opportunity.h
@@ -27,7 +27,8 @@
 class RemoveBlockReductionOpportunity : public ReductionOpportunity {
  public:
   // Creates the opportunity to remove |block| in |function| in |context|.
-  RemoveBlockReductionOpportunity(opt::Function* function,
+  RemoveBlockReductionOpportunity(opt::IRContext* context,
+                                  opt::Function* function,
                                   opt::BasicBlock* block);
 
   bool PreconditionHolds() override;
@@ -36,6 +37,7 @@
   void Apply() override;
 
  private:
+  opt::IRContext* context_;
   opt::Function* function_;
   opt::BasicBlock* block_;
 };
diff --git a/source/reduce/remove_block_reduction_opportunity_finder.cpp b/source/reduce/remove_block_reduction_opportunity_finder.cpp
index 27a4570..3b13728 100644
--- a/source/reduce/remove_block_reduction_opportunity_finder.cpp
+++ b/source/reduce/remove_block_reduction_opportunity_finder.cpp
@@ -32,8 +32,8 @@
   for (auto* function : GetTargetFunctions(context, target_function)) {
     for (auto bi = function->begin(); bi != function->end(); ++bi) {
       if (IsBlockValidOpportunity(context, function, &bi)) {
-        result.push_back(
-            MakeUnique<RemoveBlockReductionOpportunity>(function, &*bi));
+        result.push_back(MakeUnique<RemoveBlockReductionOpportunity>(
+            context, function, &*bi));
       }
     }
   }
diff --git a/source/reduce/remove_function_reduction_opportunity.cpp b/source/reduce/remove_function_reduction_opportunity.cpp
index ecad670..4b85058 100644
--- a/source/reduce/remove_function_reduction_opportunity.cpp
+++ b/source/reduce/remove_function_reduction_opportunity.cpp
@@ -29,8 +29,8 @@
   for (opt::Module::iterator function_it = context_->module()->begin();
        function_it != context_->module()->end(); ++function_it) {
     if (&*function_it == function_) {
-      opt::eliminatedeadfunctionsutil::EliminateFunction(context_,
-                                                         &function_it);
+      function_it.Erase();
+      context_->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
       return;
     }
   }
diff --git a/source/reduce/remove_struct_member_reduction_opportunity.cpp b/source/reduce/remove_struct_member_reduction_opportunity.cpp
index 787c629..da096e1 100644
--- a/source/reduce/remove_struct_member_reduction_opportunity.cpp
+++ b/source/reduce/remove_struct_member_reduction_opportunity.cpp
@@ -129,6 +129,8 @@
 
   // Remove the member from the struct type.
   struct_type_->RemoveInOperand(member_index_);
+
+  context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 }
 
 void RemoveStructMemberReductionOpportunity::AdjustAccessedIndices(
diff --git a/source/reduce/simple_conditional_branch_to_branch_reduction_opportunity.cpp b/source/reduce/simple_conditional_branch_to_branch_reduction_opportunity.cpp
index ca17f9e..a2be0c4 100644
--- a/source/reduce/simple_conditional_branch_to_branch_reduction_opportunity.cpp
+++ b/source/reduce/simple_conditional_branch_to_branch_reduction_opportunity.cpp
@@ -51,6 +51,8 @@
       {{SPV_OPERAND_TYPE_ID,
         {conditional_branch_instruction_->GetSingleWordInOperand(
             kTrueBranchOperandIndex)}}});
+  conditional_branch_instruction_->context()->InvalidateAnalysesExceptFor(
+      opt::IRContext::kAnalysisNone);
 }
 
 }  // namespace reduce