[LLVMdev] LLVM Concurrency and Undef

Jianzhou Zhao jianzhou at seas.upenn.edu
Sat Sep 17 06:12:12 PDT 2011


On Tue, Aug 23, 2011 at 12:08 AM, Eli Friedman <eli.friedman at gmail.com> wrote:
> On Mon, Aug 22, 2011 at 8:46 PM, Jianzhou Zhao <jianzhou at seas.upenn.edu> wrote:
>> On Mon, Aug 22, 2011 at 6:08 PM, Eli Friedman <eli.friedman at gmail.com> wrote:
>>> On Mon, Aug 22, 2011 at 2:49 PM, Santosh Nagarakatte
>>> <santosh.nagarakatte at gmail.com> wrote:
>>>> Hi all,
>>>>
>>>> I have been trying to understand the use of undef in both sequential
>>>> and concurrent programs.
>>>>
>>>> >From the LLVM Language Reference Manual, I see the following
>>>> definition of undef.
>>>> "Undef can be used anywhere a constant is expected, and indicates that
>>>> the user of the value may receive an unspecified bit-pattern".
>>>>  LLVM Language Reference manual also demonstrates how optimizers can
>>>> use these undef values to  optimize the program.
>>>>
>>>> However, on the other hand, with the LLVM Atomics and Concurrency
>>>> Guide states that
>>>> If code accesses a memory location from multiple threads at the same
>>>> time, the resulting loads return 'undef'.
>>>> This is different from the C++ memory model, which provides undefined
>>>> behavior. What is the rationale for returning an undef on racing
>>>> reads?
>>>>
>>>> LLVM Atomics and Concurrency guide also states the following
>>>> "Note that speculative loads are allowed; a load which is part of a
>>>> race returns undef, but does not have undefined behavior"
>>>>
>>>> If the speculative loads returns an undef and the returned value is
>>>> used, then it results in an undefined behavior. Am I correct?
>>>
>>> It behaves like any other undef value... which do often lead to
>>> undefined behavior.
>>>
>>>> If so, what is the purpose of returning an undef with a speculative load?
>>>> Is it to ensure that the subsequent uses of the value of the
>>>> speculatively introduced load is caught/detected by the optimization?
>>>
>>> The point is primarily to allow optimizations like LICM to introduce
>>> loads whose value is never used.  It also keeps consistent semantics
>>> through CodeGen, where some targets widen loads.
>>>
>>>> Is it possible to separate the "undef" in a sequential setting and
>>>> "undef" with speculative loads in a concurrent setting with separate
>>>> undefs?
>>>
>>> The intention is that they should have the same semantics.
>>
>> As for whether separating the sequential ``undef'' and the concurrent
>> ``undef'', there is an analogous problem that is why C defines
>> different undefined behaviors in term of contexts that result in
>> undefined behaviors. When designing any analysis tools for C to
>> prevent undefined behaviors,  we can reason about which kinds of
>> undefined behaviors can be eliminated. So classifying undefined
>> behaviors helps at the case.
>>
>> In the LLVM setting, have we already defined different kinds of
>> ``undef'' in a sequential setting? The question is whether or not LLVM
>> can define them without considering a high-level language that is
>> compiled to the IR, since usually the semantics in the high-level
>> language indicates how to classify them. However, the undef values
>> introduced by racy loads seem to be new, for example, C++ and Java do
>> not have such concepts. Then is it worth to separate it from those
>> existing undefs? Can we get any benefit from the view of compiler
>> design if not distinguishing the undefs?
>
> The conceptual undef's here will never show up in the IR because it's
> extremely difficult to prove that a race exists.
>
> Most of the effort towards tracking undefined behavior more generally
> hasn't really centered around the presence of undef's in the IR.  And
> I'm not sure they could be usefully classified because they tend to
> disappear from the IR quickly.

Did you mean the undefined values tend to disappear from the IR of LLVM 3.0?

>
> (Putting llvmdev back on the cc list.)
>
> -Eli
>



-- 
Jianzhou




More information about the llvm-dev mailing list