diff options
author | Richard Leach <richardleach@users.noreply.github.com> | 2022-08-02 21:48:26 +0000 |
---|---|---|
committer | Richard Leach <richardleach@users.noreply.github.com> | 2022-10-24 23:21:17 +0100 |
commit | 10a5c9138224597d018843f3b298a928555b67f0 (patch) | |
tree | 008b756c7b5f34777576c94ebca07c22ee4c271f /t/perf | |
parent | 71a3dd321d7fa8259a22a1ca1e87aa820a8deef2 (diff) | |
download | perl-10a5c9138224597d018843f3b298a928555b67f0.tar.gz |
OP_EMPTYAVHV - optimized empty ANONLIST/ANONHASH
This commit introduces a new OP to replace cases of OP_ANONLIST and
OP_ANONHASH where there are zero elements, which is very common in
Perl code.
As an example, `my $x = {}` is currently implemented like this:
...
6 <2> sassign vKS/2 ->7
4 <@> anonhash sK* ->5
3 <0> pushmark s ->4
5 <0> padsv[$x:1,2] sRM*/LVINTRO ->6
The pushmark serves no meaningful purpose when there are zero
elements and the anonhash, besides undoing the pushmark,
performs work that is unnecessary for this special case.
The peephole optimizer, which also checks for applicability of a
related TARGMY optimization, transforms this example into:
...
- <1> ex-sassign vKS/2 ->4
3 <@> emptyavhv[$x:1,2] vK*/LVINTRO,ANONHASH,TARGMY ->4
- <0> ex-pushmark s ->3
- <0> ex-padsv sRM*/LVINTRO ->-
Diffstat (limited to 't/perf')
-rw-r--r-- | t/perf/benchmarks | 29 | ||||
-rw-r--r-- | t/perf/opcount.t | 96 |
2 files changed, 124 insertions, 1 deletions
diff --git a/t/perf/benchmarks b/t/perf/benchmarks index 7b457abff3..92f946bbce 100644 --- a/t/perf/benchmarks +++ b/t/perf/benchmarks @@ -1367,6 +1367,31 @@ code => 'undef my $x', }, + 'expr::sassign::anonlist' => { + setup => '', + code => '$x = []' + }, + 'expr::sassign::anonlist_lex' => { + setup => 'my $x', + code => '$x = []' + }, + 'expr::sassign::my_anonlist_lex' => { + setup => '', + code => 'my $x = []' + }, + 'expr::sassign::anonhash' => { + setup => '', + code => '$x = {}' + }, + 'expr::sassign::anonhash_lex' => { + setup => 'my $x', + code => '$x = {}' + }, + 'expr::sassign::my_anonhash_lex' => { + setup => '', + code => 'my $x = {}' + }, + 'expr::sassign::my_conststr' => { setup => '', code => 'my $x = "abc"', @@ -1418,6 +1443,10 @@ code => '$x[0][1] = 1', }, + 'expr::sassign::bless_lex' => { + setup => 'my $x', + code => '$x = bless {}, "X"' + }, 'func::grep::bool0' => { desc => 'grep returning 0 items in boolean context', diff --git a/t/perf/opcount.t b/t/perf/opcount.t index cca8dec397..4651f2442e 100644 --- a/t/perf/opcount.t +++ b/t/perf/opcount.t @@ -868,9 +868,10 @@ test_opcount(0, 'my $h= {}; my @k= keys %{($h=undef)||{}};', { undef => 1, aassign => 1, + emptyavhv => 2, padav => 1, padsv => 0, - padsv_store => 1, + padsv_store => 0, sassign => 0, }); @@ -918,4 +919,97 @@ test_opcount(0, "no aelemfast_lex + sassign replacement with multideref", sassign => 1, }); +# emptyavhv optimizations + +test_opcount(0, "Empty anonlist", + sub { [] }, + { + anonlist => 0, + emptyavhv => 1, + sassign => 0, + }); +test_opcount(0, "Empty anonlist with global assignment", + sub { our $x; $x = [] }, + { + anonlist => 0, + emptyavhv => 1, + gvsv => 1, + pushmark => 0, + sassign => 1, + }); +test_opcount(0, "Empty anonlist and lexical assignment", + sub { my $x; $x = [] }, + { + anonlist => 0, + emptyavhv => 1, + padsv => 1, + pushmark => 0, + sassign => 0, + }); +test_opcount(0, "Empty anonlist and direct lexical assignment", + sub { my $x = [] }, + { + anonlist => 0, + emptyavhv => 1, + padsv => 0, + pushmark => 0, + sassign => 0, + }); +test_opcount(0, "Empty anonlist ref and direct lexical assignment", + sub { my $x = \[] }, + { + anonlist => 0, + emptyavhv => 1, + padsv => 0, + padsv_store => 1, + pushmark => 0, + sassign => 0, + srefgen => 1, + }); +test_opcount(0, "Empty anonhash", + sub { {} }, + { + anonhash => 0, + emptyavhv => 1, + sassign => 0, + }); +test_opcount(0, "Empty anonhash with global assignment", + sub { our $x; $x = {} }, + { + anonhash => 0, + emptyavhv => 1, + gvsv => 1, + pushmark => 0, + sassign => 1, + }); +test_opcount(0, "Empty anonhash and lexical assignment", + sub { my $x; $x = {} }, + { + anonhash => 0, + emptyavhv => 1, + padsv => 1, + pushmark => 0, + sassign => 0, + }); +test_opcount(0, "Empty anonhash and direct lexical assignment", + sub { my $x = {} }, + { + anonhash => 0, + emptyavhv => 1, + padsv => 0, + pushmark => 0, + sassign => 0, + }); +test_opcount(0, "Empty anonhash ref and direct lexical assignment", + sub { my $x = \{} }, + { + anonhash => 0, + emptyavhv => 1, + padsv => 0, + padsv_store => 1, + pushmark => 0, + sassign => 0, + srefgen => 1, + }); + done_testing(); |