[llvm-dev] PHI nodes for atomic variables

Qiuping Yi via llvm-dev llvm-dev at lists.llvm.org
Fri Feb 9 10:01:04 PST 2018


Dear Daniel Berlin,

I just tried MemorySSA analysis and get the next IR.
However, I feel confused by the result.

Specifically, why instruction *%3* relates to a *MemoryDef*. According to
my understanding,
I think *%3* should be related to a *MemoryUse*, right?


; Function Attrs: uwtable
define void @_Z2f1v() #3 personality i32 (...)* @__gxx_personality_v0 {
entry:
; 1 = MemoryDef(liveOnEntry)
  tail call void @checker_thread_begin(i8* getelementptr inbounds ([3 x
i8], [3 x i8]* @.str, i64 0, i64 0))
; MemoryUse(1)
  %0 = load i32, i32* @data1, align 4, !tbaa !1
  %cmp = icmp sgt i32 %0, 0
  br i1 %cmp, label %if.then, label %entry.if.end_crit_edge

entry.if.end_crit_edge:                           ; preds = %entry
; MemoryUse(1)
  %.pre = load i32, i32* @data2, align 4, !tbaa !1
  br label %if.end

if.then:                                          ; preds = %entry
; MemoryUse(1)
  %1 = load i32, i32* @data4, align 4, !tbaa !1
*; 2 = MemoryDef(1)*
*  store atomic i32 %1, i32* getelementptr inbounds (%"struct.std::atomic",
%"struct.std::atomic"* @x, i64 0, i32 0, i32 0) seq_cst, align 4*
; 3 = MemoryDef(2)
  store i32 %1, i32* @data2, align 4, !tbaa !1
  br label %if.end

if.end:                                           ; preds =
%entry.if.end_crit_edge, %if.then
; 8 = MemoryPhi({if.then,3},{entry.if.end_crit_edge,1})
  %2 = phi i32 [ %.pre, %entry.if.end_crit_edge ], [ %1, %if.then ]
; 4 = MemoryDef(8)
  store i32 %2, i32* @data3, align 4, !tbaa !1
*; 5 = MemoryDef(4)*
*  %3 = load atomic i32, i32* getelementptr inbounds
(%"struct.std::atomic", %"struct.std::atomic"* @x, i64 0, i32 0, i32 0)
seq_cst, align 4*
; 6 = MemoryDef(5)
  store i32 %3, i32* @data1, align 4, !tbaa !1
; 7 = MemoryDef(6)
  tail call void @checker_thread_end()
  ret void
}



Best regards,

Qiuping Yi
Institute Of Software
Chinese Academy of Sciences

On Thu, Feb 8, 2018 at 2:26 PM, Daniel Berlin <dberlin at dberlin.org> wrote:

>
>
> Let me try to help.
>
> On Thu, Feb 8, 2018 at 12:13 PM, Qiuping Yi via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
>
>> Thanks for your explanation.
>>
>> Do you mean that LLVM will not maintain the def-use chain for atomic
>> variables?
>>
> It is not a variable at the LLVM level.
> At the source level, it is a variable.
> At the LLVM IR level, it is lowered into memory operations.
> All of your operations were. None of them are in llvm registers.
> Some were then promoted or partially promoted into registers.
> (it looks like your output is -O1 or something and uses libstdc++ instead
> of libc++)
> The loads are loads from a memory location.  It does not have any more
> data dependence info than your atomics.
>
> The phi you are seeing is not "LLVM giving you data dependence info".
>
> Memory is not in SSA form in LLVM and has no def use chains by default.
>
> If you want an SSA form for Memory, you would have to use the MemorySSA
> analysis.
>
>
>
>> So it is impossible to directly catch the fact that the load of x at the
>> statement 'data1 = x; ' dependents on data4 (because of the statement
>> x=data4 )?
>> If I want to get such information, may be the only solution is to
>> traverse all the predecessors of the statement 'data1 = x;'.
>>
>
> This will not work either in general.
>
>
>>
>>
>>
>> Best regards,
>>
>> Qiuping Yi
>> Institute Of Software
>> Chinese Academy of Sciences
>>
>> On Thu, Feb 8, 2018 at 3:11 AM, David Chisnall <
>> David.Chisnall at cl.cam.ac.uk> wrote:
>>
>>> On 8 Feb 2018, at 04:07, Qiuping Yi via llvm-dev <
>>> llvm-dev at lists.llvm.org> wrote:
>>> >
>>> > I found that it only generated PHI node (%8 = phi i32 [ %4, %3 ], [
>>> %6, %5 ]) for non-atomic variable 'data2' but not for atomic variable x?
>>> Why?
>>>
>>> LLVM IR does not contain variables, it contains (immutable) registers.
>>> Some of these registers refer to memory locations and are usable with loads
>>> and stores.  The notion of ‘atomic’ doesn’t make sense in the context of a
>>> register, because registers are implicitly immutable (i.e. not updated, so
>>> atomic updates don’t make sense) and non-shared (so there’s nothing for
>>> accesses to them to be atomic with respect to).  As such, the atomic
>>> qualifier makes sense only with memory locations.  The memory address
>>> itself may be stored in a register, but updates to the location must be
>>> performed by loads and stores (or atomicrmw instructions).
>>>
>>> In the absence of any ordering constraints imposed by atomic memory
>>> operations (including fences), it is often safe to promote a sequence of
>>> loads and stores of a memory location to a single load / store pair with a
>>> sequence of registers storing temporary values.  This is allowed because,
>>> in the absence of something that establishes a happens-before relationship
>>> between threads, a thread is allowed to make writes to memory visible to
>>> other threads in any order.
>>>
>>> David
>>>
>>>
>>
>> _______________________________________________
>> LLVM Developers mailing list
>> llvm-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180209/eab1299b/attachment.html>


More information about the llvm-dev mailing list