From: CSBVAX::MRGATE!PHULVER%OCVAXC@VB.CC.CMU.EDU@SMTP 5-APR-1988 21:59 To: ARISIA::EVERHART Subj: re: 2 FORTRAN questions. Is FORTRAN faster than C? Received: from VB.CC.CMU.EDU by KL.SRI.COM with TCP; Mon 4 Apr 88 20:22:31-PDT Date: Mon, 4 Apr 88 23:22 EDT From: Barron Hulver x8290 Subject: re: 2 FORTRAN questions. Is FORTRAN faster than C? To: info-vax@KL.SRI.COM X-VMS-To: CMCCVB::IN%"info-vax@kl.sri.com",PHULVER 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); } ---------------------------------------------------------