diff options
author | Roland Levillain <rpl@google.com> | 2014-09-25 10:10:38 +0100 |
---|---|---|
committer | Roland Levillain <rpl@google.com> | 2014-09-25 10:10:38 +0100 |
commit | 6b46923ff0197c95f1e7ea0bc730961df6725cc9 (patch) | |
tree | 45cf685a23c70f95b1d16b7d3d67369d6148a514 /compiler/optimizing | |
parent | c0d36abb12cdbb9469039c1dc153a586bd984015 (diff) | |
download | art-6b46923ff0197c95f1e7ea0bc730961df6725cc9.zip art-6b46923ff0197c95f1e7ea0bc730961df6725cc9.tar.gz art-6b46923ff0197c95f1e7ea0bc730961df6725cc9.tar.bz2 |
Optimizing compiler: check inputs & uses definitions in CFG.
Ensure each input and each use of an instruction is defined
in a block of the control-flow graph.
Change-Id: If4a83b02825230329b0b4fd84255dcb7c3219684
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/graph_checker.cc | 32 | ||||
-rw-r--r-- | compiler/optimizing/nodes.cc | 9 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 3 |
3 files changed, 44 insertions, 0 deletions
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index e36b1cd..589b44a 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -141,6 +141,38 @@ void GraphChecker::VisitInstruction(HInstruction* instruction) { } errors_.Insert(error.str()); } + + // Ensure the inputs of `instruction` are defined in a block of the graph. + for (HInputIterator input_it(instruction); !input_it.Done(); + input_it.Advance()) { + HInstruction* input = input_it.Current(); + const HInstructionList& list = input->IsPhi() + ? input->GetBlock()->GetPhis() + : input->GetBlock()->GetInstructions(); + if (!list.Contains(input)) { + std::stringstream error; + error << "Input " << input->GetId() + << " of instruction " << instruction->GetId() + << " is not defined in a basic block of the control-flow graph."; + errors_.Insert(error.str()); + } + } + + // Ensure the uses of `instruction` are defined in a block of the graph. + for (HUseIterator<HInstruction> use_it(instruction->GetUses()); + !use_it.Done(); use_it.Advance()) { + HInstruction* use = use_it.Current()->GetUser(); + const HInstructionList& list = use->IsPhi() + ? use->GetBlock()->GetPhis() + : use->GetBlock()->GetInstructions(); + if (!list.Contains(use)) { + std::stringstream error; + error << "User " << use->GetId() + << " of instruction " << instruction->GetId() + << " is not defined in a basic block of the control-flow graph."; + errors_.Insert(error.str()); + } + } } void SSAChecker::VisitBasicBlock(HBasicBlock* block) { diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 09412a9..f85ac51 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -427,6 +427,15 @@ void HInstructionList::RemoveInstruction(HInstruction* instruction) { } } +bool HInstructionList::Contains(HInstruction* instruction) const { + for (HInstructionIterator it(*this); !it.Done(); it.Advance()) { + if (it.Current() == instruction) { + return true; + } + } + return false; +} + bool HInstructionList::FoundBefore(const HInstruction* instruction1, const HInstruction* instruction2) const { DCHECK_EQ(instruction1->GetBlock(), instruction2->GetBlock()); diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index be6b355..5e2dec1 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -57,6 +57,9 @@ class HInstructionList { void AddInstruction(HInstruction* instruction); void RemoveInstruction(HInstruction* instruction); + // Return true if this list contains `instruction`. + bool Contains(HInstruction* instruction) const; + // Return true if `instruction1` is found before `instruction2` in // this instruction list and false otherwise. Abort if none // of these instructions is found. |