Update the graph flags and check consistency
Check that the flags are up to date in graph checker. Mainly a
correctness check CL but it brings slight code size reduction
(e.g. not needing vreg info if HasMonitorOperations is false).
Update loop_optimization_test to stop using `LocalRun` directly
as it meant that it was breaking assumptions (i.e. top_loop_ was
nullptr when it was expected to have a value).
Bug: 264278131
Test: art/test/testrunner/testrunner.py --host --64 --optimizing -b
Change-Id: I29765b3be46d4bd7c91ea9c80f7565a3c88fae2e
diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc
index 66a3b8b..52f1e9a 100644
--- a/compiler/optimizing/bounds_check_elimination.cc
+++ b/compiler/optimizing/bounds_check_elimination.cc
@@ -564,6 +564,19 @@
early_exit_loop_.clear();
taken_test_loop_.clear();
finite_loop_.clear();
+
+ // We may have eliminated all bounds checks so we should update the flag.
+ // TODO(solanes): Do this without a linear pass of the graph?
+ GetGraph()->SetHasBoundsChecks(false);
+ for (HBasicBlock* block : GetGraph()->GetReversePostOrder()) {
+ for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
+ HInstruction* instruction = it.Current();
+ if (instruction->IsBoundsCheck()) {
+ GetGraph()->SetHasBoundsChecks(true);
+ return;
+ }
+ }
+ }
}
private:
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 9e871c4..48d1a9d 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -103,7 +103,6 @@
graph_->SetNumberOfVRegs(code_item_accessor_.RegistersSize());
graph_->SetNumberOfInVRegs(code_item_accessor_.InsSize());
graph_->SetMaximumNumberOfOutVRegs(code_item_accessor_.OutsSize());
- graph_->SetHasTryCatch(code_item_accessor_.TriesSize() != 0);
// Use ScopedArenaAllocator for all local allocations.
ScopedArenaAllocator local_allocator(graph_->GetArenaStack());
@@ -168,7 +167,6 @@
graph_->SetNumberOfVRegs(return_vregs + num_arg_vregs);
graph_->SetNumberOfInVRegs(num_arg_vregs);
graph_->SetMaximumNumberOfOutVRegs(num_arg_vregs);
- graph_->SetHasTryCatch(false);
// Use ScopedArenaAllocator for all local allocations.
ScopedArenaAllocator local_allocator(graph_->GetArenaStack());
diff --git a/compiler/optimizing/dead_code_elimination.cc b/compiler/optimizing/dead_code_elimination.cc
index e15e731..0ce8bfa 100644
--- a/compiler/optimizing/dead_code_elimination.cc
+++ b/compiler/optimizing/dead_code_elimination.cc
@@ -629,7 +629,6 @@
}
}
- const size_t total_tries = tries.size();
size_t removed_tries = 0;
bool any_block_in_loop = false;
@@ -641,10 +640,6 @@
}
}
- if (removed_tries == total_tries) {
- graph_->SetHasTryCatch(false);
- }
-
if (removed_tries != 0) {
// We want to:
// 1) Update the dominance information
@@ -741,6 +736,33 @@
}
}
+void HDeadCodeElimination::UpdateGraphFlags() {
+ bool has_monitor_operations = false;
+ bool has_simd = false;
+ bool has_bounds_checks = false;
+ bool has_always_throwing_invokes = false;
+
+ for (HBasicBlock* block : graph_->GetReversePostOrder()) {
+ for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
+ HInstruction* instruction = it.Current();
+ if (instruction->IsMonitorOperation()) {
+ has_monitor_operations = true;
+ } else if (instruction->IsVecOperation()) {
+ has_simd = true;
+ } else if (instruction->IsBoundsCheck()) {
+ has_bounds_checks = true;
+ } else if (instruction->IsInvoke() && instruction->AsInvoke()->AlwaysThrows()) {
+ has_always_throwing_invokes = true;
+ }
+ }
+ }
+
+ graph_->SetHasMonitorOperations(has_monitor_operations);
+ graph_->SetHasSIMD(has_simd);
+ graph_->SetHasBoundsChecks(has_bounds_checks);
+ graph_->SetHasAlwaysThrowingInvokes(has_always_throwing_invokes);
+}
+
bool HDeadCodeElimination::Run() {
// Do not eliminate dead blocks if the graph has irreducible loops. We could
// support it, but that would require changes in our loop representation to handle
@@ -764,6 +786,7 @@
}
SsaRedundantPhiElimination(graph_).Run();
RemoveDeadInstructions();
+ UpdateGraphFlags();
return true;
}
diff --git a/compiler/optimizing/dead_code_elimination.h b/compiler/optimizing/dead_code_elimination.h
index 1988733..b91006b 100644
--- a/compiler/optimizing/dead_code_elimination.h
+++ b/compiler/optimizing/dead_code_elimination.h
@@ -48,6 +48,12 @@
bool SimplifyAlwaysThrows();
bool SimplifyIfs();
void ConnectSuccessiveBlocks();
+ // Updates the graph flags related to instructions (e.g. HasSIMD()) since we may have eliminated
+ // the relevant instructions. There's no need to update `SetHasTryCatch` since we do that in
+ // `ComputeTryBlockInformation`. Similarly with `HasLoops` and `HasIrreducibleLoops`: They are
+ // cleared in `ClearLoopInformation` and then set as true as part of `HLoopInformation::Populate`,
+ // if needed.
+ void UpdateGraphFlags();
// Helper struct to eliminate tries.
struct TryBelongingInformation;
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index b20b531..ca29a09 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -80,9 +80,91 @@
// as the latter might visit dead blocks removed by the dominator
// computation.
VisitReversePostOrder();
+ CheckGraphFlags();
return current_size;
}
+void GraphChecker::VisitReversePostOrder() {
+ for (HBasicBlock* block : GetGraph()->GetReversePostOrder()) {
+ if (block->IsInLoop()) {
+ flag_info_.seen_loop = true;
+ if (block->GetLoopInformation()->IsIrreducible()) {
+ flag_info_.seen_irreducible_loop = true;
+ }
+ }
+
+ VisitBasicBlock(block);
+ }
+}
+
+static const char* StrBool(bool val) {
+ return val ? "true" : "false";
+}
+
+void GraphChecker::CheckGraphFlags() {
+ if (GetGraph()->HasMonitorOperations() != flag_info_.seen_monitor_operation) {
+ AddError(
+ StringPrintf("Flag mismatch: HasMonitorOperations() (%s) should be equal to "
+ "flag_info_.seen_monitor_operation (%s)",
+ StrBool(GetGraph()->HasMonitorOperations()),
+ StrBool(flag_info_.seen_monitor_operation)));
+ }
+
+ if (GetGraph()->HasTryCatch() != flag_info_.seen_try_boundary) {
+ AddError(
+ StringPrintf("Flag mismatch: HasTryCatch() (%s) should be equal to "
+ "flag_info_.seen_try_boundary (%s)",
+ StrBool(GetGraph()->HasTryCatch()),
+ StrBool(flag_info_.seen_try_boundary)));
+ }
+
+ if (GetGraph()->HasLoops() != flag_info_.seen_loop) {
+ AddError(
+ StringPrintf("Flag mismatch: HasLoops() (%s) should be equal to "
+ "flag_info_.seen_loop (%s)",
+ StrBool(GetGraph()->HasLoops()),
+ StrBool(flag_info_.seen_loop)));
+ }
+
+ if (GetGraph()->HasIrreducibleLoops() && !GetGraph()->HasLoops()) {
+ AddError(StringPrintf("Flag mismatch: HasIrreducibleLoops() (%s) implies HasLoops() (%s)",
+ StrBool(GetGraph()->HasIrreducibleLoops()),
+ StrBool(GetGraph()->HasLoops())));
+ }
+
+ if (GetGraph()->HasIrreducibleLoops() != flag_info_.seen_irreducible_loop) {
+ AddError(
+ StringPrintf("Flag mismatch: HasIrreducibleLoops() (%s) should be equal to "
+ "flag_info_.seen_irreducible_loop (%s)",
+ StrBool(GetGraph()->HasIrreducibleLoops()),
+ StrBool(flag_info_.seen_irreducible_loop)));
+ }
+
+ if (GetGraph()->HasSIMD() != flag_info_.seen_SIMD) {
+ AddError(
+ StringPrintf("Flag mismatch: HasSIMD() (%s) should be equal to "
+ "flag_info_.seen_SIMD (%s)",
+ StrBool(GetGraph()->HasSIMD()),
+ StrBool(flag_info_.seen_SIMD)));
+ }
+
+ if (GetGraph()->HasBoundsChecks() != flag_info_.seen_bounds_checks) {
+ AddError(
+ StringPrintf("Flag mismatch: HasBoundsChecks() (%s) should be equal to "
+ "flag_info_.seen_bounds_checks (%s)",
+ StrBool(GetGraph()->HasBoundsChecks()),
+ StrBool(flag_info_.seen_bounds_checks)));
+ }
+
+ if (GetGraph()->HasAlwaysThrowingInvokes() != flag_info_.seen_always_throwing_invokes) {
+ AddError(
+ StringPrintf("Flag mismatch: HasAlwaysThrowingInvokes() (%s) should be equal to "
+ "flag_info_.seen_always_throwing_invokes (%s)",
+ StrBool(GetGraph()->HasAlwaysThrowingInvokes()),
+ StrBool(flag_info_.seen_always_throwing_invokes)));
+ }
+}
+
void GraphChecker::VisitBasicBlock(HBasicBlock* block) {
current_block_ = block;
@@ -310,12 +392,17 @@
void GraphChecker::VisitBoundsCheck(HBoundsCheck* check) {
VisitInstruction(check);
+
if (!GetGraph()->HasBoundsChecks()) {
- AddError(StringPrintf("Instruction %s:%d is a HBoundsCheck, "
- "but HasBoundsChecks() returns false",
- check->DebugName(),
- check->GetId()));
+ AddError(
+ StringPrintf("The graph doesn't have the HasBoundsChecks flag set but we saw "
+ "%s:%d in block %d.",
+ check->DebugName(),
+ check->GetId(),
+ check->GetBlock()->GetBlockId()));
}
+
+ flag_info_.seen_bounds_checks = true;
}
void GraphChecker::VisitDeoptimize(HDeoptimize* deopt) {
@@ -356,12 +443,14 @@
if (!GetGraph()->HasTryCatch()) {
AddError(
- StringPrintf("The graph doesn't have the HasTryCatch bit set but we saw "
+ StringPrintf("The graph doesn't have the HasTryCatch flag set but we saw "
"%s:%d in block %d.",
try_boundary->DebugName(),
try_boundary->GetId(),
try_boundary->GetBlock()->GetBlockId()));
}
+
+ flag_info_.seen_try_boundary = true;
}
void GraphChecker::VisitLoadException(HLoadException* load) {
@@ -387,12 +476,14 @@
if (!GetGraph()->HasMonitorOperations()) {
AddError(
- StringPrintf("The graph doesn't have the HasMonitorOperations bit set but we saw "
+ StringPrintf("The graph doesn't have the HasMonitorOperations flag set but we saw "
"%s:%d in block %d.",
monitor_op->DebugName(),
monitor_op->GetId(),
monitor_op->GetBlock()->GetBlockId()));
}
+
+ flag_info_.seen_monitor_operation = true;
}
void GraphChecker::VisitInstruction(HInstruction* instruction) {
@@ -573,9 +664,26 @@
}
}
-void GraphChecker::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) {
+void GraphChecker::VisitInvoke(HInvoke* invoke) {
VisitInstruction(invoke);
+ if (invoke->AlwaysThrows()) {
+ if (!GetGraph()->HasAlwaysThrowingInvokes()) {
+ AddError(
+ StringPrintf("The graph doesn't have the HasAlwaysThrowingInvokes flag set but we saw "
+ "%s:%d in block %d and it always throws.",
+ invoke->DebugName(),
+ invoke->GetId(),
+ invoke->GetBlock()->GetBlockId()));
+ }
+ flag_info_.seen_always_throwing_invokes = true;
+ }
+}
+
+void GraphChecker::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) {
+ // We call VisitInvoke and not VisitInstruction to de-duplicate the always throwing code check.
+ VisitInvoke(invoke);
+
if (invoke->IsStaticWithExplicitClinitCheck()) {
const HInstruction* last_input = invoke->GetInputs().back();
if (last_input == nullptr) {
@@ -1089,13 +1197,13 @@
if (instruction->NeedsTypeCheck() !=
instruction->GetSideEffects().Includes(SideEffects::CanTriggerGC())) {
- AddError(StringPrintf(
- "%s %d has a flag mismatch. An ArraySet instruction can trigger a GC iff it "
- "needs a type check. Needs type check: %s, Can trigger GC: %s",
- instruction->DebugName(),
- instruction->GetId(),
- instruction->NeedsTypeCheck() ? "true" : "false",
- instruction->GetSideEffects().Includes(SideEffects::CanTriggerGC()) ? "true" : "false"));
+ AddError(
+ StringPrintf("%s %d has a flag mismatch. An ArraySet instruction can trigger a GC iff it "
+ "needs a type check. Needs type check: %s, Can trigger GC: %s",
+ instruction->DebugName(),
+ instruction->GetId(),
+ StrBool(instruction->NeedsTypeCheck()),
+ StrBool(instruction->GetSideEffects().Includes(SideEffects::CanTriggerGC()))));
}
}
@@ -1199,6 +1307,18 @@
void GraphChecker::VisitVecOperation(HVecOperation* instruction) {
VisitInstruction(instruction);
+
+ if (!GetGraph()->HasSIMD()) {
+ AddError(
+ StringPrintf("The graph doesn't have the HasSIMD flag set but we saw "
+ "%s:%d in block %d.",
+ instruction->DebugName(),
+ instruction->GetId(),
+ instruction->GetBlock()->GetBlockId()));
+ }
+
+ flag_info_.seen_SIMD = true;
+
if (codegen_ == nullptr) {
return;
}
diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h
index 738c0d6..674798e 100644
--- a/compiler/optimizing/graph_checker.h
+++ b/compiler/optimizing/graph_checker.h
@@ -66,6 +66,7 @@
void VisitDeoptimize(HDeoptimize* instruction) override;
void VisitIf(HIf* instruction) override;
void VisitInstanceOf(HInstanceOf* check) override;
+ void VisitInvoke(HInvoke* invoke) override;
void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) override;
void VisitLoadException(HLoadException* load) override;
void VisitMonitorOperation(HMonitorOperation* monitor_operation) override;
@@ -126,6 +127,11 @@
ArenaVector<std::string> errors_;
private:
+ void VisitReversePostOrder();
+
+ // Checks that the graph's flags are set correctly.
+ void CheckGraphFlags();
+
// String displayed before dumped errors.
const char* const dump_prefix_;
ScopedArenaAllocator allocator_;
@@ -138,6 +144,17 @@
// Used to access target information.
CodeGenerator* codegen_;
+ struct FlagInfo {
+ bool seen_try_boundary = false;
+ bool seen_monitor_operation = false;
+ bool seen_loop = false;
+ bool seen_irreducible_loop = false;
+ bool seen_SIMD = false;
+ bool seen_bounds_checks = false;
+ bool seen_always_throwing_invokes = false;
+ };
+ FlagInfo flag_info_;
+
DISALLOW_COPY_AND_ASSIGN(GraphChecker);
};
diff --git a/compiler/optimizing/load_store_elimination_test.cc b/compiler/optimizing/load_store_elimination_test.cc
index b1c4805..a7a97f6 100644
--- a/compiler/optimizing/load_store_elimination_test.cc
+++ b/compiler/optimizing/load_store_elimination_test.cc
@@ -542,6 +542,7 @@
AddVecStore(entry_block_, array_, j_);
HInstruction* vstore = AddVecStore(entry_block_, array_, i_);
+ graph_->SetHasSIMD(true);
PerformLSE();
ASSERT_FALSE(IsRemoved(vstore));
@@ -557,6 +558,7 @@
AddVecStore(entry_block_, array_, i_add1_);
HInstruction* vstore = AddVecStore(entry_block_, array_, i_);
+ graph_->SetHasSIMD(true);
PerformLSE();
ASSERT_FALSE(IsRemoved(vstore));
@@ -601,6 +603,7 @@
AddArraySet(entry_block_, array_, i_, c1);
HInstruction* vload5 = AddVecLoad(entry_block_, array_, i_);
+ graph_->SetHasSIMD(true);
PerformLSE();
ASSERT_TRUE(IsRemoved(load1));
@@ -634,6 +637,7 @@
// a[j] = 1;
HInstruction* array_set = AddArraySet(return_block_, array_, j_, c1);
+ graph_->SetHasSIMD(true);
PerformLSE();
ASSERT_TRUE(IsRemoved(array_set));
@@ -671,6 +675,7 @@
// a[j] = 0;
HInstruction* a_set = AddArraySet(return_block_, array_, j_, c0);
+ graph_->SetHasSIMD(true);
PerformLSE();
ASSERT_TRUE(IsRemoved(vload));
@@ -709,6 +714,7 @@
// x = a[j];
HInstruction* load = AddArrayGet(return_block_, array_, j_);
+ graph_->SetHasSIMD(true);
PerformLSE();
ASSERT_TRUE(IsRemoved(vload));
@@ -749,6 +755,7 @@
// down: a[i,... i + 3] = [1,...1]
HInstruction* vstore4 = AddVecStore(down, array_, i_, vdata);
+ graph_->SetHasSIMD(true);
PerformLSE();
ASSERT_TRUE(IsRemoved(vstore2));
@@ -839,6 +846,7 @@
HInstruction* vstore2 = AddVecStore(loop_, array_b, phi_, vload->AsVecLoad());
HInstruction* vstore3 = AddVecStore(loop_, array_a, phi_, vstore1->InputAt(2));
+ graph_->SetHasSIMD(true);
PerformLSE();
ASSERT_FALSE(IsRemoved(vstore1));
@@ -926,6 +934,7 @@
HInstruction* vload = AddVecLoad(loop_, array_a, phi_);
HInstruction* vstore = AddVecStore(return_block_, array_, c0, vload->AsVecLoad());
+ graph_->SetHasSIMD(true);
PerformLSE();
ASSERT_FALSE(IsRemoved(vload));
@@ -949,6 +958,7 @@
HInstruction* vload = AddVecLoad(pre_header_, array_a, c0);
HInstruction* vstore = AddVecStore(return_block_, array_, c0, vload->AsVecLoad());
+ graph_->SetHasSIMD(true);
PerformLSE();
ASSERT_FALSE(IsRemoved(vload));
@@ -1025,6 +1035,7 @@
HInstruction* vstore = AddVecStore(return_block_, array_, c0, vload->AsVecLoad());
HInstruction* store = AddArraySet(return_block_, array_, c0, load);
+ graph_->SetHasSIMD(true);
PerformLSE();
ASSERT_FALSE(IsRemoved(vload));
@@ -1055,6 +1066,7 @@
HInstruction* vstore = AddVecStore(return_block_, array_, c0, vload->AsVecLoad());
HInstruction* store = AddArraySet(return_block_, array_, c0, load);
+ graph_->SetHasSIMD(true);
PerformLSE();
ASSERT_FALSE(IsRemoved(vload));
@@ -1086,6 +1098,7 @@
HInstruction* vstore1 = AddVecStore(return_block_, array_, c0, vload1->AsVecLoad());
HInstruction* vstore2 = AddVecStore(return_block_, array_, c128, vload2->AsVecLoad());
+ graph_->SetHasSIMD(true);
PerformLSE();
ASSERT_FALSE(IsRemoved(vload1));
@@ -1116,6 +1129,7 @@
HInstruction* vstore1 = AddVecStore(return_block_, array_, c0, vload1->AsVecLoad());
HInstruction* vstore2 = AddVecStore(return_block_, array_, c128, vload2->AsVecLoad());
+ graph_->SetHasSIMD(true);
PerformLSE();
ASSERT_FALSE(IsRemoved(vload1));
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 001649c..7a52502 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -507,9 +507,8 @@
graph_->SetHasLoops(false); // no more loops
}
- // Detach.
+ // Detach allocator.
loop_allocator_ = nullptr;
- last_loop_ = top_loop_ = nullptr;
return did_loop_opt;
}
@@ -530,11 +529,7 @@
AddLoop(block->GetLoopInformation());
}
}
-
- // TODO(solanes): How can `top_loop_` be null if `graph_->HasLoops()` is true?
- if (top_loop_ == nullptr) {
- return false;
- }
+ DCHECK(top_loop_ != nullptr);
// Traverse the loop hierarchy inner-to-outer and optimize. Traversal can use
// temporary data structures using the phase-local allocator. All new HIR
diff --git a/compiler/optimizing/loop_optimization_test.cc b/compiler/optimizing/loop_optimization_test.cc
index 71c6988..7f694fb 100644
--- a/compiler/optimizing/loop_optimization_test.cc
+++ b/compiler/optimizing/loop_optimization_test.cc
@@ -95,10 +95,7 @@
void PerformAnalysis() {
graph_->BuildDominatorTree();
iva_->Run();
- // Do not release the loop hierarchy.
- ScopedArenaAllocator loop_allocator(GetArenaStack());
- loop_opt_->loop_allocator_ = &loop_allocator;
- loop_opt_->LocalRun();
+ loop_opt_->Run();
}
/** Constructs string representation of computed loop hierarchy. */
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 0e85838..0876ce0 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -262,6 +262,7 @@
}
void HGraph::ClearLoopInformation() {
+ SetHasLoops(false);
SetHasIrreducibleLoops(false);
for (HBasicBlock* block : GetActiveBlocks()) {
block->SetLoopInformation(nullptr);
@@ -742,6 +743,8 @@
void HGraph::ComputeTryBlockInformation() {
// Iterate in reverse post order to propagate try membership information from
// predecessors to their successors.
+ bool graph_has_try_catch = false;
+
for (HBasicBlock* block : GetReversePostOrder()) {
if (block->IsEntryBlock() || block->IsCatchBlock()) {
// Catch blocks after simplification have only exceptional predecessors
@@ -756,6 +759,7 @@
DCHECK_IMPLIES(block->IsLoopHeader(),
!block->GetLoopInformation()->IsBackEdge(*first_predecessor));
const HTryBoundary* try_entry = first_predecessor->ComputeTryEntryOfSuccessors();
+ graph_has_try_catch |= try_entry != nullptr;
if (try_entry != nullptr &&
(block->GetTryCatchInformation() == nullptr ||
try_entry != &block->GetTryCatchInformation()->GetTryEntry())) {
@@ -764,6 +768,8 @@
block->SetTryCatchInformation(new (allocator_) TryCatchInformation(*try_entry));
}
}
+
+ SetHasTryCatch(graph_has_try_catch);
}
void HGraph::SimplifyCFG() {
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index f33b0d8..8f7635a 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -811,14 +811,11 @@
size_t temporaries_vreg_slots_;
// Flag whether there are bounds checks in the graph. We can skip
- // BCE if it's false. It's only best effort to keep it up to date in
- // the presence of code elimination so there might be false positives.
+ // BCE if it's false.
bool has_bounds_checks_;
// Flag whether there are try/catch blocks in the graph. We will skip
- // try/catch-related passes if it's false. It's only best effort to keep
- // it up to date in the presence of code elimination so there might be
- // false positives.
+ // try/catch-related passes if it's false.
bool has_try_catch_;
// Flag whether there are any HMonitorOperation in the graph. If yes this will mandate
@@ -831,14 +828,10 @@
bool has_simd_;
// Flag whether there are any loops in the graph. We can skip loop
- // optimization if it's false. It's only best effort to keep it up
- // to date in the presence of code elimination so there might be false
- // positives.
+ // optimization if it's false.
bool has_loops_;
- // Flag whether there are any irreducible loops in the graph. It's only
- // best effort to keep it up to date in the presence of code elimination
- // so there might be false positives.
+ // Flag whether there are any irreducible loops in the graph.
bool has_irreducible_loops_;
// Flag whether there are any direct calls to native code registered