Commit e39750a2 authored by dcarney's avatar dcarney Committed by Commit bot

[turbofan] smash GapInstruction into Instruction

R=titzer@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1041163002

Cr-Commit-Position: refs/heads/master@{#27538}
parent e9e8ac7a
...@@ -186,10 +186,8 @@ void CodeGenerator::RecordSafepoint(PointerMap* pointers, Safepoint::Kind kind, ...@@ -186,10 +186,8 @@ void CodeGenerator::RecordSafepoint(PointerMap* pointers, Safepoint::Kind kind,
void CodeGenerator::AssembleInstruction(Instruction* instr) { void CodeGenerator::AssembleInstruction(Instruction* instr) {
if (instr->IsGapMoves()) { AssembleGaps(instr);
// Handle parallel moves associated with the gap instruction. if (instr->IsSourcePosition()) {
AssembleGap(GapInstruction::cast(instr));
} else if (instr->IsSourcePosition()) {
AssembleSourcePosition(SourcePositionInstruction::cast(instr)); AssembleSourcePosition(SourcePositionInstruction::cast(instr));
} else { } else {
// Assemble architecture-specific code for the instruction. // Assemble architecture-specific code for the instruction.
...@@ -258,13 +256,13 @@ void CodeGenerator::AssembleSourcePosition(SourcePositionInstruction* instr) { ...@@ -258,13 +256,13 @@ void CodeGenerator::AssembleSourcePosition(SourcePositionInstruction* instr) {
} }
void CodeGenerator::AssembleGap(GapInstruction* instr) { void CodeGenerator::AssembleGaps(Instruction* instr) {
for (int i = GapInstruction::FIRST_INNER_POSITION; for (int i = Instruction::FIRST_GAP_POSITION;
i <= GapInstruction::LAST_INNER_POSITION; i++) { i <= Instruction::LAST_GAP_POSITION; i++) {
GapInstruction::InnerPosition inner_pos = Instruction::GapPosition inner_pos =
static_cast<GapInstruction::InnerPosition>(i); static_cast<Instruction::GapPosition>(i);
ParallelMove* move = instr->GetParallelMove(inner_pos); ParallelMove* move = instr->GetParallelMove(inner_pos);
if (move != NULL) resolver()->Resolve(move); if (move != nullptr) resolver()->Resolve(move);
} }
} }
......
...@@ -61,7 +61,7 @@ class CodeGenerator FINAL : public GapResolver::Assembler { ...@@ -61,7 +61,7 @@ class CodeGenerator FINAL : public GapResolver::Assembler {
// Assemble code for the specified instruction. // Assemble code for the specified instruction.
void AssembleInstruction(Instruction* instr); void AssembleInstruction(Instruction* instr);
void AssembleSourcePosition(SourcePositionInstruction* instr); void AssembleSourcePosition(SourcePositionInstruction* instr);
void AssembleGap(GapInstruction* gap); void AssembleGaps(Instruction* instr);
// =========================================================================== // ===========================================================================
// ============= Architecture-specific code generation methods. ============== // ============= Architecture-specific code generation methods. ==============
......
...@@ -593,10 +593,12 @@ void GraphC1Visualizer::PrintSchedule(const char* phase, ...@@ -593,10 +593,12 @@ void GraphC1Visualizer::PrintSchedule(const char* phase,
if (instruction_block->code_start() >= 0) { if (instruction_block->code_start() >= 0) {
int first_index = instruction_block->first_instruction_index(); int first_index = instruction_block->first_instruction_index();
int last_index = instruction_block->last_instruction_index(); int last_index = instruction_block->last_instruction_index();
PrintIntProperty("first_lir_id", LifetimePosition::FromInstructionIndex( PrintIntProperty(
first_index).Value()); "first_lir_id",
PrintIntProperty("last_lir_id", LifetimePosition::FromInstructionIndex( LifetimePosition::GapFromInstructionIndex(first_index).Value());
last_index).Value()); PrintIntProperty("last_lir_id",
LifetimePosition::InstructionFromInstructionIndex(
last_index).Value());
} }
{ {
......
...@@ -110,7 +110,10 @@ Instruction::Instruction(InstructionCode opcode) ...@@ -110,7 +110,10 @@ Instruction::Instruction(InstructionCode opcode)
: opcode_(opcode), : opcode_(opcode),
bit_field_(OutputCountField::encode(0) | InputCountField::encode(0) | bit_field_(OutputCountField::encode(0) | InputCountField::encode(0) |
TempCountField::encode(0) | IsCallField::encode(false)), TempCountField::encode(0) | IsCallField::encode(false)),
pointer_map_(NULL) {} pointer_map_(NULL) {
parallel_moves_[0] = nullptr;
parallel_moves_[1] = nullptr;
}
Instruction::Instruction(InstructionCode opcode, size_t output_count, Instruction::Instruction(InstructionCode opcode, size_t output_count,
...@@ -123,6 +126,8 @@ Instruction::Instruction(InstructionCode opcode, size_t output_count, ...@@ -123,6 +126,8 @@ Instruction::Instruction(InstructionCode opcode, size_t output_count,
TempCountField::encode(temp_count) | TempCountField::encode(temp_count) |
IsCallField::encode(false)), IsCallField::encode(false)),
pointer_map_(NULL) { pointer_map_(NULL) {
parallel_moves_[0] = nullptr;
parallel_moves_[1] = nullptr;
size_t offset = 0; size_t offset = 0;
for (size_t i = 0; i < output_count; ++i) { for (size_t i = 0; i < output_count; ++i) {
DCHECK(!outputs[i].IsInvalid()); DCHECK(!outputs[i].IsInvalid());
...@@ -139,11 +144,12 @@ Instruction::Instruction(InstructionCode opcode, size_t output_count, ...@@ -139,11 +144,12 @@ Instruction::Instruction(InstructionCode opcode, size_t output_count,
} }
bool GapInstruction::IsRedundant() const { bool Instruction::AreMovesRedundant() const {
for (int i = GapInstruction::FIRST_INNER_POSITION; for (int i = Instruction::FIRST_GAP_POSITION;
i <= GapInstruction::LAST_INNER_POSITION; i++) { i <= Instruction::LAST_GAP_POSITION; i++) {
if (parallel_moves_[i] != NULL && !parallel_moves_[i]->IsRedundant()) if (parallel_moves_[i] != nullptr && !parallel_moves_[i]->IsRedundant()) {
return false; return false;
}
} }
return true; return true;
} }
...@@ -289,6 +295,19 @@ std::ostream& operator<<(std::ostream& os, ...@@ -289,6 +295,19 @@ std::ostream& operator<<(std::ostream& os,
const Instruction& instr = *printable.instr_; const Instruction& instr = *printable.instr_;
PrintableInstructionOperand printable_op = {printable.register_configuration_, PrintableInstructionOperand printable_op = {printable.register_configuration_,
NULL}; NULL};
os << "gap ";
for (int i = Instruction::FIRST_GAP_POSITION;
i <= Instruction::LAST_GAP_POSITION; i++) {
os << "(";
if (instr.parallel_moves()[i] != NULL) {
PrintableParallelMove ppm = {printable.register_configuration_,
instr.parallel_moves()[i]};
os << ppm;
}
os << ") ";
}
os << "\n ";
if (instr.OutputCount() > 1) os << "("; if (instr.OutputCount() > 1) os << "(";
for (size_t i = 0; i < instr.OutputCount(); i++) { for (size_t i = 0; i < instr.OutputCount(); i++) {
if (i > 0) os << ", "; if (i > 0) os << ", ";
...@@ -299,20 +318,7 @@ std::ostream& operator<<(std::ostream& os, ...@@ -299,20 +318,7 @@ std::ostream& operator<<(std::ostream& os,
if (instr.OutputCount() > 1) os << ") = "; if (instr.OutputCount() > 1) os << ") = ";
if (instr.OutputCount() == 1) os << " = "; if (instr.OutputCount() == 1) os << " = ";
if (instr.IsGapMoves()) { if (instr.IsSourcePosition()) {
const GapInstruction* gap = GapInstruction::cast(&instr);
os << "gap ";
for (int i = GapInstruction::FIRST_INNER_POSITION;
i <= GapInstruction::LAST_INNER_POSITION; i++) {
os << "(";
if (gap->parallel_moves_[i] != NULL) {
PrintableParallelMove ppm = {printable.register_configuration_,
gap->parallel_moves_[i]};
os << ppm;
}
os << ") ";
}
} else if (instr.IsSourcePosition()) {
const SourcePositionInstruction* pos = const SourcePositionInstruction* pos =
SourcePositionInstruction::cast(&instr); SourcePositionInstruction::cast(&instr);
os << "position (" << pos->source_position().raw() << ")"; os << "position (" << pos->source_position().raw() << ")";
...@@ -494,9 +500,9 @@ int InstructionSequence::NextVirtualRegister() { ...@@ -494,9 +500,9 @@ int InstructionSequence::NextVirtualRegister() {
} }
GapInstruction* InstructionSequence::GetBlockStart(RpoNumber rpo) const { Instruction* InstructionSequence::GetBlockStart(RpoNumber rpo) const {
const InstructionBlock* block = InstructionBlockAt(rpo); const InstructionBlock* block = InstructionBlockAt(rpo);
return GapInstruction::cast(InstructionAt(block->code_start())); return InstructionAt(block->code_start());
} }
...@@ -522,8 +528,6 @@ void InstructionSequence::EndBlock(RpoNumber rpo) { ...@@ -522,8 +528,6 @@ void InstructionSequence::EndBlock(RpoNumber rpo) {
int InstructionSequence::AddInstruction(Instruction* instr) { int InstructionSequence::AddInstruction(Instruction* instr) {
GapInstruction* gap = GapInstruction::New(zone());
instructions_.push_back(gap);
int index = static_cast<int>(instructions_.size()); int index = static_cast<int>(instructions_.size());
instructions_.push_back(instr); instructions_.push_back(instr);
if (instr->NeedsPointerMap()) { if (instr->NeedsPointerMap()) {
...@@ -571,13 +575,6 @@ void InstructionSequence::MarkAsDouble(int virtual_register) { ...@@ -571,13 +575,6 @@ void InstructionSequence::MarkAsDouble(int virtual_register) {
} }
void InstructionSequence::AddGapMove(int index, InstructionOperand* from,
InstructionOperand* to) {
GapAt(index)->GetOrCreateParallelMove(GapInstruction::START, zone())->AddMove(
from, to, zone());
}
InstructionSequence::StateId InstructionSequence::AddFrameStateDescriptor( InstructionSequence::StateId InstructionSequence::AddFrameStateDescriptor(
FrameStateDescriptor* descriptor) { FrameStateDescriptor* descriptor) {
int deoptimization_id = static_cast<int>(deoptimization_entries_.size()); int deoptimization_id = static_cast<int>(deoptimization_entries_.size());
......
...@@ -25,8 +25,7 @@ namespace compiler { ...@@ -25,8 +25,7 @@ namespace compiler {
class Schedule; class Schedule;
// A couple of reserved opcodes are used for internal use. // A couple of reserved opcodes are used for internal use.
const InstructionCode kGapInstruction = -1; const InstructionCode kSourcePositionInstruction = -1;
const InstructionCode kSourcePositionInstruction = -2;
#define INSTRUCTION_OPERAND_LIST(V) \ #define INSTRUCTION_OPERAND_LIST(V) \
V(Constant, CONSTANT) \ V(Constant, CONSTANT) \
...@@ -543,7 +542,6 @@ class Instruction { ...@@ -543,7 +542,6 @@ class Instruction {
bool NeedsPointerMap() const { return IsCall(); } bool NeedsPointerMap() const { return IsCall(); }
bool HasPointerMap() const { return pointer_map_ != NULL; } bool HasPointerMap() const { return pointer_map_ != NULL; }
bool IsGapMoves() const { return opcode() == kGapInstruction; }
bool IsSourcePosition() const { bool IsSourcePosition() const {
return opcode() == kSourcePositionInstruction; return opcode() == kSourcePositionInstruction;
} }
...@@ -570,8 +568,37 @@ class Instruction { ...@@ -570,8 +568,37 @@ class Instruction {
OutputCount() == 0 && TempCount() == 0; OutputCount() == 0 && TempCount() == 0;
} }
enum GapPosition {
START,
END,
FIRST_GAP_POSITION = START,
LAST_GAP_POSITION = END
};
ParallelMove* GetOrCreateParallelMove(GapPosition pos, Zone* zone) {
if (parallel_moves_[pos] == nullptr) {
parallel_moves_[pos] = new (zone) ParallelMove(zone);
}
return parallel_moves_[pos];
}
ParallelMove* GetParallelMove(GapPosition pos) {
return parallel_moves_[pos];
}
const ParallelMove* GetParallelMove(GapPosition pos) const {
return parallel_moves_[pos];
}
bool AreMovesRedundant() const;
ParallelMove* const* parallel_moves() const { return &parallel_moves_[0]; }
ParallelMove** parallel_moves() { return &parallel_moves_[0]; }
protected: protected:
explicit Instruction(InstructionCode opcode); explicit Instruction(InstructionCode opcode);
private:
Instruction(InstructionCode opcode, size_t output_count, Instruction(InstructionCode opcode, size_t output_count,
InstructionOperand* outputs, size_t input_count, InstructionOperand* outputs, size_t input_count,
InstructionOperand* inputs, size_t temp_count, InstructionOperand* inputs, size_t temp_count,
...@@ -584,6 +611,7 @@ class Instruction { ...@@ -584,6 +611,7 @@ class Instruction {
InstructionCode opcode_; InstructionCode opcode_;
uint32_t bit_field_; uint32_t bit_field_;
ParallelMove* parallel_moves_[2];
PointerMap* pointer_map_; PointerMap* pointer_map_;
InstructionOperand operands_[1]; InstructionOperand operands_[1];
...@@ -599,65 +627,6 @@ struct PrintableInstruction { ...@@ -599,65 +627,6 @@ struct PrintableInstruction {
std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr); std::ostream& operator<<(std::ostream& os, const PrintableInstruction& instr);
// Represents moves inserted before an instruction due to register allocation.
// TODO(titzer): squash GapInstruction back into Instruction, since essentially
// every instruction can possibly have moves inserted before it.
class GapInstruction : public Instruction {
public:
enum InnerPosition {
START,
END,
FIRST_INNER_POSITION = START,
LAST_INNER_POSITION = END
};
ParallelMove* GetOrCreateParallelMove(InnerPosition pos, Zone* zone) {
if (parallel_moves_[pos] == NULL) {
parallel_moves_[pos] = new (zone) ParallelMove(zone);
}
return parallel_moves_[pos];
}
ParallelMove* GetParallelMove(InnerPosition pos) {
return parallel_moves_[pos];
}
const ParallelMove* GetParallelMove(InnerPosition pos) const {
return parallel_moves_[pos];
}
bool IsRedundant() const;
ParallelMove** parallel_moves() { return parallel_moves_; }
static GapInstruction* New(Zone* zone) {
void* buffer = zone->New(sizeof(GapInstruction));
return new (buffer) GapInstruction(kGapInstruction);
}
static GapInstruction* cast(Instruction* instr) {
DCHECK(instr->IsGapMoves());
return static_cast<GapInstruction*>(instr);
}
static const GapInstruction* cast(const Instruction* instr) {
DCHECK(instr->IsGapMoves());
return static_cast<const GapInstruction*>(instr);
}
protected:
explicit GapInstruction(InstructionCode opcode) : Instruction(opcode) {
parallel_moves_[START] = NULL;
parallel_moves_[END] = NULL;
}
private:
friend std::ostream& operator<<(std::ostream& os,
const PrintableInstruction& instr);
ParallelMove* parallel_moves_[LAST_INNER_POSITION + 1];
};
class SourcePositionInstruction FINAL : public Instruction { class SourcePositionInstruction FINAL : public Instruction {
public: public:
static SourcePositionInstruction* New(Zone* zone, SourcePosition position) { static SourcePositionInstruction* New(Zone* zone, SourcePosition position) {
...@@ -982,19 +951,13 @@ class InstructionSequence FINAL : public ZoneObject { ...@@ -982,19 +951,13 @@ class InstructionSequence FINAL : public ZoneObject {
void MarkAsReference(int virtual_register); void MarkAsReference(int virtual_register);
void MarkAsDouble(int virtual_register); void MarkAsDouble(int virtual_register);
void AddGapMove(int index, InstructionOperand* from, InstructionOperand* to); Instruction* GetBlockStart(RpoNumber rpo) const;
GapInstruction* GetBlockStart(RpoNumber rpo) const;
typedef InstructionDeque::const_iterator const_iterator; typedef InstructionDeque::const_iterator const_iterator;
const_iterator begin() const { return instructions_.begin(); } const_iterator begin() const { return instructions_.begin(); }
const_iterator end() const { return instructions_.end(); } const_iterator end() const { return instructions_.end(); }
const InstructionDeque& instructions() const { return instructions_; } const InstructionDeque& instructions() const { return instructions_; }
GapInstruction* GapAt(int index) const {
return GapInstruction::cast(InstructionAt(index));
}
bool IsGapAt(int index) const { return InstructionAt(index)->IsGapMoves(); }
Instruction* InstructionAt(int index) const { Instruction* InstructionAt(int index) const {
DCHECK(index >= 0); DCHECK(index >= 0);
DCHECK(index < static_cast<int>(instructions_.size())); DCHECK(index < static_cast<int>(instructions_.size()));
......
...@@ -76,10 +76,10 @@ bool JumpThreading::ComputeForwarding(Zone* local_zone, ...@@ -76,10 +76,10 @@ bool JumpThreading::ComputeForwarding(Zone* local_zone,
RpoNumber fw = block->rpo_number(); RpoNumber fw = block->rpo_number();
for (int i = block->code_start(); i < block->code_end(); ++i) { for (int i = block->code_start(); i < block->code_end(); ++i) {
Instruction* instr = code->InstructionAt(i); Instruction* instr = code->InstructionAt(i);
if (instr->IsGapMoves() && GapInstruction::cast(instr)->IsRedundant()) { if (!instr->AreMovesRedundant()) {
// skip redundant gap moves. // can't skip instructions with non redundant moves.
TRACE(" nop gap\n"); TRACE(" parallel move\n");
continue; fallthru = false;
} else if (instr->IsSourcePosition()) { } else if (instr->IsSourcePosition()) {
// skip source positions. // skip source positions.
TRACE(" src pos\n"); TRACE(" src pos\n");
......
...@@ -16,15 +16,14 @@ typedef ZoneSet<InstructionOperand> OperandSet; ...@@ -16,15 +16,14 @@ typedef ZoneSet<InstructionOperand> OperandSet;
bool GapsCanMoveOver(Instruction* instr) { bool GapsCanMoveOver(Instruction* instr) {
DCHECK(!instr->IsGapMoves());
return instr->IsSourcePosition() || instr->IsNop(); return instr->IsSourcePosition() || instr->IsNop();
} }
int FindFirstNonEmptySlot(GapInstruction* gap) { int FindFirstNonEmptySlot(Instruction* instr) {
int i = GapInstruction::FIRST_INNER_POSITION; int i = Instruction::FIRST_GAP_POSITION;
for (; i <= GapInstruction::LAST_INNER_POSITION; i++) { for (; i <= Instruction::LAST_GAP_POSITION; i++) {
auto move = gap->parallel_moves()[i]; auto move = instr->parallel_moves()[i];
if (move == nullptr) continue; if (move == nullptr) continue;
auto move_ops = move->move_operands(); auto move_ops = move->move_operands();
auto op = move_ops->begin(); auto op = move_ops->begin();
...@@ -97,52 +96,45 @@ void MoveOptimizer::CompressMoves(MoveOpVector* eliminated, ParallelMove* left, ...@@ -97,52 +96,45 @@ void MoveOptimizer::CompressMoves(MoveOpVector* eliminated, ParallelMove* left,
void MoveOptimizer::CompressBlock(InstructionBlock* block) { void MoveOptimizer::CompressBlock(InstructionBlock* block) {
auto temp_vector = temp_vector_0(); auto temp_vector = temp_vector_0();
DCHECK(temp_vector.empty()); DCHECK(temp_vector.empty());
GapInstruction* prev_gap = nullptr; Instruction* prev_instr = nullptr;
for (int index = block->code_start(); index < block->code_end(); ++index) { for (int index = block->code_start(); index < block->code_end(); ++index) {
auto instr = code()->instructions()[index]; auto instr = code()->instructions()[index];
if (!instr->IsGapMoves()) { int i = FindFirstNonEmptySlot(instr);
if (GapsCanMoveOver(instr)) continue; if (i <= Instruction::LAST_GAP_POSITION) {
if (prev_gap != nullptr) to_finalize_.push_back(prev_gap); // Move the first non-empty gap to position 0.
prev_gap = nullptr; std::swap(instr->parallel_moves()[0], instr->parallel_moves()[i]);
continue; auto left = instr->parallel_moves()[0];
} // Compress everything into position 0.
auto gap = GapInstruction::cast(instr); for (++i; i <= Instruction::LAST_GAP_POSITION; ++i) {
int i = FindFirstNonEmptySlot(gap); auto move = instr->parallel_moves()[i];
// Nothing to do here. if (move == nullptr) continue;
if (i == GapInstruction::LAST_INNER_POSITION + 1) { CompressMoves(&temp_vector, left, move);
if (prev_gap != nullptr) { }
// Slide prev_gap down so we always know where to look for it. if (prev_instr != nullptr) {
std::swap(prev_gap->parallel_moves()[0], gap->parallel_moves()[0]); // Smash left into prev_instr, killing left.
prev_gap = gap; auto pred_moves = prev_instr->parallel_moves()[0];
CompressMoves(&temp_vector, pred_moves, left);
} }
continue;
} }
// Move the first non-empty gap to position 0. if (prev_instr != nullptr) {
std::swap(gap->parallel_moves()[0], gap->parallel_moves()[i]); // Slide prev_instr down so we always know where to look for it.
auto left = gap->parallel_moves()[0]; std::swap(prev_instr->parallel_moves()[0], instr->parallel_moves()[0]);
// Compress everything into position 0.
for (++i; i <= GapInstruction::LAST_INNER_POSITION; ++i) {
auto move = gap->parallel_moves()[i];
if (move == nullptr) continue;
CompressMoves(&temp_vector, left, move);
} }
if (prev_gap != nullptr) { prev_instr = instr->parallel_moves()[0] == nullptr ? nullptr : instr;
// Smash left into prev_gap, killing left. if (GapsCanMoveOver(instr)) continue;
auto pred_moves = prev_gap->parallel_moves()[0]; if (prev_instr != nullptr) {
CompressMoves(&temp_vector, pred_moves, left); to_finalize_.push_back(prev_instr);
// Slide prev_gap down so we always know where to look for it. prev_instr = nullptr;
std::swap(prev_gap->parallel_moves()[0], gap->parallel_moves()[0]);
} }
prev_gap = gap;
} }
if (prev_gap != nullptr) to_finalize_.push_back(prev_gap); if (prev_instr != nullptr) {
to_finalize_.push_back(prev_instr);
}
} }
GapInstruction* MoveOptimizer::LastGap(InstructionBlock* block) { Instruction* MoveOptimizer::LastInstruction(InstructionBlock* block) {
int gap_index = block->last_instruction_index() - 1; return code()->instructions()[block->last_instruction_index()];
auto instr = code()->instructions()[gap_index];
return GapInstruction::cast(instr);
} }
...@@ -153,7 +145,6 @@ void MoveOptimizer::OptimizeMerge(InstructionBlock* block) { ...@@ -153,7 +145,6 @@ void MoveOptimizer::OptimizeMerge(InstructionBlock* block) {
for (auto pred_index : block->predecessors()) { for (auto pred_index : block->predecessors()) {
auto pred = code()->InstructionBlockAt(pred_index); auto pred = code()->InstructionBlockAt(pred_index);
auto last_instr = code()->instructions()[pred->last_instruction_index()]; auto last_instr = code()->instructions()[pred->last_instruction_index()];
DCHECK(!last_instr->IsGapMoves());
if (last_instr->IsSourcePosition()) continue; if (last_instr->IsSourcePosition()) continue;
if (last_instr->IsCall()) return; if (last_instr->IsCall()) return;
if (last_instr->TempCount() != 0) return; if (last_instr->TempCount() != 0) return;
...@@ -169,12 +160,12 @@ void MoveOptimizer::OptimizeMerge(InstructionBlock* block) { ...@@ -169,12 +160,12 @@ void MoveOptimizer::OptimizeMerge(InstructionBlock* block) {
// Accumulate set of shared moves. // Accumulate set of shared moves.
for (auto pred_index : block->predecessors()) { for (auto pred_index : block->predecessors()) {
auto pred = code()->InstructionBlockAt(pred_index); auto pred = code()->InstructionBlockAt(pred_index);
auto gap = LastGap(pred); auto instr = LastInstruction(pred);
if (gap->parallel_moves()[0] == nullptr || if (instr->parallel_moves()[0] == nullptr ||
gap->parallel_moves()[0]->move_operands()->is_empty()) { instr->parallel_moves()[0]->move_operands()->is_empty()) {
return; return;
} }
auto move_ops = gap->parallel_moves()[0]->move_operands(); auto move_ops = instr->parallel_moves()[0]->move_operands();
for (auto op = move_ops->begin(); op != move_ops->end(); ++op) { for (auto op = move_ops->begin(); op != move_ops->end(); ++op) {
if (op->IsRedundant()) continue; if (op->IsRedundant()) continue;
auto src = *op->source(); auto src = *op->source();
...@@ -191,34 +182,30 @@ void MoveOptimizer::OptimizeMerge(InstructionBlock* block) { ...@@ -191,34 +182,30 @@ void MoveOptimizer::OptimizeMerge(InstructionBlock* block) {
} }
if (move_map.empty() || correct_counts != move_map.size()) return; if (move_map.empty() || correct_counts != move_map.size()) return;
// Find insertion point. // Find insertion point.
GapInstruction* gap = nullptr; Instruction* instr = nullptr;
for (int i = block->first_instruction_index(); for (int i = block->first_instruction_index();
i <= block->last_instruction_index(); ++i) { i <= block->last_instruction_index(); ++i) {
auto instr = code()->instructions()[i]; instr = code()->instructions()[i];
if (instr->IsGapMoves()) { if (!GapsCanMoveOver(instr) || !instr->AreMovesRedundant()) break;
gap = GapInstruction::cast(instr);
continue;
}
if (!GapsCanMoveOver(instr)) break;
} }
DCHECK(gap != nullptr); DCHECK(instr != nullptr);
bool gap_initialized = true; bool gap_initialized = true;
if (gap->parallel_moves()[0] == nullptr || if (instr->parallel_moves()[0] == nullptr ||
gap->parallel_moves()[0]->move_operands()->is_empty()) { instr->parallel_moves()[0]->move_operands()->is_empty()) {
to_finalize_.push_back(gap); to_finalize_.push_back(instr);
} else { } else {
// Will compress after insertion. // Will compress after insertion.
gap_initialized = false; gap_initialized = false;
std::swap(gap->parallel_moves()[0], gap->parallel_moves()[1]); std::swap(instr->parallel_moves()[0], instr->parallel_moves()[1]);
} }
auto move = gap->GetOrCreateParallelMove( auto move = instr->GetOrCreateParallelMove(
static_cast<GapInstruction::InnerPosition>(0), code_zone()); static_cast<Instruction::GapPosition>(0), code_zone());
// Delete relevant entries in predecessors and move everything to block. // Delete relevant entries in predecessors and move everything to block.
bool first_iteration = true; bool first_iteration = true;
for (auto pred_index : block->predecessors()) { for (auto pred_index : block->predecessors()) {
auto pred = code()->InstructionBlockAt(pred_index); auto pred = code()->InstructionBlockAt(pred_index);
auto gap = LastGap(pred); auto instr = LastInstruction(pred);
auto move_ops = gap->parallel_moves()[0]->move_operands(); auto move_ops = instr->parallel_moves()[0]->move_operands();
for (auto op = move_ops->begin(); op != move_ops->end(); ++op) { for (auto op = move_ops->begin(); op != move_ops->end(); ++op) {
if (op->IsRedundant()) continue; if (op->IsRedundant()) continue;
MoveKey key = {*op->source(), *op->destination()}; MoveKey key = {*op->source(), *op->destination()};
...@@ -234,20 +221,20 @@ void MoveOptimizer::OptimizeMerge(InstructionBlock* block) { ...@@ -234,20 +221,20 @@ void MoveOptimizer::OptimizeMerge(InstructionBlock* block) {
} }
// Compress. // Compress.
if (!gap_initialized) { if (!gap_initialized) {
CompressMoves(&temp_vector_0(), gap->parallel_moves()[0], CompressMoves(&temp_vector_0(), instr->parallel_moves()[0],
gap->parallel_moves()[1]); instr->parallel_moves()[1]);
} }
} }
// Split multiple loads of the same constant or stack slot off into the second // Split multiple loads of the same constant or stack slot off into the second
// slot and keep remaining moves in the first slot. // slot and keep remaining moves in the first slot.
void MoveOptimizer::FinalizeMoves(GapInstruction* gap) { void MoveOptimizer::FinalizeMoves(Instruction* instr) {
auto loads = temp_vector_0(); auto loads = temp_vector_0();
DCHECK(loads.empty()); DCHECK(loads.empty());
auto new_moves = temp_vector_1(); auto new_moves = temp_vector_1();
DCHECK(new_moves.empty()); DCHECK(new_moves.empty());
auto move_ops = gap->parallel_moves()[0]->move_operands(); auto move_ops = instr->parallel_moves()[0]->move_operands();
for (auto move = move_ops->begin(); move != move_ops->end(); ++move) { for (auto move = move_ops->begin(); move != move_ops->end(); ++move) {
if (move->IsRedundant()) { if (move->IsRedundant()) {
move->Eliminate(); move->Eliminate();
...@@ -294,8 +281,8 @@ void MoveOptimizer::FinalizeMoves(GapInstruction* gap) { ...@@ -294,8 +281,8 @@ void MoveOptimizer::FinalizeMoves(GapInstruction* gap) {
loads.clear(); loads.clear();
if (new_moves.empty()) return; if (new_moves.empty()) return;
// Insert all new moves into slot 1. // Insert all new moves into slot 1.
auto slot_1 = gap->GetOrCreateParallelMove( auto slot_1 = instr->GetOrCreateParallelMove(
static_cast<GapInstruction::InnerPosition>(1), code_zone()); static_cast<Instruction::GapPosition>(1), code_zone());
DCHECK(slot_1->move_operands()->is_empty()); DCHECK(slot_1->move_operands()->is_empty());
slot_1->move_operands()->AddBlock(MoveOperands(nullptr, nullptr), slot_1->move_operands()->AddBlock(MoveOperands(nullptr, nullptr),
static_cast<int>(new_moves.size()), static_cast<int>(new_moves.size()),
......
...@@ -19,7 +19,7 @@ class MoveOptimizer FINAL { ...@@ -19,7 +19,7 @@ class MoveOptimizer FINAL {
private: private:
typedef ZoneVector<MoveOperands*> MoveOpVector; typedef ZoneVector<MoveOperands*> MoveOpVector;
typedef ZoneVector<GapInstruction*> GapInstructions; typedef ZoneVector<Instruction*> Instructions;
InstructionSequence* code() const { return code_; } InstructionSequence* code() const { return code_; }
Zone* local_zone() const { return local_zone_; } Zone* local_zone() const { return local_zone_; }
...@@ -30,13 +30,13 @@ class MoveOptimizer FINAL { ...@@ -30,13 +30,13 @@ class MoveOptimizer FINAL {
void CompressBlock(InstructionBlock* blocke); void CompressBlock(InstructionBlock* blocke);
void CompressMoves(MoveOpVector* eliminated, ParallelMove* left, void CompressMoves(MoveOpVector* eliminated, ParallelMove* left,
ParallelMove* right); ParallelMove* right);
GapInstruction* LastGap(InstructionBlock* block); Instruction* LastInstruction(InstructionBlock* block);
void OptimizeMerge(InstructionBlock* block); void OptimizeMerge(InstructionBlock* block);
void FinalizeMoves(GapInstruction* gap); void FinalizeMoves(Instruction* instr);
Zone* const local_zone_; Zone* const local_zone_;
InstructionSequence* const code_; InstructionSequence* const code_;
GapInstructions to_finalize_; Instructions to_finalize_;
MoveOpVector temp_vector_0_; MoveOpVector temp_vector_0_;
MoveOpVector temp_vector_1_; MoveOpVector temp_vector_1_;
......
...@@ -15,12 +15,12 @@ static size_t OperandCount(const Instruction* instr) { ...@@ -15,12 +15,12 @@ static size_t OperandCount(const Instruction* instr) {
} }
static void VerifyGapEmpty(const GapInstruction* gap) { static void VerifyEmptyGaps(const Instruction* instr) {
for (int i = GapInstruction::FIRST_INNER_POSITION; for (int i = Instruction::FIRST_GAP_POSITION;
i <= GapInstruction::LAST_INNER_POSITION; i++) { i <= Instruction::LAST_GAP_POSITION; i++) {
GapInstruction::InnerPosition inner_pos = Instruction::GapPosition inner_pos =
static_cast<GapInstruction::InnerPosition>(i); static_cast<Instruction::GapPosition>(i);
CHECK(!gap->GetParallelMove(inner_pos)); CHECK(instr->GetParallelMove(inner_pos) == nullptr);
} }
} }
...@@ -60,6 +60,8 @@ RegisterAllocatorVerifier::RegisterAllocatorVerifier( ...@@ -60,6 +60,8 @@ RegisterAllocatorVerifier::RegisterAllocatorVerifier(
// Construct OperandConstraints for all InstructionOperands, eliminating // Construct OperandConstraints for all InstructionOperands, eliminating
// kSameAsFirst along the way. // kSameAsFirst along the way.
for (const auto* instr : sequence->instructions()) { for (const auto* instr : sequence->instructions()) {
// All gaps should be totally unallocated at this point.
VerifyEmptyGaps(instr);
const size_t operand_count = OperandCount(instr); const size_t operand_count = OperandCount(instr);
auto* op_constraints = zone->NewArray<OperandConstraint>(operand_count); auto* op_constraints = zone->NewArray<OperandConstraint>(operand_count);
size_t count = 0; size_t count = 0;
...@@ -80,11 +82,6 @@ RegisterAllocatorVerifier::RegisterAllocatorVerifier( ...@@ -80,11 +82,6 @@ RegisterAllocatorVerifier::RegisterAllocatorVerifier(
} }
VerifyOutput(op_constraints[count]); VerifyOutput(op_constraints[count]);
} }
// All gaps should be totally unallocated at this point.
if (instr->IsGapMoves()) {
CHECK(operand_count == 0);
VerifyGapEmpty(GapInstruction::cast(instr));
}
InstructionConstraint instr_constraint = {instr, operand_count, InstructionConstraint instr_constraint = {instr, operand_count,
op_constraints}; op_constraints};
constraints()->push_back(instr_constraint); constraints()->push_back(instr_constraint);
...@@ -329,11 +326,11 @@ class OperandMap : public ZoneObject { ...@@ -329,11 +326,11 @@ class OperandMap : public ZoneObject {
map().insert(to_insert.begin(), to_insert.end()); map().insert(to_insert.begin(), to_insert.end());
} }
void RunGapInstruction(Zone* zone, const GapInstruction* gap) { void RunGaps(Zone* zone, const Instruction* instr) {
for (int i = GapInstruction::FIRST_INNER_POSITION; for (int i = Instruction::FIRST_GAP_POSITION;
i <= GapInstruction::LAST_INNER_POSITION; i++) { i <= Instruction::LAST_GAP_POSITION; i++) {
auto inner_pos = static_cast<GapInstruction::InnerPosition>(i); auto inner_pos = static_cast<Instruction::GapPosition>(i);
auto move = gap->GetParallelMove(inner_pos); auto move = instr->GetParallelMove(inner_pos);
if (move == nullptr) continue; if (move == nullptr) continue;
RunParallelMoves(zone, move); RunParallelMoves(zone, move);
} }
...@@ -648,11 +645,7 @@ void RegisterAllocatorVerifier::VerifyGapMoves(BlockMaps* block_maps, ...@@ -648,11 +645,7 @@ void RegisterAllocatorVerifier::VerifyGapMoves(BlockMaps* block_maps,
++instr_index) { ++instr_index) {
const auto& instr_constraint = constraints_[instr_index]; const auto& instr_constraint = constraints_[instr_index];
const auto instr = instr_constraint.instruction_; const auto instr = instr_constraint.instruction_;
if (instr->IsSourcePosition()) continue; current->RunGaps(zone(), instr);
if (instr->IsGapMoves()) {
current->RunGapInstruction(zone(), GapInstruction::cast(instr));
continue;
}
const auto op_constraints = instr_constraint.operand_constraints_; const auto op_constraints = instr_constraint.operand_constraints_;
size_t count = 0; size_t count = 0;
for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { for (size_t i = 0; i < instr->InputCount(); ++i, ++count) {
......
This diff is collapsed.
...@@ -20,57 +20,84 @@ enum RegisterKind { ...@@ -20,57 +20,84 @@ enum RegisterKind {
// This class represents a single point of a InstructionOperand's lifetime. For // This class represents a single point of a InstructionOperand's lifetime. For
// each instruction there are exactly two lifetime positions: the beginning and // each instruction there are four lifetime positions:
// the end of the instruction. Lifetime positions for different instructions are //
// disjoint. // [[START, END], [START, END]]
//
// Where the first half position corresponds to
//
// [GapPosition::START, GapPosition::END]
//
// and the second half position corresponds to
//
// [Lifetime::USED_AT_START, Lifetime::USED_AT_END]
//
class LifetimePosition FINAL { class LifetimePosition FINAL {
public: public:
// Return the lifetime position that corresponds to the beginning of // Return the lifetime position that corresponds to the beginning of
// the instruction with the given index. // the gap with the given index.
static LifetimePosition FromInstructionIndex(int index) { static LifetimePosition GapFromInstructionIndex(int index) {
return LifetimePosition(index * kStep); return LifetimePosition(index * kStep);
} }
// Return the lifetime position that corresponds to the beginning of
// the instruction with the given index.
static LifetimePosition InstructionFromInstructionIndex(int index) {
return LifetimePosition(index * kStep + kHalfStep);
}
// Returns a numeric representation of this lifetime position. // Returns a numeric representation of this lifetime position.
int Value() const { return value_; } int Value() const { return value_; }
// Returns the index of the instruction to which this lifetime position // Returns the index of the instruction to which this lifetime position
// corresponds. // corresponds.
int InstructionIndex() const { int ToInstructionIndex() const {
DCHECK(IsValid()); DCHECK(IsValid());
return value_ / kStep; return value_ / kStep;
} }
// Returns true if this lifetime position corresponds to the instruction // Returns true if this lifetime position corresponds to a START value
// start. bool IsStart() const { return (value_ & (kHalfStep - 1)) == 0; }
bool IsInstructionStart() const { return (value_ & (kStep - 1)) == 0; } // Returns true if this lifetime position corresponds to a gap START value
bool IsFullStart() const { return (value_ & (kStep - 1)) == 0; }
bool IsGapPosition() { return (value_ & 0x2) == 0; }
bool IsInstructionPosition() { return !IsGapPosition(); }
// Returns the lifetime position for the current START.
LifetimePosition Start() const {
DCHECK(IsValid());
return LifetimePosition(value_ & ~(kHalfStep - 1));
}
// Returns the lifetime position for the start of the instruction which // Returns the lifetime position for the current gap START.
// corresponds to this lifetime position. LifetimePosition FullStart() const {
LifetimePosition InstructionStart() const {
DCHECK(IsValid()); DCHECK(IsValid());
return LifetimePosition(value_ & ~(kStep - 1)); return LifetimePosition(value_ & ~(kStep - 1));
} }
// Returns the lifetime position for the end of the instruction which // Returns the lifetime position for the current END.
// corresponds to this lifetime position. LifetimePosition End() const {
LifetimePosition InstructionEnd() const {
DCHECK(IsValid()); DCHECK(IsValid());
return LifetimePosition(InstructionStart().Value() + kStep / 2); return LifetimePosition(Start().Value() + kHalfStep / 2);
} }
// Returns the lifetime position for the beginning of the next instruction. // Returns the lifetime position for the beginning of the next START.
LifetimePosition NextInstruction() const { LifetimePosition NextStart() const {
DCHECK(IsValid()); DCHECK(IsValid());
return LifetimePosition(InstructionStart().Value() + kStep); return LifetimePosition(Start().Value() + kHalfStep);
} }
// Returns the lifetime position for the beginning of the previous // Returns the lifetime position for the beginning of the next gap START.
// instruction. LifetimePosition NextFullStart() const {
LifetimePosition PrevInstruction() const { DCHECK(IsValid());
return LifetimePosition(FullStart().Value() + kStep);
}
// Returns the lifetime position for the beginning of the previous START.
LifetimePosition PrevStart() const {
DCHECK(IsValid()); DCHECK(IsValid());
DCHECK(value_ > 1); DCHECK(value_ >= kHalfStep);
return LifetimePosition(InstructionStart().Value() - kStep); return LifetimePosition(Start().Value() - kHalfStep);
} }
// Constructs the lifetime position which does not correspond to any // Constructs the lifetime position which does not correspond to any
...@@ -90,10 +117,11 @@ class LifetimePosition FINAL { ...@@ -90,10 +117,11 @@ class LifetimePosition FINAL {
} }
private: private:
static const int kStep = 2; static const int kHalfStep = 2;
static const int kStep = 2 * kHalfStep;
// Code relies on kStep being a power of two. // Code relies on kStep and kHalfStep being a power of two.
STATIC_ASSERT(IS_POWER_OF_TWO(kStep)); STATIC_ASSERT(IS_POWER_OF_TWO(kHalfStep));
explicit LifetimePosition(int value) : value_(value) {} explicit LifetimePosition(int value) : value_(value) {}
...@@ -495,8 +523,8 @@ class RegisterAllocator FINAL : public ZoneObject { ...@@ -495,8 +523,8 @@ class RegisterAllocator FINAL : public ZoneObject {
bool IsOutputDoubleRegisterOf(Instruction* instr, int index); bool IsOutputDoubleRegisterOf(Instruction* instr, int index);
void ProcessInstructions(const InstructionBlock* block, BitVector* live); void ProcessInstructions(const InstructionBlock* block, BitVector* live);
void MeetRegisterConstraints(const InstructionBlock* block); void MeetRegisterConstraints(const InstructionBlock* block);
void MeetConstraintsBetween(Instruction* first, Instruction* second, void MeetConstraintsBefore(int index);
int gap_index); void MeetConstraintsAfter(int index);
void MeetRegisterConstraintsForLastInstructionInBlock( void MeetRegisterConstraintsForLastInstructionInBlock(
const InstructionBlock* block); const InstructionBlock* block);
void ResolvePhis(const InstructionBlock* block); void ResolvePhis(const InstructionBlock* block);
...@@ -509,7 +537,7 @@ class RegisterAllocator FINAL : public ZoneObject { ...@@ -509,7 +537,7 @@ class RegisterAllocator FINAL : public ZoneObject {
InstructionOperand* hint); InstructionOperand* hint);
void Use(LifetimePosition block_start, LifetimePosition position, void Use(LifetimePosition block_start, LifetimePosition position,
InstructionOperand* operand, InstructionOperand* hint); InstructionOperand* operand, InstructionOperand* hint);
void AddGapMove(int index, GapInstruction::InnerPosition position, void AddGapMove(int index, Instruction::GapPosition position,
InstructionOperand* from, InstructionOperand* to); InstructionOperand* from, InstructionOperand* to);
// Helper methods for updating the life range lists. // Helper methods for updating the life range lists.
...@@ -590,7 +618,7 @@ class RegisterAllocator FINAL : public ZoneObject { ...@@ -590,7 +618,7 @@ class RegisterAllocator FINAL : public ZoneObject {
LiveRange* FixedLiveRangeFor(int index); LiveRange* FixedLiveRangeFor(int index);
LiveRange* FixedDoubleLiveRangeFor(int index); LiveRange* FixedDoubleLiveRangeFor(int index);
LiveRange* LiveRangeFor(int index); LiveRange* LiveRangeFor(int index);
GapInstruction* GetLastGap(const InstructionBlock* block); Instruction* GetLastInstruction(const InstructionBlock* block);
const char* RegisterName(int allocation_index); const char* RegisterName(int allocation_index);
......
...@@ -206,10 +206,7 @@ TEST(InstructionIsGapAt) { ...@@ -206,10 +206,7 @@ TEST(InstructionIsGapAt) {
R.code->AddInstruction(g); R.code->AddInstruction(g);
R.code->EndBlock(R.RpoFor(b0)); R.code->EndBlock(R.RpoFor(b0));
CHECK(R.code->instructions().size() == 4); CHECK(R.code->instructions().size() == 2);
for (size_t i = 0; i < R.code->instructions().size(); ++i) {
CHECK_EQ(i % 2 == 0, R.code->instructions()[i]->IsGapMoves());
}
} }
...@@ -236,10 +233,7 @@ TEST(InstructionIsGapAt2) { ...@@ -236,10 +233,7 @@ TEST(InstructionIsGapAt2) {
R.code->AddInstruction(g1); R.code->AddInstruction(g1);
R.code->EndBlock(R.RpoFor(b1)); R.code->EndBlock(R.RpoFor(b1));
CHECK(R.code->instructions().size() == 8); CHECK(R.code->instructions().size() == 4);
for (size_t i = 0; i < R.code->instructions().size(); ++i) {
CHECK_EQ(i % 2 == 0, R.code->instructions()[i]->IsGapMoves());
}
} }
...@@ -257,21 +251,15 @@ TEST(InstructionAddGapMove) { ...@@ -257,21 +251,15 @@ TEST(InstructionAddGapMove) {
R.code->AddInstruction(g); R.code->AddInstruction(g);
R.code->EndBlock(R.RpoFor(b0)); R.code->EndBlock(R.RpoFor(b0));
CHECK(R.code->instructions().size() == 4); CHECK(R.code->instructions().size() == 2);
for (size_t i = 0; i < R.code->instructions().size(); ++i) {
CHECK_EQ(i % 2 == 0, R.code->instructions()[i]->IsGapMoves());
}
int indexes[] = {0, 2, -1};
for (int i = 0; indexes[i] >= 0; i++) {
int index = indexes[i];
UnallocatedOperand* op1 = R.NewUnallocated(index + 6);
UnallocatedOperand* op2 = R.NewUnallocated(index + 12);
R.code->AddGapMove(index, op1, op2); int index = 0;
GapInstruction* gap = R.code->GapAt(index); for (auto instr : R.code->instructions()) {
ParallelMove* move = gap->GetParallelMove(GapInstruction::START); UnallocatedOperand* op1 = R.NewUnallocated(index++);
UnallocatedOperand* op2 = R.NewUnallocated(index++);
instr->GetOrCreateParallelMove(TestInstr::START, R.zone())
->AddMove(op1, op2, R.zone());
ParallelMove* move = instr->GetParallelMove(TestInstr::START);
CHECK(move); CHECK(move);
const ZoneList<MoveOperands>* move_operands = move->move_operands(); const ZoneList<MoveOperands>* move_operands = move->move_operands();
CHECK_EQ(1, move_operands->length()); CHECK_EQ(1, move_operands->length());
......
...@@ -58,16 +58,16 @@ class TestCode : public HandleAndZoneScope { ...@@ -58,16 +58,16 @@ class TestCode : public HandleAndZoneScope {
void RedundantMoves() { void RedundantMoves() {
Start(); Start();
sequence_.AddInstruction(Instruction::New(main_zone(), kArchNop)); sequence_.AddInstruction(Instruction::New(main_zone(), kArchNop));
int index = static_cast<int>(sequence_.instructions().size()) - 2; int index = static_cast<int>(sequence_.instructions().size()) - 1;
sequence_.AddGapMove(index, RegisterOperand::New(13, main_zone()), AddGapMove(index, RegisterOperand::New(13, main_zone()),
RegisterOperand::New(13, main_zone())); RegisterOperand::New(13, main_zone()));
} }
void NonRedundantMoves() { void NonRedundantMoves() {
Start(); Start();
sequence_.AddInstruction(Instruction::New(main_zone(), kArchNop)); sequence_.AddInstruction(Instruction::New(main_zone(), kArchNop));
int index = static_cast<int>(sequence_.instructions().size()) - 2; int index = static_cast<int>(sequence_.instructions().size()) - 1;
sequence_.AddGapMove(index, ImmediateOperand::New(11, main_zone()), AddGapMove(index, ImmediateOperand::New(11, main_zone()),
RegisterOperand::New(11, main_zone())); RegisterOperand::New(11, main_zone()));
} }
void Other() { void Other() {
Start(); Start();
...@@ -96,6 +96,11 @@ class TestCode : public HandleAndZoneScope { ...@@ -96,6 +96,11 @@ class TestCode : public HandleAndZoneScope {
CHECK(current_ == NULL); CHECK(current_ == NULL);
Start(true); Start(true);
} }
void AddGapMove(int index, InstructionOperand* from, InstructionOperand* to) {
sequence_.InstructionAt(index)
->GetOrCreateParallelMove(Instruction::START, main_zone())
->AddMove(from, to, main_zone());
}
}; };
......
...@@ -11,13 +11,11 @@ namespace compiler { ...@@ -11,13 +11,11 @@ namespace compiler {
class MoveOptimizerTest : public InstructionSequenceTest { class MoveOptimizerTest : public InstructionSequenceTest {
public: public:
GapInstruction* LastGap() { Instruction* LastInstruction() { return sequence()->instructions().back(); }
return GapInstruction::cast(*(sequence()->instructions().rbegin() + 1));
}
void AddMove(GapInstruction* gap, TestOperand from, TestOperand to, void AddMove(Instruction* instr, TestOperand from, TestOperand to,
GapInstruction::InnerPosition pos = GapInstruction::START) { Instruction::GapPosition pos = Instruction::START) {
auto parallel_move = gap->GetOrCreateParallelMove(pos, zone()); auto parallel_move = instr->GetOrCreateParallelMove(pos, zone());
parallel_move->AddMove(ConvertMoveArg(from), ConvertMoveArg(to), zone()); parallel_move->AddMove(ConvertMoveArg(from), ConvertMoveArg(to), zone());
} }
...@@ -86,16 +84,16 @@ class MoveOptimizerTest : public InstructionSequenceTest { ...@@ -86,16 +84,16 @@ class MoveOptimizerTest : public InstructionSequenceTest {
TEST_F(MoveOptimizerTest, RemovesRedundant) { TEST_F(MoveOptimizerTest, RemovesRedundant) {
StartBlock(); StartBlock();
EmitNop(); auto first_instr = EmitNop();
AddMove(LastGap(), Reg(0), Reg(1)); AddMove(first_instr, Reg(0), Reg(1));
EmitNop(); auto last_instr = EmitNop();
AddMove(LastGap(), Reg(1), Reg(0)); AddMove(last_instr, Reg(1), Reg(0));
EndBlock(Last()); EndBlock(Last());
Optimize(); Optimize();
auto gap = LastGap(); CHECK_EQ(0, NonRedundantSize(first_instr->parallel_moves()[0]));
auto move = gap->parallel_moves()[0]; auto move = last_instr->parallel_moves()[0];
CHECK_EQ(1, NonRedundantSize(move)); CHECK_EQ(1, NonRedundantSize(move));
CHECK(Contains(move, Reg(0), Reg(1))); CHECK(Contains(move, Reg(0), Reg(1)));
} }
...@@ -105,7 +103,7 @@ TEST_F(MoveOptimizerTest, SplitsConstants) { ...@@ -105,7 +103,7 @@ TEST_F(MoveOptimizerTest, SplitsConstants) {
StartBlock(); StartBlock();
EndBlock(Last()); EndBlock(Last());
auto gap = LastGap(); auto gap = LastInstruction();
AddMove(gap, Const(1), Slot(0)); AddMove(gap, Const(1), Slot(0));
AddMove(gap, Const(1), Slot(1)); AddMove(gap, Const(1), Slot(1));
AddMove(gap, Const(1), Reg(0)); AddMove(gap, Const(1), Reg(0));
...@@ -131,18 +129,18 @@ TEST_F(MoveOptimizerTest, SimpleMerge) { ...@@ -131,18 +129,18 @@ TEST_F(MoveOptimizerTest, SimpleMerge) {
StartBlock(); StartBlock();
EndBlock(Jump(2)); EndBlock(Jump(2));
AddMove(LastGap(), Reg(0), Reg(1)); AddMove(LastInstruction(), Reg(0), Reg(1));
StartBlock(); StartBlock();
EndBlock(Jump(1)); EndBlock(Jump(1));
AddMove(LastGap(), Reg(0), Reg(1)); AddMove(LastInstruction(), Reg(0), Reg(1));
StartBlock(); StartBlock();
EndBlock(Last()); EndBlock(Last());
Optimize(); Optimize();
auto move = LastGap()->parallel_moves()[0]; auto move = LastInstruction()->parallel_moves()[0];
CHECK_EQ(1, NonRedundantSize(move)); CHECK_EQ(1, NonRedundantSize(move));
CHECK(Contains(move, Reg(0), Reg(1))); CHECK(Contains(move, Reg(0), Reg(1)));
} }
...@@ -154,13 +152,13 @@ TEST_F(MoveOptimizerTest, SimpleMergeCycle) { ...@@ -154,13 +152,13 @@ TEST_F(MoveOptimizerTest, SimpleMergeCycle) {
StartBlock(); StartBlock();
EndBlock(Jump(2)); EndBlock(Jump(2));
auto gap_0 = LastGap(); auto gap_0 = LastInstruction();
AddMove(gap_0, Reg(0), Reg(1)); AddMove(gap_0, Reg(0), Reg(1));
AddMove(LastGap(), Reg(1), Reg(0)); AddMove(LastInstruction(), Reg(1), Reg(0));
StartBlock(); StartBlock();
EndBlock(Jump(1)); EndBlock(Jump(1));
auto gap_1 = LastGap(); auto gap_1 = LastInstruction();
AddMove(gap_1, Reg(0), Reg(1)); AddMove(gap_1, Reg(0), Reg(1));
AddMove(gap_1, Reg(1), Reg(0)); AddMove(gap_1, Reg(1), Reg(0));
...@@ -169,9 +167,9 @@ TEST_F(MoveOptimizerTest, SimpleMergeCycle) { ...@@ -169,9 +167,9 @@ TEST_F(MoveOptimizerTest, SimpleMergeCycle) {
Optimize(); Optimize();
CHECK(gap_0->IsRedundant()); CHECK(gap_0->AreMovesRedundant());
CHECK(gap_1->IsRedundant()); CHECK(gap_1->AreMovesRedundant());
auto move = LastGap()->parallel_moves()[0]; auto move = LastInstruction()->parallel_moves()[0];
CHECK_EQ(2, NonRedundantSize(move)); CHECK_EQ(2, NonRedundantSize(move));
CHECK(Contains(move, Reg(0), Reg(1))); CHECK(Contains(move, Reg(0), Reg(1)));
CHECK(Contains(move, Reg(1), Reg(0))); CHECK(Contains(move, Reg(1), Reg(0)));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment