[LLVMdev] LLVMdev Digest, Vol 76, Issue 43

John Criswell criswell at illinois.edu
Tue Oct 26 07:32:14 PDT 2010


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




More information about the llvm-dev mailing list