Aliaksei Zasenka
2014-Oct-17 09:24 UTC
[LLVMdev] opt -O2 leads to incorrect operation (possibly a bug in the DSE)
Hi all, Consider the following example: define void @fn(i8* %buf) #0 { entry: %arrayidx = getelementptr i8* %buf, i64 18 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %arrayidx, i8* %buf, i64 18, i32 1, i1 false) %arrayidx1 = getelementptr i8* %buf, i64 18 store i8 1, i8* %arrayidx1, align 1 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, i64 18, i32 1, i1 false) ret void } I ran opt -O2 ex.ll -S, and got: define void @fn(i8* nocapture %buf) #0 { entry: %arrayidx = getelementptr i8* %buf, i64 18 store i8 1, i8* %arrayidx, align 1 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, i64 18, i32 1, i1 false) ret void } In that case previous contents of bytes 0-17 are overwritten by bytes 18-35 (pre-opt code doesn't do that). Another point, if I change the code to: define void @fn(i8* %buf) #0 { entry: %arrayidx = getelementptr i8* %buf, i64 18 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %arrayidx, i8* %buf, i64 18, i32 1, i1 false) ;changing 19th byte, not 18th: %arrayidx1 = getelementptr i8* %buf, i64 19 store i8 1, i8* %arrayidx1, align 1 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, i64 18, i32 1, i1 false) ret void } I get correct piece of code: define void @fn(i8* nocapture %buf) #0 { entry: %arrayidx = getelementptr i8* %buf, i64 18 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %arrayidx, i8* %buf, i64 18, i32 1, i1 false) %arrayidx1 = getelementptr i8* %buf, i64 19 store i8 1, i8* %arrayidx1, align 1 tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, i64 18, i32 1, i1 false) ret void } Adding some datalayout to module also solves the issue. -print-after-all shows that the 'Dead Store Elimination' pass erases first call to memcpy. I found that the following code in DeadStoreElimination.cpp leads to such behavior: if (DL == nullptr && Later.Ptr->getType() == Earlier.Ptr->getType()) return OverwriteComplete; Is this issue a bug in DSE or maybe I'm doing some wrong? Best regards, Alexey -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20141017/376f01fb/attachment.html>
Hal Finkel
2014-Oct-17 11:30 UTC
[LLVMdev] opt -O2 leads to incorrect operation (possibly a bug in the DSE)
----- Original Message -----> From: "Aliaksei Zasenka" <listhex at gmail.com> > To: LLVMdev at cs.uiuc.edu > Sent: Friday, October 17, 2014 4:24:27 AM > Subject: [LLVMdev] opt -O2 leads to incorrect operation (possibly a bug in the DSE) > > Hi all, > > Consider the following example: > > define void @fn(i8* %buf) #0 { > entry: > %arrayidx = getelementptr i8* %buf, i64 18 > tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %arrayidx, i8* %buf, > i64 18, i32 1, i1 false) > %arrayidx1 = getelementptr i8* %buf, i64 18 > store i8 1, i8* %arrayidx1, align 1 > tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, > i64 18, i32 1, i1 false) > ret void > } > > > > I ran opt -O2 ex.ll -S, and got: > > define void @fn(i8* nocapture %buf) #0 { > entry: > %arrayidx = getelementptr i8* %buf, i64 18 > store i8 1, i8* %arrayidx, align 1 > tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, > i64 18, i32 1, i1 false) > ret void > } > > > In that case previous contents of bytes 0-17 are overwritten by bytes > 18-35 (pre-opt code doesn't do that). > > > > Another point, if I change the code to: > > define void @fn(i8* %buf) #0 { > entry: > %arrayidx = getelementptr i8* %buf, i64 18 > tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %arrayidx, i8* %buf, > i64 18, i32 1, i1 false) > > ;changing 19th byte, not 18th: > > %arrayidx1 = getelementptr i8* %buf, i64 19 > store i8 1, i8* %arrayidx1, align 1 > tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, > i64 18, i32 1, i1 false) > ret void > } > > > > I get correct piece of code: > > define void @fn(i8* nocapture %buf) #0 { > entry: > %arrayidx = getelementptr i8* %buf, i64 18 > tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %arrayidx, i8* %buf, > i64 18, i32 1, i1 false) > %arrayidx1 = getelementptr i8* %buf, i64 19 > store i8 1, i8* %arrayidx1, align 1 > tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, > i64 18, i32 1, i1 false) > ret void > } > > Adding some datalayout to module also solves the issue. > > -print-after-all shows that the 'Dead Store Elimination' pass erases > first call to memcpy. > > I found that the following code in DeadStoreElimination.cpp leads to > such behavior: > if (DL == nullptr && Later.Ptr->getType() == Earlier.Ptr->getType()) > return OverwriteComplete; > > > Is this issue a bug in DSE or maybe I'm doing some wrong? >Looks like a bug in DSE, you're not doing anything wrong. We don't test much without data layouts anymore. This code might pre-date DSE's handling of memcpy intrinsics (just a guess). In any case, we'll fix it. -Hal> > > > Best regards, > Alexey > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >-- Hal Finkel Assistant Computational Scientist Leadership Computing Facility Argonne National Laboratory
Aliaksei Zasenka
2014-Oct-17 11:57 UTC
[LLVMdev] opt -O2 leads to incorrect operation (possibly a bug in the DSE)
Hal, Thanks for your answer. Should I report a bug? Best regards, Alexey 2014-10-17 14:30 GMT+03:00 Hal Finkel <hfinkel at anl.gov>:> ----- Original Message ----- > > From: "Aliaksei Zasenka" <listhex at gmail.com> > > To: LLVMdev at cs.uiuc.edu > > Sent: Friday, October 17, 2014 4:24:27 AM > > Subject: [LLVMdev] opt -O2 leads to incorrect operation (possibly a bug > in the DSE) > > > > Hi all, > > > > Consider the following example: > > > > define void @fn(i8* %buf) #0 { > > entry: > > %arrayidx = getelementptr i8* %buf, i64 18 > > tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %arrayidx, i8* %buf, > > i64 18, i32 1, i1 false) > > %arrayidx1 = getelementptr i8* %buf, i64 18 > > store i8 1, i8* %arrayidx1, align 1 > > tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, > > i64 18, i32 1, i1 false) > > ret void > > } > > > > > > > > I ran opt -O2 ex.ll -S, and got: > > > > define void @fn(i8* nocapture %buf) #0 { > > entry: > > %arrayidx = getelementptr i8* %buf, i64 18 > > store i8 1, i8* %arrayidx, align 1 > > tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, > > i64 18, i32 1, i1 false) > > ret void > > } > > > > > > In that case previous contents of bytes 0-17 are overwritten by bytes > > 18-35 (pre-opt code doesn't do that). > > > > > > > > Another point, if I change the code to: > > > > define void @fn(i8* %buf) #0 { > > entry: > > %arrayidx = getelementptr i8* %buf, i64 18 > > tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %arrayidx, i8* %buf, > > i64 18, i32 1, i1 false) > > > > ;changing 19th byte, not 18th: > > > > %arrayidx1 = getelementptr i8* %buf, i64 19 > > store i8 1, i8* %arrayidx1, align 1 > > tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, > > i64 18, i32 1, i1 false) > > ret void > > } > > > > > > > > I get correct piece of code: > > > > define void @fn(i8* nocapture %buf) #0 { > > entry: > > %arrayidx = getelementptr i8* %buf, i64 18 > > tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %arrayidx, i8* %buf, > > i64 18, i32 1, i1 false) > > %arrayidx1 = getelementptr i8* %buf, i64 19 > > store i8 1, i8* %arrayidx1, align 1 > > tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, > > i64 18, i32 1, i1 false) > > ret void > > } > > > > Adding some datalayout to module also solves the issue. > > > > -print-after-all shows that the 'Dead Store Elimination' pass erases > > first call to memcpy. > > > > I found that the following code in DeadStoreElimination.cpp leads to > > such behavior: > > if (DL == nullptr && Later.Ptr->getType() == Earlier.Ptr->getType()) > > return OverwriteComplete; > > > > > > Is this issue a bug in DSE or maybe I'm doing some wrong? > > > > Looks like a bug in DSE, you're not doing anything wrong. We don't test > much without data layouts anymore. This code might pre-date DSE's handling > of memcpy intrinsics (just a guess). In any case, we'll fix it. > > -Hal > > > > > > > > > Best regards, > > Alexey > > > > _______________________________________________ > > LLVM Developers mailing list > > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev > > > > -- > Hal Finkel > Assistant Computational Scientist > Leadership Computing Facility > Argonne National Laboratory >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20141017/af5ac0ed/attachment.html>
Apparently Analagous Threads
- [LLVMdev] What's the Alias Analysis does clang use ?
- [PATCH] D26127: [MemorySSA] Repair AccessList invariants after insertion of new MemoryUseOrDef.
- LLVM-IR store-load propagation
- [LLVMdev] What's the Alias Analysis does clang use ?
- RFC phantom memory intrinsic