Skip to content

Instantly share code, notes, and snippets.

@MasterDuke17
Last active November 7, 2020 18:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MasterDuke17/46b89eae73953d78b20fbd4c6c6cc060 to your computer and use it in GitHub Desktop.
Save MasterDuke17/46b89eae73953d78b20fbd4c6c6cc060 to your computer and use it in GitHub Desktop.
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) {
[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