<div dir="ltr"><div>Hi all,<br><br><span id="result_box" class="" lang="en"><span class="">Consider the following example:<br><br>define void @fn(i8* %buf) #0 {<br>entry:<br>  %arrayidx = getelementptr i8* %buf, i64 18<br>  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %arrayidx, i8* %buf, i64 18, i32 1, i1 false)<br>  %arrayidx1 = getelementptr i8* %buf, i64 18<br>  store i8 1, i8* %arrayidx1, align 1<br>  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, i64 18, i32 1, i1 false)<br>  ret void<br>}<br><br></span></span></div><div><div>I ran opt -O2 ex.ll -S, and got:</div><div><br>define void @fn(i8* nocapture %buf) #0 {<br>entry:<br>  %arrayidx = getelementptr i8* %buf, i64 18<br>  store i8 1, i8* %arrayidx, align 1<br>  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, i64 18, i32 1, i1 false)<br>  ret void<br>}<br><br></div><div>In that case previous contents of bytes 0-17 are overwritten by bytes 18-35 (pre-opt code doesn't do that).<br><br></div><div></div><div>Another point, if I change the code to:<br><br><span id="result_box" class="" lang="en"><span class="">define void @fn(i8* %buf) #0 {<br>entry:<br>  %arrayidx = getelementptr i8* %buf, i64 18<br>  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %arrayidx, i8* %buf, i64 18, i32 1, i1 false)<br></span></span></div><div><span id="result_box" class="" lang="en"><span class="">;changing 19th byte, not 18th:<br></span></span></div><div><span id="result_box" class="" lang="en"><span class="">  %arrayidx1 = getelementptr i8* %buf, i64 19<br>  store i8 1, i8* %arrayidx1, align 1<br>  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, i64 18, i32 1, i1 false)<br>  ret void<br>}</span></span><br></div><div><br></div><div>I get correct piece of code:<br><br>define void @fn(i8* nocapture %buf) #0 {<br>entry:<br>  %arrayidx = getelementptr i8* %buf, i64 18<br>  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %arrayidx, i8* %buf, i64 18, i32 1, i1 false)<br>  %arrayidx1 = getelementptr i8* %buf, i64 19<br>  store i8 1, i8* %arrayidx1, align 1<br>  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, i64 18, i32 1, i1 false)<br>  ret void<br>}<br><br>Adding some datalayout to module also solves the issue. <br><br>-print-after-all shows that the 'Dead Store Elimination' pass erases first call to memcpy.<br><br>I found that the following code in DeadStoreElimination.cpp leads to such behavior:<br>      if (DL == nullptr && Later.Ptr->getType() == Earlier.Ptr->getType())<br>        return OverwriteComplete;<br><br></div><div>Is this issue a bug in DSE or maybe I'm doing some wrong?<br></div><div></div><div><br></div><div>Best regards,<br>Alexey<br></div></div></div>