diff options
author | 2022-12-16 19:28:47 +0000 | |
---|---|---|
committer | 2023-01-13 16:19:02 +0000 | |
commit | 74da668328e1c501742a864d23ba8c114ece5e64 (patch) | |
tree | a8e6d643230ff9bec8ae8878cd8d1021b813a3e5 /compiler/optimizing/graph_checker.cc | |
parent | 1f3861de4cacb51eacbb624e377b9dc7d7f96cc1 (diff) |
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
Diffstat (limited to 'compiler/optimizing/graph_checker.cc')
-rw-r--r-- | compiler/optimizing/graph_checker.cc | 148 |
1 files changed, 134 insertions, 14 deletions
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index b20b53178f..ca29a09440 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -80,9 +80,91 @@ size_t GraphChecker::Run(bool pass_change, size_t last_size) { // 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::VisitBasicBlock(HBasicBlock* block) { 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 @@ void GraphChecker::VisitTryBoundary(HTryBoundary* try_boundary) { 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 @@ void GraphChecker::VisitMonitorOperation(HMonitorOperation* monitor_op) { 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::VisitInstruction(HInstruction* instruction) { } } -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 @@ void GraphChecker::VisitArraySet(HArraySet* instruction) { 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::VisitTypeConversion(HTypeConversion* instruction) { 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; } |