On 10/26/10 3:11 AM, Duncan Sands wrote:> Hi Torok,
>
>>>> Well...strictly as LLVM IR I find externally visible incorrect
>>>> behavior unlikely, it's just a "different
definition". For C and
>>>> C++, I'd be looking at more complicated variations of
>>>>
>>>> int main()
>>>> {
>>>> volatile int i = 1;
>>>> return 0;
>>>> }
>>>>
>>>> It's clear that the LLVM IR representation of i cannot be
simply
>>>> IR-volatile qualified, as that load gets optimized out while C
and
>>>> C++ won't optimize it out. I'd *hope* that DragonEgg
and llvm-gcc
>>>> both leave the load of i in, when in --pedantic mode. [That
is, I
>>>> expect it to take something more intricate than this elementary
>>>> test case to trigger any bugs here.]
>>> both dragonegg and llvm-gcc remove the volatile. I don't see
why they
>>> shouldn't, since the program behaves exactly the same (as far
as
>>> anyone external can tell) as if it had been left there.
>> What if its address is taken, or it is a global variable?
> the volatile is only removed if it can be proved that doing so is harmless.
> It is not removed in the cases you mention.
How do you know that removing it is harmless? Volatile is sometimes
used when the compiler's ability to determine what is safe won't work.
Consider an operating system. I write some code that does the following:
a) Load registers into some LLVM IR registers (using inline asm)
b) Modify the registers slightly
c) Use volatile stores to save the registers into a stack-allocated area
d) Context switch
e) Use volatile loads to reload the registers from the stack-allocated area
In this case, the volatiles are necessary; otherwise, the compiler
(which knows nothing about the context switch code) may elide the stores
to the stack memory (thinking it can keep state in processor registers),
resulting in incorrect behavior.
Now, while I've based this off of the Linux 2.4 kernel's context
switching code, I'll grant that this is a bit contrived; context
switching code is usually written in assembly, and so the volatile loads
and stores can be coded in the assembly code portion. However, this
example should work, too, but your optimizations might break it
(depending on what they do with the assembly code that does the actual
context switch).
There may be more realistic examples I can think of. For example,
perhaps you are debugging code and just want to mark something volatile
temporarily so that it gets written to memory and is easier to find.
Perhaps someone is writing some crazy multi-threaded thing that scans
the stack of another thread by just knowing where the stacks of each
thread are at. Maybe I just want something to be volatile to study the
speed difference between optimizing and not optimizing code. The point
is that volatile should mean volatile; the loads and stores shouldn't go
away. If we could trust the compiler to figure out when the
loads/stores could be optimized away, we wouldn't have to mark them
volatile.
Regarding someone else's comment that the volatile keyword is like the
register keyword, I don't believe they're the same. I believe register
is defined as a hint whereas volatile is supposed to be respected by the
compiler (language lawyers: feel free to correct me if I'm wrong).
In my opinion, I think you guys are really overthinking this: volatile
should be volatile should be volatile. It makes the behavior of
volatile easy to understand, it makes it easy to use, it allows LLVM to
support the rules for the volatile keyword in C (AFAIK), and it doesn't
require you to guess all the different, contorted ways in which volatile
could be used.
-- John T.
> Ciao,
>
> Duncan.
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev