Path: utzoo!censor!geac!torsqnt!news-server.csri.toronto.edu!cs.utexas.edu!yale!mintaka!spdcc!iecc!compilers-sender From: pardo@cs.washington.edu (David Keppel) Newsgroups: comp.compilers Subject: Re: Squashing C Source Keywords: optimize Message-ID: <14176@june.cs.washington.edu> Date: 17 Dec 90 02:42:14 GMT References: <10767.9012051639@subnode.sari.ed.ac.uk> <14662@goofy.megatest.UUCP> Sender: compilers-sender@iecc.cambridge.ma.us Reply-To: pardo@cs.washington.edu (David Keppel) Organization: University of Washington, Computer Science, Seattle Lines: 68 Approved: compilers@iecc.cambridge.ma.us >>[I want to create one huge main()] megatest!djones@decwrl.dec.com (Dave Jones) writes: >[Why? It will certainly make the resulting object code slower.] >[For example, call/return is an efficient way to save/restore > registers; the program will be larger unless procedures have only > one call site; a larger program is usually slower; you will have to > reinvent procedure calls to handle recursion.] Um, er, ah, well, uh... I'm not the original author so I can't comment on why s/he wanted to do it. It does seem to me, though, that you're imagining a particular model for how things get expanded. I don't see any particular reason why ANY of the problems mentioned above are ``problems''. * Call/return as an efficient way to save/restore registers The VAX and Tahoes are optimized to save and restore registers in call/return, but also have an explict register save with mask instruction that does the same thing without the overhead of setting up the argument/frame pointer(s), etc. The 680x0 family has a similar instruction. On many RISCy machines -- and on a number of CISCy machines -- register save/restore is left almost entirely up to the programmer, the major exceptions being CISCy machines that dedicate the program counter and the stack pointer. * The program will be larger unless procedures have only one call site. That's assuming that you have a function inlined everywhere that they appear. An alternative is to take each function |x| and produce a label |x| and a set of ``calling conventions'' for transferring control to that label. You do wind up reinventing the procedure call, it is true, but you also wind up with equivalent-size code. * A larger program will generally be slower That depends in great detail on things like caching behavior. Strictly inling long squences is almost always a lose, but shorter sequences can profitably be replicated at a substantial increase in ojbect code size if, say, the larger code improves prefetching. * You have to reinvent procedure calls to handle recursion. Excluding the case of tail calling, yes, you do have to reinvent procedure calls. However, you might get more freedom about designing custom calling conventions. In summary, aggressive compilers such as the MIPS compiler generally try to create one large procedure out of a program. They generally don't inline recursive calls unless they are tail-recursive. The major difference is that they reserve ``squashing everything in to one big function'' for e.g., link time. Yeah, well, I'd like to squash C source, too, but for my needs it's the best programming language I have avaialable. ;-D on ( But working on it anyway ) Pardo -- Send compilers articles to compilers@iecc.cambridge.ma.us or {ima | spdcc | world}!iecc!compilers. Meta-mail to compilers-request.