diff options
author | 2015-09-15 12:34:35 +0000 | |
---|---|---|
committer | 2015-09-15 12:34:35 +0000 | |
commit | b505997b2176bd29a108cb6c33d06d4ef29ba001 (patch) | |
tree | 05316a1837f77729f87b4fe25bfa7eb2b9e9549c /compiler/optimizing/graph_checker.cc | |
parent | 5c1a3374adff0d5c6c8e2248fffd7549eb3a6bae (diff) | |
parent | 77a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23 (diff) |
Merge "Revert "Revert "ART: Register allocation and runtime support for try/catch"""
Diffstat (limited to 'compiler/optimizing/graph_checker.cc')
-rw-r--r-- | compiler/optimizing/graph_checker.cc | 79 |
1 files changed, 68 insertions, 11 deletions
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index 3e358358ae..074ed71025 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -382,17 +382,6 @@ void SSAChecker::VisitBasicBlock(HBasicBlock* block) { } } - // Check Phi uniqueness (no two Phis with the same type refer to the same register). - for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) { - HPhi* phi = it.Current()->AsPhi(); - if (phi->GetNextEquivalentPhiWithSameType() != nullptr) { - std::stringstream type_str; - type_str << phi->GetType(); - AddError(StringPrintf("Equivalent phi (%d) found for VReg %d with type: %s", - phi->GetId(), phi->GetRegNumber(), type_str.str().c_str())); - } - } - // Ensure try membership information is consistent. if (block->IsCatchBlock()) { if (block->IsTryBlock()) { @@ -577,6 +566,35 @@ static Primitive::Type PrimitiveKind(Primitive::Type type) { } } +static bool IsSameSizeConstant(HInstruction* insn1, HInstruction* insn2) { + return insn1->IsConstant() + && insn2->IsConstant() + && Primitive::Is64BitType(insn1->GetType()) == Primitive::Is64BitType(insn2->GetType()); +} + +static bool IsConstantEquivalent(HInstruction* insn1, HInstruction* insn2, BitVector* visited) { + if (insn1->IsPhi() && + insn1->AsPhi()->IsVRegEquivalentOf(insn2) && + insn1->InputCount() == insn2->InputCount()) { + // Testing only one of the two inputs for recursion is sufficient. + if (visited->IsBitSet(insn1->GetId())) { + return true; + } + visited->SetBit(insn1->GetId()); + + for (size_t i = 0, e = insn1->InputCount(); i < e; ++i) { + if (!IsConstantEquivalent(insn1->InputAt(i), insn2->InputAt(i), visited)) { + return false; + } + } + return true; + } else if (IsSameSizeConstant(insn1, insn2)) { + return insn1->AsConstant()->GetValueAsUint64() == insn2->AsConstant()->GetValueAsUint64(); + } else { + return false; + } +} + void SSAChecker::VisitPhi(HPhi* phi) { VisitInstruction(phi); @@ -636,6 +654,45 @@ void SSAChecker::VisitPhi(HPhi* phi) { } } } + + // Ensure that catch phis are sorted by their vreg number, as required by + // the register allocator and code generator. This does not apply to normal + // phis which can be constructed artifically. + if (phi->IsCatchPhi()) { + HInstruction* next_phi = phi->GetNext(); + if (next_phi != nullptr && phi->GetRegNumber() > next_phi->AsPhi()->GetRegNumber()) { + AddError(StringPrintf("Catch phis %d and %d in block %d are not sorted by their " + "vreg numbers.", + phi->GetId(), + next_phi->GetId(), + phi->GetBlock()->GetBlockId())); + } + } + + // Test phi equivalents. There should not be two of the same type and they + // should only be created for constants which were untyped in DEX. + for (HInstructionIterator phi_it(phi->GetBlock()->GetPhis()); !phi_it.Done(); phi_it.Advance()) { + HPhi* other_phi = phi_it.Current()->AsPhi(); + if (phi != other_phi && phi->GetRegNumber() == other_phi->GetRegNumber()) { + if (phi->GetType() == other_phi->GetType()) { + std::stringstream type_str; + type_str << phi->GetType(); + AddError(StringPrintf("Equivalent phi (%d) found for VReg %d with type: %s.", + phi->GetId(), + phi->GetRegNumber(), + type_str.str().c_str())); + } else { + ArenaBitVector visited(GetGraph()->GetArena(), 0, /* expandable */ true); + if (!IsConstantEquivalent(phi, other_phi, &visited)) { + AddError(StringPrintf("Two phis (%d and %d) found for VReg %d but they " + "are not equivalents of constants.", + phi->GetId(), + other_phi->GetId(), + phi->GetRegNumber())); + } + } + } + } } void SSAChecker::HandleBooleanInput(HInstruction* instruction, size_t input_index) { |