diff options
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/builder.cc | 13 | ||||
-rw-r--r-- | compiler/optimizing/builder.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 88 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm64.cc | 1 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 85 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 86 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 23 |
7 files changed, 300 insertions, 0 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index d168fc80f..4ce23d725 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -273,6 +273,14 @@ void HGraphBuilder::Unop_12x(const Instruction& instruction, Primitive::Type typ UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); } +void HGraphBuilder::Conversion_12x(const Instruction& instruction, + Primitive::Type input_type, + Primitive::Type result_type) { + HInstruction* first = LoadLocal(instruction.VRegB(), input_type); + current_block_->AddInstruction(new (arena_) HTypeConversion(result_type, first)); + UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction()); +} + template<typename T> void HGraphBuilder::Binop_23x(const Instruction& instruction, Primitive::Type type) { HInstruction* first = LoadLocal(instruction.VRegB(), type); @@ -823,6 +831,11 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 break; } + case Instruction::INT_TO_LONG: { + Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimLong); + break; + } + case Instruction::ADD_INT: { Binop_23x<HAdd>(instruction, Primitive::kPrimInt); break; diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h index eea762f83..f25415bc3 100644 --- a/compiler/optimizing/builder.h +++ b/compiler/optimizing/builder.h @@ -116,6 +116,10 @@ class HGraphBuilder : public ValueObject { template<typename T> void If_21t(const Instruction& instruction, uint32_t dex_offset); template<typename T> void If_22t(const Instruction& instruction, uint32_t dex_offset); + void Conversion_12x(const Instruction& instruction, + Primitive::Type input_type, + Primitive::Type result_type); + void BuildReturn(const Instruction& instruction, Primitive::Type type); // Builds an instance field access node and returns whether the instruction is supported. diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 6e6d64cbf..39e564a7c 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -1223,6 +1223,94 @@ void InstructionCodeGeneratorARM::VisitNeg(HNeg* neg) { } } +void LocationsBuilderARM::VisitTypeConversion(HTypeConversion* conversion) { + LocationSummary* locations = + new (GetGraph()->GetArena()) LocationSummary(conversion, LocationSummary::kNoCall); + Primitive::Type result_type = conversion->GetResultType(); + Primitive::Type input_type = conversion->GetInputType(); + switch (result_type) { + case Primitive::kPrimLong: + switch (input_type) { + case Primitive::kPrimByte: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + // int-to-long conversion. + locations->SetInAt(0, Location::RequiresRegister()); + locations->SetOut(Location::RequiresRegister(), Location::kNoOutputOverlap); + break; + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type << " to " + << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } + break; + + case Primitive::kPrimInt: + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type + << " to " << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } +} + +void InstructionCodeGeneratorARM::VisitTypeConversion(HTypeConversion* conversion) { + LocationSummary* locations = conversion->GetLocations(); + Location out = locations->Out(); + Location in = locations->InAt(0); + Primitive::Type result_type = conversion->GetResultType(); + Primitive::Type input_type = conversion->GetInputType(); + switch (result_type) { + case Primitive::kPrimLong: + switch (input_type) { + case Primitive::kPrimByte: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + // int-to-long conversion. + DCHECK(out.IsRegisterPair()); + DCHECK(in.IsRegister()); + __ Mov(out.AsRegisterPairLow<Register>(), in.As<Register>()); + // Sign extension. + __ Asr(out.AsRegisterPairHigh<Register>(), + out.AsRegisterPairLow<Register>(), + 31); + break; + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type << " to " + << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } + break; + + case Primitive::kPrimInt: + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type + << " to " << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } +} + void LocationsBuilderARM::VisitAdd(HAdd* add) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add, LocationSummary::kNoCall); diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index 90d7c3597..1c5db9e15 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -545,6 +545,7 @@ InstructionCodeGeneratorARM64::InstructionCodeGeneratorARM64(HGraph* graph, M(ParallelMove) \ M(StaticFieldGet) \ M(StaticFieldSet) \ + M(TypeConversion) \ #define UNIMPLEMENTED_INSTRUCTION_BREAK_CODE(name) name##UnimplementedInstructionBreakCode diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 1e37909be..8132e8179 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -1126,6 +1126,91 @@ void InstructionCodeGeneratorX86::VisitNeg(HNeg* neg) { } } +void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { + LocationSummary* locations = + new (GetGraph()->GetArena()) LocationSummary(conversion, LocationSummary::kNoCall); + Primitive::Type result_type = conversion->GetResultType(); + Primitive::Type input_type = conversion->GetInputType(); + switch (result_type) { + case Primitive::kPrimLong: + switch (input_type) { + case Primitive::kPrimByte: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + // int-to-long conversion. + locations->SetInAt(0, Location::RegisterLocation(EAX)); + locations->SetOut(Location::RegisterPairLocation(EAX, EDX)); + break; + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type << " to " + << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } + break; + + case Primitive::kPrimInt: + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type + << " to " << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } +} + +void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversion) { + LocationSummary* locations = conversion->GetLocations(); + Location out = locations->Out(); + Location in = locations->InAt(0); + Primitive::Type result_type = conversion->GetResultType(); + Primitive::Type input_type = conversion->GetInputType(); + switch (result_type) { + case Primitive::kPrimLong: + switch (input_type) { + case Primitive::kPrimByte: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + // int-to-long conversion. + DCHECK_EQ(out.AsRegisterPairLow<Register>(), EAX); + DCHECK_EQ(out.AsRegisterPairHigh<Register>(), EDX); + DCHECK_EQ(in.As<Register>(), EAX); + __ cdq(); + break; + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type << " to " + << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } + break; + + case Primitive::kPrimInt: + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type + << " to " << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } +} + void LocationsBuilderX86::VisitAdd(HAdd* add) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add, LocationSummary::kNoCall); diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 40eec9b15..d9eb17c0e 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -1104,6 +1104,92 @@ void InstructionCodeGeneratorX86_64::VisitNeg(HNeg* neg) { } } +void LocationsBuilderX86_64::VisitTypeConversion(HTypeConversion* conversion) { + LocationSummary* locations = + new (GetGraph()->GetArena()) LocationSummary(conversion, LocationSummary::kNoCall); + Primitive::Type result_type = conversion->GetResultType(); + Primitive::Type input_type = conversion->GetInputType(); + switch (result_type) { + case Primitive::kPrimLong: + switch (input_type) { + case Primitive::kPrimByte: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + // int-to-long conversion. + // TODO: We would benefit from a (to-be-implemented) + // Location::RegisterOrStackSlot requirement for this input. + locations->SetInAt(0, Location::RequiresRegister()); + locations->SetOut(Location::RequiresRegister()); + break; + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type << " to " + << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } + break; + + case Primitive::kPrimInt: + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type + << " to " << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } +} + +void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conversion) { + LocationSummary* locations = conversion->GetLocations(); + Location out = locations->Out(); + Location in = locations->InAt(0); + Primitive::Type result_type = conversion->GetResultType(); + Primitive::Type input_type = conversion->GetInputType(); + switch (result_type) { + case Primitive::kPrimLong: + switch (input_type) { + DCHECK(out.IsRegister()); + case Primitive::kPrimByte: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + // int-to-long conversion. + DCHECK(in.IsRegister()); + __ movsxd(out.As<CpuRegister>(), in.As<CpuRegister>()); + break; + + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type << " to " + << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } + break; + + case Primitive::kPrimInt: + case Primitive::kPrimFloat: + case Primitive::kPrimDouble: + LOG(FATAL) << "Type conversion from " << input_type + << " to " << result_type << " not yet implemented"; + break; + + default: + LOG(FATAL) << "Unexpected type conversion from " << input_type + << " to " << result_type; + } +} + void LocationsBuilderX86_64::VisitAdd(HAdd* add) { LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(add, LocationSummary::kNoCall); diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 79638b354..d7069ca31 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -516,6 +516,7 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { M(Sub, BinaryOperation) \ M(SuspendCheck, Instruction) \ M(Temporary, Instruction) \ + M(TypeConversion, Instruction) \ #define FOR_EACH_INSTRUCTION(M) \ FOR_EACH_CONCRETE_INSTRUCTION(M) \ @@ -1761,6 +1762,28 @@ class HNot : public HUnaryOperation { DISALLOW_COPY_AND_ASSIGN(HNot); }; +class HTypeConversion : public HExpression<1> { + public: + // Instantiate a type conversion of `input` to `result_type`. + HTypeConversion(Primitive::Type result_type, HInstruction* input) + : HExpression(result_type, SideEffects::None()) { + SetRawInputAt(0, input); + DCHECK_NE(input->GetType(), result_type); + } + + HInstruction* GetInput() const { return InputAt(0); } + Primitive::Type GetInputType() const { return GetInput()->GetType(); } + Primitive::Type GetResultType() const { return GetType(); } + + bool CanBeMoved() const OVERRIDE { return true; } + bool InstructionDataEquals(HInstruction* /* other */) const OVERRIDE { return true; } + + DECLARE_INSTRUCTION(TypeConversion); + + private: + DISALLOW_COPY_AND_ASSIGN(HTypeConversion); +}; + class HPhi : public HInstruction { public: HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type) |