Fix x86 type conversions. test-art-host-oat passes.
- test-art-host-oat enabled in test builds.
- Created inline versions of float-to-int and double-to-int.
- Fixed calls to helper functions for long-to-float/double and
float/double-to-long.
- Removed storePair and replaced its use with storeBaseDispWide (fixes
iput-wide and aput-wide with doubles).
- Renamed helper functions to have art_ prefix.
- Fixed move-exception to store the result back.
- Fixed floating point comparison when the destination reg is the same as
a source. The typing would get confused since the source is floating
point, but the result is int, and a clobber is needed to overwrite the
expected result type. A similar thing happens in float/double-to-int.
Change-Id: I0a876072254411aa42d6acadb8723be030727219
diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc
index 14eaf1d..c9ba285 100644
--- a/src/compiler/codegen/GenCommon.cc
+++ b/src/compiler/codegen/GenCommon.cc
@@ -1060,7 +1060,7 @@
if (isVolatile) {
oatGenMemBarrier(cUnit, kST);
}
- storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
+ storeBaseDispWide(cUnit, regPtr, 0, rlSrc.lowReg, rlSrc.highReg);
if (isVolatile) {
oatGenMemBarrier(cUnit, kSY);
}
@@ -1642,7 +1642,7 @@
oatFreeTemp(cUnit, regLen);
}
- storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
+ storeBaseDispWide(cUnit, regPtr, 0, rlSrc.lowReg, rlSrc.highReg);
oatFreeTemp(cUnit, regPtr);
} else {
diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc
index b75b9a8..01ac436 100644
--- a/src/compiler/codegen/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/MethodCodegenDriver.cc
@@ -225,9 +225,9 @@
loadWordDisp(cUnit, rSELF, exOffset, rlResult.lowReg);
loadConstant(cUnit, resetReg, 0);
storeWordDisp(cUnit, rSELF, exOffset, resetReg);
- storeValue(cUnit, rlDest, rlResult);
oatFreeTemp(cUnit, resetReg);
#endif
+ storeValue(cUnit, rlDest, rlResult);
break;
}
case Instruction::RETURN_VOID:
diff --git a/src/compiler/codegen/arm/Thumb2/Factory.cc b/src/compiler/codegen/arm/Thumb2/Factory.cc
index 533f8b4..67f7938 100644
--- a/src/compiler/codegen/arm/Thumb2/Factory.cc
+++ b/src/compiler/codegen/arm/Thumb2/Factory.cc
@@ -1009,11 +1009,6 @@
return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
}
-void storePair(CompilationUnit* cUnit, int base, int lowReg, int highReg)
-{
- storeBaseDispWide(cUnit, base, 0, lowReg, highReg);
-}
-
void loadPair(CompilationUnit* cUnit, int base, int lowReg, int highReg)
{
loadBaseDispWide(cUnit, NULL, base, 0, lowReg, highReg, INVALID_SREG);
diff --git a/src/compiler/codegen/mips/Mips32/Factory.cc b/src/compiler/codegen/mips/Mips32/Factory.cc
index 0a7dd9d..8b6f185 100644
--- a/src/compiler/codegen/mips/Mips32/Factory.cc
+++ b/src/compiler/codegen/mips/Mips32/Factory.cc
@@ -40,8 +40,6 @@
#endif
void genBarrier(CompilationUnit *cUnit);
-void storePair(CompilationUnit *cUnit, int base, int lowReg,
- int highReg);
void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg);
LIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
int rDest);
@@ -742,12 +740,6 @@
return storeBaseDispBody(cUnit, rBase, displacement, rSrcLo, rSrcHi, kLong);
}
-void storePair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
-{
- storeWordDisp(cUnit, base, LOWORD_OFFSET, lowReg);
- storeWordDisp(cUnit, base, HIWORD_OFFSET, highReg);
-}
-
void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
{
loadWordDisp(cUnit, base, LOWORD_OFFSET , lowReg);
diff --git a/src/compiler/codegen/x86/FP/X86FP.cc b/src/compiler/codegen/x86/FP/X86FP.cc
index 7c27eae..24cd7d3 100644
--- a/src/compiler/codegen/x86/FP/X86FP.cc
+++ b/src/compiler/codegen/x86/FP/X86FP.cc
@@ -124,7 +124,9 @@
RegLocation rlDest;
X86OpCode op = kX86Nop;
int srcReg;
+ int tempReg;
RegLocation rlResult;
+ LIR* branch = NULL;
switch (opcode) {
case Instruction::INT_TO_FLOAT:
longSrc = false;
@@ -151,14 +153,45 @@
op = kX86Cvtsi2sdRR;
break;
case Instruction::FLOAT_TO_INT:
+ rlSrc = oatGetSrc(cUnit, mir, 0);
+ rlSrc = loadValue(cUnit, rlSrc, kFPReg);
+ srcReg = rlSrc.lowReg;
+ rlDest = oatGetDest(cUnit, mir, 0);
+ oatClobberSReg(cUnit, rlDest.sRegLow);
+ rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ tempReg = oatAllocTempFloat(cUnit);
+
+ loadConstant(cUnit, rlResult.lowReg, 0x7fffffff);
+ newLIR2(cUnit, kX86Cvtsi2ssRR, tempReg, rlResult.lowReg);
+ newLIR2(cUnit, kX86ComissRR, srcReg, tempReg);
+ branch = newLIR2(cUnit, kX86Jcc8, 0, kX86CondA);
+ newLIR2(cUnit, kX86Cvtss2siRR, rlResult.lowReg, srcReg);
+ branch->target = newLIR0(cUnit, kPseudoTargetLabel);
+ storeValue(cUnit, rlDest, rlResult);
+ return false;
case Instruction::DOUBLE_TO_INT:
- // These are easy to implement inline except when the src is > MAX_INT/LONG the result
- // needs to be changed from 0x80000000 to 0x7FFFFFF (requires an in memory float/double
- // literal constant to compare against).
- UNIMPLEMENTED(WARNING) << "inline [df]2i " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
+ rlSrc = oatGetSrcWide(cUnit, mir, 0, 1);
+ rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
+ srcReg = rlSrc.lowReg;
+ rlDest = oatGetDest(cUnit, mir, 0);
+ oatClobberSReg(cUnit, rlDest.sRegLow);
+ rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ tempReg = oatAllocTempDouble(cUnit);
+
+ loadConstant(cUnit, rlResult.lowReg, 0x7fffffff);
+ newLIR2(cUnit, kX86Cvtsi2sdRR, tempReg, rlResult.lowReg);
+ newLIR2(cUnit, kX86ComisdRR, srcReg, tempReg);
+ branch = newLIR2(cUnit, kX86Jcc8, 0, kX86CondA);
+ newLIR2(cUnit, kX86Cvtsd2siRR, rlResult.lowReg, srcReg);
+ branch->target = newLIR0(cUnit, kPseudoTargetLabel);
+ storeValue(cUnit, rlDest, rlResult);
+ return false;
case Instruction::LONG_TO_DOUBLE:
- case Instruction::FLOAT_TO_LONG:
case Instruction::LONG_TO_FLOAT:
+ // These can be implemented inline by using memory as a 64-bit source.
+ // However, this can't be done easily if the register has been promoted.
+ UNIMPLEMENTED(WARNING) << "inline l2[df] " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
+ case Instruction::FLOAT_TO_LONG:
case Instruction::DOUBLE_TO_LONG:
return genConversionPortable(cUnit, mir);
default:
@@ -205,6 +238,7 @@
rlSrc2 = loadValueWide(cUnit, rlSrc2, kFPReg);
srcReg2 = S2D(rlSrc2.lowReg, rlSrc2.highReg);
}
+ oatClobberSReg(cUnit, rlDest.sRegLow);
RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
loadConstantNoClobber(cUnit, rlResult.lowReg, unorderedGt ? 1 : 0);
if (single) {
diff --git a/src/compiler/codegen/x86/X86/Factory.cc b/src/compiler/codegen/x86/X86/Factory.cc
index c3fb6a6..3698d2d 100644
--- a/src/compiler/codegen/x86/X86/Factory.cc
+++ b/src/compiler/codegen/x86/X86/Factory.cc
@@ -47,8 +47,6 @@
};
void genBarrier(CompilationUnit *cUnit);
-void storePair(CompilationUnit *cUnit, int base, int lowReg,
- int highReg);
void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg);
LIR *loadWordDisp(CompilationUnit *cUnit, int rBase, int displacement,
int rDest);
@@ -676,12 +674,6 @@
rSrcLo, rSrcHi, kLong, INVALID_SREG);
}
-void storePair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
-{
- storeWordDisp(cUnit, base, 0, lowReg);
- storeWordDisp(cUnit, base, 4, highReg);
-}
-
void loadPair(CompilationUnit *cUnit, int base, int lowReg, int highReg)
{
loadWordDisp(cUnit, base, 0, lowReg);