aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2011-01-02 20:43:58 +0100
committerMike Pall <mike>2011-01-02 20:43:58 +0100
commite66b5b6eeefa0cadfd80a859c71d41c2f9e076b8 (patch)
tree7f9dec9509ff5862339fdad16339743c86291889 /src
parent55a9be7809e6fa85f8051a85b8085cc8a9d36734 (diff)
downloadluajit-e66b5b6eeefa0cadfd80a859c71d41c2f9e076b8.tar.gz
luajit-e66b5b6eeefa0cadfd80a859c71d41c2f9e076b8.tar.bz2
luajit-e66b5b6eeefa0cadfd80a859c71d41c2f9e076b8.zip
Improve uint64_t <-> FP conversions in x64 backend.
Diffstat (limited to 'src')
-rw-r--r--src/lj_asm.c30
-rw-r--r--src/lj_ir.c6
-rw-r--r--src/lj_iropt.h1
3 files changed, 21 insertions, 16 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c
index 14d6d849..18944da4 100644
--- a/src/lj_asm.c
+++ b/src/lj_asm.c
@@ -1641,18 +1641,15 @@ static void asm_conv(ASMState *as, IRIns *ir)
1641 return; 1641 return;
1642#endif 1642#endif
1643 } else { /* Integer to FP conversion. */ 1643 } else { /* Integer to FP conversion. */
1644 Reg tmp = (LJ_64 && st == IRT_U64) ? ra_scratch(as, RSET_GPR) : RID_NONE;
1645 Reg left = (LJ_64 && (st == IRT_U32 || st == IRT_U64)) ? 1644 Reg left = (LJ_64 && (st == IRT_U32 || st == IRT_U64)) ?
1646 ra_alloc1(as, lref, RSET_GPR) : 1645 ra_alloc1(as, lref, RSET_GPR) :
1647 asm_fuseload(as, lref, RSET_GPR); 1646 asm_fuseload(as, lref, RSET_GPR);
1648 if (LJ_64 && st == IRT_U64) { 1647 if (LJ_64 && st == IRT_U64) {
1649 Reg tmpn = ra_scratch(as, rset_exclude(RSET_FPR, dest));
1650 MCLabel l_end = emit_label(as); 1648 MCLabel l_end = emit_label(as);
1651 emit_rr(as, XO_ADDSD, dest, tmpn); 1649 const void *k = lj_ir_k64_find(as->J, U64x(43f00000,00000000));
1652 emit_rr(as, XO_MOVD, tmpn|REX_64, tmp); 1650 emit_rma(as, XO_ADDSD, dest, k); /* Add 2^64 to compensate. */
1653 emit_loadu64(as, tmp, U64x(43f00000,00000000));
1654 emit_sjcc(as, CC_NS, l_end); 1651 emit_sjcc(as, CC_NS, l_end);
1655 emit_rr(as, XO_TEST, left|REX_64, left); 1652 emit_rr(as, XO_TEST, left|REX_64, left); /* Check if u64 >= 2^63. */
1656 } 1653 }
1657 emit_mrm(as, irt_isnum(ir->t) ? XO_CVTSI2SD : XO_CVTSI2SS, 1654 emit_mrm(as, irt_isnum(ir->t) ? XO_CVTSI2SD : XO_CVTSI2SS,
1658 dest|((LJ_64 && (st64 || st == IRT_U32)) ? REX_64 : 0), left); 1655 dest|((LJ_64 && (st64 || st == IRT_U32)) ? REX_64 : 0), left);
@@ -1675,15 +1672,22 @@ static void asm_conv(ASMState *as, IRIns *ir)
1675 ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSD2SI : XO_CVTSD2SI) : 1672 ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSD2SI : XO_CVTSD2SI) :
1676 ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSS2SI : XO_CVTSS2SI); 1673 ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSS2SI : XO_CVTSS2SI);
1677 if (LJ_64 && irt_isu64(ir->t)) { 1674 if (LJ_64 && irt_isu64(ir->t)) {
1678 Reg left = ra_alloc1(as, lref, RSET_FPR); 1675 const void *k = lj_ir_k64_find(as->J, U64x(c3f00000,00000000));
1679 Reg tmpn = ra_scratch(as, rset_exclude(RSET_FPR, left));
1680 MCLabel l_end = emit_label(as); 1676 MCLabel l_end = emit_label(as);
1681 emit_rr(as, op, dest|REX_64, tmpn); 1677 Reg left = IR(lref)->r;
1682 emit_rr(as, XO_ADDSD, tmpn, left); 1678 /* For inputs in [2^63,2^64-1] add -2^64 and convert again. */
1683 emit_rr(as, XO_MOVD, tmpn|REX_64, dest); 1679 if (ra_hasreg(left)) {
1684 emit_loadu64(as, dest, U64x(c3f00000,00000000)); 1680 Reg tmpn = ra_scratch(as, rset_exclude(RSET_FPR, left));
1681 emit_rr(as, op, dest|REX_64, tmpn);
1682 emit_rr(as, XO_ADDSD, tmpn, left);
1683 emit_rma(as, XMM_MOVRM(as), tmpn, k);
1684 } else {
1685 left = ra_allocref(as, lref, RSET_FPR);
1686 emit_rr(as, op, dest|REX_64, left);
1687 emit_rma(as, XO_ADDSD, left, k);
1688 }
1685 emit_sjcc(as, CC_NS, l_end); 1689 emit_sjcc(as, CC_NS, l_end);
1686 emit_rr(as, XO_TEST, dest|REX_64, dest); 1690 emit_rr(as, XO_TEST, dest|REX_64, dest); /* Check if dest < 2^63. */
1687 emit_rr(as, op, dest|REX_64, left); 1691 emit_rr(as, op, dest|REX_64, left);
1688 } else { 1692 } else {
1689 Reg left = asm_fuseload(as, lref, RSET_FPR); 1693 Reg left = asm_fuseload(as, lref, RSET_FPR);
diff --git a/src/lj_ir.c b/src/lj_ir.c
index 3217bc1e..89be71aa 100644
--- a/src/lj_ir.c
+++ b/src/lj_ir.c
@@ -195,7 +195,7 @@ void lj_ir_k64_freeall(jit_State *J)
195} 195}
196 196
197/* Find 64 bit constant in chained array or add it. */ 197/* Find 64 bit constant in chained array or add it. */
198static cTValue *ir_k64_find(jit_State *J, uint64_t u64) 198cTValue *lj_ir_k64_find(jit_State *J, uint64_t u64)
199{ 199{
200 K64Array *k, *kp = NULL; 200 K64Array *k, *kp = NULL;
201 TValue *ntv; 201 TValue *ntv;
@@ -249,13 +249,13 @@ found:
249/* Intern FP constant, given by its 64 bit pattern. */ 249/* Intern FP constant, given by its 64 bit pattern. */
250TRef lj_ir_knum_u64(jit_State *J, uint64_t u64) 250TRef lj_ir_knum_u64(jit_State *J, uint64_t u64)
251{ 251{
252 return lj_ir_k64(J, IR_KNUM, ir_k64_find(J, u64)); 252 return lj_ir_k64(J, IR_KNUM, lj_ir_k64_find(J, u64));
253} 253}
254 254
255/* Intern 64 bit integer constant. */ 255/* Intern 64 bit integer constant. */
256TRef lj_ir_kint64(jit_State *J, uint64_t u64) 256TRef lj_ir_kint64(jit_State *J, uint64_t u64)
257{ 257{
258 return lj_ir_k64(J, IR_KINT64, ir_k64_find(J, u64)); 258 return lj_ir_k64(J, IR_KINT64, lj_ir_k64_find(J, u64));
259} 259}
260 260
261/* Check whether a number is int and return it. -0 is NOT considered an int. */ 261/* Check whether a number is int and return it. -0 is NOT considered an int. */
diff --git a/src/lj_iropt.h b/src/lj_iropt.h
index 4739f846..12943d25 100644
--- a/src/lj_iropt.h
+++ b/src/lj_iropt.h
@@ -41,6 +41,7 @@ static LJ_AINLINE IRRef lj_ir_nextins(jit_State *J)
41LJ_FUNC TRef LJ_FASTCALL lj_ir_kint(jit_State *J, int32_t k); 41LJ_FUNC TRef LJ_FASTCALL lj_ir_kint(jit_State *J, int32_t k);
42LJ_FUNC void lj_ir_k64_freeall(jit_State *J); 42LJ_FUNC void lj_ir_k64_freeall(jit_State *J);
43LJ_FUNC TRef lj_ir_k64(jit_State *J, IROp op, cTValue *tv); 43LJ_FUNC TRef lj_ir_k64(jit_State *J, IROp op, cTValue *tv);
44LJ_FUNC cTValue *lj_ir_k64_find(jit_State *J, uint64_t u64);
44LJ_FUNC TRef lj_ir_knum_u64(jit_State *J, uint64_t u64); 45LJ_FUNC TRef lj_ir_knum_u64(jit_State *J, uint64_t u64);
45LJ_FUNC TRef lj_ir_knumint(jit_State *J, lua_Number n); 46LJ_FUNC TRef lj_ir_knumint(jit_State *J, lua_Number n);
46LJ_FUNC TRef lj_ir_kint64(jit_State *J, uint64_t u64); 47LJ_FUNC TRef lj_ir_kint64(jit_State *J, uint64_t u64);