Add a new helper RecomputeDominatorTree

It clears loop and dominance information, and builds the dominator
tree. It also dchecks that we are not calling this methods with
irreducible loops, as it is not supported.

When adding this helper we found a partial LSE bug as it was
recomputing dominator tree for irreducible loops.

Test: art/test/testrunner/testrunner.py --host --64 -b --optimizing
Bug: 304749506
Change-Id: Ia4cc72cd19779ad881fa686e52b43679fe5a64d3
diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc
index 8e6b6db..5a7b836 100644
--- a/compiler/optimizing/dead_code_elimination.cc
+++ b/compiler/optimizing/dead_code_elimination.cc
@@ -312,9 +312,7 @@
 
   // We need to re-analyze the graph in order to run DCE afterwards.
   if (rerun_dominance_and_loop_analysis) {
-    graph_->ClearLoopInformation();
-    graph_->ClearDominanceInformation();
-    graph_->BuildDominatorTree();
+    graph_->RecomputeDominatorTree();
     return true;
   }
   return false;
@@ -438,9 +436,7 @@
   // We need to re-analyze the graph in order to run DCE afterwards.
   if (simplified_one_or_more_ifs) {
     if (rerun_dominance_and_loop_analysis) {
-      graph_->ClearLoopInformation();
-      graph_->ClearDominanceInformation();
-      graph_->BuildDominatorTree();
+      graph_->RecomputeDominatorTree();
     } else {
       graph_->ClearDominanceInformation();
       // We have introduced critical edges, remove them.
@@ -808,9 +804,7 @@
   // dominator tree and try block membership.
   if (removed_one_or_more_blocks || force_recomputation) {
     if (rerun_dominance_and_loop_analysis || force_loop_recomputation) {
-      graph_->ClearLoopInformation();
-      graph_->ClearDominanceInformation();
-      graph_->BuildDominatorTree();
+      graph_->RecomputeDominatorTree();
     } else {
       graph_->ClearDominanceInformation();
       graph_->ComputeDominanceInformation();
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc
index 58fdd1c..36c3770 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -1364,7 +1364,9 @@
   }
 
   bool ShouldPerformPartialLSE() const {
-    return perform_partial_lse_ && !GetGraph()->IsCompilingOsr();
+    return perform_partial_lse_ &&
+           !GetGraph()->IsCompilingOsr() &&
+           !GetGraph()->HasIrreducibleLoops();
   }
 
   bool perform_partial_lse_;
@@ -3072,10 +3074,8 @@
                                        Handle<mirror::DexCache>(),
                                        /* is_first_run= */ false);
     rtp_fixup.Visit(ArrayRef<HInstruction* const>(new_ref_phis_));
-    GetGraph()->ClearLoopInformation();
-    GetGraph()->ClearDominanceInformation();
     GetGraph()->ClearReachabilityInformation();
-    GetGraph()->BuildDominatorTree();
+    GetGraph()->RecomputeDominatorTree();
     GetGraph()->ComputeReachabilityInformation();
   }
 
diff --git a/compiler/optimizing/load_store_elimination_test.cc b/compiler/optimizing/load_store_elimination_test.cc
index d3cf8bf..eb07113 100644
--- a/compiler/optimizing/load_store_elimination_test.cc
+++ b/compiler/optimizing/load_store_elimination_test.cc
@@ -8111,21 +8111,10 @@
   EXPECT_TRUE(loop_header->IsLoopHeader());
   EXPECT_TRUE(loop_header->GetLoopInformation()->IsIrreducible());
 
+  // Partial LSE cannot run with irreducible loops.
   EXPECT_INS_RETAINED(left_set);
-  EXPECT_INS_REMOVED(write_start);
-  EXPECT_INS_REMOVED(read_end);
-
-  HPredicatedInstanceFieldGet* pred_get =
-      FindSingleInstruction<HPredicatedInstanceFieldGet>(graph_, breturn);
-  ASSERT_NE(pred_get, nullptr);
-  ASSERT_TRUE(pred_get->GetDefaultValue()->IsPhi()) << pred_get->DumpWithArgs();
-  EXPECT_INS_EQ(pred_get->GetDefaultValue()->InputAt(0), c11);
-  EXPECT_INS_EQ(pred_get->GetDefaultValue()->InputAt(1), graph_->GetIntConstant(0));
-  ASSERT_TRUE(pred_get->GetTarget()->IsPhi()) << pred_get->DumpWithArgs();
-  EXPECT_INS_EQ(pred_get->GetTarget()->InputAt(0), graph_->GetNullConstant());
-  HNewInstance* mat = FindSingleInstruction<HNewInstance>(graph_, right->GetSinglePredecessor());
-  ASSERT_NE(mat, nullptr);
-  EXPECT_INS_EQ(pred_get->GetTarget()->InputAt(1), mat);
+  EXPECT_INS_RETAINED(write_start);
+  EXPECT_INS_RETAINED(read_end);
 }
 
 enum class UsesOrder { kDefaultOrder, kReverseOrder };
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 5795ea7..53ed49a 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -255,6 +255,14 @@
   return kAnalysisSuccess;
 }
 
+GraphAnalysisResult HGraph::RecomputeDominatorTree() {
+  DCHECK(!HasIrreducibleLoops()) << "Recomputing loop information in graphs with irreducible loops "
+                                 << "is unsupported, as it could lead to loop header changes";
+  ClearLoopInformation();
+  ClearDominanceInformation();
+  return BuildDominatorTree();
+}
+
 void HGraph::ClearDominanceInformation() {
   for (HBasicBlock* block : GetActiveBlocks()) {
     block->ClearDominanceInformation();
@@ -3001,12 +3009,7 @@
       }
     }
     if (rerun_loop_analysis) {
-      DCHECK(!outer_graph->HasIrreducibleLoops())
-          << "Recomputing loop information in graphs with irreducible loops "
-          << "is unsupported, as it could lead to loop header changes";
-      outer_graph->ClearLoopInformation();
-      outer_graph->ClearDominanceInformation();
-      outer_graph->BuildDominatorTree();
+      outer_graph->RecomputeDominatorTree();
     } else if (rerun_dominance) {
       outer_graph->ClearDominanceInformation();
       outer_graph->ComputeDominanceInformation();
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 9cf5218..3613b95 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -467,6 +467,7 @@
   void ClearLoopInformation();
   void FindBackEdges(ArenaBitVector* visited);
   GraphAnalysisResult BuildDominatorTree();
+  GraphAnalysisResult RecomputeDominatorTree();
   void SimplifyCFG();
   void SimplifyCatchBlocks();