diff options
-rw-r--r-- | compiler/optimizing/builder.cc | 5 | ||||
-rw-r--r-- | compiler/optimizing/code_generator.h | 3 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 16 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86.cc | 32 | ||||
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 32 | ||||
-rw-r--r-- | test/422-type-conversion/src/Main.java | 32 |
6 files changed, 117 insertions, 3 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 23c3b390c0..eb6181c711 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -1108,6 +1108,11 @@ bool HGraphBuilder::AnalyzeDexInstruction(const Instruction& instruction, uint32 break; } + case Instruction::FLOAT_TO_INT: { + Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimInt); + break; + } + case Instruction::INT_TO_BYTE: { Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimByte); break; diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index 4c0d3ea960..7c8f6a2d29 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -35,6 +35,9 @@ static int64_t constexpr k2Pow32EncodingForDouble = INT64_C(0x41F0000000000000); // Binary encoding of 2^31 for type double. static int64_t constexpr k2Pow31EncodingForDouble = INT64_C(0x41E0000000000000); +// Maximum value for a primitive integer. +static int32_t constexpr kPrimIntMax = 0x7fffffff; + class Assembler; class CodeGenerator; class DexCompilationUnit; diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 5b2be2e9a1..448a5a0707 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -1406,6 +1406,12 @@ void LocationsBuilderARM::VisitTypeConversion(HTypeConversion* conversion) { break; case Primitive::kPrimFloat: + // Processing a Dex `float-to-int' instruction. + locations->SetInAt(0, Location::RequiresFpuRegister()); + locations->SetOut(Location::RequiresRegister()); + locations->AddTemp(Location::RequiresFpuRegister()); + break; + case Primitive::kPrimDouble: LOG(FATAL) << "Type conversion from " << input_type << " to " << result_type << " not yet implemented"; @@ -1580,7 +1586,15 @@ void InstructionCodeGeneratorARM::VisitTypeConversion(HTypeConversion* conversio } break; - case Primitive::kPrimFloat: + case Primitive::kPrimFloat: { + // Processing a Dex `float-to-int' instruction. + SRegister temp = locations->GetTemp(0).AsFpuRegisterPairLow<SRegister>(); + __ vmovs(temp, in.AsFpuRegister<SRegister>()); + __ vcvtis(temp, temp); + __ vmovrs(out.AsRegister<Register>(), temp); + break; + } + case Primitive::kPrimDouble: LOG(FATAL) << "Type conversion from " << input_type << " to " << result_type << " not yet implemented"; diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index fd794f95d1..6f83d9faf4 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -1373,6 +1373,12 @@ void LocationsBuilderX86::VisitTypeConversion(HTypeConversion* conversion) { break; case Primitive::kPrimFloat: + // Processing a Dex `float-to-int' instruction. + locations->SetInAt(0, Location::RequiresFpuRegister()); + locations->SetOut(Location::RequiresRegister()); + locations->AddTemp(Location::RequiresFpuRegister()); + break; + case Primitive::kPrimDouble: LOG(FATAL) << "Type conversion from " << input_type << " to " << result_type << " not yet implemented"; @@ -1559,7 +1565,31 @@ void InstructionCodeGeneratorX86::VisitTypeConversion(HTypeConversion* conversio } break; - case Primitive::kPrimFloat: + case Primitive::kPrimFloat: { + // Processing a Dex `float-to-int' instruction. + XmmRegister input = in.AsFpuRegister<XmmRegister>(); + Register output = out.AsRegister<Register>(); + XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); + Label done, nan; + + __ movl(output, Immediate(kPrimIntMax)); + // temp = int-to-float(output) + __ cvtsi2ss(temp, output); + // if input >= temp goto done + __ comiss(input, temp); + __ j(kAboveEqual, &done); + // if input == NaN goto nan + __ j(kUnordered, &nan); + // output = float-to-int-truncate(input) + __ cvttss2si(output, input); + __ jmp(&done); + __ Bind(&nan); + // output = 0 + __ xorl(output, output); + __ Bind(&done); + break; + } + case Primitive::kPrimDouble: LOG(FATAL) << "Type conversion from " << input_type << " to " << result_type << " not yet implemented"; diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 4d70efcf38..47fd304969 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -1363,6 +1363,12 @@ void LocationsBuilderX86_64::VisitTypeConversion(HTypeConversion* conversion) { break; case Primitive::kPrimFloat: + // Processing a Dex `float-to-int' instruction. + locations->SetInAt(0, Location::RequiresFpuRegister()); + locations->SetOut(Location::RequiresRegister()); + locations->AddTemp(Location::RequiresFpuRegister()); + break; + case Primitive::kPrimDouble: LOG(FATAL) << "Type conversion from " << input_type << " to " << result_type << " not yet implemented"; @@ -1550,7 +1556,31 @@ void InstructionCodeGeneratorX86_64::VisitTypeConversion(HTypeConversion* conver } break; - case Primitive::kPrimFloat: + case Primitive::kPrimFloat: { + // Processing a Dex `float-to-int' instruction. + XmmRegister input = in.AsFpuRegister<XmmRegister>(); + CpuRegister output = out.AsRegister<CpuRegister>(); + XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>(); + Label done, nan; + + __ movl(output, Immediate(kPrimIntMax)); + // temp = int-to-float(output) + __ cvtsi2ss(temp, output); + // if input >= temp goto done + __ comiss(input, temp); + __ j(kAboveEqual, &done); + // if input == NaN goto nan + __ j(kUnordered, &nan); + // output = float-to-int-truncate(input) + __ cvttss2si(output, input); + __ jmp(&done); + __ Bind(&nan); + // output = 0 + __ xorl(output, output); + __ Bind(&done); + break; + } + case Primitive::kPrimDouble: LOG(FATAL) << "Type conversion from " << input_type << " to " << result_type << " not yet implemented"; diff --git a/test/422-type-conversion/src/Main.java b/test/422-type-conversion/src/Main.java index c434db37c9..e7dbe2463f 100644 --- a/test/422-type-conversion/src/Main.java +++ b/test/422-type-conversion/src/Main.java @@ -91,6 +91,9 @@ public class Main { // Generate, compile and check long-to-double Dex instructions. longToDouble(); + // Generate, compile and check float-to-int Dex instructions. + floatToInt(); + // Generate, compile and check int-to-byte Dex instructions. shortToByte(); intToByte(); @@ -313,6 +316,32 @@ public class Main { assertDoubleEquals(-9223372036854775808D, $opt$LongToDouble(-9223372036854775808L)); // -(2^63) } + private static void floatToInt() { + assertIntEquals(1, $opt$FloatToInt(1F)); + assertIntEquals(0, $opt$FloatToInt(0F)); + assertIntEquals(0, $opt$FloatToInt(-0F)); + assertIntEquals(-1, $opt$FloatToInt(-1F)); + assertIntEquals(51, $opt$FloatToInt(51F)); + assertIntEquals(-51, $opt$FloatToInt(-51F)); + assertIntEquals(0, $opt$FloatToInt(0.5F)); + assertIntEquals(0, $opt$FloatToInt(0.4999999F)); + assertIntEquals(0, $opt$FloatToInt(-0.4999999F)); + assertIntEquals(0, $opt$FloatToInt(-0.5F)); + assertIntEquals(42, $opt$FloatToInt(42.199F)); + assertIntEquals(-42, $opt$FloatToInt(-42.199F)); + assertIntEquals(2147483647, $opt$FloatToInt(2147483647F)); // 2^31 - 1 + assertIntEquals(-2147483648, $opt$FloatToInt(-2147483647F)); // -(2^31 - 1) + assertIntEquals(-2147483648, $opt$FloatToInt(-2147483648F)); // -(2^31) + assertIntEquals(2147483647, $opt$FloatToInt(2147483648F)); // (2^31) + assertIntEquals(-2147483648, $opt$FloatToInt(-2147483649F)); // -(2^31 + 1) + assertIntEquals(2147483647, $opt$FloatToInt(9223372036854775807F)); // 2^63 - 1 + assertIntEquals(-2147483648, $opt$FloatToInt(-9223372036854775807F)); // -(2^63 - 1) + assertIntEquals(-2147483648, $opt$FloatToInt(-9223372036854775808F)); // -(2^63) + assertIntEquals(0, $opt$FloatToInt(Float.NaN)); + assertIntEquals(2147483647, $opt$FloatToInt(Float.POSITIVE_INFINITY)); + assertIntEquals(-2147483648, $opt$FloatToInt(Float.NEGATIVE_INFINITY)); + } + private static void shortToByte() { assertByteEquals((byte)1, $opt$ShortToByte((short)1)); assertByteEquals((byte)0, $opt$ShortToByte((short)0)); @@ -468,6 +497,9 @@ public class Main { // This method produces a long-to-double Dex instruction. static double $opt$LongToDouble(long a){ return (double)a; } + // This method produces a float-to-int Dex instruction. + static int $opt$FloatToInt(float a){ return (int)a; } + // These methods produce int-to-byte Dex instructions. static byte $opt$ShortToByte(short a){ return (byte)a; } static byte $opt$IntToByte(int a){ return (byte)a; } |