summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing
diff options
context:
space:
mode:
authorRoland Levillain <rpl@google.com>2014-09-25 10:10:38 +0100
committerRoland Levillain <rpl@google.com>2014-09-25 10:10:38 +0100
commit6b46923ff0197c95f1e7ea0bc730961df6725cc9 (patch)
tree45cf685a23c70f95b1d16b7d3d67369d6148a514 /compiler/optimizing
parentc0d36abb12cdbb9469039c1dc153a586bd984015 (diff)
downloadart-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.cc32
-rw-r--r--compiler/optimizing/nodes.cc9
-rw-r--r--compiler/optimizing/nodes.h3
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.