From 625ef8626fcd400a65a270654ba056c48aae0e56 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Thu, 26 May 2011 18:01:55 +0200 Subject: [PATCH] Simplify helper routines for soft-float targets. Add POW rejoin. --- src/buildvm_arm.dasc | 10 ------- src/lj_ir.c | 67 +++++++++++++++++++++++++++++++++++++++++++- src/lj_opt_split.c | 20 +++++++++++++ src/lj_vm.h | 7 ++--- 4 files changed, 89 insertions(+), 15 deletions(-) diff --git a/src/buildvm_arm.dasc b/src/buildvm_arm.dasc index 4d30a95b..f2b08ed9 100644 --- a/src/buildvm_arm.dasc +++ b/src/buildvm_arm.dasc @@ -2003,16 +2003,6 @@ static void build_subroutines(BuildCtx *ctx) | eors CARG2, CARG1, RB, lsl #1 | rsbmi CARG1, CARG1, #0 // if (sign(divisor) != sign(y)) y = -y | bx lr - | - |->vm_powi: -#if LJ_HASJIT - | NYI -#endif - | - |->vm_foldfpm: -#if LJ_HASJIT - | NYI -#endif | |// Callable from C: double lj_vm_foldarith(double x, double y, int op) |// Compute x op y for basic arithmetic operators (+ - * / % ^ and unary -) diff --git a/src/lj_ir.c b/src/lj_ir.c index 59ffcfde..749b7f12 100644 --- a/src/lj_ir.c +++ b/src/lj_ir.c @@ -37,6 +37,72 @@ /* Pass IR on to next optimization in chain (FOLD). */ #define emitir(ot, a, b) (lj_ir_set(J, (ot), (a), (b)), lj_opt_fold(J)) +/* -- Helper functions for generated machine code ------------------------- */ + +#ifdef __ANDROID__ +/* Android doesn't have log2(). Oh well. */ +#define log2 lj_vm_log2 +static double lj_vm_log2(double a) +{ + return log(a) * 1.4426950408889634074; +} +#endif + +#if !LJ_TARGET_X86ORX64 +/* Unsigned x^k. */ +static double lj_vm_powui(double x, uint32_t k) +{ + double y; + lua_assert(k != 0); + for (; (k & 1) == 0; k >>= 1) x *= x; + y = x; + if ((k >>= 1) != 0) { + for (;;) { + x *= x; + if (k == 1) break; + if (k & 1) y *= x; + k >>= 1; + } + y *= x; + } + return y; +} + +/* Signed x^k. */ +static double lj_vm_powi(double x, int32_t k) +{ + if (k > 1) + return lj_vm_powui(x, (uint32_t)k); + else if (k == 1) + return x; + else if (k == 0) + return 1; + else + return 1.0 / lj_vm_powui(x, (uint32_t)-k); +} + +/* Computes fpm(x) for extended math functions. */ +double lj_vm_foldfpm(double x, int fpm) +{ + switch (fpm) { + case IRFPM_FLOOR: return lj_vm_floor(x); + case IRFPM_CEIL: return lj_vm_ceil(x); + case IRFPM_TRUNC: return lj_vm_trunc(x); + case IRFPM_SQRT: return sqrt(x); + case IRFPM_EXP: return exp(x); + case IRFPM_EXP2: return exp2(x); + case IRFPM_LOG: return log(x); + case IRFPM_LOG2: return log2(x); + case IRFPM_LOG10: return log10(x); + case IRFPM_SIN: return sin(x); + case IRFPM_COS: return cos(x); + case IRFPM_TAN: return tan(x); + default: lua_assert(0); + } + return 0; +} +#endif + /* -- IR tables ----------------------------------------------------------- */ /* IR instruction modes. */ @@ -55,7 +121,6 @@ IRCALLDEF(IRCALLCI) { NULL, 0 } }; - /* -- IR emitter ---------------------------------------------------------- */ /* Grow IR buffer at the top. */ diff --git a/src/lj_opt_split.c b/src/lj_opt_split.c index 67436a65..b9fae10f 100644 --- a/src/lj_opt_split.c +++ b/src/lj_opt_split.c @@ -191,6 +191,7 @@ static void split_ir(jit_State *J) /* Remove all IR instructions, but retain IR constants. */ J->cur.nins = REF_FIRST; + J->loopref = 0; /* Process constants and fixed references. */ for (ref = nk; ref <= REF_BASE; ref++) { @@ -243,6 +244,25 @@ static void split_ir(jit_State *J) hi = split_call_li(J, hisubst, oir, ir, IRCALL_lj_vm_powi); break; case IR_FPMATH: + /* Try to rejoin pow from EXP2, MUL and LOG2. */ + if (nir->op2 == IRFPM_EXP2 && nir->op1 > J->loopref) { + IRIns *irp = IR(nir->op1); + if (irp->o == IR_CALLN && irp->op2 == IRCALL_softfp_mul) { + IRIns *irm4 = IR(irp->op1); + IRIns *irm3 = IR(irm4->op1); + IRIns *irm12 = IR(irm3->op1); + IRIns *irl1 = IR(irm12->op1); + if (irm12->op1 > J->loopref && irl1->o == IR_CALLN && + irl1->op2 == IRCALL_log2) { + IRRef tmp = irl1->op1; /* Recycle first two args from LOG2. */ + tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), tmp, irm3->op2); + tmp = split_emit(J, IRT(IR_CARG, IRT_NIL), tmp, irm4->op2); + ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, IRCALL_pow); + hi = split_emit(J, IRT(IR_HIOP, LJ_SOFTFP), tmp, tmp); + break; + } + } + } hi = split_call_l(J, hisubst, oir, ir, IRCALL_lj_vm_floor + ir->op2); break; case IR_ATAN2: diff --git a/src/lj_vm.h b/src/lj_vm.h index 55b92c83..649280d0 100644 --- a/src/lj_vm.h +++ b/src/lj_vm.h @@ -56,10 +56,9 @@ LJ_ASMF void lj_vm_exp2(void); LJ_ASMF void lj_vm_pow_sse(void); LJ_ASMF void lj_vm_powi_sse(void); #else -LJ_ASMF void lj_vm_floor(void); -LJ_ASMF void lj_vm_ceil(void); -LJ_ASMF void lj_vm_trunc(void); -LJ_ASMF void lj_vm_powi(void); +LJ_ASMF double lj_vm_floor(double); +LJ_ASMF double lj_vm_ceil(double); +LJ_ASMF double lj_vm_trunc(double); #endif #endif