source.AsRegisterPairHigh<Register>());
} else if (source.IsFpuRegister()) {
__ movsd(Address(ESP, destination.GetStackIndex()), source.AsFpuRegister<XmmRegister>());
+ } else if (source.IsConstant()) {
+ HConstant* constant = source.GetConstant();
+ int64_t value;
+ if (constant->IsLongConstant()) {
+ value = constant->AsLongConstant()->GetValue();
+ } else {
+ DCHECK(constant->IsDoubleConstant());
+ value = bit_cast<double, int64_t>(constant->AsDoubleConstant()->GetValue());
+ }
+ __ movl(Address(ESP, destination.GetStackIndex()), Immediate(Low32Bits(value)));
+ __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), Immediate(High32Bits(value)));
} else {
- DCHECK(source.IsDoubleStackSlot());
+ DCHECK(source.IsDoubleStackSlot()) << source;
EmitParallelMoves(
Location::StackSlot(source.GetStackIndex()),
Location::StackSlot(destination.GetStackIndex()),
// Processing a Dex `int-to-byte' instruction.
if (in.IsRegister()) {
__ movsxb(out.AsRegister<Register>(), in.AsRegister<ByteRegister>());
- } else if (in.IsStackSlot()) {
- __ movsxb(out.AsRegister<Register>(), Address(ESP, in.GetStackIndex()));
} else {
DCHECK(in.GetConstant()->IsIntConstant());
int32_t value = in.GetConstant()->AsIntConstant()->GetValue();
if (second.IsRegisterPair()) {
__ addl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>());
__ adcl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>());
- } else {
+ } else if (second.IsDoubleStackSlot()) {
__ addl(first.AsRegisterPairLow<Register>(), Address(ESP, second.GetStackIndex()));
__ adcl(first.AsRegisterPairHigh<Register>(),
Address(ESP, second.GetHighStackIndex(kX86WordSize)));
+ } else {
+ DCHECK(second.IsConstant()) << second;
+ int64_t value = second.GetConstant()->AsLongConstant()->GetValue();
+ __ addl(first.AsRegisterPairLow<Register>(), Immediate(Low32Bits(value)));
+ __ adcl(first.AsRegisterPairHigh<Register>(), Immediate(High32Bits(value)));
}
break;
}
if (second.IsRegisterPair()) {
__ subl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>());
__ sbbl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>());
- } else {
+ } else if (second.IsDoubleStackSlot()) {
__ subl(first.AsRegisterPairLow<Register>(), Address(ESP, second.GetStackIndex()));
__ sbbl(first.AsRegisterPairHigh<Register>(),
Address(ESP, second.GetHighStackIndex(kX86WordSize)));
+ } else {
+ DCHECK(second.IsConstant()) << second;
+ int64_t value = second.GetConstant()->AsLongConstant()->GetValue();
+ __ subl(first.AsRegisterPairLow<Register>(), Immediate(Low32Bits(value)));
+ __ sbbl(first.AsRegisterPairHigh<Register>(), Immediate(High32Bits(value)));
}
break;
}
break;
case Primitive::kPrimLong: {
locations->SetInAt(0, Location::RequiresRegister());
- // TODO: Currently this handles only stack operands:
- // - we don't have enough registers because we currently use Quick ABI.
- // - by the time we have a working register allocator we will probably change the ABI
- // and fix the above.
- // - we don't have a way yet to request operands on stack but the base line compiler
- // will leave the operands on the stack with Any().
locations->SetInAt(1, Location::Any());
locations->SetOut(Location::SameAsFirstInput());
// Needed for imul on 32bits with 64bits output.
}
case Primitive::kPrimLong: {
- DCHECK(second.IsDoubleStackSlot());
-
Register in1_hi = first.AsRegisterPairHigh<Register>();
Register in1_lo = first.AsRegisterPairLow<Register>();
- Address in2_hi(ESP, second.GetHighStackIndex(kX86WordSize));
- Address in2_lo(ESP, second.GetStackIndex());
Register eax = locations->GetTemp(0).AsRegister<Register>();
Register edx = locations->GetTemp(1).AsRegister<Register>();
DCHECK_EQ(EAX, eax);
DCHECK_EQ(EDX, edx);
- // input: in1 - 64 bits, in2 - 64 bits
+ // input: in1 - 64 bits, in2 - 64 bits.
// output: in1
// formula: in1.hi : in1.lo = (in1.lo * in2.hi + in1.hi * in2.lo)* 2^32 + in1.lo * in2.lo
// parts: in1.hi = in1.lo * in2.hi + in1.hi * in2.lo + (in1.lo * in2.lo)[63:32]
// parts: in1.lo = (in1.lo * in2.lo)[31:0]
-
- __ movl(eax, in2_hi);
- // eax <- in1.lo * in2.hi
- __ imull(eax, in1_lo);
- // in1.hi <- in1.hi * in2.lo
- __ imull(in1_hi, in2_lo);
- // in1.hi <- in1.lo * in2.hi + in1.hi * in2.lo
- __ addl(in1_hi, eax);
- // move in1_lo to eax to prepare for double precision
- __ movl(eax, in1_lo);
- // edx:eax <- in1.lo * in2.lo
- __ mull(in2_lo);
- // in1.hi <- in2.hi * in1.lo + in2.lo * in1.hi + (in1.lo * in2.lo)[63:32]
- __ addl(in1_hi, edx);
- // in1.lo <- (in1.lo * in2.lo)[31:0];
- __ movl(in1_lo, eax);
+ if (second.IsConstant()) {
+ DCHECK(second.GetConstant()->IsLongConstant());
+
+ int64_t value = second.GetConstant()->AsLongConstant()->GetValue();
+ int32_t low_value = Low32Bits(value);
+ int32_t high_value = High32Bits(value);
+ Immediate low(low_value);
+ Immediate high(high_value);
+
+ __ movl(eax, high);
+ // eax <- in1.lo * in2.hi
+ __ imull(eax, in1_lo);
+ // in1.hi <- in1.hi * in2.lo
+ __ imull(in1_hi, low);
+ // in1.hi <- in1.lo * in2.hi + in1.hi * in2.lo
+ __ addl(in1_hi, eax);
+ // move in2_lo to eax to prepare for double precision
+ __ movl(eax, low);
+ // edx:eax <- in1.lo * in2.lo
+ __ mull(in1_lo);
+ // in1.hi <- in2.hi * in1.lo + in2.lo * in1.hi + (in1.lo * in2.lo)[63:32]
+ __ addl(in1_hi, edx);
+ // in1.lo <- (in1.lo * in2.lo)[31:0];
+ __ movl(in1_lo, eax);
+ } else if (second.IsRegisterPair()) {
+ Register in2_hi = second.AsRegisterPairHigh<Register>();
+ Register in2_lo = second.AsRegisterPairLow<Register>();
+
+ __ movl(eax, in2_hi);
+ // eax <- in1.lo * in2.hi
+ __ imull(eax, in1_lo);
+ // in1.hi <- in1.hi * in2.lo
+ __ imull(in1_hi, in2_lo);
+ // in1.hi <- in1.lo * in2.hi + in1.hi * in2.lo
+ __ addl(in1_hi, eax);
+ // move in1_lo to eax to prepare for double precision
+ __ movl(eax, in1_lo);
+ // edx:eax <- in1.lo * in2.lo
+ __ mull(in2_lo);
+ // in1.hi <- in2.hi * in1.lo + in2.lo * in1.hi + (in1.lo * in2.lo)[63:32]
+ __ addl(in1_hi, edx);
+ // in1.lo <- (in1.lo * in2.lo)[31:0];
+ __ movl(in1_lo, eax);
+ } else {
+ DCHECK(second.IsDoubleStackSlot()) << second;
+ Address in2_hi(ESP, second.GetHighStackIndex(kX86WordSize));
+ Address in2_lo(ESP, second.GetStackIndex());
+
+ __ movl(eax, in2_hi);
+ // eax <- in1.lo * in2.hi
+ __ imull(eax, in1_lo);
+ // in1.hi <- in1.hi * in2.lo
+ __ imull(in1_hi, in2_lo);
+ // in1.hi <- in1.lo * in2.hi + in1.hi * in2.lo
+ __ addl(in1_hi, eax);
+ // move in1_lo to eax to prepare for double precision
+ __ movl(eax, in1_lo);
+ // edx:eax <- in1.lo * in2.lo
+ __ mull(in2_lo);
+ // in1.hi <- in2.hi * in1.lo + in2.lo * in1.hi + (in1.lo * in2.lo)[63:32]
+ __ addl(in1_hi, edx);
+ // in1.lo <- (in1.lo * in2.lo)[31:0];
+ __ movl(in1_lo, eax);
+ }
break;
}
case Primitive::kPrimLong: {
if (right.IsRegisterPair()) {
__ cmpl(left.AsRegisterPairHigh<Register>(), right.AsRegisterPairHigh<Register>());
- } else {
- DCHECK(right.IsDoubleStackSlot());
+ } else if (right.IsDoubleStackSlot()) {
__ cmpl(left.AsRegisterPairHigh<Register>(),
Address(ESP, right.GetHighStackIndex(kX86WordSize)));
+ } else {
+ DCHECK(right.IsConstant()) << right;
+ __ cmpl(left.AsRegisterPairHigh<Register>(),
+ Immediate(High32Bits(right.GetConstant()->AsLongConstant()->GetValue())));
}
__ j(kLess, &less); // Signed compare.
__ j(kGreater, &greater); // Signed compare.
if (right.IsRegisterPair()) {
__ cmpl(left.AsRegisterPairLow<Register>(), right.AsRegisterPairLow<Register>());
- } else {
- DCHECK(right.IsDoubleStackSlot());
+ } else if (right.IsDoubleStackSlot()) {
__ cmpl(left.AsRegisterPairLow<Register>(), Address(ESP, right.GetStackIndex()));
+ } else {
+ DCHECK(right.IsConstant()) << right;
+ __ cmpl(left.AsRegisterPairLow<Register>(),
+ Immediate(Low32Bits(right.GetConstant()->AsLongConstant()->GetValue())));
}
break;
}
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+
+ // The output overlaps in case of long: we don't want the low move to overwrite
+ // the object's location.
+ locations->SetOut(Location::RequiresRegister(),
+ (instruction->GetType() == Primitive::kPrimLong) ? Location::kOutputOverlap
+ : Location::kNoOutputOverlap);
if (field_info.IsVolatile() && (field_info.GetFieldType() == Primitive::kPrimLong)) {
// Long values can be loaded atomically into an XMM using movsd.
__ psrlq(temp, Immediate(32));
__ movd(out.AsRegisterPairHigh<Register>(), temp);
} else {
+ DCHECK_NE(base, out.AsRegisterPairLow<Register>());
__ movl(out.AsRegisterPairLow<Register>(), Address(base, offset));
codegen_->MaybeRecordImplicitNullCheck(instruction);
__ movl(out.AsRegisterPairHigh<Register>(), Address(base, kX86WordSize + offset));
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
- locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap);
+ // The output overlaps in case of long: we don't want the low move to overwrite
+ // the array's location.
+ locations->SetOut(Location::RequiresRegister(),
+ (instruction->GetType() == Primitive::kPrimLong) ? Location::kOutputOverlap
+ : Location::kNoOutputOverlap);
}
void InstructionCodeGeneratorX86::VisitArrayGet(HArrayGet* instruction) {
case Primitive::kPrimLong: {
uint32_t data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value();
Location out = locations->Out();
+ DCHECK_NE(obj, out.AsRegisterPairLow<Register>());
if (index.IsConstant()) {
size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset;
__ movl(out.AsRegisterPairLow<Register>(), Address(obj, offset));
DCHECK(destination.IsStackSlot()) << destination;
__ movl(Address(ESP, destination.GetStackIndex()), Immediate(value));
}
- } else {
- DCHECK(constant->IsFloatConstant());
+ } else if (constant->IsFloatConstant()) {
float value = constant->AsFloatConstant()->GetValue();
Immediate imm(bit_cast<float, int32_t>(value));
if (destination.IsFpuRegister()) {
DCHECK(destination.IsStackSlot()) << destination;
__ movl(Address(ESP, destination.GetStackIndex()), imm);
}
+ } else if (constant->IsLongConstant()) {
+ int64_t value = constant->AsLongConstant()->GetValue();
+ int32_t low_value = Low32Bits(value);
+ int32_t high_value = High32Bits(value);
+ Immediate low(low_value);
+ Immediate high(high_value);
+ if (destination.IsDoubleStackSlot()) {
+ __ movl(Address(ESP, destination.GetStackIndex()), low);
+ __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), high);
+ } else {
+ __ movl(destination.AsRegisterPairLow<Register>(), low);
+ __ movl(destination.AsRegisterPairHigh<Register>(), high);
+ }
+ } else {
+ DCHECK(constant->IsDoubleConstant());
+ double dbl_value = constant->AsDoubleConstant()->GetValue();
+ int64_t value = bit_cast<double, int64_t>(dbl_value);
+ int32_t low_value = Low32Bits(value);
+ int32_t high_value = High32Bits(value);
+ Immediate low(low_value);
+ Immediate high(high_value);
+ if (destination.IsFpuRegister()) {
+ XmmRegister dest = destination.AsFpuRegister<XmmRegister>();
+ if (value == 0) {
+ // Easy handling of 0.0.
+ __ xorpd(dest, dest);
+ } else {
+ __ pushl(high);
+ __ pushl(low);
+ __ movsd(dest, Address(ESP, 0));
+ __ addl(ESP, Immediate(8));
+ }
+ } else {
+ DCHECK(destination.IsDoubleStackSlot()) << destination;
+ __ movl(Address(ESP, destination.GetStackIndex()), low);
+ __ movl(Address(ESP, destination.GetHighStackIndex(kX86WordSize)), high);
+ }
}
} else {
LOG(FATAL) << "Unimplemented move: " << destination << " <- " << source;
Exchange32(source.AsFpuRegister<XmmRegister>(), destination.GetStackIndex());
} else if (destination.IsFpuRegister() && source.IsStackSlot()) {
Exchange32(destination.AsFpuRegister<XmmRegister>(), source.GetStackIndex());
+ } else if (source.IsFpuRegister() && destination.IsDoubleStackSlot()) {
+ // Take advantage of the 16 bytes in the XMM register.
+ XmmRegister reg = source.AsFpuRegister<XmmRegister>();
+ Address stack(ESP, destination.GetStackIndex());
+ // Load the double into the high doubleword.
+ __ movhpd(reg, stack);
+
+ // Store the low double into the destination.
+ __ movsd(reg, stack);
+
+ // Move the high double to the low double.
+ __ psrldq(reg, Immediate(8));
+ } else if (destination.IsFpuRegister() && source.IsDoubleStackSlot()) {
+ // Take advantage of the 16 bytes in the XMM register.
+ XmmRegister reg = destination.AsFpuRegister<XmmRegister>();
+ Address stack(ESP, source.GetStackIndex());
+ // Load the double into the high doubleword.
+ __ movhpd(reg, stack);
+
+ // Store the low double into the destination.
+ __ movsd(reg, stack);
+
+ // Move the high double to the low double.
+ __ psrldq(reg, Immediate(8));
+ } else if (destination.IsDoubleStackSlot() && source.IsDoubleStackSlot()) {
+ Exchange(destination.GetStackIndex(), source.GetStackIndex());
+ Exchange(destination.GetHighStackIndex(kX86WordSize), source.GetHighStackIndex(kX86WordSize));
} else {
LOG(FATAL) << "Unimplemented: source: " << source << ", destination: " << destination;
}
__ xorl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>());
__ xorl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>());
}
- } else {
+ } else if (second.IsDoubleStackSlot()) {
if (instruction->IsAnd()) {
__ andl(first.AsRegisterPairLow<Register>(), Address(ESP, second.GetStackIndex()));
__ andl(first.AsRegisterPairHigh<Register>(),
__ xorl(first.AsRegisterPairHigh<Register>(),
Address(ESP, second.GetHighStackIndex(kX86WordSize)));
}
+ } else {
+ DCHECK(second.IsConstant()) << second;
+ int64_t value = second.GetConstant()->AsLongConstant()->GetValue();
+ Immediate low(Low32Bits(value));
+ Immediate high(High32Bits(value));
+ if (instruction->IsAnd()) {
+ __ andl(first.AsRegisterPairLow<Register>(), low);
+ __ andl(first.AsRegisterPairHigh<Register>(), high);
+ } else if (instruction->IsOr()) {
+ __ orl(first.AsRegisterPairLow<Register>(), low);
+ __ orl(first.AsRegisterPairHigh<Register>(), high);
+ } else {
+ DCHECK(instruction->IsXor());
+ __ xorl(first.AsRegisterPairLow<Register>(), low);
+ __ xorl(first.AsRegisterPairHigh<Register>(), high);
+ }
}
}
}
// allocate SRegister.
static int GetHighForLowRegister(int reg) { return reg + 1; }
static bool IsLowRegister(int reg) { return (reg & 1) == 0; }
+static bool IsLowOfUnalignedPairInterval(LiveInterval* low) {
+ return GetHighForLowRegister(low->GetRegister()) != low->GetHighInterval()->GetRegister();
+}
RegisterAllocator::RegisterAllocator(ArenaAllocator* allocator,
CodeGenerator* codegen,
reserved_out_slots_ = 1 + codegen->GetGraph()->GetMaximumNumberOfOutVRegs();
}
-bool RegisterAllocator::CanAllocateRegistersFor(const HGraph& graph,
+bool RegisterAllocator::CanAllocateRegistersFor(const HGraph& graph ATTRIBUTE_UNUSED,
InstructionSet instruction_set) {
- if (!Supports(instruction_set)) {
- return false;
- }
- if (instruction_set == kArm64
+ return instruction_set == kArm64
|| instruction_set == kX86_64
|| instruction_set == kArm
- || instruction_set == kThumb2) {
- return true;
- }
- for (size_t i = 0, e = graph.GetBlocks().Size(); i < e; ++i) {
- for (HInstructionIterator it(graph.GetBlocks().Get(i)->GetInstructions());
- !it.Done();
- it.Advance()) {
- HInstruction* current = it.Current();
- if (instruction_set == kX86 && current->GetType() == Primitive::kPrimLong) {
- return false;
- }
- }
- }
- return true;
+ || instruction_set == kX86
+ || instruction_set == kThumb2;
}
static bool ShouldProcess(bool processing_core_registers, LiveInterval* interval) {
return false;
}
- if (current->IsLowInterval() && free_until[GetHighForLowRegister(reg)] == 0) {
- return false;
+ if (current->IsLowInterval()) {
+ // If the high register of this interval is not available, we need to spill.
+ int high_reg = current->GetHighInterval()->GetRegister();
+ if (high_reg == kNoRegister) {
+ high_reg = GetHighForLowRegister(reg);
+ }
+ if (free_until[high_reg] == 0) {
+ return false;
+ }
}
current->SetRegister(reg);
return reg;
}
-bool RegisterAllocator::TrySplitNonPairIntervalAt(size_t position,
- size_t first_register_use,
- size_t* next_use) {
+bool RegisterAllocator::TrySplitNonPairOrUnalignedPairIntervalAt(size_t position,
+ size_t first_register_use,
+ size_t* next_use) {
for (size_t i = 0, e = active_.Size(); i < e; ++i) {
LiveInterval* active = active_.Get(i);
DCHECK(active->HasRegister());
+ if (active->IsFixed()) continue;
+ if (active->IsHighInterval()) continue;
+ if (first_register_use > next_use[active->GetRegister()]) continue;
+
// Split the first interval found.
- if (first_register_use <= next_use[active->GetRegister()]
- && !active->IsLowInterval()
- && !active->IsHighInterval()) {
+ if (!active->IsLowInterval() || IsLowOfUnalignedPairInterval(active)) {
LiveInterval* split = Split(active, position);
active_.DeleteAt(i);
if (split != active) {
DCHECK_NE(reg, kNoRegister);
if (should_spill) {
DCHECK(!current->IsHighInterval());
- bool is_allocation_at_use_site = (current->GetStart() == (first_register_use - 1));
+ bool is_allocation_at_use_site = (current->GetStart() >= (first_register_use - 1));
if (current->IsLowInterval()
&& is_allocation_at_use_site
- && TrySplitNonPairIntervalAt(current->GetStart(), first_register_use, next_use)) {
+ && TrySplitNonPairOrUnalignedPairIntervalAt(current->GetStart(),
+ first_register_use,
+ next_use)) {
// If we're allocating a register for `current` because the instruction at
// that position requires it, but we think we should spill, then there are
- // non-pair intervals blocking the allocation. We split the first
- // interval found, and put ourselves first in the `unhandled_` list.
+ // non-pair intervals or unaligned pair intervals blocking the allocation.
+ // We split the first interval found, and put ourselves first in the
+ // `unhandled_` list.
LiveInterval* existing = unhandled_->Peek();
DCHECK(existing->IsHighInterval());
DCHECK_EQ(existing->GetLowInterval(), current);
|| destination.IsDoubleStackSlot();
}
-void RegisterAllocator::AddInputMoveFor(HInstruction* user,
+void RegisterAllocator::AddMove(HParallelMove* move,
+ Location source,
+ Location destination,
+ HInstruction* instruction,
+ Primitive::Type type) const {
+ if (type == Primitive::kPrimLong
+ && codegen_->ShouldSplitLongMoves()
+ // The parallel move resolver knows how to deal with long constants.
+ && !source.IsConstant()) {
+ move->AddMove(source.ToLow(), destination.ToLow(), instruction);
+ move->AddMove(source.ToHigh(), destination.ToHigh(), nullptr);
+ } else {
+ move->AddMove(source, destination, instruction);
+ }
+}
+
+void RegisterAllocator::AddInputMoveFor(HInstruction* input,
+ HInstruction* user,
Location source,
Location destination) const {
if (source.Equals(destination)) return;
move = previous->AsParallelMove();
}
DCHECK_EQ(move->GetLifetimePosition(), user->GetLifetimePosition());
- move->AddMove(source, destination, nullptr);
+ AddMove(move, source, destination, nullptr, input->GetType());
}
static bool IsInstructionStart(size_t position) {
at = liveness_.GetInstructionFromPosition((position + 1) / 2);
// Note that parallel moves may have already been inserted, so we explicitly
// ask for the first instruction of the block: `GetInstructionFromPosition` does
- // not contain the moves.
+ // not contain the `HParallelMove` instructions.
at = at->GetBlock()->GetFirstInstruction();
+
+ if (at->GetLifetimePosition() < position) {
+ // We may insert moves for split siblings and phi spills at the beginning of the block.
+ // Since this is a different lifetime position, we need to go to the next instruction.
+ DCHECK(at->IsParallelMove());
+ at = at->GetNext();
+ }
+
if (at->GetLifetimePosition() != position) {
DCHECK_GT(at->GetLifetimePosition(), position);
move = new (allocator_) HParallelMove(allocator_);
}
}
DCHECK_EQ(move->GetLifetimePosition(), position);
- move->AddMove(source, destination, instruction);
+ AddMove(move, source, destination, instruction, instruction->GetType());
}
void RegisterAllocator::InsertParallelMoveAtExitOf(HBasicBlock* block,
} else {
move = previous->AsParallelMove();
}
- move->AddMove(source, destination, instruction);
+ AddMove(move, source, destination, instruction, instruction->GetType());
}
void RegisterAllocator::InsertParallelMoveAtEntryOf(HBasicBlock* block,
HInstruction* first = block->GetFirstInstruction();
HParallelMove* move = first->AsParallelMove();
+ size_t position = block->GetLifetimeStart();
// This is a parallel move for connecting blocks. We need to differentiate
// it with moves for connecting siblings in a same block, and input moves.
- if (move == nullptr || move->GetLifetimePosition() != block->GetLifetimeStart()) {
+ if (move == nullptr || move->GetLifetimePosition() != position) {
move = new (allocator_) HParallelMove(allocator_);
- move->SetLifetimePosition(block->GetLifetimeStart());
+ move->SetLifetimePosition(position);
block->InsertInstructionBefore(move, first);
}
- move->AddMove(source, destination, instruction);
+ AddMove(move, source, destination, instruction, instruction->GetType());
}
void RegisterAllocator::InsertMoveAfter(HInstruction* instruction,
move->SetLifetimePosition(position);
instruction->GetBlock()->InsertInstructionBefore(move, instruction->GetNext());
}
- move->AddMove(source, destination, instruction);
+ AddMove(move, source, destination, instruction, instruction->GetType());
}
void RegisterAllocator::ConnectSiblings(LiveInterval* interval) {
if (expected_location.IsUnallocated()) {
locations->SetInAt(use->GetInputIndex(), source);
} else if (!expected_location.IsConstant()) {
- AddInputMoveFor(use->GetUser(), source, expected_location);
+ AddInputMoveFor(interval->GetDefinedBy(), use->GetUser(), source, expected_location);
}
} else {
DCHECK(use->GetUser()->IsInvoke());
Location source = input->GetLiveInterval()->GetLocationAt(
predecessor->GetLifetimeEnd() - 1);
Location destination = phi->GetLiveInterval()->ToLocation();
- InsertParallelMoveAtExitOf(predecessor, nullptr, source, destination);
+ InsertParallelMoveAtExitOf(predecessor, phi, source, destination);
}
}
}