aberno@questor.wimsey.bc.ca (Anthony Berno) (12/17/90)
I generally prefer Pascal programming, but I have come up against what seems like a real deficiency in the language. I never really thought about it before, but there does not seem to be any equivalent to the ++ or -- operator in Pascal. I was doing some speed checks on array accessing today, and it occured to me that in doing something like incrementing an entry by one, the computer was doing rather a lot of work! Either there is no way to do a quick increment in Pascal, or I'm missing something in my knowledge, or I'm wrong about the speed difference between things like ++(variable) and (variable):=(variable)+1 Any comments? This is pretty basic, I know, but I never considered it before. :) Excuse me while I go get my asbestos suit on.
roy@phri.nyu.edu (Roy Smith) (12/18/90)
aberno@questor.wimsey.bc.ca (Anthony Berno) writes: > Either there is no way to do a quick increment in Pascal, or I'm missing > something in my knowledge, or I'm wrong about the speed difference between > things like ++(variable) and (variable):=(variable)+1 I've never written a single line of pascal in my life, but in C, x++ and x = x + 1 are absolutely and completely identical (as is x += 1). Any decent compiler should generate exactly the same code for all three. The ++ and -- operators are just syntactic sugar. I'm not a language lawyer, so I won't stick my head out about things like foo[bar(foo[i])]++ vs. foo[bar(foo[i])] = foo[bar(foo[i])] + 1 but for incrementing simple variables, it makes no difference. There are lots of good reasons not to like Pascal, but this isn't one of them. -- Roy Smith, Public Health Research Institute 455 First Avenue, New York, NY 10016 roy@alanine.phri.nyu.edu -OR- {att,cmcl2,rutgers,hombre}!phri!roy "Arcane? Did you say arcane? It wouldn't be Unix if it wasn't arcane!"
sec@cs.umn.edu (Stephen E. Collins) (12/18/90)
In <1990Dec17.160242.5095@phri.nyu.edu> roy@phri.nyu.edu (Roy Smith) writes: > I've never written a single line of pascal in my life, but in C, >x++ and x = x + 1 are absolutely and completely identical (as is x += 1). >Any decent compiler should generate exactly the same code for all three. Decent is the key word here. If your compiler does not optimize, you're likely to get different code for these, and with the number of shoddy software products on the market these days, you might want to investigate. To wit, most CPUs have some sort of increment instruction in the hardware, so a shoddy compiler may generate something like the following code: x := x+1: LOAD X ADD 1 STORE X -or- x++: INC X Stephen E. Collins University of Minnesota Microcomputer & Workstation Networks Center sec@boombox.micro.umn.edu | sec@umnacvx.bitnet | FAX: (612)625-6817
keith@Apple.COM (Keith Rollin) (12/18/90)
In article <q72au3w163w@questor.wimsey.bc.ca> aberno@questor.wimsey.bc.ca (Anthony Berno) writes: >I generally prefer Pascal programming, but I have come up against what >seems like a real deficiency in the language. I never really thought >about it before, but there does not seem to be any equivalent to >the ++ or -- operator in Pascal. I was doing some speed checks on >array accessing today, and it occured to me that in doing something >like incrementing an entry by one, the computer was doing rather a >lot of work! > >Either there is no way to do a quick increment in Pascal, or I'm missing >something in my knowledge, or I'm wrong about the speed difference between >things like >++(variable) and >(variable):=(variable)+1 You could look into the built-in functions PREV and SUCC. However, the last time I checked them out (which was around 3.0A2 timeframe), using i := i + 1 actually generated better code. Go figure. I can't. Perhaps it's because PREV and SUCC also work with general enumerated types other than bytes, integers, and longints. -- ------------------------------------------------------------------------------ Keith Rollin --- Apple Computer, Inc. --- Developer Technical Support INTERNET: keith@apple.com UUCP: {decwrl, hoptoad, nsc, sun, amdahl}!apple!keith "Argue for your Apple, and sure enough, it's yours" - Keith Rollin, Contusions
mrn@eplunix.UUCP (Mark R. Nilsen) (12/18/90)
in article <q72au3w163w@questor.wimsey.bc.ca>, aberno@questor.wimsey.bc.ca (Anthony Berno) says: > I was doing some speed checks on > array accessing today, and it occured to me that in doing something > like incrementing an entry by one, the computer was doing rather a > lot of work! > In Pascal getting to an array element with: MyArray[i] := Data; Has the computer taking the address of MyArray and adding (i * Sizeof(Data)). In C stepping through an array with: MyArray++ = Data; Has the computer taking the address of MyArray and incrementing by Sizeof(Data). In C you bypass an integer multiply. That is one of the nice things about C. You can of course still do it the slow way in C with MyArray[i] = Data, and the compiler will do the multiply. Think Pascal lets you do some pointer calculations but you have to do the size calculations yourself, in C the compiler will do them for you (in the case of ++). --Mark.
stevewi@hpspdra.HP.COM (Steve Witten) (12/18/90)
You can use the 'succ' and 'pred' operators/functions in Pascal to accomplish the same function as '++' and '--'. So: integer i,j,k; ... j := succ(i); { same as 'j=i++' } k := pred(i); { same as 'k=i--' } ... However, you have to remember that '++/--' are positional as well. You cannot recreate this behavior. You also cannot recreate the behavior of 'x++' without an assignment in Pascal. =============================================================================== Steve Witten stevewi%hpspdra@hplabs.hp.com Intelligent Networks Operation ...!hplabs!hpspdra!stevewi Hewlett-Packard Co. stevewi@hpspdra.spd.hp.com
ewright@convex.com (Edward V. Wright) (12/18/90)
In <1990Dec17.172613.7941@cs.umn.edu> sec@cs.umn.edu (Stephen E. Collins) writes: >To wit, most CPUs have some sort of increment instruction in the hardware, >so a shoddy compiler may generate something like the following code: >x := x+1: LOAD X > ADD 1 > STORE X > -or- >x++: INC X Actually, this would have to be >x++: LOAD X > INC X > STORE X Unless you have an instruction to increment variables in memory!
peirce@outpost.UUCP (Michael Peirce) (12/18/90)
In article <q72au3w163w@questor.wimsey.bc.ca>, aberno@questor.wimsey.bc.ca (Anthony Berno) writes: > > I generally prefer Pascal programming, but I have come up against what > seems like a real deficiency in the language. I never really thought > about it before, but there does not seem to be any equivalent to > the ++ or -- operator in Pascal. I was doing some speed checks on > array accessing today, and it occured to me that in doing something > like incrementing an entry by one, the computer was doing rather a > lot of work! > > Either there is no way to do a quick increment in Pascal, or I'm missing > something in my knowledge, or I'm wrong about the speed difference between > things like > ++(variable) and > (variable):=(variable)+1 > > Any comments? This is pretty basic, I know, but I never considered it > before. :) Excuse me while I go get my asbestos suit on. Using X := X + 1; rather than the c style X++; is more a matter of style than substance. Just to make sure I Iooked at the code generated from a "X := X + 1;" statement (using DUMPOBJ in MPW) and found the use of "ADDQ.W #$1,-2(A6)". The same instruction was generated by C for both "X++;" and "X = X + 1;" too. Don't worry, be happy. Pascal does a pretty good job for you. -- michael -- Michael Peirce -- {apple,decwrl}!claris!outpost!peirce -- Peirce Software -- Suite 301, 719 Hibiscus Place -- Macintosh Programming -- San Jose, California 95117 -- & Consulting -- (408) 244-6554, AppleLink: PEIRCE
roy@phri.nyu.edu (Roy Smith) (12/18/90)
I asserted that: > in C, x++ and x=x+1 are absolutely and completely identical (as is x+=1). > Any decent compiler should generate exactly the same code for all three. sec@cs.umn.edu (Stephen E. Collins) replied: > Decent is the key word here. If your compiler does not optimize, you're > likely to get different code for these, and with the number of shoddy > software products on the market these days, you might want to investigate. My first impression of Stephen's posting was "well, any compiler that's so bad it can't generate code for x=x+1 as good as it does for x++ must really be the pits". So, I tried an experiment. I compiled: a () { int x; x = 1; x = x + 1; } b () { int x; x = 1; x++; } on my SunOS-3.5.2 system using the stock C compiler, with and without -O and compared the code generated with -S. I'll confess to never having learned the m68k instruction set, but it sure looks like in both cases, b() generated more efficient code than a(). Stripping away the function entry and exit code, basically you have: without -O flag with -O flag a() movl #0x1,a6@(-0x4) moveq #1,d0 movl a6@(-0x4),d0 movl d0,a6@(-4) addql #0x1,d0 addql #1,d0 movl d0,a6@(-0x4) movl d0,a6@(-4) b() movl #0x1,a6@(-0x4) moveq #1,d1 addql #0x1,a6@(-0x4) movl d1,a6@(-4) addql #1,a6@(-4) Clearly, either I was out of line making my original assertion or the stock SunOS-3.5.2 C compiler really is the pits! Maybe a little of both? Anyway, I'll still stand by my original assertion, that the -- and ++ operators are just syntactic sugar and the lack of them does not, by itself, make Pascal a worse language. It's not fair to heap the sins of poor compiler implementations on the language itself (unless there is something inherent in the language that makes it hard to write good compilers). As an afterthought, I would hope that the C compiler Sun is now unbundling and charging real money for would generate better code than the stock one they used to ship. -- Roy Smith, Public Health Research Institute 455 First Avenue, New York, NY 10016 roy@alanine.phri.nyu.edu -OR- {att,cmcl2,rutgers,hombre}!phri!roy "Arcane? Did you say arcane? It wouldn't be Unix if it wasn't arcane!"
minich@d.cs.okstate.edu (Robert Minich) (12/18/90)
by stevewi@hpspdra.HP.COM (Steve Witten): | You can use the 'succ' and 'pred' operators/functions in Pascal to | accomplish the same function as '++' and '--'. So: | | integer i,j,k; | | ... | | j := succ(i); { same as 'j=i++' } | k := pred(i); { same as 'k=i--' } | | ... | | However, you have to remember that '++/--' are positional as well. | You cannot recreate this behavior. You also cannot recreate the | behavior of 'x++' without an assignment in Pascal. Do you not use C very often or are you VERY tired? The above Pascal statements are equivalent to j := i + 1; k := i - 1; whereas the C translates to Pascal as j = i++; | j := j + i; | i := i + 1; k = i--; | k := i - 1; | i := i - 1; The pred() and succ() functions are really used to get increment ordinal types whereas C doesn't care too much about types and will increment, say, a char by 1 without blinking. Someone has already posted MPW C's output so I thought I'd see what THINK C 4.0.2 does with the following: alpha() { int x; x = 1; x = x + 1; } beta () { int x; x = 1; x++; } main () { alpha(); beta(); } ALPHA +0000 LINK A6,#$FFFE +0004 MOVEQ #$01,D0 | tmp = 1; +0006 MOVE.W D0,-$0002(A6) | x = tmp; <== ick +000A MOVE.W -$0002(A6),D0 | tmp = x; <== +000E ADDQ.W #$1,D0 | tmp = tmp + 1; +0010 MOVE.W D0,-$0002(A6) | x = tmp; +0014 UNLK A6 +0016 RTS BETA +0000 LINK A6,#$FFFE +0004 MOVEQ #$01,D0 | tmp = 1; +0006 MOVE.W D0,-$0002(A6) | x = tmp; +000A ADDQ.W #$1,-$0002(A6) | x = x + 1; +000E UNLK A6 +0010 RTS I also tried {x += 1;} and it produced identical asm to BETA, which is OK. What I don't understand is what the heck is going on around what I marked "ick." Surely such a minute optimisation as not reading back what you just wrote is not too difficult to code. (Of course, I don't write compilers, either. :-) However, I think the ideal would be to replace ALPHA's +0004 MOVEQ #$01,D0 | tmp = 1; +0006 MOVE.W D0,-$0002(A6) | x = tmp; <== ick +000A MOVE.W -$0002(A6),D0 | tmp = x; <== +000E ADDQ.W #$1,D0 | tmp = tmp + 1; +0010 MOVE.W D0,-$0002(A6) | x = tmp; with MOVEQ.W #$1,-$0002(A6) | x = 1; ADDQ.W #$1,-$0002(A6) | x = x + 1; and be done with it. BETA is almost that ideal but Th C insists on using a register temp for x=1. I guess I can live with it if only because I don't like modifying asm by hand on a regular basis. :-) Now a really fancy optimizer would figure out that x always ends up as 2 or even that x is never used outside this scope and so forget about the calling ALPHA altogether. For the heck of it, I looked at what THINK Pascal 2.02 generated for the program below. It looks like the old Th Pascal betters the current Th C... program Test; procedure alpha; var i: integer; begin i := 1; i := i + 1; end; begin alpha; end. ALPHA +0000 2840EA LINK A6,#$FFEE +0004 2840EE MOVE.L D7,-(A7) push(D7) +0006 2840F0 MOVEQ #$01,D7 i := 1; +0008 2840F2 ADDQ.W #$1,D7 i := i + 1; +000A 2840F4 MOVE.L (A7)+,D7 pop(D7) +000C 2840F6 UNLK A6 +000E 2840F8 RTS Here, I don't understand what the deal is with saving D7 before use but I also don't remember Pascal calling conventions, so this may be proper. If anyone would like to add Th Pascal 3.0 output, that would be great, too. (I decided Pascal was getting on my nerves and the 3.0 upgrade was way too expensive for "just to have it around.") -- |_ /| | Robert Minich | |\'o.O' | Oklahoma State University| "I'm a newcomer here, but does the |=(___)= | minich@d.cs.okstate.edu | net ever lay any argument to rest?" | U | - Ackphtth | -- dan herrick
sandy@snoopy.cs.umass.edu (& Wise) (12/18/90)
> Either there is no way to do a quick increment in Pascal ... Pascal does not have an increment operator. Wirth acknowledged this problem with the design of Modula-2 when he added the forms: INC ( variable ); DEC ( variable ); However, I think Pascal will let you can use the successor function. This doesn't eliminate the assignment, but does explicitly request the increment: variable := SUCC ( variable ); > ... or I'm missing something in my knowledge, or I'm wrong about the >speed difference between things like > ++(variable) and > (variable):=(variable)+1 The speed difference between the two depends on the quality of the optimizations, and context (e.g., in a FOR loop, Pascal's implicit increment can usually be done as part of the test and branch instruction, while in C the increment is an explicit statement, and the optimizer must catch it). -- Alexander Erskine Wise /\/\/\/\/\/\/\/\/\/\/\/\ Software Development Laboratory /\/\/\/\/\/\/\/\/\/\/\/\/\/\ WISE@CS.UMASS.EDU /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ \/\/\ This situation calls for large amounts of unadulterated CHOCOLATE! /\/\/\
hodas@saul.cis.upenn.edu (Josh Hodas) (12/18/90)
In article <1990Dec18.042748.6765@d.cs.okstate.edu> minich@d.cs.okstate.edu (Robert Minich) writes: >by stevewi@hpspdra.HP.COM (Steve Witten): >| You can use the 'succ' and 'pred' operators/functions in Pascal to >| accomplish the same function as '++' and '--'. So: >| >| integer i,j,k; >| >| ... >| >| j := succ(i); { same as 'j=i++' } >| k := pred(i); { same as 'k=i--' } >| >| ... >| >| However, you have to remember that '++/--' are positional as well. >| You cannot recreate this behavior. You also cannot recreate the >| behavior of 'x++' without an assignment in Pascal. > > Do you not use C very often or are you VERY tired? The above Pascal >statements are equivalent to > > j := i + 1; > k := i - 1; > >whereas the C translates to Pascal as > >j = i++; | j := j + i; > | i := i + 1; >k = i--; | k := i - 1; > | i := i - 1; > Robert, Do you not use C very often or are you VERY tired? Sorry, I couldn't resist. j = i++ => j := i; i := i + 1; K = i-- => K := i; i := i - 1; and, for completeness: j = ++i => i := i + 1; j := i; K = i-- => i := i - 1; k := i; Josh ---------------------------------------------------------------------------- Josh Hodas Home Phone: (215) 222-7112 4223 Pine Street School Office Phone: (215) 898-9514 Philadelphia, PA 19104 New E-Mail Address: hodas@saul.cis.upenn.edu
n67786@lehtori.tut.fi (Nieminen Tero) (12/19/90)
I also tried {x += 1;} and it produced identical asm to BETA, which is OK. What I don't understand is what the heck is going on around what I marked "ick." Surely such a minute optimisation as not reading back what you just wrote is not too difficult to code. (Of course, I don't write compilers, either. :-) However, I think the ideal would be to replace ALPHA's +0004 MOVEQ #$01,D0 | tmp = 1; +0006 MOVE.W D0,-$0002(A6) | x = tmp; <== ick +000A MOVE.W -$0002(A6),D0 | tmp = x; <== +000E ADDQ.W #$1,D0 | tmp = tmp + 1; +0010 MOVE.W D0,-$0002(A6) | x = tmp; with MOVEQ.W #$1,-$0002(A6) | x = 1; ADDQ.W #$1,-$0002(A6) | x = x + 1; and be done with it. OK. Would someone out there with a Motorola 68000/020/030 (or most notably 040 manual) check which one uses the leas clock sycles. Don't be that easily fooled by the number of lines of code produced if speed is what you are after. Operations on registers (ie. the move-to-reg add-to-reg) tend to be a lot faster in Motorola processors (especially 040) than operations on memory locations. Just my 0.02 worth. -- Tero Nieminen Tampere University of Technology n67786@cc.tut.fi Tampere, Finland, Europe
minich@d.cs.okstate.edu (Robert Minich) (12/19/90)
by hodas@saul.cis.upenn.edu (Josh Hodas): >minich@d.cs.okstate.edu (Robert Minich) writes: >#by stevewi@hpspdra.HP.COM (Steve Witten): ># ># [...] ># ># ># Do you not use C very often or are you VERY tired? The above Pascal >#statements are equivalent to > > Do you not use C very often or are you VERY tired? I guess I shouldn't post at 2am without a Jolt break. :-) > Sorry, I couldn't resist. Understandably... seeing as I couldn't resist the first mistake, myself! Exec summary: Thanks Josh. I goofed but so did Steve. Got it? -- |_ /| | Robert Minich | |\'o.O' | Oklahoma State University| "I'm a newcomer here, but does the |=(___)= | minich@d.cs.okstate.edu | net ever lay any argument to rest?" | U | - Ackphtth | -- dan herrick
n67786@lehtori.tut.fi (Nieminen Tero) (12/19/90)
In article <16650@imag.imag.fr> gourdol@imag.imag.fr (Gourdol Arnaud) writes:
Writing optimisation for Pascal IS more difficult than for C, in the
sens that in C, when we use the ++ operator you say to the compiler
"Hey, stupid, don't forget to use the INC operator that exist
in assembly language!"
When you do i := i + 1; in Pascal, the compiler must detect that
it can (and should) use the inc operator. Much more difficult
when the expression is a bit complicated (like a[i]).
If the C compilers optimization is any good it WILL notice such cases
too. But this kind of optimization is not in any way illegal in Pascal
and it's the compilers defect not to catch it (be that C or Pascal
compiler, or any other for that matter).
I would rather say that since C language is so much closer to machine
level, you might be tempted to consider programmers decisions better
optimization than what the compiler could produce. It hasbeen proven
many times that in non trivial cases Fortran compilers produce better
code for accessing elements of array than equivalent C compiler even
though the Fortran code uses indexes in stead of pointers (at least in
source code level). What exactly the compiler output is is entirely up
to the compiler (like it should be in my opinion). In the era of
pipelined processor architecture it is especially wise to leave the
optimization for the compiler. And the less the language has to do with
the hardware the easier it should be to make the compiler optimizing
optimal (since it doesn't need to watch out for any bad decisions made
by the programmer).
There is still no good compiler on the Mac (except GCC maybe ?)
either in C or Pascal.
True enough. Or for any other language for that matter.
(Of course, LSP and LSC are REAL love for programming and debugging
as compared to cc, dbx and adb on Sun !!!)
Arnaud.
--
Tero Nieminen Tampere University of Technology
n67786@cc.tut.fi Tampere, Finland, Europe
gourdol@imag.imag.fr (Gourdol Arnaud) (12/19/90)
LSP and LSC are both not very good compilers, I mean for the code
the build being not "good" code. BTW MPW C3.0 is not a good compiler
either.
I had the chance to write a compiler and so have been involved
in comparing different compilers performance, bot on the Mac and
on Sun. Sun C compiler IS very good. There are many levels of
optimisation (4 in fact) which can be actived with -O1 to -O4.
With -O4 if you write a program like :
main()
{ int i,j;
i = 0;
j = 1;
i = j++ + 1;
};
the compiler will produce... nothing. (Hey ! this code does
nothing, does it ?)
Writing optimisation for Pascal IS more difficult than for C, in the
sens that in C, when we use the ++ operator you say to the compiler
"Hey, stupid, don't forget to use the INC operator that exist
in assembly language!"
When you do i := i + 1; in Pascal, the compiler must detect that
it can (and should) use the inc operator. Much more difficult
when the expression is a bit complicated (like a[i]).
There is still no good compiler on the Mac (except GCC maybe ?)
either in C or Pascal.
(Of course, LSP and LSC are REAL love for programming and debugging
as compared to cc, dbx and adb on Sun !!!)
Arnaud.
philip@pescadero.Stanford.EDU (Philip Machanick) (12/19/90)
In article <SANDY.90Dec18095930@snoopy.cs.umass.edu>, sandy@snoopy.cs.umass.edu (& Wise) writes: |> The speed difference between the two depends on the quality of the |> optimizations, and context (e.g., in a FOR loop, Pascal's implicit |> increment can usually be done as part of the test and branch |> instruction, while in C the increment is an explicit statement, and |> the optimizer must catch it). Since we are in reading compiler output mode, would someone care to compare the code produced by the following Pascal: program test; var i:integer; begin for i:=1 to 10 do {something} end. and C: main() { int i; for (i=1; i<= 10; i++) /* do something */ ; } As with the ++ examples, there is no reason a _good_ compiler should do better or worse with either, but the C case is slightly more difficult, as noted above. -- Philip Machanick philip@pescadero.stanford.edu
peirce@outpost.UUCP (Michael Peirce) (12/19/90)
In article <1990Dec18.215406.29735@Neon.Stanford.EDU>, philip@pescadero.Stanford.EDU (Philip Machanick) writes: > > In article <SANDY.90Dec18095930@snoopy.cs.umass.edu>, sandy@snoopy.cs.umass.edu (& Wise) writes: > |> The speed difference between the two depends on the quality of the > |> optimizations, and context (e.g., in a FOR loop, Pascal's implicit > |> increment can usually be done as part of the test and branch > |> instruction, while in C the increment is an explicit statement, and > |> the optimizer must catch it). > > Since we are in reading compiler output mode, would someone care to compare > the code produced by the following Pascal: > > program test; > var i:integer; > begin > for i:=1 to 10 do {something} > end. > > and C: > > main() > { int i; > for (i=1; i<= 10; i++) /* do something */ > ; > } OK, but I made one change: since MPW C uses 32-bit ints and MPW Pascal integers are 16-bit, I changed the pascal example to use LongInts as they are 32-bits. Here are the two sources: The Pascal Source - UNIT Test; INTERFACE PROCEDURE testit(x:LONGINT); IMPLEMENTATION PROCEDURE SomeThing(a,b: LONGINT); EXTERNAL; PROCEDURE Testit(x:LONGINT); VAR i : LONGINT; BEGIN FOR i := 1 to 10 DO BEGIN SomeThing(i,x); END; END; END. And the MPW C source - void SomeThing(int a, int b); external; void test(int x) { int i; for (i=1;i<= 10;i++) { SomeThing(i,x); } }; And now the results from the MPW DUMPOBJ tool: For Pascal - -- Enter the routine 00000000: 4E56 FFFC 'NV..' LINK A6,#$FFFC 00000004: 2F07 '/.' MOVE.L D7,-(A7) -- set for the FOR loop 00000006: 7E01 '~.' MOVEQ #$01,D7 00000008: 600C '`.' BRA.S *+$000E ; 00000016 -- do the subroutine call 0000000A: 2F07 '/.' MOVE.L D7,-(A7) 0000000C: 2F2E 0008 '/...' MOVE.L $0008(A6),-(A7) 00000010: 4EBA 0000 'N...' JSR SOMETHING ; id: 3 -- process the FOR loop 00000014: 5287 'R.' ADDQ.L #$1,D7 00000016: 700A 'p.' MOVEQ #$0A,D0 00000018: B087 '..' CMP.L D7,D0 0000001A: 6CEE 'l.' BGE.S *-$0010 ; 0000000A -- exit the routine 0000001C: 2E1F '..' MOVE.L (A7)+,D7 0000001E: 4E5E 'N^' UNLK A6 00000020: 2E9F '..' MOVE.L (A7)+,(A7) 00000022: 4E75 'Nu' RTS And the C - -- Enter the routine 00000000: 4E56 0000 'NV..' LINK A6,#$0000 00000004: 48E7 1300 'H...' MOVEM.L D3/D6/D7,-(A7) -- set for the FOR loop 00000008: 2C2E 0008 ',...' MOVE.L $0008(A6),D6 0000000C: 7E01 '~.' MOVEQ #$01,D7 -- do the subroutine call 0000000E: 2F06 '/.' MOVE.L D6,-(A7) 00000010: 2F07 '/.' MOVE.L D7,-(A7) 00000012: 4EBA 0000 'N...' JSR SomeThing ; id: 3 00000016: 508F 'P.' ADDQ.L #$8,A7 -- process the FOR loop 00000018: 2007 ' .' MOVE.L D7,D0 0000001A: 5287 'R.' ADDQ.L #$1,D7 0000001C: 700A 'p.' MOVEQ #$0A,D0 0000001E: B087 '..' CMP.L D7,D0 00000020: 6CEC 'l.' BGE.S *-$0012 ; 0000000E -- exit the routine 00000022: 4CEE 00C8 FFF4 'L.....' MOVEM.L -$000C(A6),D3/D6/D7 00000028: 4E5E 'N^' UNLK A6 0000002A: 4E75 'Nu' RTS Pascal generates a few less instruction. I'm not sure which is faster - I was too lazy to count cycles. But again this shows that they're both pretty close. Declaring the C routines to be Pascal, i.e. Pascal style calling conventions didn't change the byte count. -- michael -- Michael Peirce -- {apple,decwrl}!claris!outpost!peirce -- Peirce Software -- Suite 301, 719 Hibiscus Place -- Macintosh Programming -- San Jose, California 95117 -- & Consulting -- (408) 244-6554, AppleLink: PEIRCE
Lawson.English@p88.f15.n300.z1.fidonet.org (Lawson English) (12/19/90)
Anthony Berno writes in a message to All AB> Either there is no way to do a quick increment in Pascal, or AB> I'm missing something in my knowledge, or I'm wrong about the AB> speed difference between things like ++(variable) and (variable):=(variable)+1- AB> If your compiler is bad at optimization (and all Apple compilers are notoriously bad), then it won't recognize the special case of inc x for x := x+1; Of course, as most Apple products are slowed down by the trap dispatcher, thrid-party optimization is pretty much a waste unless a substantial amount of time is spent in arithmatic or searching/sorting. Consider: the average graphics program on a Plus spends 20% of its time in the trap dispatcher. The average '020 machine spends 60% of its time there. I don't know how much time is spent there in the 030 machines but I would not be surprised if as much as 75-80% of the time is spent there. This assumes that SANE is being used instead of the '881/882. Regions are another area where graphics slows to a crawl: if you are sure that your program will never write outside of the screen (you're doing a copybits for instance), set your clip region to a rectangle, rather than let the cute rounded corners of the screen be used. This can speed up full-screen drawing by quite a bit. My first programming job on the Mac was providing the software background/support for software optimization of the accellerator/graphics board. Some 0f the stuff in the 128k ROMS was pretty scary we found. Lawson -- Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!300!15.88!Lawson.English Internet: Lawson.English@p88.f15.n300.z1.fidonet.org
alexr@apple.com (Alex Rosenberg) (12/20/90)
In article <0B010004.o0u3z7@outpost.UUCP> peirce@outpost.UUCP (Michael Peirce) writes: > Here are the two sources: > > The Pascal Source - > > UNIT Test; > > INTERFACE > > PROCEDURE testit(x:LONGINT); > > IMPLEMENTATION > > PROCEDURE SomeThing(a,b: LONGINT); EXTERNAL; > > PROCEDURE Testit(x:LONGINT); > VAR > i : LONGINT; > BEGIN > FOR i := 1 to 10 DO BEGIN > SomeThing(i,x); > END; > END; > > END. > > And the MPW C source - > > void SomeThing(int a, int b); external; > > void test(int x) > { > int i; > > for (i=1;i<= 10;i++) { > SomeThing(i,x); > } > }; The MPW C case can be optimized like: void test(int x) { int i; for (i=10; i; --i) { SomeThing(i,x); } }; MPW C should end up using a DBRA loop for this, which uses less instructions. Note the predecriment, as in MPW C, prefix operations on register-based variables (as "i" should is) are tighter than postfix. (Note that while I think that the Pascal compiler can generate DBRA loops, I'm not sure it will in this case.) By far, the handiest tool for this sort of investigation is UltraSlimFast. This MPW tool can be found on the System 7.0 Beta CD. It prints object code next to the source code, matching lines up as much as possible. --------------------------------------------------------------------------- - Alexander M. Rosenberg - INTERNET: alexr@apple.com - Yoyodyne - - 330 1/2 Waverley St. - UUCP:ucbvax!apple!alexr - Propulsion - - Palo Alto, CA 94301 - - Systems - - (415) 329-8463 - Nobody is my employer so - :-) - - (408) 974-3110 - nobody cares what I say. - -
jmunkki@hila.hut.fi (Juri Munkki) (12/20/90)
n67786@lehtori.tut.fi (Nieminen Tero) writes: > OK. What I don't understand is what the heck is going on around what I > marked "ick." Surely such a minute optimisation as not reading back what > you just wrote is not too difficult to code. (Of course, I don't write > compilers, either. :-) However, I think the ideal would be to replace > ALPHA's > > +0004 MOVEQ #$01,D0 | tmp = 1; > +0006 MOVE.W D0,-$0002(A6) | x = tmp; <== ick > +000A MOVE.W -$0002(A6),D0 | tmp = x; <== > +000E ADDQ.W #$1,D0 | tmp = tmp + 1; > +0010 MOVE.W D0,-$0002(A6) | x = tmp; One thing to remember about the Think C compiler is that it doesn't automatically allocate register variables. The Think Pascal examples that we have seen here allocated a register variable and used that. That's why they saved the register in the stack first and then initialized it. If you really want to write something as stupid as the subroutine that has been discussed here, write it like this in Think C: void dotest() { register int i=1; i++; } This produces: move.l D7,-(sp) moveq.l #1,D7 addq.w #1,D7 move.l (sp)+,D7 rts Looks good to me. Of course Think C is not an optimizing compiler in the strict sense of the word. IMHO, C is just a fancy assembler that produces portable code... Also, Think C 4.02 produces the following code, if I omit the register allocation: link A6,-2 moveq.l #1,D0 move.w D0,-2(A6) addq.l #1,-2(A6) unlk A6 rts Changing the initializer to something like 1024 will change the code so that we have: link A6,-2 move.w #1024,-2(A6) addq.l #1,-2(A6) unlk A6 rts To be honest, I don't find this thread useful. The best way to learn about these things is to read a basic text on compilers or take a course on compiler design. The reason why C doesn't produce all that good code with i=i+1 is because it has i++ available, so programmers use that and there is no need to waste time trying to optimize i=i+1, since it doesn't usually occur in normal code. Pascal compilers run into i:=i+1 all the time, so they have to watch for it. ____________________________________________________________________________ / Juri Munkki / Helsinki University of Technology / Wind / Project / / jmunkki@hut.fi / Computing Center Macintosh Support / Surf / STORM / ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hawley@adobe.COM (Steve Hawley) (12/20/90)
Although this has less to do with Mac programming than programming in general,
I remember reading an article about optimization when I was in a compiler
class. The gist of the article was that benchmarks the author had done
revealed that the code generated by available Pascal compilers was really
slow in comparison to that of FORTRAN compilers. The reasoning was that
programmers had been using FORTRAN (at that time) for computationally intensive
tasks, and out of need, the compilers were tweaked to optimize the living
daylights out of the code, whereas nobody bothered using Pascal for "real"
tasks, so nobody bothered optimizing the compiler. Vicious circle. It's not
completely the case that the language is defficient, but the optimizers were
lousy (or non-existent).
Of course there are some things the language won't let you do, and the structure
of Pascal doesn't help the compiler writer optimize.
Autoincrement and autodecrement were not added to C merely as syntactic sugar.
They were added in as a concession to the fact that addition and subtraction
of small constants are commonplace in programming, and as such we can
accomplish several things:
1) Reduce the amount of typing the programmer needs to do.
2) Factor out the special case from the optimizer into the parser.
3) Provide a closer tie to the target machine.
4) Complicate the parser.
For example, if I write a routine to copy a string, in C I would do this
strcpy(dst, src)
char *dst, *src;
{
while ((*dst++ = *src++) != '\0');
}
in Pascal (assuming the same null terminated strings):
procedure strcpy(dst, src: ^char);
{ 'scuse my Pascal, I haven't had to code in it actively for several years }
begin
while (src^ <> CHR(0)) do begin
dst^ := src^;
dst := SUCC(dst)
src := SUCC(src);
end;
dst^ := src^ { copy the NULL }
end;
So what's my point? I don't know, I've kind of lost it. Oh right, I was
defending Pascal. Both functions are abstractions of what you want to do:
copy data from point a to point b using a sentinel.
On a processor with relatively few capabilities, the C version might generate
something like this:
L0: move src, a0
move (a0), d0 get char
add #$1, a0 assuming we can do arithmetic on address registers
move a0, src
move dst, a0
move d0, (a0) copy char
add #$1, a0
move a0, dst
cmp #$0, d0 sentinel test
bne L0
The Pascal code may generate this:
move src, a0
L0: move (a0), d0
cmp #$0, d0
beq L1
move dst, a0
move d0, (a0)
add #$1, (a0)
move a0, dst
move src, a0
add #$1, a0
move a0, src
jump L0
L1 move dst, a0
move d0, a0
and lo and behold, the C is a 10 instruction loop, the Pascal an 11 instruction
loop. Of course, this isn't a real instruction set and I've purposely limited
its capabilities, but how far is it from a RISC processor? Not far. Not far
at all. The RISC processor would do most of the work in registers and
eliminate a lot of the memory juggling.
Of course, withthe Pascal, you must pray that your optimizer has the sense to
do good work for you.
With a 68000 target processor, there's no reason to get the following assembly
language from the C code:
move.l src, a0
move.l dst, a1
L0: move.b (a0)+,(a1)+
bne L0
Which you won't get from Think C, by the way, unless you declare your variables
to be registers...
Whatever.
Steve Hawley
hawley@adobe.com
--
"I'm sick and tired of being told that ordinary decent people are fed up with
being sick and tired. I know I'm certainly not, and I'm sick and tired of
begin told that I am." -Monty Python
minich@d.cs.okstate.edu (Robert Minich) (12/20/90)
by alexr@apple.com (Alex Rosenberg): | By far, the handiest tool for this sort of investigation is UltraSlimFast. | This MPW tool can be found on the System 7.0 Beta CD. It prints object | code next to the source code, matching lines up as much as possible. How about a tool to calculate cycle counts for given chunks of code for various cpus (68000, 010, 020, 030, 040) and differing wait states? That would make these micro-optimisations much easier. :-) -- |_ /| | Robert Minich | |\'o.O' | Oklahoma State University| "I'm a newcomer here, but does the |=(___)= | minich@d.cs.okstate.edu | net ever lay any argument to rest?" | U | - Ackphtth | -- dan herrick
jfr@locus.com (Jon Rosen) (12/21/90)
In article <q72au3w163w@questor.wimsey.bc.ca> aberno@questor.wimsey.bc.ca (Anthony Berno) writes: >I generally prefer Pascal programming, but I have come up against what >seems like a real deficiency in the language. I never really thought >about it before, but there does not seem to be any equivalent to >the ++ or -- operator in Pascal. I was doing some speed checks on >array accessing today, and it occured to me that in doing something >like incrementing an entry by one, the computer was doing rather a >lot of work! > >Either there is no way to do a quick increment in Pascal, or I'm missing >something in my knowledge, or I'm wrong about the speed difference between >things like >++(variable) and >(variable):=(variable)+1 > Your observation is a good one... However, it is not a quality of the language itself that causes the suboptimal performance, but rather the quality of the optimizer... A good Pascal compiler will recognize the construct X := X+1; and perform the appropriate machine code in the best way possible to increment the variable X by 1... Depending on the machine that is being used, this may be a direct register or memory increment instruction or it may end up the same as the assignment statement X := X+2; with a different value being added... In C, X = X+1; and X++; may also be implemented differently depending on the machine or identically... The IBM 370 mainframe, for instance, has no increment/decrement instructions (well, BCTR might be used here, for decrementing) so the C version of these statements is indentical... An example of where a Pascal compiler can be more optimal than a suboptimal C compiler is the WITH statement. Within the domain of a WITH record statement, most good Pascal compilers will attempt to hold a pointer to the record in aworking register... In C compilers, since all structure usages require explicit pointing (struct.field), the compiler that does not do good optimization of the use of a set of structure references might throw constantly reload the register with the pointer to struct... So language makes it easier for compilers to do certain things, but the compiler itself still has to take advantage and the underlying machine architecture has to be able to provide the tools for taking advantage... Otherwise, it really doesn't matter... Jon R.
Lawson.English@p88.f15.n300.z1.fidonet.org (Lawson English) (12/22/90)
Nieminen Tero writes in a message to All NT> There is still no good compiler on the Mac (except GCC maybe NT> ?) either in C or Pascal. NT> True enough. Or for any other language for that matter. NT> (Of course, LSP and LSC are REAL love for programming and debugging NT> as compared to cc, dbx and adb on Sun !!!) Obviously you never tested HyperC on the Mac. That little gem (non-supported for the last few years) would compile smaller code than any other Mac compiler (usually 40-60% smaller). Its problems were myriad; however, if anyone wants to get the source code, it's still available. Lawson -- Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!300!15.88!Lawson.English Internet: Lawson.English@p88.f15.n300.z1.fidonet.org
Lawson.English@p88.f15.n300.z1.fidonet.org (Lawson English) (12/22/90)
Edward V. Wright writes in a message to All EVW> >x++: LOAD X > INC X > STORE X EVW> Unless you have an instruction to increment variables in memory! As I recall, MC68xxx DOES have an increment of an indexed memory location. The '020 has a direct memory inc (I think). Lawson -- Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!300!15.88!Lawson.English Internet: Lawson.English@p88.f15.n300.z1.fidonet.org
Chris.Gehlker@p12.f56.n114.z1.fidonet.org (Chris Gehlker) (12/24/90)
SEC> Decent is the key word here. If your compiler does not optimize, SEC> you're likely to get different code for these, and with the number SEC> of shoddy software products on the market these days, you might SEC> want to investigate. I've disassembled enough C and Pascal, both THINK and MPW, to know that they all generate and Addq.x #1,dx for this instruction no matter how you write it. j := j + 1; j := Succ(j); j = j + 1; j++; ++j; j += 1; all generate exactly the same code. -- Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!56.12!Chris.Gehlker Internet: Chris.Gehlker@p12.f56.n114.z1.fidonet.org
Chris.Gehlker@p12.f56.n114.z1.fidonet.org (Chris Gehlker) (12/24/90)
AB> I generally prefer Pascal programming, but I have come up against AB> what seems like a real deficiency in the language. I never really AB> thought about it before, but there does not seem to be any equivalent AB> to the ++ or -- operator in Pascal. I was doing some speed checks AB> on array accessing today, and it occured to me that in doing AB> something like incrementing an entry by one, the computer was AB> doing rather a lot of work! AB> Either there is no way to do a quick increment in Pascal, or AB> I'm missing something in my knowledge, or I'm wrong about the AB> speed difference between things like ++(variable) and (variable):=(variable)+1 You are right about the loss of efficiency in accessing arrays but wrong about the source of the inefficiency. Variable := Variable +1 or Variable := Succ(variable) will generate exactly the same code as variable++, namely a addq.x #1,Dx. Where Pascal falls down is in address arthmetic: for i := 1 to rows do for j := 1 to columns do thearray[i,j] := something; will generate a run time multiply to each time through the inner loop to figure out the offset from the start of the array. On the Mac you can work around this by writing something like: Type elementPtr = ^integer; var theElement, arrayStart:longint; ... arrayStart := longint(@thearray[1,1]); theElement := 0 while theElement <= longint(@theArray[rows,columns]) do begin elementPtr(arrayStart + theElement)^ := something; theElement := theElement + sizeof(integer) end; This gives a big speedup at the cost of clarity and portability. -- Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!56.12!Chris.Gehlker Internet: Chris.Gehlker@p12.f56.n114.z1.fidonet.org
Chris.Gehlker@p12.f56.n114.z1.fidonet.org (Chris Gehlker) (12/24/90)
RM> Here, I don't understand what the deal is with saving D7 before RM> use but I also don't remember Pascal calling conventions, so RM> this may be proper. If anyone would like to add Th Pascal 3.0 RM> output, that would be great, too. (I decided Pascal was getting RM> on my nerves and the 3.0 upgrade was way too expensive for "just RM> to have it around.") THINK Pascal 3.0.1 generated code identical to your 2.02 example whether I wrote it as i := i + 1; or i := succ(i); As for the C, guys from Symantic have said here quite a bit that their philosophy is that if the programmer wants a variable to be register, she should declare it register. This is diametrically opposit tp the MPW philsophy. -- Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!56.12!Chris.Gehlker Internet: Chris.Gehlker@p12.f56.n114.z1.fidonet.org
sampson@cod.NOSC.MIL (Charles H. Sampson) (01/08/91)
In article <33176.27759EC3@stjhmc.fidonet.org> Chris.Gehlker@p12.f56.n114.z1.fidonet.org (Chris Gehlker) writes: >Where Pascal falls down is in address arthmetic: >for i := 1 to rows do > for j := 1 to columns do > thearray[i,j] := something; >will generate a run time multiply to each time through the inner loop to >figure >out the offset from the start of the array. On the Mac you can work around >this by writing something like: ... I've just picked up this thread, so I hope my comment hasn't been made already. The above complaint appears to be against the Pascal language for not doing a good job on array accesses. The fault is not the language, it's the compiler. There is an ancient code optimization technique called strength-reduction that will remove all the multiplies in favor of setting up an initial address outside the loop and then calculating the next address inside the loop by addition, just like the deleted example did. This tech- nique is so old and understood so well that many don't even consider it an optimization any more -- just a standard code-generation technique. As to why your favorite compiler isn't doing it, you'll have to ask the vendor. Charlie
Chris.Gehlker@p12.f56.n114.z1.fidonet.org (Chris Gehlker) (01/09/91)
CHS> I've just picked up this thread, so I hope my comment hasn't CHS> been made already. The above complaint appears to be against CHS> the Pascal language for not doing a good job on array accesses. CHS> The fault is not the language, it's the compiler. I'm just getting back here after being off line for awhile and I've missed the intervening posts but your point is well taken. The example I had in mind, as opposed to the example I posted, was more complicated. I was thinking of a simulation where each cell had to learn the status of it's neighbors. The pointer arithmetic was a little harrier than simpliy initiallizing an array. I don't think either MPW Pascal or LSP do any stress reduction. In fact I've disassembled eneough LSP to be sure that it doesn't. I'll have to check MPW. -- Uucp: ...{gatech,ames,rutgers}!ncar!asuvax!stjhmc!56.12!Chris.Gehlker Internet: Chris.Gehlker@p12.f56.n114.z1.fidonet.org
siegel@endor.uucp (Rich Siegel) (01/11/91)
In article <34587.278C73DB@stjhmc.fidonet.org> Chris.Gehlker@p12.f56.n114.z1.fidonet.org (Chris Gehlker) writes: > >I don't think either MPW Pascal or LSP do any stress reduction. In fact I've >disassembled eneough LSP to be sure that it doesn't. I'll have to check MPW. Actually, THINK Pascal does do stress reduction, because it compiles so fast. You get work done, so you stay on schedule, and that reduces the stress level of yourself, and consequently of those around you. ;-) R. Rich Siegel Symantec Languages Group Internet: siegel@endor.harvard.edu "...she's dressed in yellow, she says 'Hello, come sit next to me, you fine fellow..."
Bruce.Hoult@bbs.actrix.gen.nz (01/14/91)
Chris Gehlker writes: >I don't think either MPW Pascal or LSP do any stress reduction. They don't do much strength reduction either :-) -- Bruce.Hoult@bbs.actrix.gen.nz Twisted pair: +64 4 772 116 BIX: brucehoult Last Resort: PO Box 4145 Wellington, NZ "...a plan so cunning, you could pin a tail on it and call it a weasel..."