diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2014-07-11 10:57:49 +0100 |
---|---|---|
committer | Nicolas Geoffray <ngeoffray@google.com> | 2014-07-21 09:54:20 +0100 |
commit | 96f89a290eb67d7bf4b1636798fa28df14309cc7 (patch) | |
tree | ca2b484a18107f8253aa7774cde304586a31bc60 /compiler | |
parent | 4436e926aa8e64ac7e4c4afb81f2a59b2477045a (diff) | |
download | art-96f89a290eb67d7bf4b1636798fa28df14309cc7.tar.gz art-96f89a290eb67d7bf4b1636798fa28df14309cc7.tar.bz2 art-96f89a290eb67d7bf4b1636798fa28df14309cc7.zip |
Add assembly operations with constants in optimizing compiler.
Change-Id: I5bcc35ab50d4457186effef5592a75d7f4e5b65f
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/Android.mk | 2 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 112 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 33 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 92 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/graph_visualizer.cc | 4 | ||||
-rw-r--r-- | compiler/optimizing/locations.cc | 7 | ||||
-rw-r--r-- | compiler/optimizing/locations.h | 46 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 28 | ||||
-rw-r--r-- | compiler/optimizing/register_allocator.cc | 24 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_arm.cc | 5 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_arm.h | 4 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_thumb2.cc | 16 | ||||
-rw-r--r-- | compiler/utils/assembler_thumb_test.cc | 17 | ||||
-rw-r--r-- | compiler/utils/assembler_thumb_test_expected.cc.inc | 4 | ||||
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.cc | 32 | ||||
-rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.h | 4 |
19 files changed, 339 insertions, 103 deletions
diff --git a/compiler/Android.mk b/compiler/Android.mk index 02dad2ae36..ac2f9d6240 100644 --- a/compiler/Android.mk +++ b/compiler/Android.mk @@ -95,8 +95,8 @@ LIBART_COMPILER_SRC_FILES := \ optimizing/register_allocator.cc \ optimizing/ssa_builder.cc \ optimizing/ssa_liveness_analysis.cc \ - optimizing/ssa_type_propagation.cc \ optimizing/ssa_phi_elimination.cc \ + optimizing/ssa_type_propagation.cc \ trampolines/trampoline_compiler.cc \ utils/arena_allocator.cc \ utils/arena_bit_vector.cc \ diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 9d17fb137a..bc1e75ba16 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -378,11 +378,17 @@ void CodeGeneratorARM::Move64(Location destination, Location source) { } void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstruction* move_for) { + LocationSummary* locations = instruction->GetLocations(); + if (locations != nullptr && locations->Out().Equals(location)) { + return; + } + if (instruction->AsIntConstant() != nullptr) { int32_t value = instruction->AsIntConstant()->GetValue(); if (location.IsRegister()) { __ LoadImmediate(location.AsArm().AsCoreRegister(), value); } else { + DCHECK(location.IsStackSlot()); __ LoadImmediate(IP, value); __ str(IP, Address(SP, location.GetStackIndex())); } @@ -392,6 +398,7 @@ void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstr __ LoadImmediate(location.AsArm().AsRegisterPairLow(), Low32Bits(value)); __ LoadImmediate(location.AsArm().AsRegisterPairHigh(), High32Bits(value)); } else { + DCHECK(location.IsDoubleStackSlot()); __ LoadImmediate(IP, Low32Bits(value)); __ str(IP, Address(SP, location.GetStackIndex())); __ LoadImmediate(IP, High32Bits(value)); @@ -425,11 +432,11 @@ void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstr case Primitive::kPrimShort: case Primitive::kPrimNot: case Primitive::kPrimInt: - Move32(location, instruction->GetLocations()->Out()); + Move32(location, locations->Out()); break; case Primitive::kPrimLong: - Move64(location, instruction->GetLocations()->Out()); + Move64(location, locations->Out()); break; default: @@ -479,20 +486,33 @@ void InstructionCodeGeneratorARM::VisitIf(HIf* if_instr) { HCondition* condition = cond->AsCondition(); if (condition->NeedsMaterialization()) { // Condition has been materialized, compare the output to 0 - if (!if_instr->GetLocations()->InAt(0).IsRegister()) { - LOG(FATAL) << "Materialized condition is not in an ARM register"; - } + DCHECK(if_instr->GetLocations()->InAt(0).IsRegister()); __ cmp(if_instr->GetLocations()->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(0)); __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()), EQ); } else { // Condition has not been materialized, use its inputs as the comparison and its // condition as the branch condition. - __ cmp(condition->GetLocations()->InAt(0).AsArm().AsCoreRegister(), - ShifterOperand(condition->GetLocations()->InAt(1).AsArm().AsCoreRegister())); + LocationSummary* locations = condition->GetLocations(); + if (locations->InAt(1).IsRegister()) { + __ cmp(locations->InAt(0).AsArm().AsCoreRegister(), + ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister())); + } else { + DCHECK(locations->InAt(1).IsConstant()); + int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); + ShifterOperand operand; + if (ShifterOperand::CanHoldArm(value, &operand)) { + __ cmp(locations->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(value)); + } else { + Register temp = IP; + __ LoadImmediate(temp, value); + __ cmp(locations->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(temp)); + } + } __ b(codegen_->GetLabelOf(if_instr->IfTrueSuccessor()), ARMCondition(condition->GetCondition())); } + if (!codegen_->GoesToNextBlock(if_instr->GetBlock(), if_instr->IfFalseSuccessor())) { __ b(codegen_->GetLabelOf(if_instr->IfFalseSuccessor())); } @@ -502,7 +522,7 @@ void InstructionCodeGeneratorARM::VisitIf(HIf* if_instr) { void LocationsBuilderARM::VisitCondition(HCondition* comp) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(comp); locations->SetInAt(0, Location::RequiresRegister()); - locations->SetInAt(1, Location::RequiresRegister()); + locations->SetInAt(1, Location::RegisterOrConstant(comp->InputAt(1))); if (comp->NeedsMaterialization()) { locations->SetOut(Location::RequiresRegister()); } @@ -510,16 +530,29 @@ void LocationsBuilderARM::VisitCondition(HCondition* comp) { } void InstructionCodeGeneratorARM::VisitCondition(HCondition* comp) { - if (comp->NeedsMaterialization()) { - LocationSummary* locations = comp->GetLocations(); + if (!comp->NeedsMaterialization()) return; + + LocationSummary* locations = comp->GetLocations(); + if (locations->InAt(1).IsRegister()) { __ cmp(locations->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister())); - __ it(ARMCondition(comp->GetCondition()), kItElse); - __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(1), - ARMCondition(comp->GetCondition())); - __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(0), - ARMOppositeCondition(comp->GetCondition())); + } else { + DCHECK(locations->InAt(1).IsConstant()); + int32_t value = locations->InAt(1).GetConstant()->AsIntConstant()->GetValue(); + ShifterOperand operand; + if (ShifterOperand::CanHoldArm(value, &operand)) { + __ cmp(locations->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(value)); + } else { + Register temp = IP; + __ LoadImmediate(temp, value); + __ cmp(locations->InAt(0).AsArm().AsCoreRegister(), ShifterOperand(temp)); + } } + __ it(ARMCondition(comp->GetCondition()), kItElse); + __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(1), + ARMCondition(comp->GetCondition())); + __ mov(locations->Out().AsArm().AsCoreRegister(), ShifterOperand(0), + ARMOppositeCondition(comp->GetCondition())); } void LocationsBuilderARM::VisitEqual(HEqual* comp) { @@ -612,20 +645,17 @@ void InstructionCodeGeneratorARM::VisitStoreLocal(HStoreLocal* store) { } void LocationsBuilderARM::VisitIntConstant(HIntConstant* constant) { - // TODO: Support constant locations. LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant); - locations->SetOut(Location::RequiresRegister()); + locations->SetOut(Location::ConstantLocation(constant)); constant->SetLocations(locations); } void InstructionCodeGeneratorARM::VisitIntConstant(HIntConstant* constant) { - codegen_->Move(constant, constant->GetLocations()->Out(), nullptr); } void LocationsBuilderARM::VisitLongConstant(HLongConstant* constant) { - // TODO: Support constant locations. LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant); - locations->SetOut(Location::RequiresRegister()); + locations->SetOut(Location::ConstantLocation(constant)); constant->SetLocations(locations); } @@ -762,7 +792,7 @@ void LocationsBuilderARM::VisitAdd(HAdd* add) { case Primitive::kPrimInt: case Primitive::kPrimLong: { locations->SetInAt(0, Location::RequiresRegister()); - locations->SetInAt(1, Location::RequiresRegister()); + locations->SetInAt(1, Location::RegisterOrConstant(add->InputAt(1))); locations->SetOut(Location::RequiresRegister()); break; } @@ -784,9 +814,15 @@ void InstructionCodeGeneratorARM::VisitAdd(HAdd* add) { LocationSummary* locations = add->GetLocations(); switch (add->GetResultType()) { case Primitive::kPrimInt: - __ add(locations->Out().AsArm().AsCoreRegister(), - locations->InAt(0).AsArm().AsCoreRegister(), - ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister())); + if (locations->InAt(1).IsRegister()) { + __ add(locations->Out().AsArm().AsCoreRegister(), + locations->InAt(0).AsArm().AsCoreRegister(), + ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister())); + } else { + __ AddConstant(locations->Out().AsArm().AsCoreRegister(), + locations->InAt(0).AsArm().AsCoreRegister(), + locations->InAt(1).GetConstant()->AsIntConstant()->GetValue()); + } break; case Primitive::kPrimLong: @@ -816,7 +852,7 @@ void LocationsBuilderARM::VisitSub(HSub* sub) { case Primitive::kPrimInt: case Primitive::kPrimLong: { locations->SetInAt(0, Location::RequiresRegister()); - locations->SetInAt(1, Location::RequiresRegister()); + locations->SetInAt(1, Location::RegisterOrConstant(sub->InputAt(1))); locations->SetOut(Location::RequiresRegister()); break; } @@ -837,11 +873,18 @@ void LocationsBuilderARM::VisitSub(HSub* sub) { void InstructionCodeGeneratorARM::VisitSub(HSub* sub) { LocationSummary* locations = sub->GetLocations(); switch (sub->GetResultType()) { - case Primitive::kPrimInt: - __ sub(locations->Out().AsArm().AsCoreRegister(), - locations->InAt(0).AsArm().AsCoreRegister(), - ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister())); + case Primitive::kPrimInt: { + if (locations->InAt(1).IsRegister()) { + __ sub(locations->Out().AsArm().AsCoreRegister(), + locations->InAt(0).AsArm().AsCoreRegister(), + ShifterOperand(locations->InAt(1).AsArm().AsCoreRegister())); + } else { + __ AddConstant(locations->Out().AsArm().AsCoreRegister(), + locations->InAt(0).AsArm().AsCoreRegister(), + -locations->InAt(1).GetConstant()->AsIntConstant()->GetValue()); + } break; + } case Primitive::kPrimLong: __ subs(locations->Out().AsArm().AsRegisterPairLow(), @@ -1161,7 +1204,16 @@ void ParallelMoveResolverARM::EmitMove(size_t index) { __ StoreToOffset(kStoreWord, IP, SP, destination.GetStackIndex()); } } else { - LOG(FATAL) << "Unimplemented"; + DCHECK(source.IsConstant()); + DCHECK(source.GetConstant()->AsIntConstant() != nullptr); + int32_t value = source.GetConstant()->AsIntConstant()->GetValue(); + if (destination.IsRegister()) { + __ LoadImmediate(destination.AsArm().AsCoreRegister(), value); + } else { + DCHECK(destination.IsStackSlot()); + __ LoadImmediate(IP, value); + __ str(IP, Address(SP, destination.GetStackIndex())); + } } } diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h index 3cc16aa3f3..85ab22b178 100644 --- a/compiler/optimizing/code_generator_arm.h +++ b/compiler/optimizing/code_generator_arm.h @@ -89,7 +89,7 @@ class LocationsBuilderARM : public HGraphVisitor { #define DECLARE_VISIT_INSTRUCTION(name) \ virtual void Visit##name(H##name* instr); - FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) + FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) #undef DECLARE_VISIT_INSTRUCTION @@ -107,7 +107,7 @@ class InstructionCodeGeneratorARM : public HGraphVisitor { #define DECLARE_VISIT_INSTRUCTION(name) \ virtual void Visit##name(H##name* instr); - FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) + FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) #undef DECLARE_VISIT_INSTRUCTION diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 4e69a0cad8..af267d82e1 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -473,6 +473,10 @@ void InstructionCodeGeneratorX86::VisitIf(HIf* if_instr) { // LHS is guaranteed to be in a register (see LocationsBuilderX86::VisitCondition). if (rhs.IsRegister()) { __ cmpl(lhs.AsX86().AsCpuRegister(), rhs.AsX86().AsCpuRegister()); + } else if (rhs.IsConstant()) { + HIntConstant* instruction = rhs.GetConstant()->AsIntConstant(); + Immediate imm(instruction->AsIntConstant()->GetValue()); + __ cmpl(lhs.AsX86().AsCpuRegister(), imm); } else { __ cmpl(lhs.AsX86().AsCpuRegister(), Address(ESP, rhs.GetStackIndex())); } @@ -530,7 +534,7 @@ void LocationsBuilderX86::VisitCondition(HCondition* comp) { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::Any()); if (comp->NeedsMaterialization()) { - locations->SetOut(Location::SameAsFirstInput()); + locations->SetOut(Location::RequiresRegister()); } comp->SetLocations(locations); } @@ -541,6 +545,10 @@ void InstructionCodeGeneratorX86::VisitCondition(HCondition* comp) { if (locations->InAt(1).IsRegister()) { __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(), locations->InAt(1).AsX86().AsCpuRegister()); + } else if (locations->InAt(1).IsConstant()) { + HConstant* instruction = locations->InAt(1).GetConstant(); + Immediate imm(instruction->AsIntConstant()->GetValue()); + __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(), imm); } else { __ cmpl(locations->InAt(0).AsX86().AsCpuRegister(), Address(ESP, locations->InAt(1).GetStackIndex())); @@ -598,20 +606,17 @@ void InstructionCodeGeneratorX86::VisitGreaterThanOrEqual(HGreaterThanOrEqual* c } void LocationsBuilderX86::VisitIntConstant(HIntConstant* constant) { - // TODO: Support constant locations. LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant); - locations->SetOut(Location::RequiresRegister()); + locations->SetOut(Location::ConstantLocation(constant)); constant->SetLocations(locations); } void InstructionCodeGeneratorX86::VisitIntConstant(HIntConstant* constant) { - codegen_->Move(constant, constant->GetLocations()->Out(), nullptr); } void LocationsBuilderX86::VisitLongConstant(HLongConstant* constant) { - // TODO: Support constant locations. LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant); - locations->SetOut(Location::RequiresRegister()); + locations->SetOut(Location::ConstantLocation(constant)); constant->SetLocations(locations); } @@ -769,6 +774,10 @@ void InstructionCodeGeneratorX86::VisitAdd(HAdd* add) { if (locations->InAt(1).IsRegister()) { __ addl(locations->InAt(0).AsX86().AsCpuRegister(), locations->InAt(1).AsX86().AsCpuRegister()); + } else if (locations->InAt(1).IsConstant()) { + HConstant* instruction = locations->InAt(1).GetConstant(); + Immediate imm(instruction->AsIntConstant()->GetValue()); + __ addl(locations->InAt(0).AsX86().AsCpuRegister(), imm); } else { __ addl(locations->InAt(0).AsX86().AsCpuRegister(), Address(ESP, locations->InAt(1).GetStackIndex())); @@ -838,6 +847,10 @@ void InstructionCodeGeneratorX86::VisitSub(HSub* sub) { if (locations->InAt(1).IsRegister()) { __ subl(locations->InAt(0).AsX86().AsCpuRegister(), locations->InAt(1).AsX86().AsCpuRegister()); + } else if (locations->InAt(1).IsConstant()) { + HConstant* instruction = locations->InAt(1).GetConstant(); + Immediate imm(instruction->AsIntConstant()->GetValue()); + __ subl(locations->InAt(0).AsX86().AsCpuRegister(), imm); } else { __ subl(locations->InAt(0).AsX86().AsCpuRegister(), Address(ESP, locations->InAt(1).GetStackIndex())); @@ -1178,6 +1191,14 @@ void ParallelMoveResolverX86::EmitMove(size_t index) { MoveMemoryToMemory(destination.GetStackIndex(), source.GetStackIndex()); } + } else if (source.IsConstant()) { + HIntConstant* instruction = source.GetConstant()->AsIntConstant(); + Immediate imm(instruction->AsIntConstant()->GetValue()); + if (destination.IsRegister()) { + __ movl(destination.AsX86().AsCpuRegister(), imm); + } else { + __ movl(Address(ESP, destination.GetStackIndex()), imm); + } } else { LOG(FATAL) << "Unimplemented"; } diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h index d622d2a685..9c12771f44 100644 --- a/compiler/optimizing/code_generator_x86.h +++ b/compiler/optimizing/code_generator_x86.h @@ -90,7 +90,7 @@ class LocationsBuilderX86 : public HGraphVisitor { #define DECLARE_VISIT_INSTRUCTION(name) \ virtual void Visit##name(H##name* instr); - FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) + FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) #undef DECLARE_VISIT_INSTRUCTION @@ -108,7 +108,7 @@ class InstructionCodeGeneratorX86 : public HGraphVisitor { #define DECLARE_VISIT_INSTRUCTION(name) \ virtual void Visit##name(H##name* instr); - FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) + FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) #undef DECLARE_VISIT_INSTRUCTION diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index e3ce5ceb4f..4bda08235c 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -329,7 +329,14 @@ void InstructionCodeGeneratorX86_64::VisitIf(HIf* if_instr) { } else { Location lhs = condition->GetLocations()->InAt(0); Location rhs = condition->GetLocations()->InAt(1); - __ cmpl(lhs.AsX86_64().AsCpuRegister(), rhs.AsX86_64().AsCpuRegister()); + if (rhs.IsRegister()) { + __ cmpl(lhs.AsX86_64().AsCpuRegister(), rhs.AsX86_64().AsCpuRegister()); + } else if (rhs.IsConstant()) { + __ cmpl(lhs.AsX86_64().AsCpuRegister(), + Immediate(rhs.GetConstant()->AsIntConstant()->GetValue())); + } else { + __ cmpl(lhs.AsX86_64().AsCpuRegister(), Address(CpuRegister(RSP), rhs.GetStackIndex())); + } __ j(X86_64Condition(condition->GetCondition()), codegen_->GetLabelOf(if_instr->IfTrueSuccessor())); } @@ -382,7 +389,7 @@ void InstructionCodeGeneratorX86_64::VisitStoreLocal(HStoreLocal* store) { void LocationsBuilderX86_64::VisitCondition(HCondition* comp) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(comp); locations->SetInAt(0, Location::RequiresRegister()); - locations->SetInAt(1, Location::RequiresRegister()); + locations->SetInAt(1, Location::Any()); if (comp->NeedsMaterialization()) { locations->SetOut(Location::RequiresRegister()); } @@ -391,8 +398,17 @@ void LocationsBuilderX86_64::VisitCondition(HCondition* comp) { void InstructionCodeGeneratorX86_64::VisitCondition(HCondition* comp) { if (comp->NeedsMaterialization()) { - __ cmpq(comp->GetLocations()->InAt(0).AsX86_64().AsCpuRegister(), - comp->GetLocations()->InAt(1).AsX86_64().AsCpuRegister()); + LocationSummary* locations = comp->GetLocations(); + if (locations->InAt(1).IsRegister()) { + __ cmpq(locations->InAt(0).AsX86_64().AsCpuRegister(), + locations->InAt(1).AsX86_64().AsCpuRegister()); + } else if (locations->InAt(1).IsConstant()) { + __ cmpq(locations->InAt(0).AsX86_64().AsCpuRegister(), + Immediate(locations->InAt(1).GetConstant()->AsIntConstant()->GetValue())); + } else { + __ cmpq(locations->InAt(0).AsX86_64().AsCpuRegister(), + Address(CpuRegister(RSP), locations->InAt(1).GetStackIndex())); + } __ setcc(X86_64Condition(comp->GetCondition()), comp->GetLocations()->Out().AsX86_64().AsCpuRegister()); } @@ -480,25 +496,21 @@ void InstructionCodeGeneratorX86_64::VisitCompare(HCompare* compare) { } void LocationsBuilderX86_64::VisitIntConstant(HIntConstant* constant) { - // TODO: Support constant locations. LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant); - locations->SetOut(Location::RequiresRegister()); + locations->SetOut(Location::ConstantLocation(constant)); constant->SetLocations(locations); } void InstructionCodeGeneratorX86_64::VisitIntConstant(HIntConstant* constant) { - codegen_->Move(constant, constant->GetLocations()->Out(), nullptr); } void LocationsBuilderX86_64::VisitLongConstant(HLongConstant* constant) { - // TODO: Support constant locations. LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(constant); - locations->SetOut(Location::RequiresRegister()); + locations->SetOut(Location::ConstantLocation(constant)); constant->SetLocations(locations); } void InstructionCodeGeneratorX86_64::VisitLongConstant(HLongConstant* constant) { - codegen_->Move(constant, constant->GetLocations()->Out(), nullptr); } void LocationsBuilderX86_64::VisitReturnVoid(HReturnVoid* ret) { @@ -666,7 +678,12 @@ void InstructionCodeGeneratorX86_64::VisitInvokeStatic(HInvokeStatic* invoke) { void LocationsBuilderX86_64::VisitAdd(HAdd* add) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add); switch (add->GetResultType()) { - case Primitive::kPrimInt: + case Primitive::kPrimInt: { + locations->SetInAt(0, Location::RequiresRegister()); + locations->SetInAt(1, Location::Any()); + locations->SetOut(Location::SameAsFirstInput()); + break; + } case Primitive::kPrimLong: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RequiresRegister()); @@ -693,8 +710,17 @@ void InstructionCodeGeneratorX86_64::VisitAdd(HAdd* add) { locations->Out().AsX86_64().AsCpuRegister().AsRegister()); switch (add->GetResultType()) { case Primitive::kPrimInt: { - __ addl(locations->InAt(0).AsX86_64().AsCpuRegister(), - locations->InAt(1).AsX86_64().AsCpuRegister()); + if (locations->InAt(1).IsRegister()) { + __ addl(locations->InAt(0).AsX86_64().AsCpuRegister(), + locations->InAt(1).AsX86_64().AsCpuRegister()); + } else if (locations->InAt(1).IsConstant()) { + HConstant* instruction = locations->InAt(1).GetConstant(); + Immediate imm(instruction->AsIntConstant()->GetValue()); + __ addl(locations->InAt(0).AsX86_64().AsCpuRegister(), imm); + } else { + __ addl(locations->InAt(0).AsX86_64().AsCpuRegister(), + Address(CpuRegister(RSP), locations->InAt(1).GetStackIndex())); + } break; } case Primitive::kPrimLong: { @@ -718,7 +744,12 @@ void InstructionCodeGeneratorX86_64::VisitAdd(HAdd* add) { void LocationsBuilderX86_64::VisitSub(HSub* sub) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(sub); switch (sub->GetResultType()) { - case Primitive::kPrimInt: + case Primitive::kPrimInt: { + locations->SetInAt(0, Location::RequiresRegister()); + locations->SetInAt(1, Location::Any()); + locations->SetOut(Location::SameAsFirstInput()); + break; + } case Primitive::kPrimLong: { locations->SetInAt(0, Location::RequiresRegister()); locations->SetInAt(1, Location::RequiresRegister()); @@ -745,8 +776,17 @@ void InstructionCodeGeneratorX86_64::VisitSub(HSub* sub) { locations->Out().AsX86_64().AsCpuRegister().AsRegister()); switch (sub->GetResultType()) { case Primitive::kPrimInt: { - __ subl(locations->InAt(0).AsX86_64().AsCpuRegister(), - locations->InAt(1).AsX86_64().AsCpuRegister()); + if (locations->InAt(1).IsRegister()) { + __ subl(locations->InAt(0).AsX86_64().AsCpuRegister(), + locations->InAt(1).AsX86_64().AsCpuRegister()); + } else if (locations->InAt(1).IsConstant()) { + HConstant* instruction = locations->InAt(1).GetConstant(); + Immediate imm(instruction->AsIntConstant()->GetValue()); + __ subl(locations->InAt(0).AsX86_64().AsCpuRegister(), imm); + } else { + __ subl(locations->InAt(0).AsX86_64().AsCpuRegister(), + Address(CpuRegister(RSP), locations->InAt(1).GetStackIndex())); + } break; } case Primitive::kPrimLong: { @@ -1008,6 +1048,26 @@ void ParallelMoveResolverX86_64::EmitMove(size_t index) { __ movq(CpuRegister(TMP), Address(CpuRegister(RSP), source.GetStackIndex())); __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP)); } + } else if (source.IsConstant()) { + HConstant* constant = source.GetConstant(); + if (constant->IsIntConstant()) { + Immediate imm(constant->AsIntConstant()->GetValue()); + if (destination.IsRegister()) { + __ movl(destination.AsX86_64().AsCpuRegister(), imm); + } else { + __ movl(Address(CpuRegister(RSP), destination.GetStackIndex()), imm); + } + } else if (constant->IsLongConstant()) { + int64_t value = constant->AsLongConstant()->GetValue(); + if (destination.IsRegister()) { + __ movq(destination.AsX86_64().AsCpuRegister(), Immediate(value)); + } else { + __ movq(CpuRegister(TMP), Immediate(value)); + __ movq(Address(CpuRegister(RSP), destination.GetStackIndex()), CpuRegister(TMP)); + } + } else { + LOG(FATAL) << "Unimplemented constant type"; + } } else { LOG(FATAL) << "Unimplemented"; } diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h index 8283dda4a5..a20ca3f260 100644 --- a/compiler/optimizing/code_generator_x86_64.h +++ b/compiler/optimizing/code_generator_x86_64.h @@ -87,7 +87,7 @@ class LocationsBuilderX86_64 : public HGraphVisitor { #define DECLARE_VISIT_INSTRUCTION(name) \ virtual void Visit##name(H##name* instr); - FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) + FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) #undef DECLARE_VISIT_INSTRUCTION @@ -105,7 +105,7 @@ class InstructionCodeGeneratorX86_64 : public HGraphVisitor { #define DECLARE_VISIT_INSTRUCTION(name) \ virtual void Visit##name(H##name* instr); - FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) + FOR_EACH_CONCRETE_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) #undef DECLARE_VISIT_INSTRUCTION diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc index f033e2e22b..f011e85cc0 100644 --- a/compiler/optimizing/graph_visualizer.cc +++ b/compiler/optimizing/graph_visualizer.cc @@ -108,6 +108,10 @@ class HGraphVisualizerPrinter : public HGraphVisitor { } else { codegen_.DumpCoreRegister(output_, location.reg().RegId()); } + } else if (location.IsConstant()) { + output_ << "constant"; + } else if (location.IsInvalid()) { + output_ << "invalid"; } else if (location.IsStackSlot()) { output_ << location.GetStackIndex() << "(sp)"; } else { diff --git a/compiler/optimizing/locations.cc b/compiler/optimizing/locations.cc index 98766d2701..468cfb7923 100644 --- a/compiler/optimizing/locations.cc +++ b/compiler/optimizing/locations.cc @@ -29,4 +29,11 @@ LocationSummary::LocationSummary(HInstruction* instruction) } } + +Location Location::RegisterOrConstant(HInstruction* instruction) { + return instruction->IsConstant() + ? Location::ConstantLocation(instruction->AsConstant()) + : Location::RequiresRegister(); +} + } // namespace art diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h index 40a39ad80d..aaddb099a6 100644 --- a/compiler/optimizing/locations.h +++ b/compiler/optimizing/locations.h @@ -24,6 +24,7 @@ namespace art { +class HConstant; class HInstruction; /** @@ -34,23 +35,33 @@ class Location : public ValueObject { public: enum Kind { kInvalid = 0, - kStackSlot = 1, // Word size slot. - kDoubleStackSlot = 2, // 64bit stack slot. - kRegister = 3, + kConstant = 1, + kStackSlot = 2, // Word size slot. + kDoubleStackSlot = 3, // 64bit stack slot. + kRegister = 4, // On 32bits architectures, quick can pass a long where the // low bits are in the last parameter register, and the high // bits are in a stack slot. The kQuickParameter kind is for // handling this special case. - kQuickParameter = 4, + kQuickParameter = 5, // Unallocated location represents a location that is not fixed and can be // allocated by a register allocator. Each unallocated location has // a policy that specifies what kind of location is suitable. Payload // contains register allocation policy. - kUnallocated = 5, + kUnallocated = 6, }; Location() : value_(kInvalid) { + // Verify that non-tagged location kinds do not interfere with kConstantTag. + COMPILE_ASSERT((kInvalid & kLocationTagMask) != kConstant, TagError); + COMPILE_ASSERT((kUnallocated & kLocationTagMask) != kConstant, TagError); + COMPILE_ASSERT((kStackSlot & kLocationTagMask) != kConstant, TagError); + COMPILE_ASSERT((kDoubleStackSlot & kLocationTagMask) != kConstant, TagError); + COMPILE_ASSERT((kRegister & kLocationTagMask) != kConstant, TagError); + COMPILE_ASSERT((kConstant & kLocationTagMask) == kConstant, TagError); + COMPILE_ASSERT((kQuickParameter & kLocationTagMask) == kConstant, TagError); + DCHECK(!IsValid()); } @@ -61,6 +72,20 @@ class Location : public ValueObject { return *this; } + bool IsConstant() const { + return (value_ & kLocationTagMask) == kConstant; + } + + static Location ConstantLocation(HConstant* constant) { + DCHECK(constant != nullptr); + return Location(kConstant | reinterpret_cast<uword>(constant)); + } + + HConstant* GetConstant() const { + DCHECK(IsConstant()); + return reinterpret_cast<HConstant*>(value_ & ~kLocationTagMask); + } + bool IsValid() const { return value_ != kInvalid; } @@ -69,11 +94,6 @@ class Location : public ValueObject { return !IsValid(); } - bool IsConstant() const { - // TODO: support constants. - return false; - } - // Empty location. Used if there the location should be ignored. static Location NoLocation() { return Location(); @@ -162,12 +182,13 @@ class Location : public ValueObject { const char* DebugString() const { switch (GetKind()) { - case kInvalid: return "?"; + case kInvalid: return "I"; case kRegister: return "R"; case kStackSlot: return "S"; case kDoubleStackSlot: return "DS"; case kQuickParameter: return "Q"; case kUnallocated: return "U"; + case kConstant: return "C"; } return "?"; } @@ -196,6 +217,8 @@ class Location : public ValueObject { return UnallocatedLocation(kRequiresRegister); } + static Location RegisterOrConstant(HInstruction* instruction); + // The location of the first input to the instruction will be // used to replace this unallocated location. static Location SameAsFirstInput() { @@ -215,6 +238,7 @@ class Location : public ValueObject { // Number of bits required to encode Kind value. static constexpr uint32_t kBitsForKind = 4; static constexpr uint32_t kBitsForPayload = kWordSize * kBitsPerByte - kBitsForKind; + static constexpr uword kLocationTagMask = 0x3; explicit Location(uword value) : value_(value) {} diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index e87b044cc9..61a6f6b1b6 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -408,7 +408,7 @@ class HBasicBlock : public ArenaObject { DISALLOW_COPY_AND_ASSIGN(HBasicBlock); }; -#define FOR_EACH_INSTRUCTION(M) \ +#define FOR_EACH_CONCRETE_INSTRUCTION(M) \ M(Add) \ M(Condition) \ M(Equal) \ @@ -440,6 +440,9 @@ class HBasicBlock : public ArenaObject { M(NullCheck) \ M(Temporary) \ +#define FOR_EACH_INSTRUCTION(M) \ + FOR_EACH_CONCRETE_INSTRUCTION(M) \ + M(Constant) #define FORWARD_DECLARATION(type) class H##type; FOR_EACH_INSTRUCTION(FORWARD_DECLARATION) @@ -1078,11 +1081,21 @@ class HStoreLocal : public HTemplateInstruction<2> { DISALLOW_COPY_AND_ASSIGN(HStoreLocal); }; +class HConstant : public HExpression<0> { + public: + explicit HConstant(Primitive::Type type) : HExpression(type) {} + + DECLARE_INSTRUCTION(Constant); + + private: + DISALLOW_COPY_AND_ASSIGN(HConstant); +}; + // Constants of the type int. Those can be from Dex instructions, or // synthesized (for example with the if-eqz instruction). -class HIntConstant : public HExpression<0> { +class HIntConstant : public HConstant { public: - explicit HIntConstant(int32_t value) : HExpression(Primitive::kPrimInt), value_(value) {} + explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {} int32_t GetValue() const { return value_; } @@ -1094,14 +1107,12 @@ class HIntConstant : public HExpression<0> { DISALLOW_COPY_AND_ASSIGN(HIntConstant); }; -class HLongConstant : public HExpression<0> { +class HLongConstant : public HConstant { public: - explicit HLongConstant(int64_t value) : HExpression(Primitive::kPrimLong), value_(value) {} + explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {} int64_t GetValue() const { return value_; } - virtual Primitive::Type GetType() const { return Primitive::kPrimLong; } - DECLARE_INSTRUCTION(LongConstant); private: @@ -1278,13 +1289,12 @@ class HPhi : public HInstruction { DECLARE_INSTRUCTION(Phi); - protected: + private: GrowableArray<HInstruction*> inputs_; const uint32_t reg_number_; Primitive::Type type_; bool is_live_; - private: DISALLOW_COPY_AND_ASSIGN(HPhi); }; diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc index 68130dd5fc..bd3a7d9767 100644 --- a/compiler/optimizing/register_allocator.cc +++ b/compiler/optimizing/register_allocator.cc @@ -153,13 +153,13 @@ void RegisterAllocator::AllocateRegistersInternal() { if (current->HasRegister()) { DCHECK(instruction->IsParameterValue()); inactive_.Add(current); - } else if (current->HasSpillSlot()) { - DCHECK(instruction->IsParameterValue()); + } else if (current->HasSpillSlot() || instruction->IsConstant()) { // Split before first register use. size_t first_register_use = current->FirstRegisterUse(); if (first_register_use != kNoLifetime) { LiveInterval* split = Split(current, first_register_use - 1); - // The new interval may start at a late + // Don't add direclty to `unhandled_`, it needs to be sorted and the start + // of this new interval might be after intervals already in the list. AddToUnhandled(split); } else { // Nothing to do, we won't allocate a register for this value. @@ -579,6 +579,11 @@ void RegisterAllocator::AllocateSpillSlotFor(LiveInterval* interval) { return; } + if (defined_by->IsConstant()) { + // Constants don't need a spill slot. + return; + } + LiveInterval* last_sibling = interval; while (last_sibling->GetNextSibling() != nullptr) { last_sibling = last_sibling->GetNextSibling(); @@ -644,11 +649,16 @@ static Location ConvertToLocation(LiveInterval* interval) { if (interval->HasRegister()) { return Location::RegisterLocation(ManagedRegister(interval->GetRegister())); } else { - DCHECK(interval->GetParent()->HasSpillSlot()); - if (NeedTwoSpillSlot(interval->GetType())) { - return Location::DoubleStackSlot(interval->GetParent()->GetSpillSlot()); + HInstruction* defined_by = interval->GetParent()->GetDefinedBy(); + if (defined_by->IsConstant()) { + return defined_by->GetLocations()->Out(); } else { - return Location::StackSlot(interval->GetParent()->GetSpillSlot()); + DCHECK(interval->GetParent()->HasSpillSlot()); + if (NeedTwoSpillSlot(interval->GetType())) { + return Location::DoubleStackSlot(interval->GetParent()->GetSpillSlot()); + } else { + return Location::StackSlot(interval->GetParent()->GetSpillSlot()); + } } } } diff --git a/compiler/utils/arm/assembler_arm.cc b/compiler/utils/arm/assembler_arm.cc index 5fe82468b9..671ccb642c 100644 --- a/compiler/utils/arm/assembler_arm.cc +++ b/compiler/utils/arm/assembler_arm.cc @@ -73,6 +73,11 @@ std::ostream& operator<<(std::ostream& os, const Condition& rhs) { return os; } +ShifterOperand::ShifterOperand(uint32_t immed) + : type_(kImmediate), rm_(kNoRegister), rs_(kNoRegister), + is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(immed) { + CHECK(immed < (1u << 12) || ArmAssembler::ModifiedImmediate(immed) != kInvalidModifiedImmediate); +} uint32_t ShifterOperand::encodingArm() const { diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h index be19174093..54965f678f 100644 --- a/compiler/utils/arm/assembler_arm.h +++ b/compiler/utils/arm/assembler_arm.h @@ -35,9 +35,7 @@ class ShifterOperand { is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(0) { } - explicit ShifterOperand(uint32_t immed) : type_(kImmediate), rm_(kNoRegister), rs_(kNoRegister), - is_rotate_(false), is_shift_(false), shift_(kNoShift), rotate_(0), immed_(immed) { - } + explicit ShifterOperand(uint32_t immed); // Data-processing operands - Register explicit ShifterOperand(Register rm) : type_(kRegister), rm_(rm), rs_(kNoRegister), diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc index 2ce4fd22bd..c693ec0fe1 100644 --- a/compiler/utils/arm/assembler_thumb2.cc +++ b/compiler/utils/arm/assembler_thumb2.cc @@ -619,7 +619,8 @@ bool Thumb2Assembler::Is32BitDataProcessing(Condition cond, return true; } - bool can_contain_high_register = opcode == MOV || opcode == ADD || opcode == SUB; + bool can_contain_high_register = (opcode == MOV) + || ((opcode == ADD || opcode == SUB) && (rn == rd)); if (IsHighRegister(rd) || IsHighRegister(rn)) { if (can_contain_high_register) { @@ -757,23 +758,21 @@ void Thumb2Assembler::Emit32BitDataProcessing(Condition cond, int32_t encoding = 0; if (so.IsImmediate()) { // Check special cases. - if ((opcode == SUB || opcode == ADD) && rn == SP) { - // There are special ADD/SUB rd, SP, #imm12 instructions. + if ((opcode == SUB || opcode == ADD) && (so.GetImmediate() < (1u << 12))) { if (opcode == SUB) { thumb_opcode = 0b0101; } else { thumb_opcode = 0; } uint32_t imm = so.GetImmediate(); - CHECK_LT(imm, (1u << 12)); uint32_t i = (imm >> 11) & 1; uint32_t imm3 = (imm >> 8) & 0b111; uint32_t imm8 = imm & 0xff; encoding = B31 | B30 | B29 | B28 | B25 | - B19 | B18 | B16 | thumb_opcode << 21 | + rn << 16 | rd << 8 | i << 26 | imm3 << 12 | @@ -882,7 +881,12 @@ void Thumb2Assembler::Emit16BitDataProcessing(Condition cond, } break; - case CMN: thumb_opcode = 0b1011; rn = so.GetRegister(); break; + case CMN: { + thumb_opcode = 0b1011; + rd = rn; + rn = so.GetRegister(); + break; + } case ORR: thumb_opcode = 0b1100; break; case MOV: dp_opcode = 0; diff --git a/compiler/utils/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc index 68cb6569b1..25928da39c 100644 --- a/compiler/utils/assembler_thumb_test.cc +++ b/compiler/utils/assembler_thumb_test.cc @@ -14,7 +14,10 @@ * limitations under the License. */ +#include <dirent.h> #include <fstream> +#include <sys/types.h> +#include <map> #include "gtest/gtest.h" #include "utils/arm/assembler_thumb2.h" @@ -40,6 +43,8 @@ namespace arm { static constexpr bool kPrintResults = false; #endif +static const char* TOOL_PREFIX = "arm-linux-androideabi-"; + void SetAndroidData() { const char* data = getenv("ANDROID_DATA"); if (data == nullptr) { @@ -109,9 +114,9 @@ std::string GetAndroidToolsDir() { // Suffix on toolsdir will be something like "arm-eabi-4.8" while ((entry = readdir(dir)) != nullptr) { std::string subdir = toolsdir + std::string("/") + std::string(entry->d_name); - size_t eabi = subdir.find("arm-eabi-"); + size_t eabi = subdir.find(TOOL_PREFIX); if (eabi != std::string::npos) { - std::string suffix = subdir.substr(eabi + sizeof("arm-eabi-")); + std::string suffix = subdir.substr(eabi + sizeof(TOOL_PREFIX)); double version = strtod(suffix.c_str(), nullptr); if (version > maxversion) { maxversion = version; @@ -169,19 +174,19 @@ void dump(std::vector<uint8_t>& code, const char* testname) { char cmd[256]; // Assemble the .S - snprintf(cmd, sizeof(cmd), "%sarm-eabi-as %s -o %s.o", toolsdir.c_str(), filename, filename); + snprintf(cmd, sizeof(cmd), "%s%sas %s -o %s.o", toolsdir.c_str(), TOOL_PREFIX, filename, filename); system(cmd); // Remove the $d symbols to prevent the disassembler dumping the instructions // as .word - snprintf(cmd, sizeof(cmd), "%sarm-eabi-objcopy -N '$d' %s.o %s.oo", toolsdir.c_str(), + snprintf(cmd, sizeof(cmd), "%s%sobjcopy -N '$d' %s.o %s.oo", toolsdir.c_str(), TOOL_PREFIX, filename, filename); system(cmd); // Disassemble. - snprintf(cmd, sizeof(cmd), "%sarm-eabi-objdump -d %s.oo | grep '^ *[0-9a-f][0-9a-f]*:'", - toolsdir.c_str(), filename); + snprintf(cmd, sizeof(cmd), "%s%sobjdump -d %s.oo | grep '^ *[0-9a-f][0-9a-f]*:'", + toolsdir.c_str(), TOOL_PREFIX, filename); if (kPrintResults) { // Print the results only, don't check. This is used to generate new output for inserting // into the .inc file. diff --git a/compiler/utils/assembler_thumb_test_expected.cc.inc b/compiler/utils/assembler_thumb_test_expected.cc.inc index 3943e3713b..18035f391c 100644 --- a/compiler/utils/assembler_thumb_test_expected.cc.inc +++ b/compiler/utils/assembler_thumb_test_expected.cc.inc @@ -48,8 +48,8 @@ const char* DataProcessingRegisterResults[] = { const char* DataProcessingImmediateResults[] = { " 0: 2055 movs r0, #85 ; 0x55\n", " 2: f06f 0055 mvn.w r0, #85 ; 0x55\n", - " 6: f101 0055 add.w r0, r1, #85 ; 0x55\n", - " a: f1a1 0055 sub.w r0, r1, #85 ; 0x55\n", + " 6: f201 0055 addw r0, r1, #85 ; 0x55\n", + " a: f2a1 0055 subw r0, r1, #85 ; 0x55\n", " e: f001 0055 and.w r0, r1, #85 ; 0x55\n", " 12: f041 0055 orr.w r0, r1, #85 ; 0x55\n", " 16: f081 0055 eor.w r0, r1, #85 ; 0x55\n", diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc index 78738d8934..fe9349be33 100644 --- a/compiler/utils/x86_64/assembler_x86_64.cc +++ b/compiler/utils/x86_64/assembler_x86_64.cc @@ -869,6 +869,22 @@ void X86_64Assembler::cmpq(CpuRegister reg0, CpuRegister reg1) { } +void X86_64Assembler::cmpq(CpuRegister reg, const Immediate& imm) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + CHECK(imm.is_int32()); // cmpq only supports 32b immediate. + EmitRex64(reg); + EmitComplex(7, Operand(reg), imm); +} + + +void X86_64Assembler::cmpq(CpuRegister reg, const Address& address) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitRex64(reg); + EmitUint8(0x3B); + EmitOperand(reg.LowBits(), address); +} + + void X86_64Assembler::addl(CpuRegister dst, CpuRegister src) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitOptionalRex32(dst, src); @@ -1063,6 +1079,14 @@ void X86_64Assembler::addq(CpuRegister reg, const Immediate& imm) { } +void X86_64Assembler::addq(CpuRegister dst, const Address& address) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitRex64(dst); + EmitUint8(0x03); + EmitOperand(dst.LowBits(), address); +} + + void X86_64Assembler::addq(CpuRegister dst, CpuRegister src) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); // 0x01 is addq r/m64 <- r/m64 + r64, with op1 in r/m and op2 in reg: so reverse EmitRex64 @@ -1118,6 +1142,14 @@ void X86_64Assembler::subq(CpuRegister dst, CpuRegister src) { } +void X86_64Assembler::subq(CpuRegister reg, const Address& address) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitRex64(reg); + EmitUint8(0x2B); + EmitOperand(reg.LowBits() & 7, address); +} + + void X86_64Assembler::subl(CpuRegister reg, const Address& address) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitOptionalRex32(reg, address); diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h index 7514854829..330d2d58d9 100644 --- a/compiler/utils/x86_64/assembler_x86_64.h +++ b/compiler/utils/x86_64/assembler_x86_64.h @@ -385,6 +385,8 @@ class X86_64Assembler FINAL : public Assembler { void cmpl(const Address& address, const Immediate& imm); void cmpq(CpuRegister reg0, CpuRegister reg1); + void cmpq(CpuRegister reg0, const Immediate& imm); + void cmpq(CpuRegister reg0, const Address& address); void testl(CpuRegister reg1, CpuRegister reg2); void testl(CpuRegister reg, const Immediate& imm); @@ -408,6 +410,7 @@ class X86_64Assembler FINAL : public Assembler { void addq(CpuRegister reg, const Immediate& imm); void addq(CpuRegister dst, CpuRegister src); + void addq(CpuRegister dst, const Address& address); void subl(CpuRegister dst, CpuRegister src); void subl(CpuRegister reg, const Immediate& imm); @@ -415,6 +418,7 @@ class X86_64Assembler FINAL : public Assembler { void subq(CpuRegister reg, const Immediate& imm); void subq(CpuRegister dst, CpuRegister src); + void subq(CpuRegister dst, const Address& address); void cdq(); |