diff options
author | 2012-08-07 14:18:16 -0700 | |
---|---|---|
committer | 2012-08-07 16:24:08 -0700 | |
commit | 77ae36b35d47393335bf5399cab9c91ccf08e88f (patch) | |
tree | 736bfd865e7bfd7caf6c8bc282fa9d04d16232f7 /src/compiler/codegen | |
parent | e37543ed52379bcf08f57ebb3510846294a7102c (diff) |
Fix and enable inlining of some intrinsics on x86.
Inlined min/max int, String isEmpty/length, and abs int/long.
Change-Id: I24aa1b403ee5c8437d63c58dbe1504494ce106ef
Diffstat (limited to 'src/compiler/codegen')
-rw-r--r-- | src/compiler/codegen/GenInvoke.cc | 39 | ||||
-rw-r--r-- | src/compiler/codegen/x86/Assemble.cc | 2 | ||||
-rw-r--r-- | src/compiler/codegen/x86/X86LIR.h | 1 |
3 files changed, 38 insertions, 4 deletions
diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc index 9f1d58e304..f1653aa4b0 100644 --- a/src/compiler/codegen/GenInvoke.cc +++ b/src/compiler/codegen/GenInvoke.cc @@ -665,7 +665,7 @@ bool genInlinedCharAt(CompilationUnit* cUnit, CallInfo* info) 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 @@ bool genInlinedMinMaxInt(CompilationUnit *cUnit, CallInfo* info, bool isMin) 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 genInlinedMinMaxInt(CompilationUnit *cUnit, CallInfo* info, bool isMin) 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 @@ bool genInlinedStringIsEmptyOrLength(CompilationUnit* cUnit, CallInfo* info, 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 genInlinedStringIsEmptyOrLength(CompilationUnit* cUnit, CallInfo* info, 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 @@ bool genInlinedAbsLong(CompilationUnit *cUnit, CallInfo* info) 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 genInlinedIndexOf(CompilationUnit* cUnit, CallInfo* info, bool zeroBased) { #if defined(TARGET_ARM) - oatClobberCalleeSave(cUnit); oatLockCallTemps(cUnit); // Using fixed registers int regPtr = rARG0; diff --git a/src/compiler/codegen/x86/Assemble.cc b/src/compiler/codegen/x86/Assemble.cc index 0c5d3cf481..2da370d530 100644 --- a/src/compiler/codegen/x86/Assemble.cc +++ b/src/compiler/codegen/x86/Assemble.cc @@ -209,6 +209,8 @@ ENCODING_MAP(Cmp, IS_LOAD, 0, 0, SHIFT_ENCODING_MAP(Sar, 0x7), #undef SHIFT_ENCODING_MAP + { kX86Cmc, kNullary, NO_OPERAND, { 0, 0, 0xF5, 0, 0, 0, 0, 0}, "Cmc", "" }, + { kX86Test8RI, kRegImm, IS_BINARY_OP | REG_USE0 | SETS_CCODES, { 0, 0, 0xF6, 0, 0, 0, 0, 1}, "Test8RI", "!0r,!1d" }, { kX86Test8MI, kMemImm, IS_LOAD | IS_TERTIARY_OP | REG_USE0 | SETS_CCODES, { 0, 0, 0xF6, 0, 0, 0, 0, 1}, "Test8MI", "[!0r+!1d],!2d" }, { kX86Test8AI, kArrayImm, IS_LOAD | IS_QUIN_OP | REG_USE01 | SETS_CCODES, { 0, 0, 0xF6, 0, 0, 0, 0, 1}, "Test8AI", "[!0r+!1r<<!2d+!3d],!4d" }, diff --git a/src/compiler/codegen/x86/X86LIR.h b/src/compiler/codegen/x86/X86LIR.h index 72c8c03dea..7a9d90d26e 100644 --- a/src/compiler/codegen/x86/X86LIR.h +++ b/src/compiler/codegen/x86/X86LIR.h @@ -395,6 +395,7 @@ enum X86OpCode { BinaryShiftOpCode(kX86Shr), BinaryShiftOpCode(kX86Sar), #undef BinaryShiftOpcode + kX86Cmc, #define UnaryOpcode(opcode, reg, mem, array) \ opcode ## 8 ## reg, opcode ## 8 ## mem, opcode ## 8 ## array, \ opcode ## 16 ## reg, opcode ## 16 ## mem, opcode ## 16 ## array, \ |