This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
regexec.c: Use ANYOF bitmap lookup in more cases
authorKarl Williamson <khw@cpan.org>
Sun, 18 Nov 2018 22:46:07 +0000 (15:46 -0700)
committerKarl Williamson <khw@cpan.org>
Tue, 27 Nov 2018 05:24:33 +0000 (22:24 -0700)
ANYOFish nodes have a bitmap.  If we know the value is in the bitmap
range, then flags that apply to out-of-range values are irrelevant.
Other flags being set indicate that the desired answer is more
complicated than just using a bitmap lookup.  But exclude this
irrelevant flag from that calculation when we know the value is in the
bitmap.

There are other flags that it is possible to exclude, but not without
further conditionals, or unsharing code, and are either rarely set or
are for node types that we don't worry so much about optimal
performance, like /l and /d.  The changes introduced by this commit
are determined at .c compile time except for a runtime mask, and hence
don't introduce new branches that may destroy the instruction cache
pipeline.

regexec.c

index 32cea3f..1756a95 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -2221,7 +2221,10 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
             REXEC_FBC_CLASS_SCAN(1, /* 1=>is-utf8 */
                       reginclass(prog, c, (U8*)s, (U8*) strend, utf8_target));
         }
-        else if (ANYOF_FLAGS(c)) {
+        else if (ANYOF_FLAGS(c) & ~ ANYOF_MATCHES_ALL_ABOVE_BITMAP) {
+            /* We know that s is in the bitmap range since the target isn't
+             * UTF-8, so what happens for out-of-range values is not relevant,
+             * so exclude that from the flags */
             REXEC_FBC_CLASS_SCAN(0, reginclass(prog,c, (U8*)s, (U8*)s+1, 0));
         }
         else {
@@ -6701,7 +6704,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
             if (NEXTCHR_IS_EOS)
                 sayNO;
            if (  (! utf8_target || UTF8_IS_INVARIANT(*locinput))
-               && ! ANYOF_FLAGS(scan))
+               && ! (ANYOF_FLAGS(scan) & ~ ANYOF_MATCHES_ALL_ABOVE_BITMAP))
             {
                 if (! ANYOF_BITMAP_TEST(scan, * (U8 *) (locinput))) {
                    sayNO;
@@ -9363,7 +9366,7 @@ S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p,
                hardcount++;
            }
        }
-        else if (ANYOF_FLAGS(p)) {
+        else if (ANYOF_FLAGS(p) & ~ ANYOF_MATCHES_ALL_ABOVE_BITMAP) {
            while (scan < loceol
                     && reginclass(prog, p, (U8*)scan, (U8*)scan+1, 0))
                scan++;