[PATCH] D16622: Value: Provide a shortcut in stripPointerCastsAndOffsets()
Hal Finkel via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 27 02:36:08 PST 2016
hfinkel added a subscriber: hfinkel.
hfinkel added a comment.
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.
Repository:
rL LLVM
http://reviews.llvm.org/D16622
More information about the llvm-commits
mailing list