graph_checker.cc revision db216f4d49ea1561a74261c29f1264952232728a
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "graph_checker.h"
18
19#include <map>
20#include <string>
21#include <sstream>
22
23#include "base/bit_vector-inl.h"
24#include "base/stringprintf.h"
25
26namespace art {
27
28void GraphChecker::VisitBasicBlock(HBasicBlock* block) {
29  current_block_ = block;
30
31  // Check consistency with respect to predecessors of `block`.
32  const GrowableArray<HBasicBlock*>& predecessors = block->GetPredecessors();
33  std::map<HBasicBlock*, size_t> predecessors_count;
34  for (size_t i = 0, e = predecessors.Size(); i < e; ++i) {
35    HBasicBlock* p = predecessors.Get(i);
36    ++predecessors_count[p];
37  }
38  for (auto& pc : predecessors_count) {
39    HBasicBlock* p = pc.first;
40    size_t p_count_in_block_predecessors = pc.second;
41    const GrowableArray<HBasicBlock*>& p_successors = p->GetSuccessors();
42    size_t block_count_in_p_successors = 0;
43    for (size_t j = 0, f = p_successors.Size(); j < f; ++j) {
44      if (p_successors.Get(j) == block) {
45        ++block_count_in_p_successors;
46      }
47    }
48    if (p_count_in_block_predecessors != block_count_in_p_successors) {
49      AddError(StringPrintf(
50          "Block %d lists %zu occurrences of block %d in its predecessors, whereas "
51          "block %d lists %zu occurrences of block %d in its successors.",
52          block->GetBlockId(), p_count_in_block_predecessors, p->GetBlockId(),
53          p->GetBlockId(), block_count_in_p_successors, block->GetBlockId()));
54    }
55  }
56
57  // Check consistency with respect to successors of `block`.
58  const GrowableArray<HBasicBlock*>& successors = block->GetSuccessors();
59  std::map<HBasicBlock*, size_t> successors_count;
60  for (size_t i = 0, e = successors.Size(); i < e; ++i) {
61    HBasicBlock* s = successors.Get(i);
62    ++successors_count[s];
63  }
64  for (auto& sc : successors_count) {
65    HBasicBlock* s = sc.first;
66    size_t s_count_in_block_successors = sc.second;
67    const GrowableArray<HBasicBlock*>& s_predecessors = s->GetPredecessors();
68    size_t block_count_in_s_predecessors = 0;
69    for (size_t j = 0, f = s_predecessors.Size(); j < f; ++j) {
70      if (s_predecessors.Get(j) == block) {
71        ++block_count_in_s_predecessors;
72      }
73    }
74    if (s_count_in_block_successors != block_count_in_s_predecessors) {
75      AddError(StringPrintf(
76          "Block %d lists %zu occurrences of block %d in its successors, whereas "
77          "block %d lists %zu occurrences of block %d in its predecessors.",
78          block->GetBlockId(), s_count_in_block_successors, s->GetBlockId(),
79          s->GetBlockId(), block_count_in_s_predecessors, block->GetBlockId()));
80    }
81  }
82
83  // Ensure `block` ends with a branch instruction.
84  if (!block->EndsWithControlFlowInstruction()) {
85    AddError(StringPrintf("Block %d does not end with a branch instruction.",
86                          block->GetBlockId()));
87  }
88
89  // Visit this block's list of phis.
90  for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
91    HInstruction* current = it.Current();
92    // Ensure this block's list of phis contains only phis.
93    if (!current->IsPhi()) {
94      AddError(StringPrintf("Block %d has a non-phi in its phi list.",
95                            current_block_->GetBlockId()));
96    }
97    if (current->GetNext() == nullptr && current != block->GetLastPhi()) {
98      AddError(StringPrintf("The recorded last phi of block %d does not match "
99                            "the actual last phi %d.",
100                            current_block_->GetBlockId(),
101                            current->GetId()));
102    }
103    current->Accept(this);
104  }
105
106  // Visit this block's list of instructions.
107  for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
108    HInstruction* current = it.Current();
109    // Ensure this block's list of instructions does not contains phis.
110    if (current->IsPhi()) {
111      AddError(StringPrintf("Block %d has a phi in its non-phi list.",
112                            current_block_->GetBlockId()));
113    }
114    if (current->GetNext() == nullptr && current != block->GetLastInstruction()) {
115      AddError(StringPrintf("The recorded last instruction of block %d does not match "
116                            "the actual last instruction %d.",
117                            current_block_->GetBlockId(),
118                            current->GetId()));
119    }
120    current->Accept(this);
121  }
122}
123
124void GraphChecker::VisitBoundsCheck(HBoundsCheck* check) {
125  if (!GetGraph()->HasBoundsChecks()) {
126    AddError(StringPrintf("Instruction %s:%d is a HBoundsCheck, "
127                          "but HasBoundsChecks() returns false",
128                          check->DebugName(),
129                          check->GetId()));
130  }
131
132  // Perform the instruction base checks too.
133  VisitInstruction(check);
134}
135
136void GraphChecker::VisitInstruction(HInstruction* instruction) {
137  if (seen_ids_.IsBitSet(instruction->GetId())) {
138    AddError(StringPrintf("Instruction id %d is duplicate in graph.",
139                          instruction->GetId()));
140  } else {
141    seen_ids_.SetBit(instruction->GetId());
142  }
143
144  // Ensure `instruction` is associated with `current_block_`.
145  if (instruction->GetBlock() == nullptr) {
146    AddError(StringPrintf("%s %d in block %d not associated with any block.",
147                          instruction->IsPhi() ? "Phi" : "Instruction",
148                          instruction->GetId(),
149                          current_block_->GetBlockId()));
150  } else if (instruction->GetBlock() != current_block_) {
151    AddError(StringPrintf("%s %d in block %d associated with block %d.",
152                          instruction->IsPhi() ? "Phi" : "Instruction",
153                          instruction->GetId(),
154                          current_block_->GetBlockId(),
155                          instruction->GetBlock()->GetBlockId()));
156  }
157
158  // Ensure the inputs of `instruction` are defined in a block of the graph.
159  for (HInputIterator input_it(instruction); !input_it.Done();
160       input_it.Advance()) {
161    HInstruction* input = input_it.Current();
162    const HInstructionList& list = input->IsPhi()
163        ? input->GetBlock()->GetPhis()
164        : input->GetBlock()->GetInstructions();
165    if (!list.Contains(input)) {
166      AddError(StringPrintf("Input %d of instruction %d is not defined "
167                            "in a basic block of the control-flow graph.",
168                            input->GetId(),
169                            instruction->GetId()));
170    }
171  }
172
173  // Ensure the uses of `instruction` are defined in a block of the graph,
174  // and the entry in the use list is consistent.
175  for (HUseIterator<HInstruction*> use_it(instruction->GetUses());
176       !use_it.Done(); use_it.Advance()) {
177    HInstruction* use = use_it.Current()->GetUser();
178    const HInstructionList& list = use->IsPhi()
179        ? use->GetBlock()->GetPhis()
180        : use->GetBlock()->GetInstructions();
181    if (!list.Contains(use)) {
182      AddError(StringPrintf("User %s:%d of instruction %d is not defined "
183                            "in a basic block of the control-flow graph.",
184                            use->DebugName(),
185                            use->GetId(),
186                            instruction->GetId()));
187    }
188    size_t use_index = use_it.Current()->GetIndex();
189    if ((use_index >= use->InputCount()) || (use->InputAt(use_index) != instruction)) {
190      AddError(StringPrintf("User %s:%d of instruction %d has a wrong "
191                            "UseListNode index.",
192                            use->DebugName(),
193                            use->GetId(),
194                            instruction->GetId()));
195    }
196  }
197
198  // Ensure the environment uses entries are consistent.
199  for (HUseIterator<HEnvironment*> use_it(instruction->GetEnvUses());
200       !use_it.Done(); use_it.Advance()) {
201    HEnvironment* use = use_it.Current()->GetUser();
202    size_t use_index = use_it.Current()->GetIndex();
203    if ((use_index >= use->Size()) || (use->GetInstructionAt(use_index) != instruction)) {
204      AddError(StringPrintf("Environment user of %s:%d has a wrong "
205                            "UseListNode index.",
206                            instruction->DebugName(),
207                            instruction->GetId()));
208    }
209  }
210
211  // Ensure 'instruction' has pointers to its inputs' use entries.
212  for (size_t i = 0, e = instruction->InputCount(); i < e; ++i) {
213    HUserRecord<HInstruction*> input_record = instruction->InputRecordAt(i);
214    HInstruction* input = input_record.GetInstruction();
215    HUseListNode<HInstruction*>* use_node = input_record.GetUseNode();
216    size_t use_index = use_node->GetIndex();
217    if ((use_node == nullptr)
218        || !input->GetUses().Contains(use_node)
219        || (use_index >= e)
220        || (use_index != i)) {
221      AddError(StringPrintf("Instruction %s:%d has an invalid pointer to use entry "
222                            "at input %u (%s:%d).",
223                            instruction->DebugName(),
224                            instruction->GetId(),
225                            static_cast<unsigned>(i),
226                            input->DebugName(),
227                            input->GetId()));
228    }
229  }
230}
231
232void GraphChecker::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) {
233  VisitInstruction(invoke);
234
235  if (invoke->IsStaticWithExplicitClinitCheck()) {
236    size_t last_input_index = invoke->InputCount() - 1;
237    HInstruction* last_input = invoke->InputAt(last_input_index);
238    if (last_input == nullptr) {
239      AddError(StringPrintf("Static invoke %s:%d marked as having an explicit clinit check "
240                            "has a null pointer as last input.",
241                            invoke->DebugName(),
242                            invoke->GetId()));
243    }
244    if (!last_input->IsClinitCheck() && !last_input->IsLoadClass()) {
245      AddError(StringPrintf("Static invoke %s:%d marked as having an explicit clinit check "
246                            "has a last instruction (%s:%d) which is neither a clinit check "
247                            "nor a load class instruction.",
248                            invoke->DebugName(),
249                            invoke->GetId(),
250                            last_input->DebugName(),
251                            last_input->GetId()));
252    }
253  }
254}
255
256void SSAChecker::VisitBasicBlock(HBasicBlock* block) {
257  super_type::VisitBasicBlock(block);
258
259  // Ensure there is no critical edge (i.e., an edge connecting a
260  // block with multiple successors to a block with multiple
261  // predecessors).
262  if (block->GetSuccessors().Size() > 1) {
263    for (size_t j = 0; j < block->GetSuccessors().Size(); ++j) {
264      HBasicBlock* successor = block->GetSuccessors().Get(j);
265      if (successor->GetPredecessors().Size() > 1) {
266        AddError(StringPrintf("Critical edge between blocks %d and %d.",
267                              block->GetBlockId(),
268                              successor->GetBlockId()));
269      }
270    }
271  }
272
273  // Check Phi uniqueness (no two Phis with the same type refer to the same register).
274  for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
275    HPhi* phi = it.Current()->AsPhi();
276    if (phi->GetNextEquivalentPhiWithSameType() != nullptr) {
277      std::stringstream type_str;
278      type_str << phi->GetType();
279      AddError(StringPrintf("Equivalent phi (%d) found for VReg %d with type: %s",
280          phi->GetId(), phi->GetRegNumber(), type_str.str().c_str()));
281    }
282  }
283
284  if (block->IsLoopHeader()) {
285    CheckLoop(block);
286  }
287}
288
289void SSAChecker::CheckLoop(HBasicBlock* loop_header) {
290  int id = loop_header->GetBlockId();
291  HLoopInformation* loop_information = loop_header->GetLoopInformation();
292
293  // Ensure the pre-header block is first in the list of
294  // predecessors of a loop header.
295  if (!loop_header->IsLoopPreHeaderFirstPredecessor()) {
296    AddError(StringPrintf(
297        "Loop pre-header is not the first predecessor of the loop header %d.",
298        id));
299  }
300
301  // Ensure the loop header has only one incoming branch and the remaining
302  // predecessors are back edges.
303  size_t num_preds = loop_header->GetPredecessors().Size();
304  if (num_preds < 2) {
305    AddError(StringPrintf(
306        "Loop header %d has less than two predecessors: %zu.",
307        id,
308        num_preds));
309  } else {
310    HBasicBlock* first_predecessor = loop_header->GetPredecessors().Get(0);
311    if (loop_information->IsBackEdge(*first_predecessor)) {
312      AddError(StringPrintf(
313          "First predecessor of loop header %d is a back edge.",
314          id));
315    }
316    for (size_t i = 1, e = loop_header->GetPredecessors().Size(); i < e; ++i) {
317      HBasicBlock* predecessor = loop_header->GetPredecessors().Get(i);
318      if (!loop_information->IsBackEdge(*predecessor)) {
319        AddError(StringPrintf(
320            "Loop header %d has multiple incoming (non back edge) blocks.",
321            id));
322      }
323    }
324  }
325
326  const ArenaBitVector& loop_blocks = loop_information->GetBlocks();
327
328  // Ensure back edges belong to the loop.
329  size_t num_back_edges = loop_information->GetBackEdges().Size();
330  if (num_back_edges == 0) {
331    AddError(StringPrintf(
332        "Loop defined by header %d has no back edge.",
333        id));
334  } else {
335    for (size_t i = 0; i < num_back_edges; ++i) {
336      int back_edge_id = loop_information->GetBackEdges().Get(i)->GetBlockId();
337      if (!loop_blocks.IsBitSet(back_edge_id)) {
338        AddError(StringPrintf(
339            "Loop defined by header %d has an invalid back edge %d.",
340            id,
341            back_edge_id));
342      }
343    }
344  }
345
346  // Ensure all blocks in the loop are live and dominated by the loop header.
347  for (uint32_t i : loop_blocks.Indexes()) {
348    HBasicBlock* loop_block = GetGraph()->GetBlocks().Get(i);
349    if (loop_block == nullptr) {
350      AddError(StringPrintf("Loop defined by header %d contains a previously removed block %d.",
351                            id,
352                            i));
353    } else if (!loop_header->Dominates(loop_block)) {
354      AddError(StringPrintf("Loop block %d not dominated by loop header %d.",
355                            i,
356                            id));
357    }
358  }
359
360  // If this is a nested loop, ensure the outer loops contain a superset of the blocks.
361  for (HLoopInformationOutwardIterator it(*loop_header); !it.Done(); it.Advance()) {
362    HLoopInformation* outer_info = it.Current();
363    if (!loop_blocks.IsSubsetOf(&outer_info->GetBlocks())) {
364      AddError(StringPrintf("Blocks of loop defined by header %d are not a subset of blocks of "
365                            "an outer loop defined by header %d.",
366                            id,
367                            outer_info->GetHeader()->GetBlockId()));
368    }
369  }
370}
371
372void SSAChecker::VisitInstruction(HInstruction* instruction) {
373  super_type::VisitInstruction(instruction);
374
375  // Ensure an instruction dominates all its uses.
376  for (HUseIterator<HInstruction*> use_it(instruction->GetUses());
377       !use_it.Done(); use_it.Advance()) {
378    HInstruction* use = use_it.Current()->GetUser();
379    if (!use->IsPhi() && !instruction->StrictlyDominates(use)) {
380      AddError(StringPrintf("Instruction %d in block %d does not dominate "
381                            "use %d in block %d.",
382                            instruction->GetId(), current_block_->GetBlockId(),
383                            use->GetId(), use->GetBlock()->GetBlockId()));
384    }
385  }
386
387  // Ensure an instruction having an environment is dominated by the
388  // instructions contained in the environment.
389  HEnvironment* environment = instruction->GetEnvironment();
390  if (environment != nullptr) {
391    for (size_t i = 0, e = environment->Size(); i < e; ++i) {
392      HInstruction* env_instruction = environment->GetInstructionAt(i);
393      if (env_instruction != nullptr
394          && !env_instruction->StrictlyDominates(instruction)) {
395        AddError(StringPrintf("Instruction %d in environment of instruction %d "
396                              "from block %d does not dominate instruction %d.",
397                              env_instruction->GetId(),
398                              instruction->GetId(),
399                              current_block_->GetBlockId(),
400                              instruction->GetId()));
401      }
402    }
403  }
404}
405
406static Primitive::Type PrimitiveKind(Primitive::Type type) {
407  switch (type) {
408    case Primitive::kPrimBoolean:
409    case Primitive::kPrimByte:
410    case Primitive::kPrimShort:
411    case Primitive::kPrimChar:
412    case Primitive::kPrimInt:
413      return Primitive::kPrimInt;
414    default:
415      return type;
416  }
417}
418
419void SSAChecker::VisitPhi(HPhi* phi) {
420  VisitInstruction(phi);
421
422  // Ensure the first input of a phi is not itself.
423  if (phi->InputAt(0) == phi) {
424    AddError(StringPrintf("Loop phi %d in block %d is its own first input.",
425                          phi->GetId(),
426                          phi->GetBlock()->GetBlockId()));
427  }
428
429  // Ensure the number of inputs of a phi is the same as the number of
430  // its predecessors.
431  const GrowableArray<HBasicBlock*>& predecessors =
432    phi->GetBlock()->GetPredecessors();
433  if (phi->InputCount() != predecessors.Size()) {
434    AddError(StringPrintf(
435        "Phi %d in block %d has %zu inputs, "
436        "but block %d has %zu predecessors.",
437        phi->GetId(), phi->GetBlock()->GetBlockId(), phi->InputCount(),
438        phi->GetBlock()->GetBlockId(), predecessors.Size()));
439  } else {
440    // Ensure phi input at index I either comes from the Ith
441    // predecessor or from a block that dominates this predecessor.
442    for (size_t i = 0, e = phi->InputCount(); i < e; ++i) {
443      HInstruction* input = phi->InputAt(i);
444      HBasicBlock* predecessor = predecessors.Get(i);
445      if (!(input->GetBlock() == predecessor
446            || input->GetBlock()->Dominates(predecessor))) {
447        AddError(StringPrintf(
448            "Input %d at index %zu of phi %d from block %d is not defined in "
449            "predecessor number %zu nor in a block dominating it.",
450            input->GetId(), i, phi->GetId(), phi->GetBlock()->GetBlockId(),
451            i));
452      }
453    }
454  }
455  // Ensure that the inputs have the same primitive kind as the phi.
456  for (size_t i = 0, e = phi->InputCount(); i < e; ++i) {
457    HInstruction* input = phi->InputAt(i);
458    if (PrimitiveKind(input->GetType()) != PrimitiveKind(phi->GetType())) {
459        AddError(StringPrintf(
460            "Input %d at index %zu of phi %d from block %d does not have the "
461            "same type as the phi: %s versus %s",
462            input->GetId(), i, phi->GetId(), phi->GetBlock()->GetBlockId(),
463            Primitive::PrettyDescriptor(input->GetType()),
464            Primitive::PrettyDescriptor(phi->GetType())));
465    }
466  }
467  if (phi->GetType() != HPhi::ToPhiType(phi->GetType())) {
468    AddError(StringPrintf("Phi %d in block %d does not have an expected phi type: %s",
469                          phi->GetId(),
470                          phi->GetBlock()->GetBlockId(),
471                          Primitive::PrettyDescriptor(phi->GetType())));
472  }
473}
474
475void SSAChecker::HandleBooleanInput(HInstruction* instruction, size_t input_index) {
476  HInstruction* input = instruction->InputAt(input_index);
477  if (input->IsIntConstant()) {
478    int32_t value = input->AsIntConstant()->GetValue();
479    if (value != 0 && value != 1) {
480      AddError(StringPrintf(
481          "%s instruction %d has a non-Boolean constant input %d whose value is: %d.",
482          instruction->DebugName(),
483          instruction->GetId(),
484          static_cast<int>(input_index),
485          value));
486    }
487  } else if (input->GetType() == Primitive::kPrimInt
488             && (input->IsPhi() || input->IsAnd() || input->IsOr() || input->IsXor())) {
489    // TODO: We need a data-flow analysis to determine if the Phi or
490    //       binary operation is actually Boolean. Allow for now.
491  } else if (input->GetType() != Primitive::kPrimBoolean) {
492    AddError(StringPrintf(
493        "%s instruction %d has a non-Boolean input %d whose type is: %s.",
494        instruction->DebugName(),
495        instruction->GetId(),
496        static_cast<int>(input_index),
497        Primitive::PrettyDescriptor(input->GetType())));
498  }
499}
500
501void SSAChecker::VisitIf(HIf* instruction) {
502  VisitInstruction(instruction);
503  HandleBooleanInput(instruction, 0);
504}
505
506void SSAChecker::VisitBooleanNot(HBooleanNot* instruction) {
507  VisitInstruction(instruction);
508  HandleBooleanInput(instruction, 0);
509}
510
511void SSAChecker::VisitCondition(HCondition* op) {
512  VisitInstruction(op);
513  if (op->GetType() != Primitive::kPrimBoolean) {
514    AddError(StringPrintf(
515        "Condition %s %d has a non-Boolean result type: %s.",
516        op->DebugName(), op->GetId(),
517        Primitive::PrettyDescriptor(op->GetType())));
518  }
519  HInstruction* lhs = op->InputAt(0);
520  HInstruction* rhs = op->InputAt(1);
521  if (PrimitiveKind(lhs->GetType()) != PrimitiveKind(rhs->GetType())) {
522    AddError(StringPrintf(
523        "Condition %s %d has inputs of different types: %s, and %s.",
524        op->DebugName(), op->GetId(),
525        Primitive::PrettyDescriptor(lhs->GetType()),
526        Primitive::PrettyDescriptor(rhs->GetType())));
527  }
528  if (!op->IsEqual() && !op->IsNotEqual()) {
529    if ((lhs->GetType() == Primitive::kPrimNot)) {
530      AddError(StringPrintf(
531          "Condition %s %d uses an object as left-hand side input.",
532          op->DebugName(), op->GetId()));
533    } else if (rhs->GetType() == Primitive::kPrimNot) {
534      AddError(StringPrintf(
535          "Condition %s %d uses an object as right-hand side input.",
536          op->DebugName(), op->GetId()));
537    }
538  }
539}
540
541void SSAChecker::VisitBinaryOperation(HBinaryOperation* op) {
542  VisitInstruction(op);
543  if (op->IsUShr() || op->IsShr() || op->IsShl()) {
544    if (PrimitiveKind(op->InputAt(1)->GetType()) != Primitive::kPrimInt) {
545      AddError(StringPrintf(
546          "Shift operation %s %d has a non-int kind second input: "
547          "%s of type %s.",
548          op->DebugName(), op->GetId(),
549          op->InputAt(1)->DebugName(),
550          Primitive::PrettyDescriptor(op->InputAt(1)->GetType())));
551    }
552  } else {
553    if (PrimitiveKind(op->InputAt(0)->GetType()) != PrimitiveKind(op->InputAt(1)->GetType())) {
554      AddError(StringPrintf(
555          "Binary operation %s %d has inputs of different types: "
556          "%s, and %s.",
557          op->DebugName(), op->GetId(),
558          Primitive::PrettyDescriptor(op->InputAt(0)->GetType()),
559          Primitive::PrettyDescriptor(op->InputAt(1)->GetType())));
560    }
561  }
562
563  if (op->IsCompare()) {
564    if (op->GetType() != Primitive::kPrimInt) {
565      AddError(StringPrintf(
566          "Compare operation %d has a non-int result type: %s.",
567          op->GetId(),
568          Primitive::PrettyDescriptor(op->GetType())));
569    }
570  } else {
571    // Use the first input, so that we can also make this check for shift operations.
572    if (PrimitiveKind(op->GetType()) != PrimitiveKind(op->InputAt(0)->GetType())) {
573      AddError(StringPrintf(
574          "Binary operation %s %d has a result type different "
575          "from its input type: %s vs %s.",
576          op->DebugName(), op->GetId(),
577          Primitive::PrettyDescriptor(op->GetType()),
578          Primitive::PrettyDescriptor(op->InputAt(0)->GetType())));
579    }
580  }
581}
582
583void SSAChecker::VisitConstant(HConstant* instruction) {
584  HBasicBlock* block = instruction->GetBlock();
585  if (!block->IsEntryBlock()) {
586    AddError(StringPrintf(
587        "%s %d should be in the entry block but is in block %d.",
588        instruction->DebugName(),
589        instruction->GetId(),
590        block->GetBlockId()));
591  }
592}
593
594}  // namespace art
595