Update copyright notices with scripts/update-copyrights
[glibc.git] / scripts / bench.pl
blob569cd5156ac1194e6ec6e45eb48ef8c75707a8ea
1 #! /usr/bin/perl -w
2 # Copyright (C) 2013-2014 Free Software Foundation, Inc.
3 # This file is part of the GNU C Library.
5 # The GNU C Library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License, or (at your option) any later version.
10 # The GNU C Library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with the GNU C Library; if not, see
17 # <http://www.gnu.org/licenses/>.
20 use strict;
21 use warnings;
22 # Generate a benchmark source file for a given input.
24 if (@ARGV < 1) {
25 die "Usage: bench.pl <function>"
28 my $func = $ARGV[0];
29 my @args;
30 my $ret = "void";
31 my $getret = "";
33 # We create a hash of inputs for each variant of the test.
34 my $variant = "";
35 my @curvals;
36 my %vals;
37 my @include_headers;
38 my @include_sources;
39 my $incl;
41 open INPUTS, "<$func-inputs" or die $!;
43 LINE:while (<INPUTS>) {
44 chomp;
46 # Directives.
47 if (/^## ([\w-]+): (.*)/) {
48 # Function argument types.
49 if ($1 eq "args") {
50 @args = split(":", $2);
53 # Function return type.
54 elsif ($1 eq "ret") {
55 $ret = $2;
58 elsif ($1 eq "includes") {
59 @include_headers = split (",", $2);
62 elsif ($1 eq "include-sources") {
63 @include_sources = split (",", $2);
66 # New variant. This is the only directive allowed in the body of the
67 # inputs to separate inputs into variants. All others should be at the
68 # top or else all hell will break loose.
69 elsif ($1 eq "name") {
71 # Save values in the previous variant.
72 my @copy = @curvals;
73 $vals{$variant} = \@copy;
75 # Prepare for the next.
76 $variant=$2;
77 undef @curvals;
78 next LINE;
81 else {
82 die "Unknown directive: ".$1;
86 # Skip over comments and blank lines.
87 if (/^#/ || /^$/) {
88 next LINE;
90 push (@curvals, $_);
94 my $bench_func = "#define CALL_BENCH_FUNC(v, i) $func (";
96 # Output variables. These include the return value as well as any pointers
97 # that may get passed into the function, denoted by the <> around the type.
98 my $outvars = "";
100 if ($ret ne "void") {
101 $outvars = "static $ret volatile ret;\n";
104 # Print the definitions and macros.
105 foreach $incl (@include_headers) {
106 print "#include <" . $incl . ">\n";
109 # Print the source files.
110 foreach $incl (@include_sources) {
111 print "#include \"" . $incl . "\"\n";
114 if (@args > 0) {
115 # Save values in the last variant.
116 $vals{$variant} = \@curvals;
117 my $struct =
118 "struct _variants
120 const char *name;
121 int count;
122 struct args *in;
123 };\n";
125 my $arg_struct = "struct args {";
127 my $num = 0;
128 my $arg;
129 foreach $arg (@args) {
130 if ($num > 0) {
131 $bench_func = "$bench_func,";
134 $_ = $arg;
135 if (/<(.*)\*>/) {
136 # Output variables. These have to be pointers, so dereference once by
137 # dropping one *.
138 $outvars = $outvars . "static $1 out$num;\n";
139 $bench_func = "$bench_func &out$num";
141 else {
142 $arg_struct = "$arg_struct $arg volatile arg$num;";
143 $bench_func = "$bench_func variants[v].in[i].arg$num";
146 $num = $num + 1;
149 $arg_struct = $arg_struct . "};\n";
150 $bench_func = $bench_func . ");\n";
152 print $bench_func;
153 print $arg_struct;
154 print $struct;
156 my $c = 0;
157 my $key;
159 # Print the input arrays.
160 foreach $key (keys %vals) {
161 my @arr = @{$vals{$key}};
163 print "struct args in" . $c . "[" . @arr . "] = {\n";
164 foreach (@arr) {
165 print "{$_},\n";
167 print "};\n\n";
168 $c += 1;
171 # The variants. Each variant then points to the appropriate input array we
172 # defined above.
173 print "struct _variants variants[" . (keys %vals) . "] = {\n";
174 $c = 0;
175 foreach $key (keys %vals) {
176 print "{\"$func($key)\", " . @{$vals{$key}} . ", in$c},\n";
177 $c += 1;
179 print "};\n\n";
180 # Finally, print the last set of macros.
181 print "#define NUM_VARIANTS $c\n";
182 print "#define NUM_SAMPLES(i) (variants[i].count)\n";
183 print "#define VARIANT(i) (variants[i].name)\n";
185 else {
186 print $bench_func . ");\n";
187 print "#define NUM_VARIANTS (1)\n";
188 print "#define NUM_SAMPLES(v) (1)\n";
189 print "#define VARIANT(v) FUNCNAME \"()\"\n"
192 # Print the output variable definitions.
193 print "$outvars\n";
195 # In some cases not storing a return value seems to result in the function call
196 # being optimized out.
197 if ($ret ne "void") {
198 $getret = "ret = ";
201 # And we're done.
202 print "#define BENCH_FUNC(i, j) ({$getret CALL_BENCH_FUNC (i, j);})\n";
204 print "#define FUNCNAME \"$func\"\n";
205 print "#include \"bench-skeleton.c\"\n";