Fix and enable inlining of some intrinsics on x86.
Inlined min/max int, String isEmpty/length, and abs int/long.
Change-Id: I24aa1b403ee5c8437d63c58dbe1504494ce106ef
diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc
index 9f1d58e..f1653aa 100644
--- a/src/compiler/codegen/GenInvoke.cc
+++ b/src/compiler/codegen/GenInvoke.cc
@@ -665,7 +665,7 @@
bool genInlinedMinMaxInt(CompilationUnit *cUnit, CallInfo* info, bool isMin)
{
-#if defined(TARGET_ARM)
+#if defined(TARGET_ARM) || defined(TARGET_X86)
RegLocation rlSrc1 = info->args[0];
RegLocation rlSrc2 = info->args[1];
rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
@@ -673,10 +673,19 @@
RegLocation rlDest = inlineTarget(cUnit, info);
RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
+#if defined(TARGET_ARM)
opIT(cUnit, (isMin) ? kArmCondGt : kArmCondLt, "E");
opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc2.lowReg);
opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc1.lowReg);
genBarrier(cUnit);
+#elif defined(TARGET_X86)
+ LIR* branch = newLIR2(cUnit, kX86Jcc8, 0, isMin ? kX86CondG : kX86CondL);
+ opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc1.lowReg);
+ LIR* branch2 = newLIR1(cUnit, kX86Jmp8, 0);
+ branch->target = newLIR0(cUnit, kPseudoTargetLabel);
+ opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc2.lowReg);
+ branch2->target = newLIR0(cUnit, kPseudoTargetLabel);
+#endif
storeValue(cUnit, rlDest, rlResult);
return true;
#else
@@ -688,7 +697,7 @@
bool genInlinedStringIsEmptyOrLength(CompilationUnit* cUnit, CallInfo* info,
bool isEmpty)
{
-#if defined(TARGET_ARM)
+#if defined(TARGET_ARM) || defined(TARGET_X86)
// dst = src.length();
RegLocation rlObj = info->args[0];
rlObj = loadValue(cUnit, rlObj, kCoreReg);
@@ -699,9 +708,14 @@
rlResult.lowReg);
if (isEmpty) {
// dst = (dst == 0);
+#if defined(TARGET_ARM)
int tReg = oatAllocTemp(cUnit);
opRegReg(cUnit, kOpNeg, tReg, rlResult.lowReg);
opRegRegReg(cUnit, kOpAdc, rlResult.lowReg, rlResult.lowReg, tReg);
+#elif defined(TARGET_X86)
+ opRegImm(cUnit, kOpSub, rlResult.lowReg, 1);
+ opRegImm(cUnit, kOpLsr, rlResult.lowReg, 31);
+#endif
}
storeValue(cUnit, rlDest, rlResult);
return true;
@@ -712,7 +726,7 @@
bool genInlinedAbsInt(CompilationUnit *cUnit, CallInfo* info)
{
-#if defined(TARGET_ARM)
+#if defined(TARGET_ARM) || defined(TARGET_X86)
RegLocation rlSrc = info->args[0];
rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
RegLocation rlDest = inlineTarget(cUnit, info);
@@ -745,6 +759,24 @@
opRegReg(cUnit, kOpXor, rlResult.highReg, signReg);
storeValueWide(cUnit, rlDest, rlResult);
return true;
+#elif defined(TARGET_X86)
+ // Reuse source registers to avoid running out of temps
+ RegLocation rlSrc = info->args[0];
+ rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
+ RegLocation rlDest = inlineTargetWide(cUnit, info);
+ RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
+ opRegCopyWide(cUnit, rlResult.lowReg, rlResult.highReg, rlSrc.lowReg, rlSrc.highReg);
+ oatFreeTemp(cUnit, rlSrc.lowReg);
+ oatFreeTemp(cUnit, rlSrc.highReg);
+ int signReg = oatAllocTemp(cUnit);
+ // abs(x) = y<=x>>31, (x+y)^y.
+ opRegRegImm(cUnit, kOpAsr, signReg, rlResult.highReg, 31);
+ opRegReg(cUnit, kOpAdd, rlResult.lowReg, signReg);
+ opRegReg(cUnit, kOpAdc, rlResult.highReg, signReg);
+ opRegReg(cUnit, kOpXor, rlResult.lowReg, signReg);
+ opRegReg(cUnit, kOpXor, rlResult.highReg, signReg);
+ storeValueWide(cUnit, rlDest, rlResult);
+ return true;
#else
return false;
#endif
@@ -782,7 +814,6 @@
bool zeroBased)
{
#if defined(TARGET_ARM)
-
oatClobberCalleeSave(cUnit);
oatLockCallTemps(cUnit); // Using fixed registers
int regPtr = rARG0;