-
-
Save MasterDuke17/46b89eae73953d78b20fbd4c6c6cc060 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git src/NQP/Optimizer.nqp src/NQP/Optimizer.nqp | |
index 83332dab7..26f5fd5ba 100644 | |
--- src/NQP/Optimizer.nqp | |
+++ src/NQP/Optimizer.nqp | |
@@ -250,6 +250,26 @@ class NQP::Optimizer { | |
self.visit_children($op); | |
} | |
+ # turn simple `if <string> ~~ / <literal> / {` into `if nqp::index(<string>, <literal>) && <string> ~~ / <literal> / {` | |
+ if $opname eq 'if' { | |
+ if nqp::istype($op[0], QAST::Op) && $op[0].op eq 'callmethod' && $op[0].name eq 'ACCEPTS' && | |
+ nqp::istype($op[0][0], QAST::Op) && $op[0][0].op eq 'callmethod' && $op[0][0].name eq 'new' && | |
+ nqp::istype($op[0][0][1], QAST::Block) && nqp::istype($op[0][0][1][1], QAST::Regex) | |
+ { | |
+ my $c := $op[0][0][1][1]; | |
+ if (my $lit := $c.ann('can_optimize_literal')) ne '0' { | |
+ my $index := | |
+ QAST::Op.new(:op('if'), | |
+ QAST::Op.new(:op('isge_i'), | |
+ QAST::Op.new(:op('index'), $op[0][1], QAST::SVal.new(:value($lit))), | |
+ QAST::IVal.new(:value(0))), | |
+ $op[0]); | |
+ $op[0] := $index; | |
+ note($op.dump) if nqp::existskey(nqp::getenvhash(), 'NQP_LIT_REGEX_OPT'); | |
+ } | |
+ } | |
+ } | |
+ | |
# nqp::ctx and nqp::curlexpad capture the current context and so poisons lowering | |
if %op_poisons_lowering{$opname} { | |
self.poison_lowering(); | |
diff --git src/QAST/Node.nqp src/QAST/Node.nqp | |
index ff6f925bd..5e9dce010 100644 | |
--- src/QAST/Node.nqp | |
+++ src/QAST/Node.nqp | |
@@ -162,7 +162,7 @@ class QAST::Node { | |
my $v := %!annotations{$k}; | |
try { | |
if nqp::isconcrete($v) { | |
- if $k eq 'IN_DECL' || $k eq 'BY' || $k eq 'statement_id' { | |
+ if $k eq 'IN_DECL' || $k eq 'BY' || $k eq 'statement_id' || $k eq 'can_optimize_literal' { | |
nqp::push(@anns, ':' ~ $k ~ '<' ~ $v ~ '>'); | |
} | |
else { # dunno how to introspect | |
diff --git src/QRegex/P6Regex/Optimizer.nqp src/QRegex/P6Regex/Optimizer.nqp | |
index 320abb63c..d63d568ac 100644 | |
--- src/QRegex/P6Regex/Optimizer.nqp | |
+++ src/QRegex/P6Regex/Optimizer.nqp | |
@@ -2,19 +2,26 @@ class QRegex::Optimizer { | |
has @!outer; | |
has $!level; | |
has $!main_opt; | |
+ has $!top; | |
method optimize($node, $outer, *%adverbs) { | |
$!level := nqp::getlexdyn('$*LEVEL') // %adverbs<optimize> // 2; | |
$!main_opt := %adverbs<main_lang_optimizer>; | |
@!outer := [$outer]; | |
+ $!top := $node; | |
my $type := $node.rxtype; | |
if $type eq 'concat' { | |
- return self.visit_concat($node); | |
+ my $c := self.visit_concat($node); | |
+ #note($!top.dump) if nqp::existskey(nqp::getenvhash(), 'NQP_LIT_REGEX_OPT'); | |
+ return $c; | |
} elsif $type eq 'subrule' { | |
$node := $!main_opt($node) if $!main_opt; | |
- return self.simplify_assertion($node); | |
+ my $a := self.simplify_assertion($node); | |
+ #note($!top.dump) if nqp::existskey(nqp::getenvhash(), 'NQP_LIT_REGEX_OPT'); | |
+ return $a; | |
} else { | |
self.visit_children($node); | |
+ #note($!top.dump) if nqp::existskey(nqp::getenvhash(), 'NQP_LIT_REGEX_OPT'); | |
} | |
$node | |
} | |
@@ -152,9 +159,11 @@ class QRegex::Optimizer { | |
if $type eq 'concat' { | |
$node[$i] := self.visit_concat($visit); | |
} elsif $type eq 'literal' { | |
+ $!top.annotate('can_optimize_literal', $visit[0]) unless $!top.has_ann('can_optimize_literal'); | |
} elsif $type eq 'quant' { | |
self.visit_children($visit); | |
} elsif $type eq 'subrule' { | |
+ #$!top.annotate('can_optimize_literal', 0); | |
$node[$i] := $!main_opt($node[$i]) if $!main_opt; | |
$node[$i] := self.simplify_assertion($visit); | |
} elsif $type eq 'qastnode' { | |
@@ -167,8 +176,11 @@ class QRegex::Optimizer { | |
} elsif $type eq 'dynquant' { | |
$node[$i] := $!main_opt($node[$i]) if $!main_opt; | |
} elsif $type eq 'pass' || $type eq 'fail' { | |
+ } elsif $type eq 'alt' || $type eq 'altseq' { | |
+ $!top.annotate('can_optimize_literal', 0); | |
+ self.visit_children($visit); | |
} else { | |
- # alt, altseq, conjseq, conj, quant | |
+ # conjseq, conj, quant | |
self.visit_children($visit); | |
} | |
} elsif nqp::istype($visit, QAST::Block) { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[dan@alexandria nqp]$ NQP_LIT_REGEX_OPT=1 ./nqp-m --target=optimize -e 'if "123def78" ~~ / "def" / { say("match") } else { say("no match") }' | |
- QAST::CompUnit | |
[post_deserialize] | |
- QAST::Op(forceouterctx) | |
- QAST::BVal(2) | |
- QAST::Op(callmethod load_setting) | |
- QAST::Op(getcurhllsym) | |
- QAST::SVal(ModuleLoader) | |
- QAST::SVal(NQPCORE) | |
- QAST::Stmts | |
- QAST::Op(bindattr) | |
- QAST::WVal(NQPRegex) | |
- QAST::WVal(NQPRegex) | |
- QAST::SVal($!do) | |
- QAST::BVal(1) | |
- QAST::Stmts | |
[main] | |
- QAST::Stmts | |
- QAST::Op(call) | |
- QAST::BVal(2) | |
- QAST::Var+{QAST::SpecialArg}(local ARGS :decl(param) :flat) | |
[load] | |
- QAST::Op(call) | |
- QAST::BVal(2) | |
[children] | |
- QAST::Block(:name(<mainline>) :cuid(2)) | |
│ - QAST::Var(local __lowered_lex_3 :decl(param)) | |
│ - QAST::Stmts | |
│ - QAST::Var(lexical GLOBALish :decl(static)) | |
│ - QAST::Var(lexical $?PACKAGE :decl(static)) | |
│ - QAST::Var(lexical EXPORT :decl(static)) | |
│ - QAST::Stmts | |
│ - QAST::Op(bind) | |
│ - QAST::Var(local ctxsave :decl(var)) | |
│ - QAST::Var(contextual $*CTXSAVE) | |
│ - QAST::Op(unless) | |
│ - QAST::Op(isnull) | |
│ - QAST::Var(local ctxsave) | |
│ - QAST::Op(if) | |
│ - QAST::Op(can) | |
│ - QAST::Var(local ctxsave) | |
│ - QAST::SVal(ctxsave) | |
│ - QAST::Op(callmethod ctxsave) | |
│ - QAST::Var(local ctxsave) | |
│ - QAST::Stmts if \"123def78\" ~~ / \"def\" / { say(\"match\") } ... | |
│ - QAST::Stmts | |
│ - QAST::Op(if) \"123def78\" ~~ / \"def\" / { say(\"match\") } | |
│ - QAST::Op(if) | |
│ - QAST::Op(isge_i) | |
│ - QAST::Op(index) | |
│ - QAST::SVal(123def78) | |
│ - QAST::SVal(def) | |
│ - QAST::IVal(0) | |
│ - QAST::Op(callmethod ACCEPTS) ~~ | |
│ - QAST::Op(callmethod new) :sink<?> | |
│ - QAST::VarWithFallback(associative ) | |
│ [fallback] | |
│ - QAST::Op(ifnull) | |
│ - QAST::Op(atkey) | |
│ - QAST::Op(who) | |
│ - QAST::WVal(GLOBALish) | |
│ - QAST::SVal(NQPRegex) | |
│ - QAST::WVal(NQPMu) | |
│ [children] | |
│ - QAST::Op(who) | |
│ - QAST::Var(lexical $?PACKAGE) | |
│ - QAST::SVal(NQPRegex) | |
│ - QAST::Block(:name() :cuid(1)) :orig_qast<?> :compile_time_dummy<?> | |
│ │ - QAST::Stmts | |
│ │ - QAST::Var(local __lowered_lex_1 :decl(param)) | |
│ │ - QAST::Op(bind) | |
│ │ - QAST::Var(local self :decl(var)) | |
│ │ - QAST::Var(local __lowered_lex_1) | |
│ │ - QAST::Var(lexical $¢ :decl(var)) | |
│ │ - QAST::Var(local __lowered_lex_2 :decl(var)) | |
│ │ - QAST::Regex+{QAST::RegexCursorType}(:rxtype(concat) :subtype() :cursor_type(NQPMatch)) | |
│ │ - QAST::Regex(:rxtype(scan) :subtype()) | |
│ │ - def | |
│ │ - QAST::Regex(:rxtype(literal) :subtype()) \"def\" | |
│ │ - def | |
│ │ - QAST::Regex(:rxtype(pass) :subtype()) | |
│ - QAST::SVal(123def78) | |
│ - QAST::Stmts { say(\"match\") } | |
│ - QAST::Stmts | |
│ - QAST::Stmts say(\"match\") | |
│ - QAST::Stmts | |
│ - QAST::Op(call &say) say(\"match\") | |
│ - QAST::SVal(match) | |
│ - QAST::Stmts { say(\"no match\") } | |
│ - QAST::Stmts | |
│ - QAST::Stmts say(\"no match\") | |
│ - QAST::Stmts | |
│ - QAST::Op(call &say) say(\"no match\") | |
│ - QAST::SVal(no match) | |
│ - QAST::Stmts |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment