Commit d9a7461297 for perl

commit d9a746129777bed0b96456319a8cc5fe8ca066c4
Author: Richard Leach <rich+perl@hyphen-dash-hyphen.info>
Date:   Sun Oct 11 14:35:17 2026 +0000

    regcomp.c: Enable \R (LNBREAK) start class

    When `\R` was added in 5.10.0, both a regnode for matching and a start
    class for finding candidates were added, but (at least in the first
    commit) the start class didn't get wired in for use.

    The start class isn't used in blead today, but the code for it remains in
    `S_find_byclass` with no nearby comment remarking on why it isn't used.
    Since the `LNBREAK` start class seems more performant than the `ANYOF` start
    class that is otherwise used, this commit adds a case to
    `Perl_re_op_compile` to enable use of the `LNBREAK` start class.

    When the start class finds a candidate match quickly, there's no discernible
    difference between `LNBREAK` and `ANYOF`. For example:

        my $x = "\r\nbob"; for (0 .. 2_000_000) { $x =~ /\R(?:a|b|o){3}/; }

    * blead:
    ```
                286.60 msec task-clock                       #    0.997 CPUs utilized
         1,216,583,412      cycles                           #    4.245 GHz
         4,611,480,233      instructions                     #    3.79  insn per cycle
           920,789,702      branches                         #    3.213 G/sec
                87,351      branch-misses                    #    0.01% of all branches
    ```
    * patched:
    ```
                286.72 msec task-clock                       #    0.997 CPUs utilized
         1,221,483,806      cycles                           #    4.260 GHz
         4,497,331,066      instructions                     #    3.68  insn per cycle
           904,754,197      branches                         #    3.156 G/sec
                82,028      branch-misses                    #    0.01% of all branches
    ```

    But if much searching has to be done to find the first candidate, `LNBREAK`
    is noticeably better. For example:

        my $x = ("A"x500_000_000)."\r\nbob"; $x =~ /\R(?:a|b|o){3}/;

    * blead:
    ```
              1,542.94 msec task-clock                       #    0.999 CPUs utilized
         7,029,095,549      cycles                           #    4.556 GHz
        34,618,078,066      instructions                     #    4.92  insn per cycle
         6,517,492,546      branches                         #    4.224 G/sec
             1,413,693      branch-misses                    #    0.02% of all branches
    ```
    * patched:
    ```
                330.02 msec task-clock                       #    0.998 CPUs utilized
         1,466,984,351      cycles                           #    4.445 GHz
         7,115,654,408      instructions                     #    4.85  insn per cycle
         2,016,938,870      branches                         #    6.112 G/sec
             1,326,788      branch-misses                    #    0.07% of all branches
    ```

diff --git a/regcomp.c b/regcomp.c
index 6f2455b35d..cecb747844 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -2075,6 +2075,8 @@ Perl_re_op_compile(pTHX_ SV ** const patternp, int pat_count,
             first = REGNODE_AFTER(first);
             goto again;
         }
+        else if (REGNODE_TYPE(OP(first)) == LNBREAK)
+            RExC_rxi->regstclass = first;
         else if (OP(first) == GPOS) {
             RExC_rx->intflags |= PREGf_ANCH_GPOS;
             first = REGNODE_AFTER_type(first,tregnode_GPOS);
diff --git a/t/re/opt.t b/t/re/opt.t
index 7b63b7c57c..ad7323e3fe 100644
--- a/t/re/opt.t
+++ b/t/re/opt.t
@@ -287,3 +287,8 @@ abc(*ACCEPT)xyz	3	0+abc	-	-

 # Nested branches that should not be flattened
 (?:(?:(?:|x)|(?:|y))|(?:(?:|z)|w))q	1	-	0:1+q	-	empty alternatives; prefix is zero-width, literal floats
+
+# LNBREAK does get its own start class
+\R	1	-	-	stclass=LNBREAK	\R start class
+\Rfoo	4	-	1:2+foo	stclass=LNBREAK	\R start class with floating substr
+\R+foo	4	-	1+foo	skip,stclass=LNBREAK	\R+ start class with PLUS and floating substr