Also, if i has a volatile-qualified type, the compiler ought to go
through the motions of loading its value.
On first reading, I'm not certain about that. C89 2.1.2.3 Program Execution
specifies that,
In the abstract machine, all expressions are evaluated as specified
by the semantics. An actual implementation need not evaluate part
of an expression if it can deduce that its value is not used
and that no needed side effects are produced (including any caused
by calling a function or accessing a volatile object.)
My (possibly naive) intepretation of that is:
- if there are multiple volatile variables, then accessing i just -might-
happen to change one of the other ones, so if any of the other
variables are used after that point, the access must be done
- if i is not used after that point and it is the only volatile
variable, then no "needed side effects are produced" and the
access could be discarded
The above is based upon the assumption that -reading- a volatile
variable does not produce an -output- in the environment; a quick
skim over the discussion of volatile seems to me to imply that
C does not worry about such possibilities. But plausibly the wording
of the standard is saying, "The overall implementation, drawing
upon detailed knowledge of the architecture, might be able to figure
out which reads of volatiles might trigger extra behaviour and which
ones will never do so; and for the ones that are certain never to do so,
the implementation could skip the read access."
(For example, if a volatile variable is block scope, or is file scope
and there are no volatile-qualified writes to it in other routines
in the file scope, and the address of the variable is not passed
around, then the only way to change the variable value would be through
a debugger... which wouldn't trigger any side effects anyhow.
On the other hand, if a variable has extern scope then even though
intra-procedure analysis might seem to indicate the variable has no
side effects, on some systems the address of extern variables can
be specified at link time, and the address might be that of a
memory-mapped I/O register... which an even more sophisticated system
might be able to detect...)