]> git.ipfire.org Git - thirdparty/LuaJIT.git/commitdiff
Simplify helper routines for soft-float targets. Add POW rejoin.
authorMike Pall <mike>
Thu, 26 May 2011 16:01:55 +0000 (18:01 +0200)
committerMike Pall <mike>
Thu, 26 May 2011 16:01:55 +0000 (18:01 +0200)
src/buildvm_arm.dasc
src/lj_ir.c
src/lj_opt_split.c
src/lj_vm.h

index 4d30a95b7a66da2b854f4c0896facf8a79681eec..f2b08ed9b91944211747219d4aef7d4c9bb3139f 100644 (file)
@@ -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 -)
index 59ffcfde80dfd8ddb91265a15e2128549bf7f882..749b7f126902bea188a9f6eb699d2d2634333cf5 100644 (file)
 /* 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. */
index 67436a65c038fc088ebb7149ca9378bae726f4e7..b9fae10f9a2013742504c5e088a612df4a3a9250 100644 (file)
@@ -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:
index 55b92c838ff34bfae290a9a30e2a236e6eea5858..649280d0954c969b3c03b847d85f6c2abcffdb53 100644 (file)
@@ -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