mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-10-30 10:45:40 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			206 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			206 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
| #! /usr/bin/perl -w
 | |
| # Copyright (C) 2013-2014 Free Software Foundation, Inc.
 | |
| # This file is part of the GNU C Library.
 | |
| 
 | |
| # The GNU C Library is free software; you can redistribute it and/or
 | |
| # modify it under the terms of the GNU Lesser General Public
 | |
| # License as published by the Free Software Foundation; either
 | |
| # version 2.1 of the License, or (at your option) any later version.
 | |
| 
 | |
| # The GNU C Library is distributed in the hope that it will be useful,
 | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| # Lesser General Public License for more details.
 | |
| 
 | |
| # You should have received a copy of the GNU Lesser General Public
 | |
| # License along with the GNU C Library; if not, see
 | |
| # <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| 
 | |
| use strict;
 | |
| use warnings;
 | |
| # Generate a benchmark source file for a given input.
 | |
| 
 | |
| if (@ARGV < 1) {
 | |
|   die "Usage: bench.pl <function>"
 | |
| }
 | |
| 
 | |
| my $func = $ARGV[0];
 | |
| my @args;
 | |
| my $ret = "void";
 | |
| my $getret = "";
 | |
| 
 | |
| # We create a hash of inputs for each variant of the test.
 | |
| my $variant = "";
 | |
| my @curvals;
 | |
| my %vals;
 | |
| my @include_headers;
 | |
| my @include_sources;
 | |
| my $incl;
 | |
| 
 | |
| open INPUTS, "<$func-inputs" or die $!;
 | |
| 
 | |
| LINE:while (<INPUTS>) {
 | |
|   chomp;
 | |
| 
 | |
|   # Directives.
 | |
|   if (/^## ([\w-]+): (.*)/) {
 | |
|     # Function argument types.
 | |
|     if ($1 eq "args") {
 | |
|       @args = split(":", $2);
 | |
|     }
 | |
| 
 | |
|     # Function return type.
 | |
|     elsif ($1 eq "ret") {
 | |
|       $ret = $2;
 | |
|     }
 | |
| 
 | |
|     elsif ($1 eq "includes") {
 | |
|       @include_headers = split (",", $2);
 | |
|     }
 | |
| 
 | |
|     elsif ($1 eq "include-sources") {
 | |
|       @include_sources = split (",", $2);
 | |
|     }
 | |
| 
 | |
|     # New variant.  This is the only directive allowed in the body of the
 | |
|     # inputs to separate inputs into variants.  All others should be at the
 | |
|     # top or else all hell will break loose.
 | |
|     elsif ($1 eq "name") {
 | |
| 
 | |
|       # Save values in the previous variant.
 | |
|       my @copy = @curvals;
 | |
|       $vals{$variant} = \@copy;
 | |
| 
 | |
|       # Prepare for the next.
 | |
|       $variant=$2;
 | |
|       undef @curvals;
 | |
|       next LINE;
 | |
|     }
 | |
| 
 | |
|     else {
 | |
|       die "Unknown directive: ".$1;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   # Skip over comments and blank lines.
 | |
|   if (/^#/ || /^$/) {
 | |
|     next LINE;
 | |
|   }
 | |
|   push (@curvals, $_);
 | |
| }
 | |
| 
 | |
| 
 | |
| my $bench_func = "#define CALL_BENCH_FUNC(v, i) $func (";
 | |
| 
 | |
| # Output variables.  These include the return value as well as any pointers
 | |
| # that may get passed into the function, denoted by the <> around the type.
 | |
| my $outvars = "";
 | |
| 
 | |
| if ($ret ne "void") {
 | |
|   $outvars = "static $ret volatile ret;\n";
 | |
| }
 | |
| 
 | |
| # Print the definitions and macros.
 | |
| foreach $incl (@include_headers) {
 | |
|   print "#include <" . $incl . ">\n";
 | |
| }
 | |
| 
 | |
| # Print the source files.
 | |
| foreach $incl (@include_sources) {
 | |
|   print "#include \"" . $incl . "\"\n";
 | |
| }
 | |
| 
 | |
| if (@args > 0) {
 | |
|   # Save values in the last variant.
 | |
|   $vals{$variant} = \@curvals;
 | |
|   my $struct =
 | |
|     "struct _variants
 | |
|     {
 | |
|       const char *name;
 | |
|       int count;
 | |
|       struct args *in;
 | |
|     };\n";
 | |
| 
 | |
|   my $arg_struct = "struct args {";
 | |
| 
 | |
|   my $num = 0;
 | |
|   my $arg;
 | |
|   foreach $arg (@args) {
 | |
|     if ($num > 0) {
 | |
|       $bench_func = "$bench_func,";
 | |
|     }
 | |
| 
 | |
|     $_ = $arg;
 | |
|     if (/<(.*)\*>/) {
 | |
|       # Output variables.  These have to be pointers, so dereference once by
 | |
|       # dropping one *.
 | |
|       $outvars = $outvars . "static $1 out$num;\n";
 | |
|       $bench_func = "$bench_func &out$num";
 | |
|     }
 | |
|     else {
 | |
|       $arg_struct = "$arg_struct $arg volatile arg$num;";
 | |
|       $bench_func = "$bench_func variants[v].in[i].arg$num";
 | |
|     }
 | |
| 
 | |
|     $num = $num + 1;
 | |
|   }
 | |
| 
 | |
|   $arg_struct = $arg_struct . "};\n";
 | |
|   $bench_func = $bench_func . ");\n";
 | |
| 
 | |
|   print $bench_func;
 | |
|   print $arg_struct;
 | |
|   print $struct;
 | |
| 
 | |
|   my $c = 0;
 | |
|   my $key;
 | |
| 
 | |
|   # Print the input arrays.
 | |
|   foreach $key (keys %vals) {
 | |
|     my @arr = @{$vals{$key}};
 | |
| 
 | |
|     print "struct args in" . $c . "[" . @arr . "] = {\n";
 | |
|     foreach (@arr) {
 | |
|       print "{$_},\n";
 | |
|     }
 | |
|     print "};\n\n";
 | |
|     $c += 1;
 | |
|   }
 | |
| 
 | |
|   # The variants.  Each variant then points to the appropriate input array we
 | |
|   # defined above.
 | |
|   print "struct _variants variants[" . (keys %vals) . "] = {\n";
 | |
|   $c = 0;
 | |
|   foreach $key (keys %vals) {
 | |
|     print "{\"$func($key)\", " . @{$vals{$key}} . ", in$c},\n";
 | |
|     $c += 1;
 | |
|   }
 | |
|   print "};\n\n";
 | |
|   # Finally, print the last set of macros.
 | |
|   print "#define NUM_VARIANTS $c\n";
 | |
|   print "#define NUM_SAMPLES(i) (variants[i].count)\n";
 | |
|   print "#define VARIANT(i) (variants[i].name)\n";
 | |
| }
 | |
| else {
 | |
|   print $bench_func . ");\n";
 | |
|   print "#define NUM_VARIANTS (1)\n";
 | |
|   print "#define NUM_SAMPLES(v) (1)\n";
 | |
|   print "#define VARIANT(v) FUNCNAME \"()\"\n"
 | |
| }
 | |
| 
 | |
| # Print the output variable definitions.
 | |
| print "$outvars\n";
 | |
| 
 | |
| # In some cases not storing a return value seems to result in the function call
 | |
| # being optimized out.
 | |
| if ($ret ne "void") {
 | |
|   $getret = "ret = ";
 | |
| }
 | |
| 
 | |
| # And we're done.
 | |
| print "#define BENCH_FUNC(i, j) ({$getret CALL_BENCH_FUNC (i, j);})\n";
 | |
| 
 | |
| print "#define FUNCNAME \"$func\"\n";
 | |
| print "#include \"bench-skeleton.c\"\n";
 |