diff options
author | 2015-03-06 16:10:14 +0000 | |
---|---|---|
committer | 2015-03-06 16:10:14 +0000 | |
commit | 154552e666347d41d95d7619c6ee56249ff4feca (patch) | |
tree | b8bdb820be33317f23ef1d3e43d13b2b6bfb3ba5 /compiler/optimizing | |
parent | b4ba354cf8d22b261205494875cc014f18587b50 (diff) |
Revert "[optimizing] Enable x86 long support."
Few libcore failures.
This reverts commit b4ba354cf8d22b261205494875cc014f18587b50.
Change-Id: I4a28d853e730dff9b69aec9555505803cf2fcd63
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/code_generator.h | 16 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 235 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.h | 2 | ||||
-rw-r--r-- | compiler/optimizing/locations.h | 22 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 15 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/register_allocator.cc | 110 | ||||
-rw-r--r-- | compiler/optimizing/register_allocator.h | 24 | ||||
-rw-r--r-- | compiler/optimizing/ssa_liveness_analysis.h | 6 |
9 files changed, 113 insertions, 319 deletions
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index b8f4572abd..5146afad8d 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -153,13 +153,17 @@ class CodeGenerator { virtual size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) = 0; // Restores the register from the stack. Returns the size taken on stack. virtual size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) = 0; - - virtual size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0; - virtual size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0; - + virtual size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) { + UNUSED(stack_index, reg_id); + UNIMPLEMENTED(FATAL); + UNREACHABLE(); + } + virtual size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) { + UNUSED(stack_index, reg_id); + UNIMPLEMENTED(FATAL); + UNREACHABLE(); + } virtual bool NeedsTwoRegisters(Primitive::Type type) const = 0; - // Returns whether we should split long moves in parallel moves. - virtual bool ShouldSplitLongMoves() const { return false; } bool IsCoreCalleeSaveRegister(int reg) const { return (core_callee_save_mask_ & (1 << reg)) != 0; diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 7f2ea021da..4b8adddfe6 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -673,19 +673,8 @@ void CodeGeneratorX86::Move64(Location destination, Location source) { 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()) << source; + DCHECK(source.IsDoubleStackSlot()); EmitParallelMoves( Location::StackSlot(source.GetStackIndex()), Location::StackSlot(destination.GetStackIndex()), @@ -1566,6 +1555,8 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio // 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(); @@ -1901,15 +1892,10 @@ void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) { if (second.IsRegisterPair()) { __ addl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>()); __ adcl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>()); - } else if (second.IsDoubleStackSlot()) { + } else { __ 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; } @@ -1979,15 +1965,10 @@ void InstructionCodeGeneratorX86::VisitSub(HSub* sub) { if (second.IsRegisterPair()) { __ subl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>()); __ sbbl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>()); - } else if (second.IsDoubleStackSlot()) { + } else { __ 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; } @@ -2018,6 +1999,12 @@ void LocationsBuilderX86::VisitMul(HMul* mul) { 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. @@ -2059,83 +2046,39 @@ void InstructionCodeGeneratorX86::VisitMul(HMul* mul) { } 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] - 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); - } + + __ 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; } @@ -2731,24 +2674,18 @@ void InstructionCodeGeneratorX86::VisitCompare(HCompare* compare) { case Primitive::kPrimLong: { if (right.IsRegisterPair()) { __ cmpl(left.AsRegisterPairHigh<Register>(), right.AsRegisterPairHigh<Register>()); - } else if (right.IsDoubleStackSlot()) { - __ cmpl(left.AsRegisterPairHigh<Register>(), - Address(ESP, right.GetHighStackIndex(kX86WordSize))); } else { - DCHECK(right.IsConstant()) << right; + DCHECK(right.IsDoubleStackSlot()); __ cmpl(left.AsRegisterPairHigh<Register>(), - Immediate(High32Bits(right.GetConstant()->AsLongConstant()->GetValue()))); + Address(ESP, right.GetHighStackIndex(kX86WordSize))); } __ j(kLess, &less); // Signed compare. __ j(kGreater, &greater); // Signed compare. if (right.IsRegisterPair()) { __ cmpl(left.AsRegisterPairLow<Register>(), right.AsRegisterPairLow<Register>()); - } 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()))); + DCHECK(right.IsDoubleStackSlot()); + __ cmpl(left.AsRegisterPairLow<Register>(), Address(ESP, right.GetStackIndex())); } break; } @@ -2833,12 +2770,7 @@ void LocationsBuilderX86::HandleFieldGet(HInstruction* instruction, const FieldI LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); locations->SetInAt(0, Location::RequiresRegister()); - - // 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); + locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); if (field_info.IsVolatile() && (field_info.GetFieldType() == Primitive::kPrimLong)) { // Long values can be loaded atomically into an XMM using movsd. @@ -2895,7 +2827,6 @@ void InstructionCodeGeneratorX86::HandleFieldGet(HInstruction* instruction, __ 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)); @@ -3133,11 +3064,7 @@ void LocationsBuilderX86::VisitArrayGet(HArrayGet* instruction) { new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall); locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1))); - // 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); + locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); } void InstructionCodeGeneratorX86::VisitArrayGet(HArrayGet* instruction) { @@ -3211,7 +3138,6 @@ 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)); @@ -3643,7 +3569,8 @@ void ParallelMoveResolverX86::EmitMove(size_t index) { DCHECK(destination.IsStackSlot()) << destination; __ movl(Address(ESP, destination.GetStackIndex()), Immediate(value)); } - } else if (constant->IsFloatConstant()) { + } else { + DCHECK(constant->IsFloatConstant()); float value = constant->AsFloatConstant()->GetValue(); Immediate imm(bit_cast<float, int32_t>(value)); if (destination.IsFpuRegister()) { @@ -3656,43 +3583,6 @@ void ParallelMoveResolverX86::EmitMove(size_t index) { 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; @@ -3760,33 +3650,6 @@ void ParallelMoveResolverX86::EmitSwap(size_t index) { 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; } @@ -4088,7 +3951,7 @@ void InstructionCodeGeneratorX86::HandleBitwiseOperation(HBinaryOperation* instr __ xorl(first.AsRegisterPairLow<Register>(), second.AsRegisterPairLow<Register>()); __ xorl(first.AsRegisterPairHigh<Register>(), second.AsRegisterPairHigh<Register>()); } - } else if (second.IsDoubleStackSlot()) { + } else { if (instruction->IsAnd()) { __ andl(first.AsRegisterPairLow<Register>(), Address(ESP, second.GetStackIndex())); __ andl(first.AsRegisterPairHigh<Register>(), @@ -4103,22 +3966,6 @@ void InstructionCodeGeneratorX86::HandleBitwiseOperation(HBinaryOperation* instr __ 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); - } } } } diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h index c5763de05e..f5a9b7d1f7 100644 --- a/compiler/optimizing/code_generator_x86.h +++ b/compiler/optimizing/code_generator_x86.h @@ -245,8 +245,6 @@ class CodeGeneratorX86 : public CodeGenerator { return type == Primitive::kPrimLong; } - bool ShouldSplitLongMoves() const OVERRIDE { return true; } - Label* GetFrameEntryLabel() { return &frame_entry_label_; } private: diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h index 566c0daf1e..198cc15cce 100644 --- a/compiler/optimizing/locations.h +++ b/compiler/optimizing/locations.h @@ -211,25 +211,15 @@ class Location : public ValueObject { } Location ToLow() const { - if (IsRegisterPair()) { - return Location::RegisterLocation(low()); - } else if (IsFpuRegisterPair()) { - return Location::FpuRegisterLocation(low()); - } else { - DCHECK(IsDoubleStackSlot()); - return Location::StackSlot(GetStackIndex()); - } + return IsRegisterPair() + ? Location::RegisterLocation(low()) + : Location::FpuRegisterLocation(low()); } Location ToHigh() const { - if (IsRegisterPair()) { - return Location::RegisterLocation(high()); - } else if (IsFpuRegisterPair()) { - return Location::FpuRegisterLocation(high()); - } else { - DCHECK(IsDoubleStackSlot()); - return Location::StackSlot(GetHighStackIndex(4)); - } + return IsRegisterPair() + ? Location::RegisterLocation(high()) + : Location::FpuRegisterLocation(high()); } static uintptr_t EncodeStackIndex(intptr_t stack_index) { diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 6945ff0d53..b7dd756452 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -3289,19 +3289,8 @@ class HParallelMove : public HTemplateInstruction<0> { if (kIsDebugBuild) { if (instruction != nullptr) { for (size_t i = 0, e = moves_.Size(); i < e; ++i) { - if (moves_.Get(i).GetInstruction() == instruction) { - // Special case the situation where the move is for the spill slot - // of the instruction. - if ((GetPrevious() == instruction) - || ((GetPrevious() == nullptr) - && instruction->IsPhi() - && instruction->GetBlock() == GetBlock())) { - DCHECK_NE(destination.GetKind(), moves_.Get(i).GetDestination().GetKind()) - << "Doing parallel moves for the same instruction."; - } else { - DCHECK(false) << "Doing parallel moves for the same instruction."; - } - } + DCHECK_NE(moves_.Get(i).GetInstruction(), instruction) + << "Doing parallel moves for the same instruction."; } } for (size_t i = 0, e = moves_.Size(); i < e; ++i) { diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 9971daf371..eb984248a9 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -523,7 +523,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, dex_file, dex_compilation_unit, &pass_info_printer); - } else if (shouldOptimize && can_allocate_registers) { + } else if (shouldOptimize && RegisterAllocator::Supports(instruction_set)) { LOG(FATAL) << "Could not allocate registers in optimizing compiler"; UNREACHABLE(); } else { diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc index c1760d192b..54e62a5b2c 100644 --- a/compiler/optimizing/register_allocator.cc +++ b/compiler/optimizing/register_allocator.cc @@ -32,9 +32,6 @@ static constexpr size_t kDefaultNumberOfSpillSlots = 4; // 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, @@ -73,13 +70,28 @@ RegisterAllocator::RegisterAllocator(ArenaAllocator* allocator, reserved_out_slots_ = 1 + codegen->GetGraph()->GetMaximumNumberOfOutVRegs(); } -bool RegisterAllocator::CanAllocateRegistersFor(const HGraph& graph ATTRIBUTE_UNUSED, +bool RegisterAllocator::CanAllocateRegistersFor(const HGraph& graph, InstructionSet instruction_set) { - return instruction_set == kArm64 + if (!Supports(instruction_set)) { + return false; + } + if (instruction_set == kArm64 || instruction_set == kX86_64 || instruction_set == kArm - || instruction_set == kX86 - || instruction_set == kThumb2; + || 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; } static bool ShouldProcess(bool processing_core_registers, LiveInterval* interval) { @@ -759,15 +771,8 @@ bool RegisterAllocator::TryAllocateFreeReg(LiveInterval* current) { 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; - } + if (current->IsLowInterval() && free_until[GetHighForLowRegister(reg)] == 0) { + return false; } current->SetRegister(reg); @@ -826,18 +831,16 @@ int RegisterAllocator::FindAvailableRegister(size_t* next_use) const { return reg; } -bool RegisterAllocator::TrySplitNonPairOrUnalignedPairIntervalAt(size_t position, - size_t first_register_use, - size_t* next_use) { +bool RegisterAllocator::TrySplitNonPairIntervalAt(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 (!active->IsLowInterval() || IsLowOfUnalignedPairInterval(active)) { + if (first_register_use <= next_use[active->GetRegister()] + && !active->IsLowInterval() + && !active->IsHighInterval()) { LiveInterval* split = Split(active, position); active_.DeleteAt(i); if (split != active) { @@ -931,17 +934,14 @@ bool RegisterAllocator::AllocateBlockedReg(LiveInterval* current) { 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 - && TrySplitNonPairOrUnalignedPairIntervalAt(current->GetStart(), - first_register_use, - next_use)) { + && TrySplitNonPairIntervalAt(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 or unaligned pair intervals blocking the allocation. - // We split the first interval found, and put ourselves first in the - // `unhandled_` list. + // non-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); @@ -1203,24 +1203,7 @@ static bool IsValidDestination(Location destination) { || destination.IsDoubleStackSlot(); } -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, +void RegisterAllocator::AddInputMoveFor(HInstruction* user, Location source, Location destination) const { if (source.Equals(destination)) return; @@ -1239,7 +1222,7 @@ void RegisterAllocator::AddInputMoveFor(HInstruction* input, move = previous->AsParallelMove(); } DCHECK_EQ(move->GetLifetimePosition(), user->GetLifetimePosition()); - AddMove(move, source, destination, nullptr, input->GetType()); + move->AddMove(source, destination, nullptr); } static bool IsInstructionStart(size_t position) { @@ -1268,16 +1251,8 @@ void RegisterAllocator::InsertParallelMoveAt(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 `HParallelMove` instructions. + // not contain the moves. 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_); @@ -1319,7 +1294,7 @@ void RegisterAllocator::InsertParallelMoveAt(size_t position, } } DCHECK_EQ(move->GetLifetimePosition(), position); - AddMove(move, source, destination, instruction, instruction->GetType()); + move->AddMove(source, destination, instruction); } void RegisterAllocator::InsertParallelMoveAtExitOf(HBasicBlock* block, @@ -1349,7 +1324,7 @@ void RegisterAllocator::InsertParallelMoveAtExitOf(HBasicBlock* block, } else { move = previous->AsParallelMove(); } - AddMove(move, source, destination, instruction, instruction->GetType()); + move->AddMove(source, destination, instruction); } void RegisterAllocator::InsertParallelMoveAtEntryOf(HBasicBlock* block, @@ -1361,15 +1336,14 @@ 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() != position) { + if (move == nullptr || move->GetLifetimePosition() != block->GetLifetimeStart()) { move = new (allocator_) HParallelMove(allocator_); - move->SetLifetimePosition(position); + move->SetLifetimePosition(block->GetLifetimeStart()); block->InsertInstructionBefore(move, first); } - AddMove(move, source, destination, instruction, instruction->GetType()); + move->AddMove(source, destination, instruction); } void RegisterAllocator::InsertMoveAfter(HInstruction* instruction, @@ -1393,7 +1367,7 @@ void RegisterAllocator::InsertMoveAfter(HInstruction* instruction, move->SetLifetimePosition(position); instruction->GetBlock()->InsertInstructionBefore(move, instruction->GetNext()); } - AddMove(move, source, destination, instruction, instruction->GetType()); + move->AddMove(source, destination, instruction); } void RegisterAllocator::ConnectSiblings(LiveInterval* interval) { @@ -1427,7 +1401,7 @@ void RegisterAllocator::ConnectSiblings(LiveInterval* interval) { if (expected_location.IsUnallocated()) { locations->SetInAt(use->GetInputIndex(), source); } else if (!expected_location.IsConstant()) { - AddInputMoveFor(interval->GetDefinedBy(), use->GetUser(), source, expected_location); + AddInputMoveFor(use->GetUser(), source, expected_location); } } else { DCHECK(use->GetUser()->IsInvoke()); @@ -1674,7 +1648,7 @@ void RegisterAllocator::Resolve() { Location source = input->GetLiveInterval()->GetLocationAt( predecessor->GetLifetimeEnd() - 1); Location destination = phi->GetLiveInterval()->ToLocation(); - InsertParallelMoveAtExitOf(predecessor, phi, source, destination); + InsertParallelMoveAtExitOf(predecessor, nullptr, source, destination); } } } diff --git a/compiler/optimizing/register_allocator.h b/compiler/optimizing/register_allocator.h index fcc61128a6..579f069f5e 100644 --- a/compiler/optimizing/register_allocator.h +++ b/compiler/optimizing/register_allocator.h @@ -66,6 +66,13 @@ class RegisterAllocator { bool log_fatal_on_failure); static bool CanAllocateRegistersFor(const HGraph& graph, InstructionSet instruction_set); + static bool Supports(InstructionSet instruction_set) { + return instruction_set == kArm + || instruction_set == kArm64 + || instruction_set == kThumb2 + || instruction_set == kX86 + || instruction_set == kX86_64; + } size_t GetNumberOfSpillSlots() const { return int_spill_slots_.Size() @@ -114,21 +121,12 @@ class RegisterAllocator { Location source, Location destination) const; void InsertMoveAfter(HInstruction* instruction, Location source, Location destination) const; - void AddInputMoveFor(HInstruction* input, - HInstruction* user, - Location source, - Location destination) const; + void AddInputMoveFor(HInstruction* user, Location source, Location destination) const; void InsertParallelMoveAt(size_t position, HInstruction* instruction, Location source, Location destination) const; - void AddMove(HParallelMove* move, - Location source, - Location destination, - HInstruction* instruction, - Primitive::Type type) const; - // Helper methods. void AllocateRegistersInternal(); void ProcessInstruction(HInstruction* instruction); @@ -138,11 +136,9 @@ class RegisterAllocator { int FindAvailableRegisterPair(size_t* next_use, size_t starting_at) const; int FindAvailableRegister(size_t* next_use) const; - // Try splitting an active non-pair or unaligned pair interval at the given `position`. + // Try splitting an active non-pair interval at the given `position`. // Returns whether it was successful at finding such an interval. - bool TrySplitNonPairOrUnalignedPairIntervalAt(size_t position, - size_t first_register_use, - size_t* next_use); + bool TrySplitNonPairIntervalAt(size_t position, size_t first_register_use, size_t* next_use); ArenaAllocator* const allocator_; CodeGenerator* const codegen_; diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h index 5787f0cc4e..9ff2f205d8 100644 --- a/compiler/optimizing/ssa_liveness_analysis.h +++ b/compiler/optimizing/ssa_liveness_analysis.h @@ -373,17 +373,13 @@ class LiveInterval : public ArenaObject<kArenaAllocMisc> { if (location.IsUnallocated()) { if ((location.GetPolicy() == Location::kRequiresRegister) || (location.GetPolicy() == Location::kSameAsFirstInput - && (locations->InAt(0).IsRegister() - || locations->InAt(0).IsRegisterPair() - || locations->InAt(0).GetPolicy() == Location::kRequiresRegister))) { + && locations->InAt(0).GetPolicy() == Location::kRequiresRegister)) { return position; } else if ((location.GetPolicy() == Location::kRequiresFpuRegister) || (location.GetPolicy() == Location::kSameAsFirstInput && locations->InAt(0).GetPolicy() == Location::kRequiresFpuRegister)) { return position; } - } else if (location.IsRegister() || location.IsRegisterPair()) { - return position; } } |