xref: /openbsd/gnu/usr.bin/perl/t/perf/benchmarks (revision 6f40fd34)
1#!perl
2
3# This file specifies an array-of-hashes that define snippets of code that
4# can be run by various measurement and profiling tools.
5#
6# The basic idea is that any time you add an optimisation that is intended
7# to make a particular construct faster, then you should add that construct
8# to this file.
9#
10# Under the normal test suite, the test file benchmarks.t does a basic
11# compile and run of each of these snippets; not to test performance,
12# but just to ensure that the code doesn't have errors.
13#
14# Over time, it is intended that various measurement and profiling tools
15# will be written that can run selected (or all) snippets in various
16# environments. These will not be run as part of a normal test suite run.
17#
18# It is intended that the tests in this file will be lightweight; e.g.
19# a hash access, an empty function call, or a single regex match etc.
20#
21# This file is designed to be read in by 'do' (and in such a way that
22# multiple versions of this file from different releases can be read in
23# by a single process).
24#
25# The top-level array has name/hash pairs (we use an array rather than a
26# hash so that duplicate keys can be spotted) Each name is a token that
27# describes a particular test. Code will be compiled in the package named
28# after the token, so it should match /^(\w|::)+$/a. It is intended that
29# this can be used on the command line of tools to select particular
30# tests.
31# In addition, the package names are arranged into an informal hierarchy
32# whose top members are (this is subject to change):
33#
34#     call::     subroutine and method handling
35#     expr::     expressions: e.g. $x=1, $foo{bar}[0]
36#     loop::     structural code like for, while(), etc
37#     regex::    regular expressions
38#     string::   string handling
39#
40#
41# Each hash has three fields:
42#
43#   desc is a description of the test
44#   setup is a string containing setup code
45#   code  is a string containing the code to run in a loop
46#
47# So typically a benchmark tool might do something like
48#
49#   eval "package $token; $setup; for (1..1000000) { $code }"
50#
51# Currently the only tool that uses this file is Porting/bench.pl;
52# try C<perl Porting/bench.pl --help> for more info
53
54
55[
56    'call::sub::empty' => {
57        desc    => 'function call with no args or body',
58        setup   => 'sub f { }',
59        code    => 'f()',
60    },
61    'call::sub::amp_empty' => {
62        desc    => '&foo function call with no args or body',
63        setup   => 'sub f { }; @_ = ();',
64        code    => '&f',
65    },
66    'call::sub::args3' => {
67        desc    => 'function call with 3 local lexical vars',
68        setup   => 'sub f { my ($a, $b, $c) = @_; 1 }',
69        code    => 'f(1,2,3)',
70    },
71    'call::sub::args2_ret1' => {
72        desc    => 'function call with 2 local lex vars and 1 return value',
73        setup   => 'my $x; sub f { my ($a, $b) = @_; $a+$b }',
74        code    => '$x = f(1,2)',
75    },
76    'call::sub::args2_ret1temp' => {
77        desc    => 'function call with 2 local lex vars and 1 return TEMP value',
78        setup   => 'my $x; sub f { my ($a, $b) = @_; \$a }',
79        code    => '$x = f(1,2)',
80    },
81    'call::sub::args3_ret3' => {
82        desc    => 'function call with 3 local lex vars and 3 return values',
83        setup   => 'my @a; sub f { my ($a, $b, $c) = @_; $a+$b, $c, 1 }',
84        code    => '@a = f(1,2,3)',
85    },
86    'call::sub::args3_ret3str' => {
87        desc    => 'function call with 3 local lex vars and 3 string return values',
88        setup   => 'my @a; sub f { my ($a, $b, $c) = @_; my @s = ("aa","bb","cc"); @s }',
89        code    => '@a = f(1,2,3)',
90    },
91    'call::sub::args3_ret3temp' => {
92        desc    => 'function call with 3 local lex vars and 3 TEMP return values',
93        setup   => 'my @a; sub f { my ($a, $b, $c) = @_; 1..3 }',
94        code    => '@a = f(1,2,3)',
95    },
96    'call::sub::recursive' => {
97        desc    => 'basic recursive function call',
98        setup   => 'my $x; sub f { my ($i) = @_; $i > 0 ? $i + f($i-1) : 0 }',
99        code    => '$x = f(1)',
100    },
101
102    'call::goto::empty' => {
103        desc    => 'goto &funtion with no args or body',
104        setup   => 'sub f { goto &g } sub g {}',
105        code    => 'f()',
106    },
107    'call::goto::args3' => {
108        desc    => 'goto &funtion with 3 local lexical vars',
109        setup   => 'sub f { goto &g } sub g { my ($a, $b, $c) = @_ }',
110        code    => 'f(1,2,3)',
111    },
112
113
114    'expr::array::lex_1const_0' => {
115        desc    => 'lexical $array[0]',
116        setup   => 'my @a = (1)',
117        code    => '$a[0]',
118    },
119    'expr::array::lex_1const_m1' => {
120        desc    => 'lexical $array[-1]',
121        setup   => 'my @a = (1)',
122        code    => '$a[-1]',
123    },
124    'expr::array::lex_2const' => {
125        desc    => 'lexical $array[const][const]',
126        setup   => 'my @a = ([1,2])',
127        code    => '$a[0][1]',
128    },
129    'expr::array::lex_2var' => {
130        desc    => 'lexical $array[$i1][$i2]',
131        setup   => 'my ($i1,$i2) = (0,1); my @a = ([1,2])',
132        code    => '$a[$i1][$i2]',
133    },
134    'expr::array::ref_lex_2var' => {
135        desc    => 'lexical $arrayref->[$i1][$i2]',
136        setup   => 'my ($i1,$i2) = (0,1); my $r = [[1,2]]',
137        code    => '$r->[$i1][$i2]',
138    },
139    'expr::array::ref_lex_3const' => {
140        desc    => 'lexical $arrayref->[const][const][const]',
141        setup   => 'my $r = [[[1,2]]]',
142        code    => '$r->[0][0][0]',
143    },
144    'expr::array::ref_expr_lex_3const' => {
145        desc    => '(lexical expr)->[const][const][const]',
146        setup   => 'my $r = [[[1,2]]]',
147        code    => '($r||0)->[0][0][0]',
148    },
149
150
151    'expr::array::pkg_1const_0' => {
152        desc    => 'package $array[0]',
153        setup   => '@a = (1)',
154        code    => '$a[0]',
155    },
156    'expr::array::pkg_1const_m1' => {
157        desc    => 'package $array[-1]',
158        setup   => '@a = (1)',
159        code    => '$a[-1]',
160    },
161    'expr::array::pkg_2const' => {
162        desc    => 'package $array[const][const]',
163        setup   => '@a = ([1,2])',
164        code    => '$a[0][1]',
165    },
166    'expr::array::pkg_2var' => {
167        desc    => 'package $array[$i1][$i2]',
168        setup   => '($i1,$i2) = (0,1); @a = ([1,2])',
169        code    => '$a[$i1][$i2]',
170    },
171    'expr::array::ref_pkg_2var' => {
172        desc    => 'package $arrayref->[$i1][$i2]',
173        setup   => '($i1,$i2) = (0,1); $r = [[1,2]]',
174        code    => '$r->[$i1][$i2]',
175    },
176    'expr::array::ref_pkg_3const' => {
177        desc    => 'package $arrayref->[const][const][const]',
178        setup   => '$r = [[[1,2]]]',
179        code    => '$r->[0][0][0]',
180    },
181    'expr::array::ref_expr_pkg_3const' => {
182        desc    => '(package expr)->[const][const][const]',
183        setup   => '$r = [[[1,2]]]',
184        code    => '($r||0)->[0][0][0]',
185    },
186
187
188    'expr::arrayhash::lex_3var' => {
189        desc    => 'lexical $h{$k1}[$i]{$k2}',
190        setup   => 'my ($i, $k1, $k2) = (0,"foo","bar");'
191                    . 'my %h = (foo => [ { bar => 1 } ])',
192        code    => '$h{$k1}[$i]{$k2}',
193    },
194    'expr::arrayhash::pkg_3var' => {
195        desc    => 'package $h{$k1}[$i]{$k2}',
196        setup   => '($i, $k1, $k2) = (0,"foo","bar");'
197                    . '%h = (foo => [ { bar => 1 } ])',
198        code    => '$h{$k1}[$i]{$k2}',
199    },
200
201
202    'expr::assign::scalar_lex_int' => {
203        desc    => 'lexical $x = 1',
204        setup   => 'my $x',
205        code    => '$x = 1',
206    },
207    'expr::assign::scalar_lex_str' => {
208        desc    => 'lexical $x = "abc"',
209        setup   => 'my $x',
210        code    => '$x = "abc"',
211    },
212    'expr::assign::scalar_lex_strint' => {
213        desc    => 'lexical $x = 1 where $x was previously a string',
214        setup   => 'my $x = "abc"',
215        code    => '$x = 1',
216    },
217    'expr::assign::scalar_lex_intstr' => {
218        desc    => 'lexical $x = "abc" where $x was previously an int',
219        setup   => 'my $x = 1;',
220        code    => '$x = "abc"',
221    },
222    'expr::assign::2list_lex' => {
223        desc    => 'lexical ($x, $y) = (1, 2)',
224        setup   => 'my ($x, $y)',
225        code    => '($x, $y) = (1, 2)',
226    },
227
228
229    'expr::hash::lex_1const' => {
230        desc    => 'lexical $hash{const}',
231        setup   => 'my %h = ("foo" => 1)',
232        code    => '$h{foo}',
233    },
234    'expr::hash::lex_2const' => {
235        desc    => 'lexical $hash{const}{const}',
236        setup   => 'my %h = (foo => { bar => 1 })',
237        code    => '$h{foo}{bar}',
238    },
239    'expr::hash::lex_2var' => {
240        desc    => 'lexical $hash{$k1}{$k2}',
241        setup   => 'my ($k1,$k2) = qw(foo bar); my %h = ($k1 => { $k2 => 1 })',
242        code    => '$h{$k1}{$k2}',
243    },
244    'expr::hash::ref_lex_2var' => {
245        desc    => 'lexical $hashref->{$k1}{$k2}',
246        setup   => 'my ($k1,$k2) = qw(foo bar); my $r = {$k1 => { $k2 => 1 }}',
247        code    => '$r->{$k1}{$k2}',
248    },
249    'expr::hash::ref_lex_3const' => {
250        desc    => 'lexical $hashref->{const}{const}{const}',
251        setup   => 'my $r = {foo => { bar => { baz => 1 }}}',
252        code    => '$r->{foo}{bar}{baz}',
253    },
254    'expr::hash::ref_expr_lex_3const' => {
255        desc    => '(lexical expr)->{const}{const}{const}',
256        setup   => 'my $r = {foo => { bar => { baz => 1 }}}',
257        code    => '($r||0)->{foo}{bar}{baz}',
258    },
259
260
261    'expr::hash::pkg_1const' => {
262        desc    => 'package $hash{const}',
263        setup   => '%h = ("foo" => 1)',
264        code    => '$h{foo}',
265    },
266    'expr::hash::pkg_2const' => {
267        desc    => 'package $hash{const}{const}',
268        setup   => '%h = (foo => { bar => 1 })',
269        code    => '$h{foo}{bar}',
270    },
271    'expr::hash::pkg_2var' => {
272        desc    => 'package $hash{$k1}{$k2}',
273        setup   => '($k1,$k2) = qw(foo bar); %h = ($k1 => { $k2 => 1 })',
274        code    => '$h{$k1}{$k2}',
275    },
276    'expr::hash::ref_pkg_2var' => {
277        desc    => 'package $hashref->{$k1}{$k2}',
278        setup   => '($k1,$k2) = qw(foo bar); $r = {$k1 => { $k2 => 1 }}',
279        code    => '$r->{$k1}{$k2}',
280    },
281    'expr::hash::ref_pkg_3const' => {
282        desc    => 'package $hashref->{const}{const}{const}',
283        setup   => '$r = {foo => { bar => { baz => 1 }}}',
284        code    => '$r->{foo}{bar}{baz}',
285    },
286    'expr::hash::ref_expr_pkg_3const' => {
287        desc    => '(package expr)->{const}{const}{const}',
288        setup   => '$r = {foo => { bar => { baz => 1 }}}',
289        code    => '($r||0)->{foo}{bar}{baz}',
290    },
291
292
293    'expr::hash::exists_lex_2var' => {
294        desc    => 'lexical exists $hash{$k1}{$k2}',
295        setup   => 'my ($k1,$k2) = qw(foo bar); my %h = ($k1 => { $k2 => 1 });',
296        code    => 'exists $h{$k1}{$k2}',
297    },
298    'expr::hash::delete_lex_2var' => {
299        desc    => 'lexical delete $hash{$k1}{$k2}',
300        setup   => 'my ($k1,$k2) = qw(foo bar); my %h = ($k1 => { $k2 => 1 });',
301        code    => 'delete $h{$k1}{$k2}',
302    },
303
304
305    # using a const string as second arg to index triggers using FBM.
306    # the FBM matcher special-cases 1,2-byte strings.
307    #
308    'expr::index::short_const1' => {
309        desc    => 'index of a short string against a 1 char const substr',
310        setup   => 'my $x = "aaaab"',
311        code    => 'index $x, "b"',
312    },
313    'expr::index::long_const1' => {
314        desc    => 'index of a long string against a 1 char const substr',
315        setup   => 'my $x = "a" x 1000 . "b"',
316        code    => 'index $x, "b"',
317    },
318    'expr::index::short_const2aabc_bc' => {
319        desc    => 'index of a short string against a 2 char const substr',
320        setup   => 'my $x = "aaaabc"',
321        code    => 'index $x, "bc"',
322    },
323    'expr::index::long_const2aabc_bc' => {
324        desc    => 'index of a long string against a 2 char const substr',
325        setup   => 'my $x = "a" x 1000 . "bc"',
326        code    => 'index $x, "bc"',
327    },
328    'expr::index::long_const2aa_ab' => {
329        desc    => 'index of a long string aaa.. against const substr "ab"',
330        setup   => 'my $x = "a" x 1000',
331        code    => 'index $x, "ab"',
332    },
333    'expr::index::long_const2bb_ab' => {
334        desc    => 'index of a long string bbb.. against const substr "ab"',
335        setup   => 'my $x = "b" x 1000',
336        code    => 'index $x, "ab"',
337    },
338    'expr::index::long_const2aa_bb' => {
339        desc    => 'index of a long string aaa.. against const substr "bb"',
340        setup   => 'my $x = "a" x 1000',
341        code    => 'index $x, "bb"',
342    },
343    # this one is designed to be pathological
344    'expr::index::long_const2ab_aa' => {
345        desc    => 'index of a long string abab.. against const substr "aa"',
346        setup   => 'my $x = "ab" x 500',
347        code    => 'index $x, "aa"',
348    },
349    # near misses with gaps, 1st letter
350    'expr::index::long_const2aaxx_xy' => {
351        desc    => 'index of a long string with "xx"s against const substr "xy"',
352        setup   => 'my $x = "aaaaaaaaxx" x 100',
353        code    => 'index $x, "xy"',
354    },
355    # near misses with gaps, 2nd letter
356    'expr::index::long_const2aayy_xy' => {
357        desc    => 'index of a long string with "yy"s against const substr "xy"',
358        setup   => 'my $x = "aaaaaaaayy" x 100',
359        code    => 'index $x, "xy"',
360    },
361    # near misses with gaps, duplicate letter
362    'expr::index::long_const2aaxy_xx' => {
363        desc    => 'index of a long string with "xy"s against const substr "xx"',
364        setup   => 'my $x = "aaaaaaaaxy" x 100',
365        code    => 'index $x, "xx"',
366    },
367    # alternating near misses with gaps
368    'expr::index::long_const2aaxxaayy_xy' => {
369        desc    => 'index of a long string with "xx/yy"s against const substr "xy"',
370        setup   => 'my $x = "aaaaaaaaxxbbbbbbbbyy" x 50',
371        code    => 'index $x, "xy"',
372    },
373    'expr::index::short_const3aabcd_bcd' => {
374        desc    => 'index of a short string against a 3 char const substr',
375        setup   => 'my $x = "aaaabcd"',
376        code    => 'index $x, "bcd"',
377    },
378    'expr::index::long_const3aabcd_bcd' => {
379        desc    => 'index of a long string against a 3 char const substr',
380        setup   => 'my $x = "a" x 1000 . "bcd"',
381        code    => 'index $x, "bcd"',
382    },
383    'expr::index::long_const3ab_abc' => {
384        desc    => 'index of a long string of "ab"s against a 3 char const substr "abc"',
385        setup   => 'my $x = "ab" x 500',
386        code    => 'index $x, "abc"',
387    },
388    'expr::index::long_const3bc_abc' => {
389        desc    => 'index of a long string of "bc"s against a 3 char const substr "abc"',
390        setup   => 'my $x = "bc" x 500',
391        code    => 'index $x, "abc"',
392    },
393    'expr::index::utf8_position_1' => {
394        desc    => 'index of a utf8 string, matching at position 1',
395        setup   => 'my $x = "abc". chr(0x100); chop $x',
396        code    => 'index $x, "b"',
397    },
398
399
400    # list assign, OP_AASSIGN
401
402
403    # (....) = ()
404
405    'expr::aassign::ma_empty' => {
406        desc    => 'my array assigned empty',
407        setup   => '',
408        code    => 'my @a = ()',
409    },
410    'expr::aassign::lax_empty' => {
411        desc    => 'non-empty lexical array assigned empty',
412        setup   => 'my @a = 1..3;',
413        code    => '@a = ()',
414    },
415    'expr::aassign::llax_empty' => {
416        desc    => 'non-empty lexical var and array assigned empty',
417        setup   => 'my ($x, @a) = 1..4;',
418        code    => '($x, @a) = ()',
419    },
420    'expr::aassign::3m_empty' => {
421        desc    => 'three my vars assigned empty',
422        setup   => '',
423        code    => 'my ($x,$y,$z) = ()',
424    },
425    'expr::aassign::3l_empty' => {
426        desc    => 'three lexical vars assigned empty',
427        setup   => 'my ($x,$y,$z)',
428        code    => '($x,$y,$z) = ()',
429    },
430    'expr::aassign::pa_empty' => {
431        desc    => 'package array assigned empty',
432        setup   => '',
433        code    => '@a = ()',
434    },
435    'expr::aassign::pax_empty' => {
436        desc    => 'non-empty package array assigned empty',
437        setup   => '@a = (1,2,3)',
438        code    => '@a = ()',
439    },
440    'expr::aassign::3p_empty' => {
441        desc    => 'three package vars assigned empty',
442        setup   => '($x,$y,$z) = 1..3;',
443        code    => '($x,$y,$z) = ()',
444    },
445
446    # (....) = (1,2,3)
447
448    'expr::aassign::ma_3c' => {
449        desc    => 'my array assigned 3 consts',
450        setup   => '',
451        code    => 'my @a = (1,2,3)',
452    },
453    'expr::aassign::lax_3c' => {
454        desc    => 'non-empty lexical array assigned 3 consts',
455        setup   => 'my @a = 1..3;',
456        code    => '@a = (1,2,3)',
457    },
458    'expr::aassign::llax_3c' => {
459        desc    => 'non-empty lexical var and array assigned 3 consts',
460        setup   => 'my ($x, @a) = 1..4;',
461        code    => '($x, @a) = (1,2,3)',
462    },
463    'expr::aassign::3m_3c' => {
464        desc    => 'three my vars assigned 3 consts',
465        setup   => '',
466        code    => 'my ($x,$y,$z) = (1,2,3)',
467    },
468    'expr::aassign::3l_3c' => {
469        desc    => 'three lexical vars assigned 3 consts',
470        setup   => 'my ($x,$y,$z)',
471        code    => '($x,$y,$z) = (1,2,3)',
472    },
473    'expr::aassign::pa_3c' => {
474        desc    => 'package array assigned 3 consts',
475        setup   => '',
476        code    => '@a = (1,2,3)',
477    },
478    'expr::aassign::pax_3c' => {
479        desc    => 'non-empty package array assigned 3 consts',
480        setup   => '@a = (1,2,3)',
481        code    => '@a = (1,2,3)',
482    },
483    'expr::aassign::3p_3c' => {
484        desc    => 'three package vars assigned 3 consts',
485        setup   => '($x,$y,$z) = 1..3;',
486        code    => '($x,$y,$z) = (1,2,3)',
487    },
488
489    # (....) = @lexical
490
491    'expr::aassign::ma_la' => {
492        desc    => 'my array assigned lexical array',
493        setup   => 'my @init = 1..3;',
494        code    => 'my @a = @init',
495    },
496    'expr::aassign::lax_la' => {
497        desc    => 'non-empty lexical array assigned lexical array',
498        setup   => 'my @init = 1..3; my @a = 1..3;',
499        code    => '@a = @init',
500    },
501    'expr::aassign::llax_la' => {
502        desc    => 'non-empty lexical var and array assigned lexical array',
503        setup   => 'my @init = 1..3; my ($x, @a) = 1..4;',
504        code    => '($x, @a) = @init',
505    },
506    'expr::aassign::3m_la' => {
507        desc    => 'three my vars assigned lexical array',
508        setup   => 'my @init = 1..3;',
509        code    => 'my ($x,$y,$z) = @init',
510    },
511    'expr::aassign::3l_la' => {
512        desc    => 'three lexical vars assigned lexical array',
513        setup   => 'my @init = 1..3; my ($x,$y,$z)',
514        code    => '($x,$y,$z) = @init',
515    },
516    'expr::aassign::pa_la' => {
517        desc    => 'package array assigned lexical array',
518        setup   => 'my @init = 1..3;',
519        code    => '@a = @init',
520    },
521    'expr::aassign::pax_la' => {
522        desc    => 'non-empty package array assigned lexical array',
523        setup   => 'my @init = 1..3; @a = @init',
524        code    => '@a = @init',
525    },
526    'expr::aassign::3p_la' => {
527        desc    => 'three package vars assigned lexical array',
528        setup   => 'my @init = 1..3; ($x,$y,$z) = 1..3;',
529        code    => '($x,$y,$z) = @init',
530    },
531
532    # (....) = @package
533
534    'expr::aassign::ma_pa' => {
535        desc    => 'my array assigned package array',
536        setup   => '@init = 1..3;',
537        code    => 'my @a = @init',
538    },
539    'expr::aassign::lax_pa' => {
540        desc    => 'non-empty lexical array assigned package array',
541        setup   => '@init = 1..3; my @a = 1..3;',
542        code    => '@a = @init',
543    },
544    'expr::aassign::llax_pa' => {
545        desc    => 'non-empty lexical var and array assigned package array',
546        setup   => '@init = 1..3; my ($x, @a) = 1..4;',
547        code    => '($x, @a) = @init',
548    },
549    'expr::aassign::3m_pa' => {
550        desc    => 'three my vars assigned package array',
551        setup   => '@init = 1..3;',
552        code    => 'my ($x,$y,$z) = @init',
553    },
554    'expr::aassign::3l_pa' => {
555        desc    => 'three lexical vars assigned package array',
556        setup   => '@init = 1..3; my ($x,$y,$z)',
557        code    => '($x,$y,$z) = @init',
558    },
559    'expr::aassign::pa_pa' => {
560        desc    => 'package array assigned package array',
561        setup   => '@init = 1..3;',
562        code    => '@a = @init',
563    },
564    'expr::aassign::pax_pa' => {
565        desc    => 'non-empty package array assigned package array',
566        setup   => '@init = 1..3; @a = @init',
567        code    => '@a = @init',
568    },
569    'expr::aassign::3p_pa' => {
570        desc    => 'three package vars assigned package array',
571        setup   => '@init = 1..3; ($x,$y,$z) = 1..3;',
572        code    => '($x,$y,$z) = @init',
573    },
574
575    # (....) = @_;
576
577    'expr::aassign::ma_defary' => {
578        desc    => 'my array assigned @_',
579        setup   => '@_ = 1..3;',
580        code    => 'my @a = @_',
581    },
582    'expr::aassign::lax_defary' => {
583        desc    => 'non-empty lexical array assigned @_',
584        setup   => '@_ = 1..3; my @a = 1..3;',
585        code    => '@a = @_',
586    },
587    'expr::aassign::llax_defary' => {
588        desc    => 'non-empty lexical var and array assigned @_',
589        setup   => '@_ = 1..3; my ($x, @a) = 1..4;',
590        code    => '($x, @a) = @_',
591    },
592    'expr::aassign::3m_defary' => {
593        desc    => 'three my vars assigned @_',
594        setup   => '@_ = 1..3;',
595        code    => 'my ($x,$y,$z) = @_',
596    },
597    'expr::aassign::3l_defary' => {
598        desc    => 'three lexical vars assigned @_',
599        setup   => '@_ = 1..3; my ($x,$y,$z)',
600        code    => '($x,$y,$z) = @_',
601    },
602    'expr::aassign::pa_defary' => {
603        desc    => 'package array assigned @_',
604        setup   => '@_ = 1..3;',
605        code    => '@a = @_',
606    },
607    'expr::aassign::pax_defary' => {
608        desc    => 'non-empty package array assigned @_',
609        setup   => '@_ = 1..3; @a = @_',
610        code    => '@a = @_',
611    },
612    'expr::aassign::3p_defary' => {
613        desc    => 'three package vars assigned @_',
614        setup   => '@_ = 1..3; ($x,$y,$z) = 1..3;',
615        code    => '($x,$y,$z) = @_',
616    },
617
618
619    # (....) = ($lex1,$lex2,$lex3);
620
621    'expr::aassign::ma_3l' => {
622        desc    => 'my array assigned lexicals',
623        setup   => 'my ($v1,$v2,$v3) = 1..3;',
624        code    => 'my @a = ($v1,$v2,$v3)',
625    },
626    'expr::aassign::lax_3l' => {
627        desc    => 'non-empty lexical array assigned lexicals',
628        setup   => 'my ($v1,$v2,$v3) = 1..3; my @a = 1..3;',
629        code    => '@a = ($v1,$v2,$v3)',
630    },
631    'expr::aassign::llax_3l' => {
632        desc    => 'non-empty lexical var and array assigned lexicals',
633        setup   => 'my ($v1,$v2,$v3) = 1..3; my ($x, @a) = 1..4;',
634        code    => '($x, @a) = ($v1,$v2,$v3)',
635    },
636    'expr::aassign::3m_3l' => {
637        desc    => 'three my vars assigned lexicals',
638        setup   => 'my ($v1,$v2,$v3) = 1..3;',
639        code    => 'my ($x,$y,$z) = ($v1,$v2,$v3)',
640    },
641    'expr::aassign::3l_3l' => {
642        desc    => 'three lexical vars assigned lexicals',
643        setup   => 'my ($v1,$v2,$v3) = 1..3; my ($x,$y,$z)',
644        code    => '($x,$y,$z) = ($v1,$v2,$v3)',
645    },
646    'expr::aassign::pa_3l' => {
647        desc    => 'package array assigned lexicals',
648        setup   => 'my ($v1,$v2,$v3) = 1..3;',
649        code    => '@a = ($v1,$v2,$v3)',
650    },
651    'expr::aassign::pax_3l' => {
652        desc    => 'non-empty package array assigned lexicals',
653        setup   => 'my ($v1,$v2,$v3) = 1..3; @a = @_',
654        code    => '@a = ($v1,$v2,$v3)',
655    },
656    'expr::aassign::3p_3l' => {
657        desc    => 'three package vars assigned lexicals',
658        setup   => 'my ($v1,$v2,$v3) = 1..3; ($x,$y,$z) = 1..3;',
659        code    => '($x,$y,$z) = ($v1,$v2,$v3)',
660    },
661
662
663    # (....) = ($pkg1,$pkg2,$pkg3);
664
665    'expr::aassign::ma_3p' => {
666        desc    => 'my array assigned 3 package vars',
667        setup   => '($v1,$v2,$v3) = 1..3;',
668        code    => 'my @a = ($v1,$v2,$v3)',
669    },
670    'expr::aassign::lax_3p' => {
671        desc    => 'non-empty lexical array assigned 3 package vars',
672        setup   => '($v1,$v2,$v3) = 1..3; my @a = 1..3;',
673        code    => '@a = ($v1,$v2,$v3)',
674    },
675    'expr::aassign::llax_3p' => {
676        desc    => 'non-empty lexical var and array assigned 3 package vars',
677        setup   => '($v1,$v2,$v3) = 1..3; my ($x, @a) = 1..4;',
678        code    => '($x, @a) = ($v1,$v2,$v3)',
679    },
680    'expr::aassign::3m_3p' => {
681        desc    => 'three my vars assigned 3 package vars',
682        setup   => '($v1,$v2,$v3) = 1..3;',
683        code    => 'my ($x,$y,$z) = ($v1,$v2,$v3)',
684    },
685    'expr::aassign::3l_3p' => {
686        desc    => 'three lexical vars assigned 3 package vars',
687        setup   => '($v1,$v2,$v3) = 1..3; my ($x,$y,$z)',
688        code    => '($x,$y,$z) = ($v1,$v2,$v3)',
689    },
690    'expr::aassign::pa_3p' => {
691        desc    => 'package array assigned 3 package vars',
692        setup   => '($v1,$v2,$v3) = 1..3;',
693        code    => '@a = ($v1,$v2,$v3)',
694    },
695    'expr::aassign::pax_3p' => {
696        desc    => 'non-empty package array assigned 3 package vars',
697        setup   => '($v1,$v2,$v3) = 1..3; @a = @_',
698        code    => '@a = ($v1,$v2,$v3)',
699    },
700    'expr::aassign::3p_3p' => {
701        desc    => 'three package vars assigned 3 package vars',
702        setup   => '($v1,$v2,$v3) = 1..3; ($x,$y,$z) = 1..3;',
703        code    => '($x,$y,$z) = ($v1,$v2,$v3)',
704    },
705
706
707    # (....) = (1,2,$shared);
708
709    'expr::aassign::llax_2c1s' => {
710        desc    => 'non-empty lexical var and array assigned 2 consts and 1 shared var',
711        setup   => 'my ($x, @a) = 1..4;',
712        code    => '($x, @a) = (1,2,$x)',
713    },
714    'expr::aassign::3l_2c1s' => {
715        desc    => 'three lexical vars assigned 2 consts and 1 shared var',
716        setup   => 'my ($x,$y,$z) = 1..3;',
717        code    => '($x,$y,$z) = (1,2,$x)',
718    },
719    'expr::aassign::3p_2c1s' => {
720        desc    => 'three package vars assigned 2 consts and 1 shared var',
721        setup   => '($x,$y,$z) = 1..3;',
722        code    => '($x,$y,$z) = (1,2,$x)',
723    },
724
725
726    # ($a,$b) = ($b,$a);
727
728    'expr::aassign::2l_swap' => {
729        desc    => 'swap two lexical vars',
730        setup   => 'my ($a,$b) = (1,2)',
731        code    => '($a,$b) = ($b,$a)',
732    },
733    'expr::aassign::2p_swap' => {
734        desc    => 'swap two package vars',
735        setup   => '($a,$b) = (1,2)',
736        code    => '($a,$b) = ($b,$a)',
737    },
738    'expr::aassign::2laelem_swap' => {
739        desc    => 'swap two lexical vars',
740        setup   => 'my @a = (1,2)',
741        code    => '($a[0],$a[1]) = ($a[1],$a[0])',
742    },
743
744    # misc list assign
745
746    'expr::aassign::5l_4l1s' => {
747        desc    => 'long list of lexical vars, 1 shared',
748        setup   => 'my ($a,$b,$c,$d,$e) = 1..5',
749        code    => '($a,$b,$c,$d,$e) = ($a,$a,$c,$d,$e)',
750    },
751
752    'expr::aassign::5p_4p1s' => {
753        desc    => 'long list of package vars, 1 shared',
754        setup   => '($a,$b,$c,$d,$e) = 1..5',
755        code    => '($a,$b,$c,$d,$e) = ($a,$a,$c,$d,$e)',
756    },
757    'expr::aassign::5l_defary' => {
758        desc    => 'long list of lexical vars to assign @_ to',
759        setup   => '@_ = 1..5',
760        code    => 'my ($a,$b,$c,$d,$e) = @_',
761    },
762    'expr::aassign::5l1la_defary' => {
763        desc    => 'long list of lexical vars plus long slurp to assign @_ to',
764        setup   => '@_ = 1..20',
765        code    => 'my ($a,$b,$c,$d,$e,@rest) = @_',
766    },
767    'expr::aassign::1l_2l' => {
768        desc    => 'single lexical LHS',
769        setup   => 'my $x = 1;',
770        code    => '(undef,$x) = ($x,$x)',
771    },
772    'expr::aassign::2l_1l' => {
773        desc    => 'single lexical RHS',
774        setup   => 'my $x = 1;',
775        code    => '($x,$x) = ($x)',
776    },
777    'expr::aassign::2l_1ul' => {
778        desc    => 'undef and single lexical RHS',
779        setup   => 'my $x = 1;',
780        code    => '($x,$x) = (undef, $x)',
781    },
782
783
784    'expr::arith::add_lex_ii' => {
785        desc    => 'add two integers and assign to a lexical var',
786        setup   => 'my ($x,$y,$z) = 1..3;',
787        code    => '$z = $x + $y',
788    },
789    'expr::arith::add_pkg_ii' => {
790        desc    => 'add two integers and assign to a package var',
791        setup   => 'my ($x,$y) = 1..2; $z = 3;',
792        code    => '$z = $x + $y',
793    },
794    'expr::arith::add_lex_nn' => {
795        desc    => 'add two NVs and assign to a lexical var',
796        setup   => 'my ($x,$y,$z) = (1.1, 2.2, 3.3);',
797        code    => '$z = $x + $y',
798    },
799    'expr::arith::add_pkg_nn' => {
800        desc    => 'add two NVs and assign to a package var',
801        setup   => 'my ($x,$y); ($x,$y,$z) = (1.1, 2.2, 3.3);',
802        code    => '$z = $x + $y',
803    },
804    'expr::arith::add_lex_ni' => {
805        desc    => 'add an int and an NV and assign to a lexical var',
806        setup   => 'my ($x,$y,$z) = (1, 2.2, 3.3);',
807        code    => '$z = $x + $y',
808    },
809    'expr::arith::add_pkg_ni' => {
810        desc    => 'add an int and an NV and assign to a package var',
811        setup   => 'my ($x,$y); ($x,$y,$z) = (1, 2.2, 3.3);',
812        code    => '$z = $x + $y',
813    },
814
815    'expr::arith::sub_lex_ii' => {
816        desc    => 'subtract two integers and assign to a lexical var',
817        setup   => 'my ($x,$y,$z) = 1..3;',
818        code    => '$z = $x - $y',
819    },
820    'expr::arith::sub_pkg_ii' => {
821        desc    => 'subtract two integers and assign to a package var',
822        setup   => 'my ($x,$y) = 1..2; $z = 3;',
823        code    => '$z = $x - $y',
824    },
825    'expr::arith::sub_lex_nn' => {
826        desc    => 'subtract two NVs and assign to a lexical var',
827        setup   => 'my ($x,$y,$z) = (1.1, 2.2, 3.3);',
828        code    => '$z = $x - $y',
829    },
830    'expr::arith::sub_pkg_nn' => {
831        desc    => 'subtract two NVs and assign to a package var',
832        setup   => 'my ($x,$y); ($x,$y,$z) = (1.1, 2.2, 3.3);',
833        code    => '$z = $x - $y',
834    },
835    'expr::arith::sub_lex_ni' => {
836        desc    => 'subtract an int and an NV and assign to a lexical var',
837        setup   => 'my ($x,$y,$z) = (1, 2.2, 3.3);',
838        code    => '$z = $x - $y',
839    },
840    'expr::arith::sub_pkg_ni' => {
841        desc    => 'subtract an int and an NV and assign to a package var',
842        setup   => 'my ($x,$y); ($x,$y,$z) = (1, 2.2, 3.3);',
843        code    => '$z = $x - $y',
844    },
845
846    'expr::arith::mult_lex_ii' => {
847        desc    => 'multiply two integers and assign to a lexical var',
848        setup   => 'my ($x,$y,$z) = 1..3;',
849        code    => '$z = $x * $y',
850    },
851    'expr::arith::mult_pkg_ii' => {
852        desc    => 'multiply two integers and assign to a package var',
853        setup   => 'my ($x,$y) = 1..2; $z = 3;',
854        code    => '$z = $x * $y',
855    },
856    'expr::arith::mult_lex_nn' => {
857        desc    => 'multiply two NVs and assign to a lexical var',
858        setup   => 'my ($x,$y,$z) = (1.1, 2.2, 3.3);',
859        code    => '$z = $x * $y',
860    },
861    'expr::arith::mult_pkg_nn' => {
862        desc    => 'multiply two NVs and assign to a package var',
863        setup   => 'my ($x,$y); ($x,$y,$z) = (1.1, 2.2, 3.3);',
864        code    => '$z = $x * $y',
865    },
866    'expr::arith::mult_lex_ni' => {
867        desc    => 'multiply an int and an NV and assign to a lexical var',
868        setup   => 'my ($x,$y,$z) = (1, 2.2, 3.3);',
869        code    => '$z = $x * $y',
870    },
871    'expr::arith::mult_pkg_ni' => {
872        desc    => 'multiply an int and an NV and assign to a package var',
873        setup   => 'my ($x,$y); ($x,$y,$z) = (1, 2.2, 3.3);',
874        code    => '$z = $x * $y',
875    },
876
877    'expr::arith::preinc' => {
878        desc    => '++$x',
879        setup   => 'my $x = 1;',
880        code    => '++$x',
881    },
882    'expr::arith::predec' => {
883        desc    => '--$x',
884        setup   => 'my $x = 1;',
885        code    => '--$x',
886    },
887    'expr::arith::postinc' => {
888        desc    => '$x++',
889        setup   => 'my $x = 1; my $y',
890        code    => '$y = $x++', # scalar context so not optimised to ++$x
891    },
892    'expr::arith::postdec' => {
893        desc    => '$x--',
894        setup   => 'my $x = 1; my $y',
895        code    => '$y = $x--', # scalar context so not optimised to --$x
896    },
897
898    'loop::block' => {
899        desc    => 'empty basic loop',
900        setup   => ';',
901        code    => '{1;}',
902    },
903
904    'loop::do' => {
905        desc    => 'basic do block',
906        setup   => 'my $x; my $y = 2;',
907        code    => '$x = do {1; $y}', # the ';' stops the do being optimised
908    },
909
910    'loop::for::my_range1' => {
911        desc    => 'empty for loop with my var and 1 integer range',
912        setup   => '',
913        code    => 'for my $x (1..1) {}',
914    },
915    'loop::for::lex_range1' => {
916        desc    => 'empty for loop with lexical var and 1 integer range',
917        setup   => 'my $x;',
918        code    => 'for $x (1..1) {}',
919    },
920    'loop::for::pkg_range1' => {
921        desc    => 'empty for loop with package var and 1 integer range',
922        setup   => '$x = 1;',
923        code    => 'for $x (1..1) {}',
924    },
925    'loop::for::defsv_range1' => {
926        desc    => 'empty for loop with $_ and integer 1 range',
927        setup   => ';',
928        code    => 'for (1..1) {}',
929    },
930    'loop::for::my_range4' => {
931        desc    => 'empty for loop with my var and 4 integer range',
932        setup   => '',
933        code    => 'for my $x (1..4) {}',
934    },
935    'loop::for::lex_range4' => {
936        desc    => 'empty for loop with lexical var and 4 integer range',
937        setup   => 'my $x;',
938        code    => 'for $x (1..4) {}',
939    },
940    'loop::for::pkg_range4' => {
941        desc    => 'empty for loop with package var and 4 integer range',
942        setup   => '$x = 1;',
943        code    => 'for $x (1..4) {}',
944    },
945    'loop::for::defsv_range4' => {
946        desc    => 'empty for loop with $_ and integer 4 range',
947        setup   => ';',
948        code    => 'for (1..4) {}',
949    },
950
951    'loop::for::my_list1' => {
952        desc    => 'empty for loop with my var and 1 integer list',
953        setup   => '',
954        code    => 'for my $x (1) {}',
955    },
956    'loop::for::lex_list1' => {
957        desc    => 'empty for loop with lexical var and 1 integer list',
958        setup   => 'my $x;',
959        code    => 'for $x (1) {}',
960    },
961    'loop::for::pkg_list1' => {
962        desc    => 'empty for loop with package var and 1 integer list',
963        setup   => '$x = 1;',
964        code    => 'for $x (1) {}',
965    },
966    'loop::for::defsv_list1' => {
967        desc    => 'empty for loop with $_ and integer 1 list',
968        setup   => ';',
969        code    => 'for (1) {}',
970    },
971    'loop::for::my_list4' => {
972        desc    => 'empty for loop with my var and 4 integer list',
973        setup   => '',
974        code    => 'for my $x (1,2,3,4) {}',
975    },
976    'loop::for::lex_list4' => {
977        desc    => 'empty for loop with lexical var and 4 integer list',
978        setup   => 'my $x;',
979        code    => 'for $x (1,2,3,4) {}',
980    },
981    'loop::for::pkg_list4' => {
982        desc    => 'empty for loop with package var and 4 integer list',
983        setup   => '$x = 1;',
984        code    => 'for $x (1,2,3,4) {}',
985    },
986    'loop::for::defsv_list4' => {
987        desc    => 'empty for loop with $_ and integer 4 list',
988        setup   => '',
989        code    => 'for (1,2,3,4) {}',
990    },
991
992    'loop::for::my_array1' => {
993        desc    => 'empty for loop with my var and 1 integer array',
994        setup   => 'my @a = (1);',
995        code    => 'for my $x (@a) {}',
996    },
997    'loop::for::lex_array1' => {
998        desc    => 'empty for loop with lexical var and 1 integer array',
999        setup   => 'my $x; my @a = (1);',
1000        code    => 'for $x (@a) {}',
1001    },
1002    'loop::for::pkg_array1' => {
1003        desc    => 'empty for loop with package var and 1 integer array',
1004        setup   => '$x = 1; my @a = (1);',
1005        code    => 'for $x (@a) {}',
1006    },
1007    'loop::for::defsv_array1' => {
1008        desc    => 'empty for loop with $_ and integer 1 array',
1009        setup   => 'my @a = (@a);',
1010        code    => 'for (1) {}',
1011    },
1012    'loop::for::my_array4' => {
1013        desc    => 'empty for loop with my var and 4 integer array',
1014        setup   => 'my @a = (1..4);',
1015        code    => 'for my $x (@a) {}',
1016    },
1017    'loop::for::lex_array4' => {
1018        desc    => 'empty for loop with lexical var and 4 integer array',
1019        setup   => 'my $x; my @a = (1..4);',
1020        code    => 'for $x (@a) {}',
1021    },
1022    'loop::for::pkg_array4' => {
1023        desc    => 'empty for loop with package var and 4 integer array',
1024        setup   => '$x = 1; my @a = (1..4);',
1025        code    => 'for $x (@a) {}',
1026    },
1027    'loop::for::defsv_array4' => {
1028        desc    => 'empty for loop with $_ and integer 4 array',
1029        setup   => 'my @a = (1..4);',
1030        code    => 'for (@a) {}',
1031    },
1032
1033    'loop::for::next4' => {
1034        desc    => 'for loop containing only next with my var and integer 4 array',
1035        setup   => 'my @a = (1..4);',
1036        code    => 'for my $x (@a) {next}',
1037    },
1038
1039    'loop::grep::expr_3int' => {
1040        desc    => 'grep $_ > 0, 1,2,3',
1041        setup   => 'my @a',
1042        code    => '@a = grep $_ > 0, 1,2,3',
1043    },
1044
1045    'loop::grep::block_3int' => {
1046        desc    => 'grep { 1; $_ > 0} 1,2,3',
1047        setup   => 'my @a',
1048        code    => '@a = grep { 1; $_ > 0} 1,2,3',
1049    },
1050
1051    'loop::map::expr_3int' => {
1052        desc    => 'map $_+1, 1,2,3',
1053        setup   => 'my @a',
1054        code    => '@a = map $_+1, 1,2,3',
1055    },
1056
1057    'loop::map::block_3int' => {
1058        desc    => 'map { 1; $_+1} 1,2,3',
1059        setup   => 'my @a',
1060        code    => '@a = map { 1; $_+1} 1,2,3',
1061    },
1062
1063    'loop::while::i1' => {
1064        desc    => 'empty while loop 1 iteration',
1065        setup   => 'my $i = 0;',
1066        code    => 'while (++$i % 2) {}',
1067    },
1068    'loop::while::i4' => {
1069        desc    => 'empty while loop 4 iterations',
1070        setup   => 'my $i = 0;',
1071        code    => 'while (++$i % 4) {}',
1072    },
1073
1074];
1075