rang@cpsin3.cps.msu.edu (Anton Rang) (12/03/88)
I was thinking about RISC machines, and other machines with a lot of registers, and came up with a question. Since the C language doesn't have call-by-reference, is it possible to allocate variables which are passed by reference into registers? For example, the C code: scanf("%d", &N); would require that the address of N be taken to read it from the standard input. If I then have a loop: for (i=0; i<N; i++) { ... } would the final program have to read N from memory each time? Or does the C standard provide that some keyword (like 'volatile') be used to avoid possibly unsafe optimizations (like moving N into a register in the above example--the address of N could have been saved in scanf() ). Are there any architectures which allow taking the "address" of a register (say, having a reserved page)? +---------------------------+------------------------+----------------------+ | Anton Rang (grad student) | "VMS Forever!" | "Do worry...be SAD!" | | Michigan State University | rang@cpswh.cps.msu.edu | | +---------------------------+------------------------+----------------------+
tim@crackle.amd.com (Tim Olson) (12/03/88)
In article <1224@cps3xx.UUCP> rang@cpswh.cps.msu.edu (Anton Rang) writes: | I was thinking about RISC machines, and other machines with a lot of | registers, and came up with a question. Since the C language doesn't | have call-by-reference, is it possible to allocate variables which are | passed by reference into registers? | For example, the C code: | | scanf("%d", &N); | | would require that the address of N be taken to read it from the | standard input. If I then have a loop: | | for (i=0; i<N; i++) { ... } | | would the final program have to read N from memory each time? Or does | the C standard provide that some keyword (like 'volatile') be used to | avoid possibly unsafe optimizations (like moving N into a register in | the above example--the address of N could have been saved in scanf() ). On most RISC machines (CRISP is the only exception I can think of, but then it doesn't really have registers), taking the address of a local variable results in that variable residing in the memory stack rather than registers. However, it is not necessarily the case that the variable has to be read from memory if it is used in a loop. If there are no function calls or stores through pointers in the loop, then a compiler is free to cache the value of the variable in a register. However, it normally must re-read the value from memory each time if there is a function call or a pointer store. The reason is that the address of the variable was passed to an external function, and the compiler does not (normally!) know what that function did with it. It may have assigned it to a global variable, causing *every* function to have a potential alias to the "local" variable which had its address taken. In that case, any function call has the possibility of modifying the local variable, so it must be re-read from memory. This is the type of thing that the proposed "noalias" keyword for ANSI C was trying to address (no pun intended ;-) "Universal" optimizing compilers that perform inter-procedural assignment-tracking may be able to determine that the variable is not aliased, and therefore is free to be cached. -- Tim Olson Advanced Micro Devices (tim@crackle.amd.com)
gwyn@smoke.BRL.MIL (Doug Gwyn ) (12/03/88)
In article <1224@cps3xx.UUCP> rang@cpswh.cps.msu.edu (Anton Rang) writes: > scanf("%d", &N); > for (i=0; i<N; i++) { ... } >would the final program have to read N from memory each time? Or does >the C standard provide that some keyword (like 'volatile') be used to >avoid possibly unsafe optimizations (like moving N into a register in >the above example--the address of N could have been saved in scanf() ). Trying to answer what it is that I think you're really asking: 1. The C compiler code generator must allocate actual (non-register) storage for anything whose address is needed, so in the above example N's primary definition must be in addressable memory. However, a good optimizer can copy that location into a register for the loop test, and if nothing inside the loop could possibly (according to the C virtual machine model) alter the contents of N, it need not reload that cached value from memory for each test. There are optimizers that do this. 2. scanf() is required to look at its actual arguments each time it is called -- that's the whole point of function parameters. 3. It is true that functions, being separately compilable entities, can be designed so that they stash away pointers for later use, and that so-called "aliasing" (multiple possible reference paths to the same object) is a factor that has to be dealt with when designing a C implementation. The best example is a function having two pointer parameters. What if it is called with both parameters pointing to the same object? The rules of C require that each access via one of the parameters be considered as "killing" the value accessed via the other parameter, so that the other must be "reloaded" the next time it is used. The ill-fated "noalias" type qualifier was intended to provide a way for the programmer to promise that such pointers would NOT access overlapping objects, so that the cached contents accessed via the two pointers would be known to be independently modifiable without interfering with each other. That would have allowed a higher degree of optimization, especially on vector architectures like many supercomputers. As it now stands (without "noalias"), a conforming implementation must make a worst-case assumption and handle possible aliasing correctly. No keyword is needed to specify this; it's the default (and now the only) behavior. > Are there any architectures which allow taking the "address" of a >register (say, having a reserved page)? Registers also have memory addresses on some architectures, for example DEC PDP-11. I've never heard of a compiler exploiting this.
eric@pyrps5 (Eric Bergan) (12/03/88)
In article <1224@cps3xx.UUCP> rang@cpswh.cps.msu.edu (Anton Rang) writes: > Are there any architectures which allow taking the "address" of a >register (say, having a reserved page)? The Pyramid lets you take the address of a register. Basically the register windows are mapped into the process address space as part of the stack.
elg@killer.DALLAS.TX.US (Eric Green) (12/03/88)
in article <1224@cps3xx.UUCP>, rang@cpsin3.cps.msu.edu (Anton Rang) says: > have call-by-reference, is it possible to allocate variables which are > passed by reference into registers? > For example, the C code: > > scanf("%d", &N); > > would require that the address of N be taken to read it from the > standard input. If I then have a loop: > > for (i=0; i<N; i++) { ... } > > would the final program have to read N from memory each time? There was a discussion in comp.lang.c about this. There's two ways of doing this: memory-mapped register set, or "smart" compiler that tries to optimize register usage, e.g. keeping values in registers as long as possible, and only dumping them to RAM when necessary for things like the scanf call above. AMD29000, SPARC, etc. don't have memory-mapped registers, and thus use at least a semi-intelligent compiler. The Pyramid 90x has memory-mapped registers. I suspect it's because Pyramid's early "C" compiler was a bit, err, dumb (their "new" compiler, though, is quite spiffy, global optimizer and all... I tried hand-tweaking the assembly-language output once, and for the most part failed to make a bit of difference). > | Anton Rang (grad student) | "VMS Forever!" | "Do worry...be SAD!" | ^^^^^^^^^^^ Gag choke BARF (;-) -- Eric Lee Green ..!{ames,decwrl,mit-eddie,osu-cis}!killer!elg Snail Mail P.O. Box 92191 Lafayette, LA 70509 "We have treatments for disturbed persons, Nicholas. But, at least for the moment, we have no treatment for disturbing persons." -- Dr. Island
henry@utzoo.uucp (Henry Spencer) (12/04/88)
In article <1224@cps3xx.UUCP> rang@cpswh.cps.msu.edu (Anton Rang) writes: >... Since the C language doesn't >have call-by-reference, is it possible to allocate variables which are >passed by reference into registers? Within limits. Barring the possibility that the machine allows pointers to registers, the requirement is that the register and memory copies track changes to each other. This is tricky but not entirely impossible, at least in restricted cases with some arguably-dubious assumptions. >...the above example--the address of N could have been saved in scanf()... The compiler may know that it isn't, since scanf is a standard library function. It may even know it for your own functions, if it does fancy interprocedural analysis. > Are there any architectures which allow taking the "address" of a >register... The original Berkeley RISC design had registers with addresses, carefully set up in such a way that you could pass pointers to them around freely. The idea was to maximize the ability to put local variables into registers. I don't know of anybody commercial who's copied this idea. -- SunOSish, adj: requiring | Henry Spencer at U of Toronto Zoology 32-bit bug numbers. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
henry@utzoo.uucp (Henry Spencer) (12/04/88)
In article <9048@smoke.BRL.MIL> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: >... As it now stands (without "noalias"), a >conforming implementation must make a worst-case assumption and >handle possible aliasing correctly... Unless one indicates, in some implementation-dependent way, that it's not an issue, of course. Compiler options, #pragma (as near as I can tell at first glance, the October draft has not outlawed the can-change- semantics interpretation of #pragma), whatever... >Registers also have memory addresses on some architectures, for example >DEC PDP-11. I've never heard of a compiler exploiting this. On the 11, it can't, because the registers don't *really* have memory addresses. Those "addresses" are good only for use from the front panel, or emulation thereof. They don't necessarily work for programs. -- SunOSish, adj: requiring | Henry Spencer at U of Toronto Zoology 32-bit bug numbers. | uunet!attcan!utzoo!henry henry@zoo.toronto.edu
bcase@cup.portal.com (Brian bcase Case) (12/05/88)
>On most RISC machines (CRISP is the only exception I can think of, but >then it doesn't really have registers), taking the address of a local >variable results in that variable residing in the memory stack rather >than registers. Some would say that the Pyramid machines stretch the definition of RISC, but they have large, windowed register files (512) registers and the registers have memory addresses.
dieter@titan.nmt.edu (The Demented Teddy Bear) (12/05/88)
In article <1988Dec3.221843.28966@utzoo.uucp>, henry@utzoo (Henry Spencer) writes: > The original Berkeley RISC design had registers with addresses, carefully > set up in such a way that you could pass pointers to them around freely. > The idea was to maximize the ability to put local variables into registers. > I don't know of anybody commercial who's copied this idea. Umm, Henry, doesn't a PDP-10 count? Seemed kinda like a commercial system to me.... The registers certainly seemed addressable (hey, you can even point the PC at them and execute code out of them). Or have I missed something again? Dieter -- Welcome to the island. You are number six. dieter%nmt@relay.cs.net dieter@jupiter.nmt.edu