]> granicus.if.org Git - php/commitdiff
Bit test optimization
authorDmitry Stogov <dmitry@zend.com>
Tue, 8 May 2018 08:58:17 +0000 (11:58 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 8 May 2018 08:58:17 +0000 (11:58 +0300)
Zend/zend_alloc.c
Zend/zend_bitset.h
Zend/zend_portability.h
ext/json/json_encoder.c
ext/mysqlnd/mysqlnd_result.c
ext/standard/array.c

index b5c705610d6b7af9720603bd6c2ff5ea2966d51d..30f98ff50cc124de44ad10a462df4796565f4c5b 100644 (file)
@@ -587,7 +587,7 @@ static zend_always_inline int zend_mm_bitset_find_zero_and_set(zend_mm_bitset *b
 
 static zend_always_inline int zend_mm_bitset_is_set(zend_mm_bitset *bitset, int bit)
 {
-       return (bitset[bit / ZEND_MM_BITSET_LEN] & (Z_L(1) << (bit & (ZEND_MM_BITSET_LEN-1)))) != 0;
+       return ZEND_BIT_TEST(bitset, bit);
 }
 
 static zend_always_inline void zend_mm_bitset_set_bit(zend_mm_bitset *bitset, int bit)
index 65959381d914b9a2e814a86b545e8f11643c493d..eb602800a7b8e2194abc8121e57cac0198fedf72 100644 (file)
@@ -86,7 +86,7 @@ static inline uint32_t zend_bitset_len(uint32_t n)
 
 static inline zend_bool zend_bitset_in(zend_bitset set, uint32_t n)
 {
-       return (set[ZEND_BITSET_ELM_NUM(n)] & (Z_UL(1) << ZEND_BITSET_BIT_NUM(n))) != Z_UL(0);
+       return ZEND_BIT_TEST(set, n);
 }
 
 static inline void zend_bitset_incl(zend_bitset set, uint32_t n)
index 4bbe023bdf0c08ad6df827dda1b80a8c0f5bb6cc..0bef8dd3742c99c9ba02326a026a6cc8104f630f 100644 (file)
@@ -442,6 +442,13 @@ char *alloca();
 #define MAX(a, b)  (((a)>(b))?(a):(b))
 #define MIN(a, b)  (((a)<(b))?(a):(b))
 
+/* x86 instructions BT, SHL, SHR don't require masking */
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+# define ZEND_BIT_TEST(bits, bit) (((bits)[(bit) / (sizeof((bits)[0])*8)] >> (bit)) & 1)
+#else
+# define ZEND_BIT_TEST(bits, bit) (((bits)[(bit) / (sizeof((bits)[0])*8)] >> ((bit) & (sizeof((bits)[0])*8-1))) & 1)
+#endif
+
 /* We always define a function, even if there's a macro or expression we could
  * alias, so that using it in contexts where we can't make function calls
  * won't fail to compile on some machines and not others.
index 3ec12b8968b606cc5a9a470190466222732d3c6a..f28bfbd4e44186dece5f28997c43b44daf694cb6 100644 (file)
@@ -350,7 +350,7 @@ static int php_json_escape_string(
                                0xffffffff, 0x500080c4, 0x10000000, 0x00000000};
 
                        pos++;
-                       if (EXPECTED(!((charmap[us >> 5] >> (us & 0x1f)) & 1))) {
+                       if (EXPECTED(!ZEND_BIT_TEST(charmap, us))) {
                                smart_str_appendc(buf, (unsigned char) us);
                        } else {
                                switch (us) {
index 653197e302fd735fcfd08f511a7b909aa931291e..b436f23ac0b3fb3b02e64c0deb3c452380ede2c5 100644 (file)
@@ -108,7 +108,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest)(MYSQLND_RE
 
                for (i = 0; i < result->row_count; i++) {
                        /* (i / 8) & the_bit_for_i*/
-                       if ((initialized[i >> 3] >> (i & 7)) & 1) {
+                       if (ZEND_BIT_TEST(initialized, i)) {
                                continue;
                        }
 
@@ -1151,7 +1151,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void
                if (rc != PASS) {
                        DBG_RETURN(FAIL);
                }
-               if (!((set->initialized[set->current_row >> 3] >> (set->current_row & 7)) & 1)) {
+               if (!ZEND_BIT_TEST(set->initialized, set->current_row)) {
                        set->initialized[set->current_row >> 3] |= (1 << (set->current_row & 7)); /* mark initialized */
 
                        ++set->initialized_rows;
index cfd29378a0362bf19716ec597020acee846f73a4..7621b0616a5b36a6bd77ce2e6ecdaa82aec20350 100644 (file)
@@ -1660,14 +1660,14 @@ static zend_always_inline int php_valid_var_name(const char *var_name, size_t va
 {
 #if 1
        /* first 256 bits for first character, and second 256 bits for the next */
-       static const uint32_t charset[16] = {
+       static const uint32_t charset[8] = {
             /*  31      0   63     32   95     64   127    96 */
                        0x00000000, 0x00000000, 0x87fffffe, 0x07fffffe,
-                       0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+                       0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
+       static const uint32_t charset2[8] = {
             /*  31      0   63     32   95     64   127    96 */
                        0x00000000, 0x03ff0000, 0x87fffffe, 0x07fffffe,
-                       0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
-               };
+                       0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
 #endif
        size_t i;
        uint32_t ch;
@@ -1679,7 +1679,7 @@ static zend_always_inline int php_valid_var_name(const char *var_name, size_t va
        /* These are allowed as first char: [a-zA-Z_\x7f-\xff] */
        ch = (uint32_t)((unsigned char *)var_name)[0];
 #if 1
-       if (UNEXPECTED(!((charset[ch >> 5] >> (ch & 0x1f)) & 1))) {
+       if (UNEXPECTED(!ZEND_BIT_TEST(charset, ch))) {
 #else
        if (var_name[0] != '_' &&
                (ch < 65  /* A    */ || /* Z    */ ch > 90)  &&
@@ -1696,7 +1696,7 @@ static zend_always_inline int php_valid_var_name(const char *var_name, size_t va
                do {
                        ch = (uint32_t)((unsigned char *)var_name)[i];
 #if 1
-                       if (UNEXPECTED(!((charset[8 + (ch >> 5)] >> (ch & 0x1f)) & 1))) {
+                       if (UNEXPECTED(!ZEND_BIT_TEST(charset2, ch))) {
 #else
                        if (var_name[i] != '_' &&
                                (ch < 48  /* 0    */ || /* 9    */ ch > 57)  &&