This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
pp_leavesub(): call FREETMPS and optimise
[perl5.git] / t / perf / benchmarks
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::while::i1' => {
1034         desc    => 'empty while loop 1 iteration',
1035         setup   => 'my $i = 0;',
1036         code    => 'while (++$i % 2) {}',
1037     },
1038     'loop::while::i4' => {
1039         desc    => 'empty while loop 4 iterations',
1040         setup   => 'my $i = 0;',
1041         code    => 'while (++$i % 4) {}',
1042     },
1043
1044 ];