Hi all, There might be a bug in DeadStoreElimination.cpp. This pass eliminates stores backwards aggressively in an end BB. It does not check dependencies on stores in an end BB though. For example, in this code snippet: ... 1. %sum.safe_r47.pre-phi = phi i64* [ %sum.safe_r47.pre, %entry.for.end_crit_edge ], [ %sum.safe_r42, %for.body ] 2. %call9 = call i32 @gettimeofday(%struct.timeval* %end, %struct.timeval* null) nounwind 3. %0 = bitcast %struct.timeval* %start to i64* // eliminated by HandleEndBlock in DeadStoreElimination.cpp 4. %1 = bitcast %struct.timeval* %agg.tmp to i64* // eliminated ... 5. %tmp49 = load i64* %0, align 8 // eliminated ... 6. store i64 %tmp49, i64* %1, align 8 // eliminated ... 7. %2 = bitcast %struct.timeval* %end to i64* // eliminated ... 8. %3 = bitcast %struct.timeval* %agg.tmp12 to i64* // eliminated ... 9. %tmp50 = load i64* %2, align 8 // eliminated ... 10. store i64 %tmp50, i64* %3, align 8 // eliminated ... 11. %tv_sec = getelementptr inbounds %struct.timeval* %agg.tmp, i32 0, i32 0 12. %tv_sec.safe_r = call i32* @llvm.guard.load.p0i32(i32* %tv_sec) // intrinsic function call inserted by me 13. %tmp15 = load i32* %tv_sec.safe_r, align 4, !tbaa !4 // this loads the value stored at line 6 14. %tv_usec = getelementptr inbounds %struct.timeval* %agg.tmp, i32 0, i32 1 15. %tv_usec.safe_r = call i32* @llvm.guard.load.p0i32(i32* %tv_usec) // intrinsic function call ... 16. %tmp16 = load i32* %tv_usec.safe_r, align 4, !tbaa !4 17. %tv_sec17 = getelementptr inbounds %struct.timeval* %agg.tmp12, i32 0, i32 0 18. %tv_sec17.safe_r = call i32* @llvm.guard.load.p0i32(i32* %tv_sec17) // intrinsic function call ... 19. %tmp18 = load i32* %tv_sec17.safe_r, align 4, !tbaa !4 20. %tv_usec19 = getelementptr inbounds %struct.timeval* %agg.tmp12, i32 0, i32 1 21. %tv_usec19.safe_r = call i32* @llvm.guard.load.p0i32(i32* %tv_usec19) // intrinsic function call 22. %tmp20 = load i32* %tv_usec19.safe_r, align 4, !tbaa !4 23. %call21 = call i32 @delta(i32 %tmp15, i32 %tmp16, i32 %tmp18, i32 %tmp20) ... It is compiled by clang 2.9. This BB is an end block in a function. Intrinsic function llvm.guard.load.p0i32 is defined as follows: let Properties = [IntrNoMem, NoCapture<0>] in { def int_guard_load : Intrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>]> } Thanks a lot. Bin -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20111006/894fd8b5/attachment.html>
On Thu, Oct 6, 2011 at 2:12 PM, Zeng Bin <ezengbin at gmail.com> wrote:> Hi all, > > There might be a bug in DeadStoreElimination.cpp. This pass eliminates > stores backwards aggressively in an end BB. It does not check dependencies > on stores in an end BB though. For example, in this code snippet: > ... > 1. %sum.safe_r47.pre-phi = phi i64* [ %sum.safe_r47.pre, > %entry.for.end_crit_edge ], [ %sum.safe_r42, %for.body ] > 2. %call9 = call i32 @gettimeofday(%struct.timeval* %end, %struct.timeval* > null) nounwind > 3. %0 = bitcast %struct.timeval* %start to i64* // eliminated by > HandleEndBlock in DeadStoreElimination.cpp > 4. %1 = bitcast %struct.timeval* %agg.tmp to i64* // eliminated ... > 5. %tmp49 = load i64* %0, align 8 // eliminated > ... > 6. store i64 %tmp49, i64* %1, align 8 // eliminated > ... > 7. %2 = bitcast %struct.timeval* %end to i64* // eliminated ... > 8. %3 = bitcast %struct.timeval* %agg.tmp12 to i64* // eliminated ... > 9. %tmp50 = load i64* %2, align 8 // > eliminated ... > 10. store i64 %tmp50, i64* %3, align 8 // > eliminated ... > 11. %tv_sec = getelementptr inbounds %struct.timeval* %agg.tmp, i32 0, i32 > 0 > 12. %tv_sec.safe_r = call i32* @llvm.guard.load.p0i32(i32* %tv_sec) // > intrinsic function call inserted by me > 13. %tmp15 = load i32* %tv_sec.safe_r, align 4, !tbaa > !4 // this loads the value stored at line 6 > 14. %tv_usec = getelementptr inbounds %struct.timeval* %agg.tmp, i32 0, i32 > 1 > 15. %tv_usec.safe_r = call i32* @llvm.guard.load.p0i32(i32* %tv_usec) // > intrinsic function call ... > 16. %tmp16 = load i32* %tv_usec.safe_r, align 4, !tbaa !4 > 17. %tv_sec17 = getelementptr inbounds %struct.timeval* %agg.tmp12, i32 0, > i32 0 > 18. %tv_sec17.safe_r = call i32* @llvm.guard.load.p0i32(i32* %tv_sec17) // > intrinsic function call ... > 19. %tmp18 = load i32* %tv_sec17.safe_r, align 4, !tbaa !4 > 20. %tv_usec19 = getelementptr inbounds %struct.timeval* %agg.tmp12, i32 0, > i32 1 > 21. %tv_usec19.safe_r = call i32* @llvm.guard.load.p0i32(i32* %tv_usec19) > // intrinsic function call > 22. %tmp20 = load i32* %tv_usec19.safe_r, align 4, !tbaa !4 > 23. %call21 = call i32 @delta(i32 %tmp15, i32 %tmp16, i32 %tmp18, i32 > %tmp20) > ... > > It is compiled by clang 2.9. This BB is an end block in a function. > Intrinsic function llvm.guard.load.p0i32 is defined as follows: > let Properties = [IntrNoMem, NoCapture<0>] in { > def int_guard_load : Intrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>]> > } > > Thanks a lot.IntrNoMem means that your intrinsic doesn't access memory... I don't think that is what you want. -Eli
On Thu, Oct 6, 2011 at 2:20 PM, Eli Friedman <eli.friedman at gmail.com> wrote:> On Thu, Oct 6, 2011 at 2:12 PM, Zeng Bin <ezengbin at gmail.com> wrote: >> Hi all, >> >> There might be a bug in DeadStoreElimination.cpp. This pass eliminates >> stores backwards aggressively in an end BB. It does not check dependencies >> on stores in an end BB though. For example, in this code snippet: >> ... >> 1. %sum.safe_r47.pre-phi = phi i64* [ %sum.safe_r47.pre, >> %entry.for.end_crit_edge ], [ %sum.safe_r42, %for.body ] >> 2. %call9 = call i32 @gettimeofday(%struct.timeval* %end, %struct.timeval* >> null) nounwind >> 3. %0 = bitcast %struct.timeval* %start to i64* // eliminated by >> HandleEndBlock in DeadStoreElimination.cpp >> 4. %1 = bitcast %struct.timeval* %agg.tmp to i64* // eliminated ... >> 5. %tmp49 = load i64* %0, align 8 // eliminated >> ... >> 6. store i64 %tmp49, i64* %1, align 8 // eliminated >> ... >> 7. %2 = bitcast %struct.timeval* %end to i64* // eliminated ... >> 8. %3 = bitcast %struct.timeval* %agg.tmp12 to i64* // eliminated ... >> 9. %tmp50 = load i64* %2, align 8 // >> eliminated ... >> 10. store i64 %tmp50, i64* %3, align 8 // >> eliminated ... >> 11. %tv_sec = getelementptr inbounds %struct.timeval* %agg.tmp, i32 0, i32 >> 0 >> 12. %tv_sec.safe_r = call i32* @llvm.guard.load.p0i32(i32* %tv_sec) // >> intrinsic function call inserted by me >> 13. %tmp15 = load i32* %tv_sec.safe_r, align 4, !tbaa >> !4 // this loads the value stored at line 6 >> 14. %tv_usec = getelementptr inbounds %struct.timeval* %agg.tmp, i32 0, i32 >> 1 >> 15. %tv_usec.safe_r = call i32* @llvm.guard.load.p0i32(i32* %tv_usec) // >> intrinsic function call ... >> 16. %tmp16 = load i32* %tv_usec.safe_r, align 4, !tbaa !4 >> 17. %tv_sec17 = getelementptr inbounds %struct.timeval* %agg.tmp12, i32 0, >> i32 0 >> 18. %tv_sec17.safe_r = call i32* @llvm.guard.load.p0i32(i32* %tv_sec17) // >> intrinsic function call ... >> 19. %tmp18 = load i32* %tv_sec17.safe_r, align 4, !tbaa !4 >> 20. %tv_usec19 = getelementptr inbounds %struct.timeval* %agg.tmp12, i32 0, >> i32 1 >> 21. %tv_usec19.safe_r = call i32* @llvm.guard.load.p0i32(i32* %tv_usec19) >> // intrinsic function call >> 22. %tmp20 = load i32* %tv_usec19.safe_r, align 4, !tbaa !4 >> 23. %call21 = call i32 @delta(i32 %tmp15, i32 %tmp16, i32 %tmp18, i32 >> %tmp20) >> ... >> >> It is compiled by clang 2.9. This BB is an end block in a function. >> Intrinsic function llvm.guard.load.p0i32 is defined as follows: >> let Properties = [IntrNoMem, NoCapture<0>] in { >> def int_guard_load : Intrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>]> >> } >> >> Thanks a lot. > > IntrNoMem means that your intrinsic doesn't access memory... I don't > think that is what you want.Well, either that or the NoCapture marking is wrong. What exactly is your int_guard_load supposed to do? -Eli