[comp.os.vms] 2 FORTRAN questions. Is FORTRAN faster than C?

PHULVER%OCVAXC@VB.CC.CMU.EDU (Barron Hulver x8290) (04/05/88)

Is FORTRAN faster than C?  probably.
Which one do I use?  C.
oh well...

In order of peep-hole optimizing efficiency, here is
how I would rate various compilers:
    FORTRAN
    C
    PASCAL
    BASIC
    BASIC
    COBOL

I list basic twice because it depends on whether you use
the /LINES qualifier (the default) when compiling.

Also, whether your longwords are on longword boundaries is
a significant performance factor on most cpus.  VAX C does
seem to align longwords on longword boundaries.
I would assume FORTRAN does as well but I have not checked
this.

Finally, for production C programs be sure to link to make
it shareable:
    $ LINK  program, sys$input/options
    sys$library:vaxcrtl/share
and not:
    $ LINK  program, sys$library:vaxcrtl


...Barron Hulver
   Oberlin College
   phulver @ oberlin    (bitnet)
   phulver % ocvaxa @ vb.cc.cmu.edu    (arpanet)
   ocvaxa::phulver      (ccnet)

Here are the programs that I used to reach the above
conclusions.

------------------  TABLE  OF  CONTENTS  -------------------
PEEPB.BAS;7        
PEEPC.C;7          
PEEPCOMPILE.COM;3  
PEEPF.FOR;9        
PEEPL.COB;14       
PEEPP.PAS;4        
PEEPPRINT.COM;1    
ALIGN.COM;2        
ALIGN.RUN;2        
ALIGN.C;12         
------------- PEEPB.BAS;7         ------------------
10  rem    /*   peephole  optimization    */
20  declare integer long n,m
30  rem    /*  redundant load/store test  */
40  n = 1%
50  m = 1%
60  rem    /* test for unreachable code */
70 if (n > 0%) then goto 100
80 goto 200
90 print "label_start";
100 print "label_1";
110 goto 200
199 rem /* test for flow of control optimization */
200 if (n > 0%) goto 1100
210 goto 1500
1100 print "label_11"
1110 goto 9000
1500 print "label_15"
1510 goto 9000
9000 print "label_end"
9100 rem  /* algebraic simplification */
9110 n = n + 0%
9120 n = n * 1%
9200 rem  /* reduction in strength (add/subtract from itselt or bit shift 1 */
9210 n = n * 2%
9220 n = n / 2%
9300 rem  /* reduction in strength (bit shift 3)
9310 m = n * 8%
9320 m = n / 8%
9400 rem  /* machine idiom.  (replace add with increment instruction */
9410 n = n + 1%
9500 rem  /* no use. detect a variable assignment that is not used */
9510 m = n + 17%
9520 m = n + 14%
9600 rem  /* test for constant folding */
9610 n = 3% + 4% + 7%
9620 n = 10% + 20% + 30%
9700 rem  /* force a usage of the variables */
9710 print n,m
9999 end

------------- PEEPC.C;7           ------------------
/* peephole optimization */

main()
{
  long int n,m;

  /* redundant load/store test */

  n = 1;
  m = 1;

  /* test for unreachable code */
  if (n > 0) goto label_1;
  goto label_2;
  printf("label_start\n");

label_1:
   printf("label_1\n");
   goto label_2;

  /* test for flow of control optimization */
label_2:
   if (n > 0) goto label_11;
   goto label_15;
label_11:
   printf("label_11\n");
   goto label_end;
label_15:
   printf("label_15\n");
   goto label_end;

label_end:
   printf("label_end\n");

   /* algebraic simplification */
   n = n + 0;
   n = n * 1;

   /* reduction in strength (add/subtract from itself or bit shift 1) */
   n = n * 2;
   n = n / 2;
            
   /* reduction in strength (bit shift 3) */
   m = n * 8;
   m = n / 8;

   /* machine idiom.  (replace add with increment instruction */
   n = n + 1;

   /* no use.  detect a variable assignment that is not used */
   m = n + 17;
   m = n + 14;

   /* test for constant folding */
   n = 3 + 4 + 7;
   n = 10 + 20 + 30;

  /* force a usage of the variables */
  printf("n: %d, m: %d\n", n, m);
}
------------- PEEPCOMPILE.COM;3   ------------------
$! BASIC
$ basic/list/machine				peepb
$ basic/list=peepbn/machine/noopt		peepb
$ basic/list=peepbo/machine/check=(nooverflow,nobounds)/nolines   peepb
$!
$! C
$ cc/list/machine				peepc
$ cc/list=peepcn/machine/noopt			peepc
$!                                              
$! COBOL
$ cobol/list/machine				peepl
$ cobol/list=peepln/machine/noopt		peepl
$!
$! FORTRAN
$ fortran/list/machine				peepf
$ fortran/list=peepfn/machine/noopt		peepf
$!
$! PASCAL
$ pascal/list/machine				peepp
$ pascal/list=peeppn/machine/noopt		peepp
------------- PEEPF.FOR;9         ------------------
c
c    peephole  optimization
c
	implicit integer(a-z)

c	/* redundant load/store test */

	n = 1
	m = 1

c	/* test for unreachable code */
	if (n .gt. 0) goto 1
	goto 2
	print *,'label_start'

1	print *,'label_1'
 	goto 2

c	/* test for flow of control optimization */
2	if (n .gt. 0) goto 11
	goto 15
11	print *,'label_11'
  	goto 99
15	print *,'label_15'
  	goto 99
99	print *,'label_end'
                 

c	/* algebraic simplification */
	n = n + 0
	n = n * 1

c	/* reduction in strength (add/subtract from itself or bit shift 1 */
	n = n * 2 
	n = n / 2

c	/* reduction in strength (bit shift 3) */
	m = n * 8
	m = n / 8

c	/* machine idiom.  replace add with increment instruction */
	n = n + 1

c	/* no use. detect a variable assignment that is not used */
	m = n + 17
	m = n + 14

c	/* force a usage of the variables */
	write(8,1000) n,m
1000	format(x,i,5x,i)

	stop
	end

------------- PEEPL.COB;14        ------------------
 IDENTIFICATION DIVISION.
 PROGRAM-ID. PEEPL.
 AUTHOR. BARRON L. HULVER.
*
*  peephole optimization
*

 ENVIRONMENT DIVISION.
 CONFIGURATION SECTION.
 SOURCE-COMPUTER. X.
 OBJECT-COMPUTER. X.
 INPUT-OUTPUT SECTION.
 FILE-CONTROL.
 	SELECT OUTFILE ASSIGN TO OUTFILE_LOG.

 DATA DIVISION.
 FILE SECTION.
 FD	OUTFILE
	LABEL RECORDS ARE OMITTED,
	DATA RECORD IS OUTFILE-RECORD.
 01  OUTFILE-RECORD			PIC X(133).

 WORKING-STORAGE SECTION.
 01  MY-VARIABLES.
	03  N				PIC S9(9) COMP.
	03  M				PIC S9(9) COMP.

 PROCEDURE DIVISION.
 00-START.

*  /* Redundant load/store test */

	MOVE 1 TO N.
	MOVE 1 TO M.

*   /* Test for unreachable code */
	IF N GREATER THAN ZERO GO TO LABEL-1.
	GO TO LABEL-2.
	DISPLAY "Label_start".

LABEL-1.
	DISPLAY "Label_1".
	GO TO LABEL-2.

*   /* Test for flow of control optimization */
LABEL-2.
	IF N GREATER THAN 0 GO TO LABEL-11.
	GO TO LABEL-15.
LABEL-11.
	DISPLAY "Label_11".
	GO TO LABEL-END.
LABEL-15.
	DISPLAY "Label_15".
	GO TO LABEL-END.

LABEL-END.
	DISPLAY "Label_end".

*   /* algebraic simplification */
	ADD 0 TO N.
	MULTIPLY N BY 1 GIVING N.

*   /* reduction in strength (add/subtract from itself or bit shift 1 */
	MULTIPLY N BY 2 GIVING N.
	DIVIDE N BY 2 GIVING N.

*   /* reduction in strength (bit shift 3)
	COMPUTE M = N * 8.
	COMPUTE M = N / 8.

*   /* machine idiom.  (replace add with increment instruction) */
	COMPUTE N = N + 1.

*   /* no use.  detect a variable assignment that is not used */
	COMPUTE M = N + 17.
	COMPUTE M = N + 14.

*   /* test for constant folding */
	COMPUTE N = 3 + 4 + 7.
	COMPUTE N = 10 + 20 + 30.

*   /* force a usage of the variables */
	DISPLAY N,M.

	STOP RUN.

------------- PEEPP.PAS;4         ------------------
program peep (input, output);

var
 	n, m : integer;

label
	label_1, label_2, label_11, label_15, label_end;

begin              

{Redundant load/store test}

	n := 1;
	m := 1;
	
	{Test for unreachable code}

	if n > 0 then goto label_1;
	goto label_2;
	writeln('label_start');

label_1:
	writeln('label_1');
	goto label_2;

{Test for flow of control optimization}

label_2:
    	if n > 0 then goto label_11;
	goto label_15;
label_11:
	writeln('label_11');
	goto label_end;
label_15:
	writeln('label_15');
	goto label_end;

label_end:
	writeln('label_end');

{Algebraic simplification}
	n := n + 0;	
	n := n * 1;

{Reduction in strength (add/subtract from itself or bit-shift 1)}
	n := n * 2;
	n := n div 2; 

{Reduction in strength (bit-shift 3)}
	m := n * 8;	
	m := n div 8;

{machine idiom.  (replace add with increment instruction}
	n := n + 1;

{no use.  detect a variable assignment that is not used}
	m := n + 17;
	m := n + 14;

{test for constant folding}
	n := 3 + 4 + 7;
	n := 10 + 20 + 30;

{Force a usage of the variables}
	writeln('n = ', n, 'm = ', m);

end.
------------- PEEPPRINT.COM;1     ------------------
$ print/head/name="src optim" - 
     peepb.bas, peepc.c, peepf.for, peepl.cob, peepp.pas
$ print/head/name="std optim"  peep*.lis
$ print/head/name="no optim"   peep%n.lis
------------- ALIGN.COM;2         ------------------
$ cc/list/machine  align
$ link/map/full    align, sys$input/options
sys$library:vaxcrtl/share
$ run align
------------- ALIGN.RUN;2         ------------------
@align
$ cc/list/machine  align
$ link/map/full    align, sys$input/options
sys$library:vaxcrtl/share
$ run align
..aligned? 0, 0, 0
..addr = J      254, B      278, J2      27C, M      280
..offset = 0, 0, 0

------------- ALIGN.C;12          ------------------
main()
{
   static char  junk;
   static long int  var_1;
   static long int  var_2;
   static long int  var_3;
   static long int  var_4;
   static long int  var_5;
   static long int  var_6;
   static long int  var_7;
   static long int  var_8;
   static long int  bigstuff;
   static char      junk2;
   static long int  morestuff;
   static unsigned long junk_a;
   static unsigned long big_a;
   static unsigned long more_a;
   static unsigned long junk_m;
   static unsigned long big_m;
   static unsigned long more_m;

   junk_a = &junk;
   junk_m = junk_a % 4;
   big_a  = &bigstuff;
   big_m  = big_a % 4;
   more_a = &morestuff;
   more_m = more_a % 4;

   printf("..aligned? %d, %d, %d\n", junk, bigstuff, morestuff);
   printf("..addr = J %8X, B %8X, J2 %8X, M %8X\n", junk_a, big_a, &junk2, more_a);
   printf("..offset = %d, %d, %d\n", junk_m, big_m, more_m);

}
---------------------------------------------------------