[PATCH] D16622: Value: Provide a shortcut in stripPointerCastsAndOffsets()

Matthias Braun via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 27 22:14:42 PST 2016


MatzeB abandoned this revision.
MatzeB added a comment.

I just posted patches that

In http://reviews.llvm.org/D16622#337127, @hfinkel wrote:

> In http://reviews.llvm.org/D16622#336984, @chandlerc wrote:
>
> > Ugh. It's pretty sad that the optimizer doesn't fix this.
>
>
> I recall also seeing this problem recently in a different context, and it looked like the reason why this mattered was because the constructor ends up zeroing the stack array (instead of leaving it uninitialized).
>
> If we can fix the class implementation, or the optimizer, that would be better. It looks like there are two problems here, one is the memset (which is what I recall seeing in the profile), and the other is that we don't inline the destructor.
>
> Specifically:
>
>   $ cat /tmp/q1.cpp 
>   #include <llvm/ADT/SmallPtrSet.h>
>   #include <llvm/IR/Type.h>
>   using namespace llvm;
>  
>   bool foo(SmallPtrSetImpl<Type*> *Visited);
>  
>   bool isSized() {
>     SmallPtrSet<Type *, 4> V;
>     return foo(&V);
>   }
>   
>   $ clang++ -std=gnu++11 -O3 -S -emit-llvm -Iinclude -I/build/ppc64/llvm/include --gcc-toolchain=/install/ppc64/gcc -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -o - /tmp/q1.cpp -fno-exceptions
>   ...
>   define zeroext i1 @_Z7isSizedv() #0 {
>   entry:
>     %V = alloca %"class.llvm::SmallPtrSet", align 8
>     %0 = bitcast %"class.llvm::SmallPtrSet"* %V to i8*
>     call void @llvm.lifetime.start(i64 64, i8* %0) #3
>     %arraydecay.i = getelementptr inbounds %"class.llvm::SmallPtrSet", %"class.llvm::SmallPtrSet"* %V, i64 0, i32 1, i64 0
>     %SmallArray.i.i.i = getelementptr inbounds %"class.llvm::SmallPtrSet", %"class.llvm::SmallPtrSet"* %V, i64 0, i32 0, i32 0, i32 0
>     store i8** %arraydecay.i, i8*** %SmallArray.i.i.i, align 8, !tbaa !1
>     %1 = getelementptr inbounds %"class.llvm::SmallPtrSet", %"class.llvm::SmallPtrSet"* %V, i64 0, i32 0, i32 0, i32 1
>     store i8** %arraydecay.i, i8*** %1, align 8, !tbaa !7
>     %2 = getelementptr inbounds %"class.llvm::SmallPtrSet", %"class.llvm::SmallPtrSet"* %V, i64 0, i32 0, i32 0, i32 2
>     store i32 4, i32* %2, align 8, !tbaa !8
>     %3 = bitcast i8** %arraydecay.i to i8*
>     %4 = getelementptr inbounds %"class.llvm::SmallPtrSet", %"class.llvm::SmallPtrSet"* %V, i64 0, i32 0, i32 0, i32 3
>     call void @llvm.memset.p0i8.i64(i8* %3, i8 -1, i64 32, i32 8, i1 false) #3
>     store i32 0, i32* %4, align 4, !tbaa !9
>     %5 = getelementptr inbounds %"class.llvm::SmallPtrSet", %"class.llvm::SmallPtrSet"* %V, i64 0, i32 0, i32 0, i32 4
>     store i32 0, i32* %5, align 8, !tbaa !10
>     %6 = bitcast %"class.llvm::SmallPtrSet"* %V to %"class.llvm::SmallPtrSetImpl"*
>     %call = call zeroext i1 @_Z3fooPN4llvm15SmallPtrSetImplIPNS_4TypeEEE(%"class.llvm::SmallPtrSetImpl"* %6) #3
>     %7 = bitcast %"class.llvm::SmallPtrSet"* %V to %"class.llvm::SmallPtrSetImplBase"*
>     call void @_ZN4llvm19SmallPtrSetImplBaseD2Ev(%"class.llvm::SmallPtrSetImplBase"* nonnull %7) #3
>     call void @llvm.lifetime.end(i64 64, i8* %0) #3
>     ret i1 %call
>   }
>   ...
>   
>
> Consider, on the other hand, what happens with a SmallVector of the same type:
>
>   $ cat /tmp/q2.cpp 
>   #include <llvm/ADT/SmallVector.h>
>   #include <llvm/IR/Type.h>
>   using namespace llvm;
>  
>   bool foo(SmallVectorImpl<Type*> *Visited);
>  
>   bool isSized() {
>     SmallVector<Type *, 4> V;
>     return foo(&V);
>   }
>   
>   $ clang ... /tmp/q2.cpp ...
>   ...
>   define zeroext i1 @_Z7isSizedv() #0 {
>   entry:
>     %V = alloca %"class.llvm::SmallVector", align 8
>     %0 = bitcast %"class.llvm::SmallVector"* %V to i8*
>     call void @llvm.lifetime.start(i64 56, i8* %0) #3
>     %1 = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %V, i64 0, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0, i64 0
>     %BeginX.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %V, i64 0, i32 0, i32 0, i32 0, i32 0, i32 0
>     store i8* %1, i8** %BeginX.i.i.i.i.i, align 8, !tbaa !1
>     %EndX.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %V, i64 0, i32 0, i32 0, i32 0, i32 0, i32 1
>     store i8* %1, i8** %EndX.i.i.i.i.i, align 8, !tbaa !6
>     %CapacityX.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %V, i64 0, i32 0, i32 0, i32 0, i32 0, i32 2
>     %add.ptr.i.i.i.i.i = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %V, i64 0, i32 0, i32 0, i32 0, i32 1, i32 0, i32 0, i64 32
>     store i8* %add.ptr.i.i.i.i.i, i8** %CapacityX.i.i.i.i.i, align 8, !tbaa !7
>     %2 = getelementptr inbounds %"class.llvm::SmallVector", %"class.llvm::SmallVector"* %V, i64 0, i32 0
>     %call = call zeroext i1 @_Z3fooPN4llvm15SmallVectorImplIPNS_4TypeEEE(%"class.llvm::SmallVectorImpl"* %2) #3
>     %3 = load i8*, i8** %BeginX.i.i.i.i.i, align 8, !tbaa !1
>     %cmp.i.i = icmp eq i8* %3, %1
>     br i1 %cmp.i.i, label %_ZN4llvm15SmallVectorImplIPNS_4TypeEED2Ev.exit, label %if.then.i
>    
>   if.then.i:                                        ; preds = %entry
>     call void @free(i8* %3) #3
>     br label %_ZN4llvm15SmallVectorImplIPNS_4TypeEED2Ev.exit
>    
>   _ZN4llvm15SmallVectorImplIPNS_4TypeEED2Ev.exit:   ; preds = %entry, %if.then.i
>     call void @llvm.lifetime.end(i64 56, i8* %0) #3
>     ret i1 %call
>   }  
>   ...
>   
>
> Here we have no memset and the destructor is inlined.


I just posted reviews that should avoid the memset in the small SmallPtrSet cases. I can't measure any signifant differences with it, so we can abandon this (assuming the SmallPtrSet changes get approved).


Repository:
  rL LLVM

http://reviews.llvm.org/D16622





More information about the llvm-commits mailing list