Thanks for your explanation. Do you mean that LLVM will not maintain the def-use chain for atomic variables? 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;'. 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 > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180208/89cc461c/attachment.html>
Daniel Berlin via llvm-dev
2018-Feb-08 20:26 UTC
[llvm-dev] PHI nodes for atomic variables
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/20180208/10235373/attachment.html>
I used -O3. I will try MemorySSA analysis. Thanks! 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/ba01190a/attachment.html>
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>