Hello All, This is my first post to the parrot list, but I hope that many will follow. Thanks to all of you for working so dilligently on building this wonderful new toy for all us geeks to play with!
I am currently working on a fix to the large subroutine register allocation bug, aka, "massive spilling not yet implemented". The problem, is that the register allocation code is complex, and I'm not all that familiar with it, or even with working with compilers at the coding level. I am comming at the problem as a former graph theorist, who was a consultant to a compiler project (at UC Davis, in the late 90's where some of the work was applied toward what is the current Intel compiler). I talked a lot, and learned a lot, but didn't actually contribute any coding to the project. I also spent a lot of time coding graph coloring heuristics with C++. I expect to produce a patch soon, that will make register allocation better. To that end, I felt it was important to come up with some metrics. The first attached program (gen3.pl), which is based on Greg Purdy's gen-pra.pl, gathers data on compilation performance for varying numbers of variables and compares this to GCC. Mine also uses gnuplot to make pretty pictures. If everything is installed okay on your system, a graph will pop up displaying runtime results. I'm using Debian Linux, so it was pretty easy to set up. The second program, gen4.pl, is a randomized, automated, blackbox tester. It works similar to the above, but the corresponding parrot and GCC outputs are compared. And now, for the philosophical note ... One of the biggest wins of RISC over CISC was not that RISC was smaller, but that architects looked at actual code that would run on their machines. They removed an instruction from the instruction set if it wasn't used that frequently. They considered wheather to implement features in the hardware, or the compiler, and they tested each, to find the optimum balance. This approach may be helpful in building parrot as well, and it's what I've tried to do, in a very modest way, in my scripts. Thanks to Gregg Purdy for getting the ball rolling in this general direction. Thanks, Bill Coffman On Mon, 11 Oct 2004 09:54:31 -0400, Dan Sugalski <[EMAIL PROTECTED]> wrote: > At 4:58 PM -0700 10/2/04, Gregor N. Purdy wrote: > >Dan et al. -- > > > >I made a new version of the script that creates gen.cpp and gen.imc > >(attached). You can run it like this: > > > > perl gen-pra.pl 1000 10000 > > > >(for 1000 labels and 10000 variables) and it will create equivalent > >gen.imc and gen.cpp files. You can test-compile them with these > >commands: > > > > g++ -c gen.cpp > > > >and > > > > imcc -o x.x gen.imc > > > >on my system, the g++ compiler does eventually finish, but the imcc > >compiler is eventually killed. > > > >Maybe this could be used to drive out the underlying problems that > >are keeping parrot from compiling Dan's really large subs? > > Mmmm, degenerate behaviour! Cool, and thanks. Should help judge how > we're doing with the nastier code. > -- > Dan > > --------------------------------------it's like this------------------- > Dan Sugalski even samurai > [EMAIL PROTECTED] have teddy bears and even > teddy bears get drunk >
#!/usr/bin/perl -w use strict; die "Usage: $0 <starting_num_variables> <ending_num_variables>\n" unless @ARGV == 2; my ($start,$stop) = @ARGV; open COMP, ">compile.dat" or die "$!"; print COMP "#vars gcc imc\n"; for (my $vars=$start;$vars<=$stop;$vars++) { my ($total_locals) = $vars; my $total_labels = int ($total_locals / 2); my $labels_so_far = 1; my $locals_so_far = 0; open IMC, ">gen.imc"; open CPP, ">gen.cpp"; print IMC ".sub __MAIN\n\n"; printf IMC "\n_L_%d:\n", 1; print CPP "#include <stdio.h>\n\n"; print CPP "int main(int argc, char * arg[])\n{\n"; printf CPP "\n_L_%d:\n", 1; my %action_table = qw(l label v variable a arithmetic c control p print); my @actions = (('l')x2, ('v')x4, ('a')x9, ('c')x3, ('p')x0); while ($labels_so_far < $total_labels or $locals_so_far < $total_locals) { my $action = $action_table{$actions[rand @actions]}; if ($action eq 'label' and $labels_so_far < $total_labels) { my $this_label = ++$labels_so_far; printf IMC "\n_L_%d:\n", $this_label; printf CPP "\n_L_%d:\n", $this_label; } elsif ($action eq 'variable' and $locals_so_far < $total_locals) { my $this_local = ++$locals_so_far; my $this_value = int(rand(99)) + 1; printf IMC " .local int V_%d\n", $this_local; printf IMC " V_%d = %d\n", $this_local, $this_value; printf CPP " int V_%d;\n", $this_local; printf CPP " V_%d = %d;\n", $this_local, $this_value; } elsif ($action eq 'arithmetic' and $locals_so_far > 0) { my $result = 1 + int(rand($locals_so_far)); my $arg1 = 1 + int(rand($locals_so_far)); my $arg2 = 1 + int(rand($locals_so_far)); next if $arg1 == $arg2; my $op = qw( + - )[rand 2]; printf IMC " V_%d = V_%d %s V_%d\n", $result, $arg1, $op, $arg2; printf CPP " V_%d = V_%d %s V_%d;\n", $result, $arg1, $op, $arg2; } elsif ($action eq 'control' and $locals_so_far > 0) { my $dest = 1 + int(rand($total_labels)); my $arg1 = 1 + int(rand($locals_so_far)); my $arg2 = 1 + int(rand($locals_so_far)); next if $arg1 == $arg2; my $op = qw( < <= == != >= > )[rand 6]; printf IMC " if V_%d %s V_%d goto _L_%d\n", $arg1, $op, $arg2, $dest; printf CPP " if (V_%d %s V_%d) goto _L_%d;\n", $arg1, $op, $arg2, $dest; } elsif ($action eq 'print') { for (my $j=0; $j<$locals_so_far; $j++) { printf IMC " print \" \"\n"; printf IMC " print V_%d\n", $j+1; printf CPP " printf(\" \");\n"; printf CPP " printf(\"%%d\", V_%d);\n", $j+1; } printf IMC " print \"\\n\"\n"; printf CPP " printf(\"\\n\");\n"; } } print IMC "\n"; print IMC "end\n"; print IMC ".end\n"; print IMC "\n"; print CPP "\n"; print CPP " return 0;\n"; print CPP "}\n"; my ($gcc) = map {m/user\s*(.*)/?$1:()} `sh -c "time -p g++ -O gen.cpp" 2>&1`; my ($imc) = map {m/user\s*(.*)/?$1:()} `sh -c "time -p ../parrot -o x.x gen.imc" 2>&1`; print COMP "$vars $gcc $imc\n"; } close COMP; if (`which gnuplot`) { my $plot = <<EOT #Uncomment next two, to create a png file. #set terminal png #set out "compile.png" set title "Compile times for variable count -- GCC vs. Parrot" set logscale y plot "compile.dat" using 1:2 title 'g++ -O' with linespoints, \\ "compile.dat" using 1:3 title 'parrot -o' with linespoints #Okay to comment below if only creating png. pause -1 "Press return to continue" #reset EOT ; open PLOT, ">compile.plot" or die "failed writing compile.plot, $!"; print PLOT $plot; close PLOT; system "gnuplot compile.plot"; } exit 0;
#!/usr/bin/perl -w use strict; die "Usage: $0 <num_variables>\n" unless @ARGV == 1; my $start = shift; open COMP, ">compile.dat" or die "$!"; print COMP "#vars gcc imc\n"; for (my $vars=$start;$vars<=111;$vars++) { my ($total_locals) = $vars; my $total_labels = int ($total_locals / 2); my $labels_so_far = 1; my $locals_so_far = 0; open IMC, ">gen.imc"; open CPP, ">gen.cpp"; print IMC ".sub __MAIN\n\n"; printf IMC "\n_L_%d:\n", 0; print CPP "#include <stdio.h>\n\n"; print CPP "int main(int argc, char * arg[])\n{\n"; printf CPP "\n_L_%d:\n", 0; my %action_table = qw(l label v variable a arithmetic c control p print); my @actions = (('l')x10, ('v')x1, ('a')x30, ('c')x3, ('p')x4); while ($locals_so_far < $total_locals) { my $this_local = ++$locals_so_far; my $this_value = int(rand(99)) + 1; printf IMC " .local int V_%d\n", $this_local; printf IMC " V_%d = %d\n", $this_local, $this_value; printf CPP " int V_%d;\n", $this_local; printf CPP " V_%d = %d;\n", $this_local, $this_value; } printf IMC "\n_L_%d:\n", 1; printf CPP "\n_L_%d:\n", 1; while ($labels_so_far < $total_labels) { my $action = $action_table{$actions[rand @actions]}; if ($action eq 'label' and $labels_so_far < $total_labels) { my $this_label = ++$labels_so_far; printf IMC "\n_L_%d:\n", $this_label; printf CPP "\n_L_%d:\n", $this_label; } elsif ($action eq 'variable' and $locals_so_far < $total_locals) { my $this_local = ++$locals_so_far; my $this_value = int(rand(99)) + 1; printf IMC " .local int V_%d\n", $this_local; printf IMC " V_%d = %d\n", $this_local, $this_value; printf CPP " int V_%d;\n", $this_local; printf CPP " V_%d = %d;\n", $this_local, $this_value; } elsif ($action eq 'arithmetic' and $locals_so_far > 0) { my $result = 1 + int(rand($locals_so_far)); my $arg1 = 1 + int(rand($locals_so_far)); my $arg2 = 1 + int(rand($locals_so_far)); my $op = qw( + - )[rand 2]; printf IMC " V_%d = V_%d %s V_%d\n", $result, $arg1, $op, $arg2; printf CPP " V_%d = V_%d %s V_%d;\n", $result, $arg1, $op, $arg2; } elsif ($action eq 'control' and $locals_so_far > 0) { my $dest = 1 + int(rand($total_labels)); my $arg1 = 1 + int(rand($locals_so_far)); my $arg2 = 1 + int(rand($locals_so_far)); next if $arg1 == $arg2; my $op = qw( < <= == != >= > )[rand 6]; printf IMC " if V_%d %s V_%d goto _L_%d\n", $arg1, $op, $arg2, $dest; printf CPP " if (V_%d %s V_%d) goto _L_%d;\n", $arg1, $op, $arg2, $dest; } elsif ($action eq 'print') { for (my $j=0; $j<$locals_so_far; $j++) { printf IMC " print \" \"\n"; printf IMC " print V_%d\n", $j+1; printf CPP " printf(\" \");\n"; printf CPP " printf(\"%%d\", V_%d);\n", $j+1; } printf IMC " print \"\\n\"\n"; printf CPP " printf(\"\\n\");\n"; } } print IMC "\n"; print IMC "end\n"; print IMC ".end\n"; print IMC "\n"; print CPP "\n"; print CPP " return 0;\n"; print CPP "}\n"; my ($gcc) = map {m/user\s*(.*)/?$1:()} `sh -c "time -p g++ -O6 gen.cpp" 2>&1`; my ($imc) = map {m/user\s*(.*)/?$1:()} `sh -c "time -p ../parrot -o x.pasm gen.imc" 2>&1`; print COMP "$vars $gcc $imc\n"; if ((my $child=fork)==0) { exec "./a.out |head -1000 > a.dat"; } else { sleep 1; #print "child $child killed\n" if system "killall a.out 2>/dev/null" if kill 'TERM', $child; } #print "okay\n"; if ((my $child=fork)==0) { exec "../parrot x.pasm |head -1000 > x.dat"; } else { sleep 1; #print "child $child killed\n" if kill 'TERM', $child; system "killall parrot 2>/dev/null" if kill 'TERM', $child; } #system "ls -l a.dat x.dat"; my $s1 = -s "a.dat"; my $s2 = -s "x.dat"; if ($s1 < $s2) { rename "x.dat", "x2.dat" or die; system "head -c $s1 x2.dat > x.dat"; unlink "x2.dat" or die; $s2 = -s "x.dat"; } if ($s1 > $s2) { rename "a.dat", "a2.dat" or die; system "head -c $s2 a2.dat > a.dat"; unlink "a2.dat" or die; $s1 = -s "a.dat"; } print "$vars $gcc $imc (size==$s1)\n"; die "huh? $s1 != $s2" if $s1 != $s2; #system "wc -l a.dat x.dat"; my @diff = `diff a.dat x.dat`; die "different" if @diff; } close COMP; if (`which gnuplot`) { my $plot = <<EOT #Uncomment next two, to create a png file. #set terminal png #set out "compile.png" set title "Compile times for variable count -- GCC vs. Parrot" set logscale y plot "compile.dat" using 1:2 title 'g++ -O6' with linespoints, \\ "compile.dat" using 1:3 title 'parrot -o' with linespoints #Okay to comment below if only creating png. pause -1 "Press return to continue" #reset EOT ; open PLOT, ">compile.plot" or die "failed writing compile.plot, $!"; print PLOT $plot; close PLOT; system "gnuplot compile.plot"; } exit 0;