Add support for double-to-int & double-to-long in optimizing.
- Add support for the double-to-int and double-to-long Dex
instructions in the optimizing compiler.
- Add S1 to the list of ARM FPU parameter registers so that
a double value can be passed as parameter during a call
to the runtime through D0.
- Have art::x86_64::X86_64Assembler::cvttsd2si work with
64-bit operands.
- Generate x86, x86-64 and ARM (but not ARM64) code for
double to int and double to long HTypeConversion nodes.
- Add related tests to test/422-type-conversion.
Change-Id: Ic93b9ec6630c26e940f7966a3346ad3fd5a2ab3a
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 5761fb1..39a9766 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1370,8 +1370,10 @@
break;
case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type
- << " to " << result_type << " not yet implemented";
+ // Processing a Dex `double-to-int' instruction.
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresFpuRegister());
break;
default:
@@ -1401,8 +1403,10 @@
break;
case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type << " to "
- << result_type << " not yet implemented";
+ // Processing a Dex `double-to-long' instruction.
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresFpuRegister());
break;
default:
@@ -1589,10 +1593,30 @@
break;
}
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type
- << " to " << result_type << " not yet implemented";
+ case Primitive::kPrimDouble: {
+ // Processing a Dex `double-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-double(output)
+ __ cvtsi2sd(temp, output);
+ // if input >= temp goto done
+ __ comisd(input, temp);
+ __ j(kAboveEqual, &done);
+ // if input == NaN goto nan
+ __ j(kUnordered, &nan);
+ // output = double-to-int-truncate(input)
+ __ cvttsd2si(output, input);
+ __ jmp(&done);
+ __ Bind(&nan);
+ // output = 0
+ __ xorl(output, output);
+ __ Bind(&done);
break;
+ }
default:
LOG(FATAL) << "Unexpected type conversion from " << input_type
@@ -1620,14 +1644,14 @@
Label done, nan;
__ movq(output, Immediate(kPrimLongMax));
- // temp = int-to-float(output)
+ // temp = long-to-float(output)
__ cvtsi2ss(temp, output, true);
// 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)
+ // output = float-to-long-truncate(input)
__ cvttss2si(output, input, true);
__ jmp(&done);
__ Bind(&nan);
@@ -1637,10 +1661,30 @@
break;
}
- case Primitive::kPrimDouble:
- LOG(FATAL) << "Type conversion from " << input_type << " to "
- << result_type << " not yet implemented";
+ case Primitive::kPrimDouble: {
+ // Processing a Dex `double-to-long' instruction.
+ XmmRegister input = in.AsFpuRegister<XmmRegister>();
+ CpuRegister output = out.AsRegister<CpuRegister>();
+ XmmRegister temp = locations->GetTemp(0).AsFpuRegister<XmmRegister>();
+ Label done, nan;
+
+ __ movq(output, Immediate(kPrimLongMax));
+ // temp = long-to-double(output)
+ __ cvtsi2sd(temp, output, true);
+ // if input >= temp goto done
+ __ comisd(input, temp);
+ __ j(kAboveEqual, &done);
+ // if input == NaN goto nan
+ __ j(kUnordered, &nan);
+ // output = double-to-long-truncate(input)
+ __ cvttsd2si(output, input, true);
+ __ jmp(&done);
+ __ Bind(&nan);
+ // output = 0
+ __ xorq(output, output);
+ __ Bind(&done);
break;
+ }
default:
LOG(FATAL) << "Unexpected type conversion from " << input_type