Path: utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!samsung!xanth!mcnc!rti!xyzzy!meissner From: meissner@dg-rtp.dg.com (Michael Meissner) Newsgroups: comp.sys.m88k Subject: Re: Register Allocation (was Re: Info about 88open & standards) Message-ID: Date: 28 Nov 89 17:46:15 GMT References: <1948@psueea.UUCP> <1989Nov14.175806.23483@paris.ics.uci.edu> <5063@tekcrl.LABS.TEK.COM> <2631@yogi.oakhill.UUCP> <1989Nov16.212149.9770@paris.ics.uci.edu> <2647@bushwood.oakhill.UUCP> Sender: usenet@xyzzy.UUCP Organization: Data General (Languages @ Research Triangle Park, NC.) Lines: 48 In-reply-to: phillip@oakhill.UUCP's message of 20 Nov 89 19:10:42 GMT In article <2647@bushwood.oakhill.UUCP> phillip@oakhill.UUCP (Mike Phillip) writes: ... | effectively be treated as "caller save" registers by performing a | depth-first traversal of the program call graph. (i.e. by the time the | caller is analyzed, it has all relevant register usage info about the | callee). The callee can then defer saving and restoring to the caller, | making the register appear as though it was operating in "caller save" | mode. There are limitations to this approach, however. These | limitations occur when the compiler does not have complete register | usage information for a particular subroutine (libraries are a commonly | cited example). Other examples include: | 1) recursive calls | 2) calls made through subroutine pointers | 3) separate compilation | | In such cases, even "globally-optimizing, inter-procedural analyzing" | compilers need to resort to a default convention, and the trade-offs of | caller vs. callee once again become relevant. Thus, OCS does not prevent | optimizing compilers from taking advantage of inter-procedural register | allocation, but provides the "default" for those cases when such | optimizations cannot be made. Separate compilation can be handled by having the compiler generate intermediate code instead of object code or some such, and having the linker generate the final code. Tail-recursive calls can be changed by the compiler into a loop or some such. Calls made through pointers or to different langauges are another problem. Calls made through pointers are somewhat rare in conventional C (except for things like EMACS and such), but they become much more mainline in object oriented languages like C++ (virtual functions). Dynamic shared libraries are another real big problem, where the function being called may not even exist when the function is called (yes I know the BCS/OCS currently do not support shared libraries directly today, but you can roll your own with memctl, and they are coming). IMHO, most users are not willing to pay the price of getting every last ounce of performance that doing global register allocation for the entire program would entail. Yes, there are some things (like the kernel itself, or X11 libraries) that it would be worth it to get every last drop of performance. I know some vendors and companies who never use the normal compiler optimizations, since they perceive that the performance is adequate (or the compilers are inadequate). -- Michael Meissner, Data General. Until 12/15: meissner@dg-rtp.DG.COM After 12/15: meissner@osf.org