diff options
| -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 e36b1cdcfd..589b44a167 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 09412a9c86..f85ac5185e 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 be6b355d22..5e2dec1623 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. |