[Pcre-svn] [867] code/trunk/sljit: JIT compiler update

Top Page
Delete this message
Author: Subversion repository
Date:  
To: pcre-svn
Subject: [Pcre-svn] [867] code/trunk/sljit: JIT compiler update
Revision: 867
          http://vcs.pcre.org/viewvc?view=rev&revision=867
Author:   zherczeg
Date:     2012-01-13 13:34:07 +0000 (Fri, 13 Jan 2012)


Log Message:
-----------
JIT compiler update

Modified Paths:
--------------
    code/trunk/sljit/sljitLir.c
    code/trunk/sljit/sljitLir.h
    code/trunk/sljit/sljitNativeARM_Thumb2.c
    code/trunk/sljit/sljitNativeMIPS_common.c
    code/trunk/sljit/sljitNativeX86_64.c
    code/trunk/sljit/sljitNativeX86_common.c


Modified: code/trunk/sljit/sljitLir.c
===================================================================
--- code/trunk/sljit/sljitLir.c    2012-01-13 12:30:12 UTC (rev 866)
+++ code/trunk/sljit/sljitLir.c    2012-01-13 13:34:07 UTC (rev 867)
@@ -895,6 +895,13 @@
     int dst, sljit_w dstw,
     int src, sljit_w srcw)
 {
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+    if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+        compiler->skip_checks = 0;
+        return;
+    }
+#endif
+
     /* If debug and verbose are disabled, all arguments are unused. */
     SLJIT_UNUSED_ARG(compiler);
     SLJIT_UNUSED_ARG(op);
@@ -1018,6 +1025,35 @@
 #endif
 }


+static SLJIT_INLINE void check_sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
+    int src1, sljit_w src1w,
+    int src2, sljit_w src2w)
+{
+    SLJIT_UNUSED_ARG(compiler);
+    SLJIT_UNUSED_ARG(type);
+    SLJIT_UNUSED_ARG(src1);
+    SLJIT_UNUSED_ARG(src1w);
+    SLJIT_UNUSED_ARG(src2);
+    SLJIT_UNUSED_ARG(src2w);
+
+    SLJIT_ASSERT(sljit_is_fpu_available());
+    SLJIT_ASSERT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP)));
+    SLJIT_ASSERT((type & 0xff) >= SLJIT_C_FLOAT_EQUAL && (type & 0xff) <= SLJIT_C_FLOAT_NOT_NAN);
+#if (defined SLJIT_DEBUG && SLJIT_DEBUG)
+    FUNCTION_FCHECK(src1, src1w);
+    FUNCTION_FCHECK(src2, src2w);
+#endif
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+    if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+        fprintf(compiler->verbose, "  fcmp%s <%s> ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : "R", jump_names[type & 0xff]);
+        sljit_verbose_fparam(src1, src1w);
+        fprintf(compiler->verbose, ", ");
+        sljit_verbose_fparam(src2, src2w);
+        fprintf(compiler->verbose, "\n");
+    }
+#endif
+}
+
 static SLJIT_INLINE void check_sljit_emit_ijump(struct sljit_compiler *compiler, int type, int src, sljit_w srcw)
 {
     /* If debug and verbose are disabled, all arguments are unused. */
@@ -1103,6 +1139,7 @@
 #endif


 #if !(defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+
 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler *compiler, int type,
     int src1, sljit_w src1w,
     int src2, sljit_w src2w)
@@ -1169,8 +1206,34 @@
 #endif
     return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP));
 }
+
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
+    int src1, sljit_w src1w,
+    int src2, sljit_w src2w)
+{
+    int flags, condition;
+
+    check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w);
+
+    condition = type & 0xff;
+    if (condition <= SLJIT_C_FLOAT_NOT_EQUAL)
+        flags = SLJIT_SET_E;
+    else
+        flags = SLJIT_SET_S;
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+    compiler->skip_checks = 1;
 #endif
+    sljit_emit_fop1(compiler, SLJIT_FCMP | flags, src1, src1w, src2, src2w);


+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+    compiler->skip_checks = 1;
+#endif
+    return sljit_emit_jump(compiler, condition | (type & SLJIT_REWRITABLE_JUMP));
+}
+
+#endif
+
 #else /* SLJIT_CONFIG_UNSUPPORTED */


 /* Empty function bodies for those machines, which are not (yet) supported. */
@@ -1379,6 +1442,20 @@
     return NULL;
 }


+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
+    int src1, sljit_w src1w,
+    int src2, sljit_w src2w)
+{
+    SLJIT_UNUSED_ARG(compiler);
+    SLJIT_UNUSED_ARG(type);
+    SLJIT_UNUSED_ARG(src1);
+    SLJIT_UNUSED_ARG(src1w);
+    SLJIT_UNUSED_ARG(src2);
+    SLJIT_UNUSED_ARG(src2w);
+    SLJIT_ASSERT_STOP();
+    return NULL;
+}
+
 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label)
 {
     SLJIT_UNUSED_ARG(jump);


Modified: code/trunk/sljit/sljitLir.h
===================================================================
--- code/trunk/sljit/sljitLir.h    2012-01-13 12:30:12 UTC (rev 866)
+++ code/trunk/sljit/sljitLir.h    2012-01-13 13:34:07 UTC (rev 867)
@@ -686,11 +686,11 @@
    Flags: destroy all flags for calls. */
 SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compiler *compiler, int type);


-/* Basic arithmetic comparison. In most architectures it is equal to
-   an SLJIT_SUB operation (with SLJIT_UNUSED destination) followed by a
-   sljit_emit_jump. However some architectures (i.e: MIPS) may employ
-   special optimizations here. It is suggested to use this comparison
-   form when flags are unimportant.
+/* Basic arithmetic comparison. In most architectures it is implemented as
+   an SLJIT_SUB operation (with SLJIT_UNUSED destination and setting
+   appropriate flags) followed by a sljit_emit_jump. However some
+   architectures (i.e: MIPS) may employ special optimizations here. It is
+   suggested to use this comparison form when appropriate.
     type must be between SLJIT_C_EQUAL and SLJIT_C_SIG_LESS_EQUAL
     type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP or SLJIT_INT_OP
    Flags: destroy flags. */
@@ -698,6 +698,20 @@
     int src1, sljit_w src1w,
     int src2, sljit_w src2w);


+/* Basic floating point comparison. In most architectures it is implemented as
+   an SLJIT_FCMP operation (setting appropriate flags) followed by a
+   sljit_emit_jump. However some architectures (i.e: MIPS) may employ
+   special optimizations here. It is suggested to use this comparison form
+   when appropriate.
+    type must be between SLJIT_C_FLOAT_EQUAL and SLJIT_C_FLOAT_NOT_NAN
+    type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
+   Flags: destroy flags.
+   Note: if either operand is NaN, the behaviour is undefined for
+         type <= SLJIT_C_FLOAT_LESS_EQUAL. */
+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
+    int src1, sljit_w src1w,
+    int src2, sljit_w src2w);
+
 /* Set the destination of the jump to this label. */
 SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label);
 /* Only for jumps defined with SLJIT_REWRITABLE_JUMP flag.
@@ -743,7 +757,7 @@
 /* --------------------------------------------------------------------- */


 #define SLJIT_MAJOR_VERSION    0
-#define SLJIT_MINOR_VERSION    82
+#define SLJIT_MINOR_VERSION    87


 /* Get the human readable name of the platfrom.
    Can be useful for debugging on platforms like ARM, where ARM and
@@ -751,7 +765,7 @@
 SLJIT_API_FUNC_ATTRIBUTE SLJIT_CONST char* sljit_get_platform_name(void);


 /* Portble helper function to get an offset of a member. */
-#define SLJIT_OFFSETOF(base, member)     ((sljit_w)(&((base*)0x10)->member) - 0x10)
+#define SLJIT_OFFSETOF(base, member) ((sljit_w)(&((base*)0x10)->member) - 0x10)


#if (defined SLJIT_UTIL_GLOBAL_LOCK && SLJIT_UTIL_GLOBAL_LOCK)
/* This global lock is useful to compile common functions. */

Modified: code/trunk/sljit/sljitNativeARM_Thumb2.c
===================================================================
--- code/trunk/sljit/sljitNativeARM_Thumb2.c    2012-01-13 12:30:12 UTC (rev 866)
+++ code/trunk/sljit/sljitNativeARM_Thumb2.c    2012-01-13 13:34:07 UTC (rev 867)
@@ -1179,6 +1179,8 @@
     if (src != SLJIT_UNUSED && src != SLJIT_RETURN_REG) {
         if (src >= SLJIT_TEMPORARY_REG1 && src <= TMP_REG3)
             FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_RETURN_REG, src)));
+        else if (src & SLJIT_IMM)
+            FAIL_IF(load_immediate(compiler, SLJIT_RETURN_REG, srcw));
         else
             FAIL_IF(emit_op_mem(compiler, WORD_SIZE, SLJIT_RETURN_REG, src, srcw));
     }


Modified: code/trunk/sljit/sljitNativeMIPS_common.c
===================================================================
--- code/trunk/sljit/sljitNativeMIPS_common.c    2012-01-13 12:30:12 UTC (rev 866)
+++ code/trunk/sljit/sljitNativeMIPS_common.c    2012-01-13 13:34:07 UTC (rev 867)
@@ -109,6 +109,7 @@
 #define BREAK        (HI(0) | LO(13))
 #define C_UN_D        (HI(17) | FMT_D | LO(49))
 #define C_UEQ_D        (HI(17) | FMT_D | LO(51))
+#define C_ULE_D        (HI(17) | FMT_D | LO(55))
 #define C_ULT_D        (HI(17) | FMT_D | LO(53))
 #define DIV        (HI(0) | LO(26))
 #define DIVU        (HI(0) | LO(27))
@@ -1588,6 +1589,81 @@
 #undef RESOLVE_IMM1
 #undef RESOLVE_IMM2


+SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compiler *compiler, int type,
+    int src1, sljit_w src1w,
+    int src2, sljit_w src2w)
+{
+    struct sljit_jump *jump;
+    sljit_ins inst;
+    int if_true;
+
+    CHECK_ERROR_PTR();
+    check_sljit_emit_fcmp(compiler, type, src1, src1w, src2, src2w);
+
+    compiler->cache_arg = 0;
+    compiler->cache_argw = 0;
+
+    if (src1 > SLJIT_FLOAT_REG4) {
+        PTR_FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG1, 1, src1, src1w));
+        src1 = TMP_FREG1;
+    }
+    if (src2 > SLJIT_FLOAT_REG4) {
+        PTR_FAIL_IF(emit_fpu_data_transfer(compiler, TMP_FREG2, 1, src2, src2w));
+        src2 = TMP_FREG2;
+    }
+
+    jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
+    PTR_FAIL_IF(!jump);
+    set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+    jump->flags |= IS_BIT16_COND;
+    type &= 0xff;
+
+    switch (type) {
+    case SLJIT_C_FLOAT_EQUAL:
+        inst = C_UEQ_D;
+        if_true = 1;
+        break;
+    case SLJIT_C_FLOAT_NOT_EQUAL:
+        inst = C_UEQ_D;
+        if_true = 0;
+        break;
+    case SLJIT_C_FLOAT_LESS:
+        inst = C_ULT_D;
+        if_true = 1;
+        break;
+    case SLJIT_C_FLOAT_GREATER_EQUAL:
+        inst = C_ULT_D;
+        if_true = 0;
+        break;
+    case SLJIT_C_FLOAT_GREATER:
+        inst = C_ULE_D;
+        if_true = 0;
+        break;
+    case SLJIT_C_FLOAT_LESS_EQUAL:
+        inst = C_ULE_D;
+        if_true = 1;
+        break;
+    case SLJIT_C_FLOAT_NAN:
+        inst = C_UN_D;
+        if_true = 1;
+        break;
+    case SLJIT_C_FLOAT_NOT_NAN:
+    default: /* Make compilers happy. */
+        inst = C_UN_D;
+        if_true = 0;
+        break;
+    }
+
+    PTR_FAIL_IF(push_inst(compiler, inst | FT(src2) | FS(src1), UNMOVABLE_INS));
+    /* Intentionally the other opcode. */
+    PTR_FAIL_IF(push_inst(compiler, (if_true ? BC1F : BC1T) | JUMP_LENGTH, UNMOVABLE_INS));
+    PTR_FAIL_IF(emit_const(compiler, TMP_REG2, 0));
+    PTR_FAIL_IF(push_inst(compiler, JR | S(TMP_REG2), UNMOVABLE_INS));
+    jump->addr = compiler->size;
+    PTR_FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS));
+    return jump;
+}
+
 #undef JUMP_LENGTH
 #undef BR_Z
 #undef BR_NZ


Modified: code/trunk/sljit/sljitNativeX86_64.c
===================================================================
--- code/trunk/sljit/sljitNativeX86_64.c    2012-01-13 12:30:12 UTC (rev 866)
+++ code/trunk/sljit/sljitNativeX86_64.c    2012-01-13 13:34:07 UTC (rev 867)
@@ -802,10 +802,17 @@
         return SLJIT_SUCCESS; /* Empty instruction. */


     if (src & SLJIT_IMM) {
-        if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS)
+        if (dst >= SLJIT_TEMPORARY_REG1 && dst <= SLJIT_NO_REGISTERS) {
+            if (sign || ((sljit_uw)srcw <= 0x7fffffff)) {
+                code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw);
+                FAIL_IF(!code);
+                *code = 0xc7;
+                return SLJIT_SUCCESS;
+            }
             return emit_load_imm64(compiler, dst, srcw);
+        }
         compiler->mode32 = 1;
-        code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(int)srcw, dst, dstw);
+        code = emit_x86_instruction(compiler, 1, SLJIT_IMM, (sljit_w)(sljit_i)srcw, dst, dstw);
         FAIL_IF(!code);
         *code = 0xc7;
         compiler->mode32 = 0;
@@ -821,23 +828,9 @@
             code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
             FAIL_IF(!code);
             *code++ = 0x63;
-        } else if (dst_r == src) {
-            compiler->mode32 = 0;
-            code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 32, dst, 0);
-            FAIL_IF(!code);
-            *code |= 0x4 << 3;
-            code = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_IMM, 32, dst, 0);
-            FAIL_IF(!code);
-            *code |= 0x7 << 3;
         } else {
-            /* xor reg, reg. */
-            code = emit_x86_instruction(compiler, 1, dst_r, 0, dst_r, 0);
-            FAIL_IF(!code);
-            *code++ = 0x33;
             compiler->mode32 = 1;
-            code = emit_x86_instruction(compiler, 1, dst_r, 0, src, srcw);
-            FAIL_IF(!code);
-            *code++ = 0x8b;
+            FAIL_IF(emit_mov(compiler, dst_r, 0, src, srcw));
             compiler->mode32 = 0;
         }
     }


Modified: code/trunk/sljit/sljitNativeX86_common.c
===================================================================
--- code/trunk/sljit/sljitNativeX86_common.c    2012-01-13 12:30:12 UTC (rev 866)
+++ code/trunk/sljit/sljitNativeX86_common.c    2012-01-13 13:34:07 UTC (rev 867)
@@ -602,34 +602,26 @@
         if (op == SLJIT_SDIV) {
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64)
             EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG2, 0);
-            EMIT_MOV(compiler, SLJIT_TEMPORARY_REG2, 0, SLJIT_TEMPORARY_REG1, 0);
-#else
-            EMIT_MOV(compiler, TMP_REGISTER, 0, SLJIT_TEMPORARY_REG1, 0);
 #endif


+            /* CDQ instruction */
 #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
-            buf = (sljit_ub*)ensure_buf(compiler, 1 + 3);
+            buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
             FAIL_IF(!buf);
-            INC_SIZE(3);
-            *buf++ = 0xc1;
-            *buf++ = 0xfa;
-            *buf = 0x1f;
+            INC_SIZE(1);
+            *buf = 0x99;
 #else
             if (compiler->mode32) {
-                buf = (sljit_ub*)ensure_buf(compiler, 1 + 3);
+                buf = (sljit_ub*)ensure_buf(compiler, 1 + 1);
                 FAIL_IF(!buf);
-                INC_SIZE(3);
-                *buf++ = 0xc1;
-                *buf++ = 0xfa;
-                *buf = 0x1f;
+                INC_SIZE(1);
+                *buf = 0x99;
             } else {
-                buf = (sljit_ub*)ensure_buf(compiler, 1 + 4);
+                buf = (sljit_ub*)ensure_buf(compiler, 1 + 2);
                 FAIL_IF(!buf);
-                INC_SIZE(4);
+                INC_SIZE(2);
                 *buf++ = REX_W;
-                *buf++ = 0xc1;
-                *buf++ = 0xfa;
-                *buf = 0x3f;
+                *buf = 0x99;
             }
 #endif
         }