<div dir="ltr"><div>So I removed the 'tail' from the call and try out different properties:</div><div>- IntrNoMem: memset() and the intrinsic are both optimized away as expected<br></div><div>- IntrWriteMem: memset() optimized away by DSE but the intrinsic isn't. I would expect both to be removed, since the intrinsic is now also a dead store.<br></div><div>- IntrReadMem: memset() and the intrinsic are both optimized away *unexpectedly* (CSE removes the intrinsic, then InstCombine removes memset). The latter is understandable, but why the intrinsic gets optimized in the first place?<br></div><div>- IntrArgMemOnly: none gets optimized away as expected</div><div>- ReadOnly<0>: none gets optimized away as expected</div><div>- ReadNone<0> / WriteOnly<0>: none gets optimized *unexpectedly*</div><div><br></div><div>Am I missing something here or there are indeed bugs here? Btw, can you tell me how and why 'tail' changes the optimizer behavior?</div><div><br></div><div>Thanks a lot for your explanation!</div><div><br></div><div><div><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr">Son Tuan Vu</div></div></div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jul 25, 2019 at 12:57 AM Doerfert, Johannes <<a href="mailto:jdoerfert@anl.gov">jdoerfert@anl.gov</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<div dir="auto" style="direction:ltr;margin:0px;padding:0px;font-family:sans-serif;font-size:11pt;color:black">
Does the behavior change if you remove the tail from the call to your intrinsic?<br>
<br>
</div>
<div dir="auto" style="direction:ltr;margin:0px;padding:0px;font-family:sans-serif;font-size:11pt;color:black">
I can later look in more detail.<br>
<br>
</div>
<div dir="auto" style="direction:ltr;margin:0px;padding:0px;font-family:sans-serif;font-size:11pt;color:black">
<span id="gmail-m_1695652473416264974OutlookSignature">
<div dir="auto" style="direction:ltr;margin:0px;padding:0px;font-family:sans-serif;font-size:11pt;color:black">
Get <a href="https://aka.ms/ghei36" target="_blank">Outlook for Android</a></div>
</span><br>
</div>
<hr style="display:inline-block;width:98%">
<div id="gmail-m_1695652473416264974divRplyFwdMsg" dir="ltr"><font style="font-size:11pt" face="Calibri, sans-serif" color="#000000"><b>From:</b> Son Tuan VU <<a href="mailto:sontuan.vu119@gmail.com" target="_blank">sontuan.vu119@gmail.com</a>><br>
<b>Sent:</b> Wednesday, July 24, 2019 6:51:10 PM<br>
<b>To:</b> Doerfert, Johannes<br>
<b>Cc:</b> llvm-dev<br>
<b>Subject:</b> Re: [llvm-dev] Intrinsics InstrReadMem memory properties</font>
<div> </div>
</div>
<div>
<div dir="ltr">
<div>Ok, now I think I've found a bug:</div>
<div><br>
</div>
<div>Consider this C code:</div>
<div>void bar(int b) {</div>
<div> int a[10];</div>
<div> memset(a, b, 10);</div>
<div>}</div>
<div><br>
</div>
<div>which generates this IR code:</div>
<div>define dso_local void @bar(i32 %b) #0 {<br>
entry: <br>
%b.addr = alloca i32, align 4 <br>
%a = alloca [10 x i32], align 16 <br>
store i32 %b, i32* %b.addr, align 4 <br>
%arraydecay = getelementptr inbounds [10 x i32], [10 x i32]* %a, i64 0, i64 0<br>
%0 = bitcast i32* %arraydecay to i8*<br>
%1 = load i32, i32* %b.addr, align 4 <br>
%2 = trunc i32 %1 to i8 <br>
call void @llvm.memset.p0i8.i64(i8* align 16 %0, i8 %2, i64 10, i1 false) <br>
ret void <br>
}</div>
<div><br>
</div>
<div>Now I have a pass that inserts an intrinsic with IntrReadMem into the IR:</div>
<div>
<div>define dso_local void @bar(i32 %b) #0 {<br>
entry: <br>
%b.addr = alloca i32, align 4 <br>
%a = alloca [10 x i32], align 16 <br>
store i32 %b, i32* %b.addr, align 4 <br>
%arraydecay = getelementptr inbounds [10 x i32], [10 x i32]* %a, i64 0, i64 0<br>
%0 = bitcast i32* %arraydecay to i8*<br>
%1 = load i32, i32* %b.addr, align 4 <br>
%2 = trunc i32 %1 to i8 <br>
call void @llvm.memset.p0i8.i64(i8* align 16 %0, i8 %2, i64 10, i1 false)<br>
<div><b> tail call void @mem_read_test(i8* %0)</b></div>
</div>
<div> ret void <br>
}</div>
<div><br>
</div>
<div>; Function Attrs: nounwind readonly <br>
declare void @mem_read_test(i8*) #2 <br>
</div>
<div><br>
</div>
<div>However, the call to memset() still got optimized away by DSE. What am I missing here? Or this is indeed a bug in DSE?</div>
<div><br>
</div>
</div>
<div>
<div>
<div dir="ltr" class="gmail-m_1695652473416264974gmail_signature">
<div dir="ltr">Son Tuan Vu</div>
</div>
</div>
<br>
</div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Wed, Jul 24, 2019 at 6:47 PM Doerfert, Johannes <<a href="mailto:jdoerfert@anl.gov" target="_blank">jdoerfert@anl.gov</a>> wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
You are on the right track. Addresses could get exposed in various ways,<br>
a probably non-exclusive list is:<br>
- passed as arguments<br>
- communicated through a global<br>
- via I/O, or more general, system calls. This includes all forms of<br>
synchronization, e.g., inter-lane communication.<br>
- transitively passed by any of the means above, e.g., the address of a<br>
pointer to the object could be exposed.<br>
<br>
So if we take the example below and add:<br>
bar(&A[50]);<br>
just before the call to unknown, we have to assume A is known to unknown<br>
now, at least if we do not have information about bar that would suggest<br>
otherwise.<br>
<br>
<br>
On 07/24, Son Tuan VU wrote:<br>
> Hi Johannes,<br>
> <br>
> Thanks for your reply. I now see more clearly how things work with these<br>
> properties. However, what would be an object whose address is potentially<br>
> known by a callee? I suppose the intrinsic arguments and global variable?<br>
> <br>
> So IIUC, if not restricted by *only properties, an intrinsic could access<br>
> to:<br>
> - only its arguments if IntrArgMemOnly specified,<br>
> - its arguments and the global variable as well if Intr*Mem (other than<br>
> IntrNoMem) specified.<br>
> <br>
> Please tell me if I'm correct or not!<br>
> <br>
> Thanks again,<br>
> <br>
> <br>
> <br>
> On Wed, Jul 24, 2019, 17:27 Doerfert, Johannes <<a href="mailto:jdoerfert@anl.gov" target="_blank">jdoerfert@anl.gov</a>> wrote:<br>
> <br>
> > Hi Son Tuan Vu,<br>
> ><br>
> > if not restricted by *writeonly*, *readonly*, or *readnone* (basically), a<br>
> > call can access any object for which the<br>
> > callee could potentially know the address. That means, if the address of<br>
> > an object cannot be known to the callee,<br>
> > it cannot access that object. An example is given below. Thus, a dead<br>
> > store can be eliminated if the memory cannot<br>
> > be read by any subsequent operation. If you think there is a bug, could<br>
> > you provide a reproducer?<br>
> ><br>
> > Example:<br>
> ><br>
> > void unknown();<br>
> > void foo() {<br>
> > int *A = malloc(100 * sizeof(A[0]));<br>
> > int B[100];<br>
> > for (int i = 0; i < 100; i++)<br>
> > A[i] = B[i] = i;<br>
> ><br>
> > // The addresses/objects A and B are not known to the unknown function<br>
> > and the stores above can be removed.<br>
> > unknown();<br>
> ><br>
> > free(A);<br>
> > }<br>
> ><br>
> > I hope this helps,<br>
> > Johannes<br>
> ><br>
> ><br>
> > ________________________________________<br>
> > From: llvm-dev <<a href="mailto:llvm-dev-bounces@lists.llvm.org" target="_blank">llvm-dev-bounces@lists.llvm.org</a>> on behalf of Son Tuan VU<br>
> > via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>><br>
> > Sent: Wednesday, July 24, 2019 08:20<br>
> > To: llvm-devmemory<br>
> > Subject: [llvm-dev] Intrinsics InstrReadMem memory properties<br>
> ><br>
> > Hello,<br>
> ><br>
> > According to include/llvm/IR/Intrinsics.td, InstrReadMem property<br>
> > indicates that the intrinsic only reads from and does not write to memory.<br>
> ><br>
> > Does this mean that it can read anywhere in the memory? Because we already<br>
> > have 'InstrArgMemOnly' for intrinsics which only access memory that its<br>
> > argument(s) point(s) to.<br>
> ><br>
> > If 'InstrReadMem' really means read from anywhere in the memory, this<br>
> > should imply that, if there's an intrinsic having this property *after* a<br>
> > dead store, the latter should not be eliminated by optimizations?<br>
> ><br>
> > This is not the current behavior of LLVM though, so it seems that my<br>
> > guesses are wrong... But at least, can someone show me the mistake here?<br>
> ><br>
> > Thanks for your time,<br>
> ><br>
> > Son Tuan Vu<br>
> ><br>
<br>
-- <br>
<br>
Johannes Doerfert<br>
Researcher<br>
<br>
Argonne National Laboratory<br>
Lemont, IL 60439, USA<br>
<br>
<a href="mailto:jdoerfert@anl.gov" target="_blank">jdoerfert@anl.gov</a><br>
</blockquote>
</div>
</div>
</div>
</blockquote></div>