May 18, 2006
I'd like to propose the gdmd script patch below to unify and simplify the maintenence of the optimizations for building GDC w/ different versions of GCC.

With the -O switch, it emits -O3, and if -inline is not specified, -fno-inline-functions is emitted. This would replace -O2, -finline-functions (w/ -inline), and various other options depending on the version of GCC that GDC is built with.

The original rational of -O2 + GCC version dependent options (instead of  just -O3) was to try and replicate what -O3 does for the different versions, but exclude the implicit function inlining.

The rational for the added -funroll-loops optimization w/ the -O switch: In many cases, this optimization can make a big difference in speed, but at the expense of slightly larger code and slightly slower compilation. I've not ran into a case where it has actually caused a program to execute slower.

Here's a summary:

Benchmark              Score    Exe Size     Compilation time
-----------------------------------------------------------
Shootout (unroll off)  66.95    492464 Avg   0.510 Avg
-funroll-loops         68.08    493100       0.539

SciMark2 (unroll off) 367.33    434330       1.25
-funroll-loops        417.11    440794       1.44

Most of the Shootout tests don't lend themselves to loop-unrolling and/or the bottleneck is in library calls (phobos wasn't recompiled using the new switches), but it's a good comparison of size and compilation speed.

The SciMark2 D code was pretty much a straight port from the C version, and slightly outperforms GCC with the same opt. switches set. IMHO, it is a good program to demonstrate the difference -funroll-loops can make.

Thanks,

- Dave

--- gdmd.bak    2006-02-12 23:09:20.000000000 -0600
+++ gdmd        2006-03-01 15:59:29.000000000 -0600
@@ -114,10 +114,10 @@
 }
 use subs qw(errorExit);

-my $gcc_version = `$gdc -dumpversion`;
-chomp $gcc_version;
-$gcc_version =~ m/^(\d+)\.(\d+)/;
-my ($gcc_maj, $gcc_min) = ( $1, $2 );
+#my $gcc_version = `$gdc -dumpversion`;
+#chomp $gcc_version;
+#$gcc_version =~ m/^(\d+)\.(\d+)/;
+#my ($gcc_maj, $gcc_min) = ( $1, $2 );

 my $target_machine = `$gdc -dumpmachine`;
 chomp $target_machine;
@@ -149,7 +149,7 @@
        printUsage;
        exit 0;
     } elsif ( $arg =~ m/^-inline$/ ) {
-       push @out, '-finline-functions';
+#      push @out, '-finline-functions';
     } elsif ( $arg =~ m/^-I(.*)$/ ) {
        foreach my $i (split pathSep, $1) {
            push @out, '-I', expandHome $i;
@@ -157,13 +157,16 @@
     } elsif ( $arg =~ m/^-L(.*)$/ ) {
        push @link_out, '-Wl,' . $1;
     } elsif ( $arg =~ m/^-O$/ ) {
-       push @out, '-O2', '-fomit-frame-pointer';
-       if ( $gcc_maj < 4) {
-           push @out, '-frename-registers';
-       }
-       if ( $gcc_maj > 3 || ( $gcc_maj == 3 && $gcc_min >= 4 ) ) {
-           push @out, '-fweb';
-       }
+    push @out, '-O3', '-fomit-frame-pointer', '-funroll-loops';
+    if( !grep(/^-inline$/,@ARGV) ) {
+        push @out, '-fno-inline-functions';
+    }
+#      if ( $gcc_maj < 4) {
+#          push @out, '-frename-registers';
+#      }
+#      if ( $gcc_maj > 3 || ( $gcc_maj == 3 && $gcc_min >= 4 ) ) {
+#          push @out, '-fweb';
+#      }
     } elsif ( $arg =~ m/^-o-$/ ) {
        push @out, '-fsyntax-only';
        $link = 0;