Path: utzoo!attcan!uunet!lll-winken!lll-lcc!ames!ncar!tank!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.lang.c Subject: Re: The world is not ready for 'volatile' Message-ID: <15248@mimsy.UUCP> Date: 3 Jan 89 21:46:17 GMT References: <141@bms-at.UUCP> <275@twwells.uucp> <15166@mimsy.UUCP> <903@husc6.harvard.edu> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 133 >>>In article <15166@mimsy.UUCP> I suggested that >>>>... ["register"] implies not-volatile and not-aliased; and it does so >>>>in a way that the compiler can reasonably enforce. (by the way, the word `implies' is key.) >>In article <9236@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes: >>>No, I reject this claim. >In article <15171@mimsy.UUCP> I answered with: >>You mean to say that a register could be aliased? Not in C! How >>about a volatile register? It is a possibility, but it seems entirely >>unnecessary. In article <903@husc6.harvard.edu> geoff@endor.harvard.edu (Geoff Clemm) replies: >I would have to second this rejection. There is nothing in the >reference manual that lets you count on register variables not being >volatile. You misinterpret (everyone always misinterprets! :-) ). The dpANS allows you to write register const k = 4; and register volatile v; but, I ask, what do these mean? The answer is that they mean the same thing as const k = 4; and volatile v; except that you may not take the address of either variable---which therefore means that the compiler need not even assign an address to either variable. This makes the effect (if any) of volatile on a register declaration dubious at best. >Now Chris, this is a total waffle. For folks that are seriously concerned >about portability, one needs a stronger argument than that "it seems entirely >unnecessary" for a compiler writer to do something -- especially since many >compiler writers ignore register declarations, which means register variables >will be as volatile or non-volatile as any other variable. For folks concerned with portability, the word `volatile' does not exist in the language (with one exception), since the actual effect of the volatile qualifier is compiler-dependent. The exception is in functions using setjmp. Optimising such functions well is hard, and the dpANS simply grants license to ignore the effect of longjmp on program flow during optimisation. This was, in my opinion, the wrong thing to do; but while we are stuck with it, remember that I was not saying that `volatile' and `register' are opposites, but merely that `register' *ought* (in some more perfect world where the dpANS were different) to imply not-aliased (it does) and not-volatile (it does not). Actually, again in my opinion, in a still more perfect world, both the dpANS and `old C' would not have the `register' keyword anyway. Moreover, for those again concerned with portability, it is necessary never to use `register volatile' even in functions using setjmp, since in old compilers---where one would `#define volatile /*empty*/'--- registers are the *only* non-volatile variables. In particular, the PDP-11 V7 C runtime system, the 3.0, 4.0, and 4.1BSD runtime systems, and most if not all SunOS runtime systems, effectively restore register variables to their state at the time of the *setjmp* call: f() { register int r = 1; jmp_buf j; if (setjmp(j)) { (void) printf("r is now %d\n", r); return; } r = 2; longjmp(j, 1); /* NOTREACHED */ } This program prints `1', not `2', in a number of systems. This is precisely the effect produced by an optimising compiler given a non-volatile variable `r' and ignoring the implicit `goto' produced by the setjmp/longjmp pair. The variable life analysis goes like this: register int r = 1 | r = constant 1 jmp_buf j | r = constant 1, j = constant if (setjmp(j)) | r = constant 1, j = /* (remember, j is passed by address) */ printf(...) | r = constant 1, j = return r = 2 | r = constant 2, j = longjmp(j, 1) | r = constant 2, j = /* note that != */ implicit return | r = dead, j = dead At this point, the compiler should replace known constants (the one instance of r) with their values. It can then delete both writes (r=1 and r=2) since they are to dead variables. The optimised function is thus if (setjmp(j)) { (void) printf("r is now %d\n", 1); return; } longjmp(j, 1); We can merrily write `register volatile int r = 1', and a dpANS- conformant compiler will do the `right thing', but the program is not portable to some widespread versions of `old C' (including SunOS 3.2, where I just tested it). The important thing is not that these implementations are not dpANS conformant (they are not), but rather that `volatile int r = 1' *will* work. Then too, I doubt that `register volatile v' will do anything different from `volatile v' in any worthwhile compiler. (Note key words `I doubt': this is an opinion, not a fact.) Anyway, the point is that `register volatile v' (but not `register volatile *v') is effectively useless. It is therefore possible---but not necessarily wise---to make `register' mean `not volatile', and to declare the volatile qualifier and the register storage class incompatible. I do not claim that this encompasses all uses for `volatile'. I claim only what I said: register implies not-aliased, and does so in a way the compiler can enforce (`&v' not allowed); and register implies (through effective uselessness) not-volatile, again in a way that the compiler can enforce (since volatility is purely the compiler's notion anyway, as far as code generation is concerned). -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris