Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Unified Diff: src/compiler/register-allocator-verifier.cc

Issue 713803002: [turbofan] add register assignment verifier (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/register-allocator-verifier.h ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/register-allocator-verifier.cc
diff --git a/src/compiler/register-allocator-verifier.cc b/src/compiler/register-allocator-verifier.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b8aefe1f12647154524928fd79b5f42104b3087e
--- /dev/null
+++ b/src/compiler/register-allocator-verifier.cc
@@ -0,0 +1,179 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/instruction.h"
+#include "src/compiler/register-allocator-verifier.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+static size_t OperandCount(const Instruction* instr) {
+ return instr->InputCount() + instr->OutputCount() + instr->TempCount();
+}
+
+
+RegisterAllocatorVerifier::RegisterAllocatorVerifier(
+ Zone* zone, const InstructionSequence* sequence)
+ : sequence_(sequence), constraints_(zone) {
+ constraints_.reserve(sequence->instructions().size());
+ for (const auto* instr : sequence->instructions()) {
+ const size_t operand_count = OperandCount(instr);
+ auto* op_constraints =
+ zone->NewArray<OperandConstraint>(static_cast<int>(operand_count));
+ // Construct OperandConstraints for all InstructionOperands, eliminating
+ // kSameAsFirst along the way.
+ size_t count = 0;
+ for (size_t i = 0; i < instr->InputCount(); ++i, ++count) {
+ BuildConstraint(instr->InputAt(i), &op_constraints[count]);
+ CHECK_NE(kSameAsFirst, op_constraints[count].type_);
+ }
+ for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) {
+ BuildConstraint(instr->OutputAt(i), &op_constraints[count]);
+ if (op_constraints[count].type_ == kSameAsFirst) {
+ CHECK(instr->InputCount() > 0);
+ op_constraints[count] = op_constraints[0];
+ }
+ }
+ for (size_t i = 0; i < instr->TempCount(); ++i, ++count) {
+ BuildConstraint(instr->TempAt(i), &op_constraints[count]);
+ CHECK_NE(kSameAsFirst, op_constraints[count].type_);
+ }
+ // All gaps should be totally unallocated at this point.
+ if (instr->IsGapMoves()) {
+ const auto* gap = GapInstruction::cast(instr);
+ for (int i = GapInstruction::FIRST_INNER_POSITION;
+ i <= GapInstruction::LAST_INNER_POSITION; i++) {
+ GapInstruction::InnerPosition inner_pos =
+ static_cast<GapInstruction::InnerPosition>(i);
+ CHECK_EQ(NULL, gap->GetParallelMove(inner_pos));
+ }
+ }
+ InstructionConstraint instr_constraint = {instr, operand_count,
+ op_constraints};
+ constraints()->push_back(instr_constraint);
+ }
+}
+
+
+void RegisterAllocatorVerifier::VerifyAssignment() {
+ CHECK(sequence()->instructions().size() == constraints()->size());
+ auto instr_it = sequence()->begin();
+ for (const auto& instr_constraint : *constraints()) {
+ const auto* instr = instr_constraint.instruction_;
+ const size_t operand_count = instr_constraint.operand_constaints_size_;
+ const auto* op_constraints = instr_constraint.operand_constraints_;
+ CHECK_EQ(instr, *instr_it);
+ CHECK(operand_count == OperandCount(instr));
+ size_t count = 0;
+ for (size_t i = 0; i < instr->InputCount(); ++i, ++count) {
+ CheckConstraint(instr->InputAt(i), &op_constraints[count]);
+ }
+ for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) {
+ CheckConstraint(instr->OutputAt(i), &op_constraints[count]);
+ }
+ for (size_t i = 0; i < instr->TempCount(); ++i, ++count) {
+ CheckConstraint(instr->TempAt(i), &op_constraints[count]);
+ }
+ ++instr_it;
+ }
+}
+
+
+void RegisterAllocatorVerifier::BuildConstraint(const InstructionOperand* op,
+ OperandConstraint* constraint) {
+ constraint->value_ = kMinInt;
+ if (op->IsConstant()) {
+ constraint->type_ = kConstant;
+ constraint->value_ = ConstantOperand::cast(op)->index();
+ } else if (op->IsImmediate()) {
+ constraint->type_ = kImmediate;
+ constraint->value_ = ImmediateOperand::cast(op)->index();
+ } else {
+ CHECK(op->IsUnallocated());
+ const auto* unallocated = UnallocatedOperand::cast(op);
+ int vreg = unallocated->virtual_register();
+ if (unallocated->basic_policy() == UnallocatedOperand::FIXED_SLOT) {
+ constraint->type_ = kFixedSlot;
+ constraint->value_ = unallocated->fixed_slot_index();
+ } else {
+ switch (unallocated->extended_policy()) {
+ case UnallocatedOperand::ANY:
+ CHECK(false);
Jarin 2014/11/10 11:24:59 What is wrong with the ANY constraint?
dcarney 2014/11/10 11:27:17 it's only used for phi gap moves, not as an instru
+ break;
+ case UnallocatedOperand::NONE:
+ if (sequence()->IsDouble(vreg)) {
+ constraint->type_ = kNoneDouble;
+ } else {
+ constraint->type_ = kNone;
+ }
+ break;
+ case UnallocatedOperand::FIXED_REGISTER:
+ constraint->type_ = kFixedRegister;
+ constraint->value_ = unallocated->fixed_register_index();
+ break;
+ case UnallocatedOperand::FIXED_DOUBLE_REGISTER:
+ constraint->type_ = kFixedDoubleRegister;
+ constraint->value_ = unallocated->fixed_register_index();
+ break;
+ case UnallocatedOperand::MUST_HAVE_REGISTER:
+ if (sequence()->IsDouble(vreg)) {
+ constraint->type_ = kDoubleRegister;
+ } else {
+ constraint->type_ = kRegister;
+ }
+ break;
+ case UnallocatedOperand::SAME_AS_FIRST_INPUT:
+ constraint->type_ = kSameAsFirst;
+ break;
+ }
+ }
+ }
+}
+
+
+void RegisterAllocatorVerifier::CheckConstraint(
+ const InstructionOperand* op, const OperandConstraint* constraint) {
+ switch (constraint->type_) {
+ case kConstant:
+ CHECK(op->IsConstant());
+ CHECK_EQ(op->index(), constraint->value_);
+ return;
+ case kImmediate:
+ CHECK(op->IsImmediate());
+ CHECK_EQ(op->index(), constraint->value_);
+ return;
+ case kRegister:
+ CHECK(op->IsRegister());
+ return;
+ case kFixedRegister:
+ CHECK(op->IsRegister());
+ CHECK_EQ(op->index(), constraint->value_);
+ return;
+ case kDoubleRegister:
+ CHECK(op->IsDoubleRegister());
+ return;
+ case kFixedDoubleRegister:
+ CHECK(op->IsDoubleRegister());
+ CHECK_EQ(op->index(), constraint->value_);
+ return;
+ case kFixedSlot:
+ CHECK(op->IsStackSlot());
+ CHECK_EQ(op->index(), constraint->value_);
+ return;
+ case kNone:
+ CHECK(op->IsRegister() || op->IsStackSlot());
+ return;
+ case kNoneDouble:
+ CHECK(op->IsDoubleRegister() || op->IsDoubleStackSlot());
+ return;
+ case kSameAsFirst:
+ CHECK(false);
+ return;
+ }
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
« no previous file with comments | « src/compiler/register-allocator-verifier.h ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698