brad@looking.UUCP (Brad Templeton) (05/03/89)
Did RISC machines cause a push in optimizing compilers? I always thought the big advantage of the RISC was that it made the low level optimizations so much simpler -- there's only one way to code the thing, so no need to worry about the best use of fancy instructions and addressing modes. High level optimizations are another matter, but they apply as well to CISC as to RISC. -- Brad Templeton, Looking Glass Software Ltd. -- Waterloo, Ontario 519/884-7473
hedrick@geneva.rutgers.edu (Charles Hedrick) (05/03/89)
>Did RISC machines cause a push in optimizing compilers? I always thought >the big advantage of the RISC was that it made the low level optimizations >so much simpler -- there's only one way to code the thing, so no need to >worry about the best use of fancy instructions and addressing modes. Sort of. Actually it's probably better to say that RISC *depended upon* a push in optimizing compilers. How much it depends upon them depends upon the specific architecture. Some of the original RISC proposals include things like delayed branching, and in fact the SPARC (Sun 4) does that. That is, a branch instruction doesn't take effect until after the next instruction. In order to produce optimal code, your compiler may have to rearrange code. Simple-minded compilers just put a no-op after the branch. Also, in order to get the benefit out of RISC, you have to be able to use all those registers. This means a compiler intended for RISC should have a good register allocation method. When you can refer to memory about as easily as a register, that's not quite as critical for CISC (though of course minimizing memory references certainly helps there too). The conventional wisdom is that RISC machines need very smart compilers in order to give reasonable performance.
gph@hpsemc.HP.COM (Paul Houtz) (05/04/89)
brad@looking.UUCP (Brad Templeton) writes: >Did RISC machines cause a push in optimizing compilers? I always thought >the big advantage of the RISC was that it made the low level optimizations >so much simpler -- there's only one way to code the thing, so no need to Your question is a little ambiguous. Are you asking if RISC machines caused a change in the INDUSTRY, or do they give impetus for a single vendor to start making optimizers? HP has RISC machines, and yes, all of a sudden we have optimizing compilers for the first time. You see, Optimizers become a big boon with RISC because instead of having complex instructions (which cannot be optimized at compile time), you have little programs that do what the CISC instructions used to do. Those little programs are software, and once they are dragged into the code, they can be optimized along with everything else in the program. Also, when you start talking about pipelining, delayed branch slots, and single cycle instructions, it actually becomes more reasonable to allow the compiler to generate whatever construct is efficient for a given function. Then it is very simple for a separate pass to do things like fill in branch delay slots, move non-dependent structures out of loops, etc.
allbery@ncoast.ORG (Brandon S. Allbery) (05/08/89)
As quoted from <3181@looking.UUCP> by brad@looking.UUCP (Brad Templeton): +--------------- | Did RISC machines cause a push in optimizing compilers? I always thought | the big advantage of the RISC was that it made the low level optimizations | so much simpler -- there's only one way to code the thing, so no need to | worry about the best use of fancy instructions and addressing modes. +--------------- I was under the impression that it had. At least one person has suggested that I was wrong -- but I'm not entirely certain of that. Optimization under RISC consists primarily of (1) recognizing that some loops will run faster when "unwound" into linear code and (2) optimizing the use of registers. The latter involves copying often-used values into a register once instead of constantly fetching it from memory, and recognizing that the "brute-force" method of using registers can result in multiple registers having the same value, and saving only one of those registers for future use while "freeing" the others up for use by the next calculation. Both can be applied to CISC code; in fact, register optimization is, if anything, *more* useful on hardware which doesn't have registers to spare. Unwinding loops isn't normally useful unless you've decided to trade code size for the absolute maximum of speed, although certain "trivial" loops might always be expanded with little cost (and, probably, equally little gain). The difference that RISC brings to it is that both are very nearly *required* for RISC, whereas CISC can get by without either; consider yours and my "favorite" compiler, AT&T's pcc. The speed benefits of RISC are quickly lost if the compiler produces code that wastes time doing things that don't really need to be done because it isn't aware of prior context. ++Brandon -- Brandon S. Allbery, moderator of comp.sources.misc allbery@ncoast.org uunet!hal.cwru.edu!ncoast!allbery ncoast!allbery@hal.cwru.edu Send comp.sources.misc submissions to comp-sources-misc@<backbone> NCoast Public Access UN*X - (216) 781-6201, 300/1200/2400 baud, login: makeuser
gph@hpsemc.HP.COM (Paul Houtz) (05/10/89)
allbery@ncoast.ORG (Brandon S. Allbery) writes: >Optimization under RISC consists primarily of (1) recognizing that some >loops will run faster when "unwound" into linear code and (2) optimizing the >use of registers. The latter involves copying often-used values into a >register once instead of constantly fetching it from memory, and recognizing >Both can be applied to CISC code; in fact, register optimization is, if >anything, *more* useful on hardware which doesn't have registers to spare. >The difference that RISC brings to it is that both are very nearly >*required* for RISC, whereas CISC can get by without either; consider yours The statement in the first paragraph is false. RISC optimization does not consist PRIMARILY of unwinding loops and optimizing registers. Optimizing registers is a big part of RISC optimization, but you left out filling branch delay slots. You see, most RISC implementations are pipelined implementations, and branches cause bubbles in pipelines. Therefore the RISC architectures usually allow the branch to occur after the instruction following the branch. That way, the bubble in the pipeline can be filled. Architecture non-specific example: Normally you would code: ld r2, *+2 Load return address in register 2 bl subprog branch to subprogram subprog st r25,$ADDIT ad $ADDIT,1 . . b r2 In a RISC implementation, the programs would look the same, except the code to get to the subroutine would be "optimized" to look like this: bl subprog ld r2, *+1 Since the instruction after the brach WILL be executed before the branch, you can save a couple of cycles by placing the branch after the load instruction. The RISC optimizers will fill branch delay slots first, then look at unwinding loops and then register optimization. However, in the compilers I have looked at, register optimization is something the compiler does, not the optimizer. Of course, all systems are not the same. Also, I think it is incorrect to say that RISC architectures MUST be optimized to have acceptable performance. I don't think that this is born out by scientific evidence availble. Rather, I would say that RISC code can benefit more from optimization, since there is no ROM microcode. You see, you can not combine millions line of ROM code and then optimize the whole mess, becuase it is ROM. With RISC, all the code is RAM resident. Theoretically, once the compiler pulls in the code it needs to do what CISC instructions used to do, the whole thing can then be optimized.