Re: [PATCH] D11859: Generating vptr assume loads
rsmith accepted this revision. rsmith added a comment. This revision is now accepted and ready to land. LGTM Comment at: test/CodeGenCXX/vtable-assume-load.cpp:24 @@ +23,3 @@ +// CHECK1-LABEL: define void @_ZN5test14fooAEv() +// CHECK1: call void @_ZN5test11AC1Ev(%struct.test1::A* +// CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}} While you're here, maybe also remove the `%struct.test1::A*` (and likewise for the tests below). http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
Prazek updated this revision to Diff 32363. Prazek added a comment. Fix for the PR24479 http://reviews.llvm.org/D11859 Files: lib/CodeGen/CGCXXABI.h lib/CodeGen/CGCall.cpp lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/ItaniumCXXABI.cpp lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGen/available-externally-hidden.cpp test/CodeGenCXX/ctor-globalopt.cpp test/CodeGenCXX/template-instantiation.cpp test/CodeGenCXX/thunks.cpp test/CodeGenCXX/virtual-base-ctor.cpp test/CodeGenCXX/vtable-assume-load.cpp test/CodeGenCXX/vtable-available-externally.cpp Index: test/CodeGenCXX/vtable-available-externally.cpp === --- test/CodeGenCXX/vtable-available-externally.cpp +++ test/CodeGenCXX/vtable-available-externally.cpp @@ -182,8 +182,8 @@ namespace Test9 { // all virtual functions are outline, so we can assume that it will // be generated in translation unit where foo is defined -// CHECK-TEST9: @_ZTVN5Test91AE = available_externally unnamed_addr constant -// CHECK-TEST9: @_ZTVN5Test91BE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91AE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91BE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual void bar(); @@ -206,39 +206,39 @@ namespace Test10 { // because A's key function is defined here, vtable is generated in this TU -// CHECK-TEST10: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant struct A { virtual void foo(); virtual void bar(); }; void A::foo() {} // Because key function is inline we will generate vtable as linkonce_odr -// CHECK-TEST10: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; inline void D::bar() {} // because B has outline key function then we can refer to -// CHECK-TEST10: @_ZTVN6Test101BE = available_externally unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101BE = available_externally unnamed_addr constant struct B : A { void foo(); void bar(); }; // C's key function (car) is outline, but C has inline virtual function so we // can't guarantee that we will be able to refer to bar from name // so (at the moment) we can't emit vtable available_externally -// CHECK-TEST10: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant struct C : A { void bar() {} // defined in body - not key function virtual inline void gar(); // inline in body - not key function virtual void car(); }; // no key function, vtable will be generated everywhere it will be used -// CHECK-TEST10: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant struct E : A {}; void g(A a) { Index: test/CodeGenCXX/vtable-assume-load.cpp === --- /dev/null +++ test/CodeGenCXX/vtable-assume-load.cpp @@ -0,0 +1,172 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-optzns -fms-extensions +// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-optzns -fms-extensions + +// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s + +namespace test1 { + +struct A { + A(); + virtual void foo(); +}; + +struct B : A { + virtual void foo(); +}; + +void g(A *a) { a-foo(); } + +// CHECK1-LABEL: define void @_ZN5test14fooAEv() +// CHECK1: call void @_ZN5test11AC1Ev(%struct.test1::A* +// CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}} +// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %[[CMP]]) +// CHECK1-LABEL: } + +void fooA() { + A a; + g(a); +} + +// CHECK1-LABEL: define void @_ZN5test14fooBEv() +// CHECK1: call void @_ZN5test11BC1Ev(%struct.test1::B* %{{.*}}) +// CHECK1: %[[VTABLE:.*]] = load i8**, i8*** %{{.*}} +// CHECK1: %[[CMP:.*]] = icmp eq i8** %[[VTABLE]], getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %[[CMP]]) +// CHECK1-LABEL: } + +void fooB() { + B b; + g(b); +} +// there should not be any assumes in the ctor that calls base ctor +// CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(%struct.test1::B* +// CHECK1-NOT: @llvm.assume( +// CHECK1-LABEL: } +} +namespace test2 { +struct A { + A(); + virtual void foo(); +}; + +struct B
Re: [PATCH] D11859: Generating vptr assume loads
rjmccall added a comment. Just a couple tweaks and then LGTM. Comment at: lib/CodeGen/CGClass.cpp:1833 @@ +1832,3 @@ + // unless we are calling base constructor - we don't want to generating + // assumption loads for not completed because vptr may still change. + if (CGM.getCodeGenOpts().OptimizationLevel 0 Please use this comment: // Generate vtable assumptions if we're constructing a complete object // with a vtable. We don't do this for base subobjects for two reasons: // first, it's incorrect for classes with virtual bases, and second, we're // about to overwrite the vptrs anyway. Comment at: lib/CodeGen/CGClass.cpp:2155 @@ -2122,1 +2154,3 @@ +for (const VPtr Vptr : Vptrs) + InitializeVTablePointer(Vptr); Please also skip the call to getVTablePointers when doStructorsInitializeVPtrs, thanks. Comment at: lib/CodeGen/ItaniumCXXABI.cpp:196 @@ +195,3 @@ + + bool doStructorsInitilizeVPtrs(const CXXRecordDecl *VTableClass) override { +return true; Typo: Initialize. http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
Prazek updated this revision to Diff 32343. Prazek marked an inline comment as done. http://reviews.llvm.org/D11859 Files: lib/CodeGen/CGCXXABI.h lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/ItaniumCXXABI.cpp lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGen/available-externally-hidden.cpp test/CodeGenCXX/ctor-globalopt.cpp test/CodeGenCXX/template-instantiation.cpp test/CodeGenCXX/thunks.cpp test/CodeGenCXX/virtual-base-ctor.cpp test/CodeGenCXX/vtable-assume-load.cpp test/CodeGenCXX/vtable-available-externally.cpp Index: test/CodeGenCXX/vtable-available-externally.cpp === --- test/CodeGenCXX/vtable-available-externally.cpp +++ test/CodeGenCXX/vtable-available-externally.cpp @@ -182,8 +182,8 @@ namespace Test9 { // all virtual functions are outline, so we can assume that it will // be generated in translation unit where foo is defined -// CHECK-TEST9: @_ZTVN5Test91AE = available_externally unnamed_addr constant -// CHECK-TEST9: @_ZTVN5Test91BE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91AE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91BE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual void bar(); @@ -206,39 +206,39 @@ namespace Test10 { // because A's key function is defined here, vtable is generated in this TU -// CHECK-TEST10: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant struct A { virtual void foo(); virtual void bar(); }; void A::foo() {} // Because key function is inline we will generate vtable as linkonce_odr -// CHECK-TEST10: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; inline void D::bar() {} // because B has outline key function then we can refer to -// CHECK-TEST10: @_ZTVN6Test101BE = available_externally unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101BE = available_externally unnamed_addr constant struct B : A { void foo(); void bar(); }; // C's key function (car) is outline, but C has inline virtual function so we // can't guarantee that we will be able to refer to bar from name // so (at the moment) we can't emit vtable available_externally -// CHECK-TEST10: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant struct C : A { void bar() {} // defined in body - not key function virtual inline void gar(); // inline in body - not key function virtual void car(); }; // no key function, vtable will be generated everywhere it will be used -// CHECK-TEST10: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant struct E : A {}; void g(A a) { Index: test/CodeGenCXX/vtable-assume-load.cpp === --- /dev/null +++ test/CodeGenCXX/vtable-assume-load.cpp @@ -0,0 +1,173 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-optzns -fms-extensions +// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-optzns -fms-extensions + +// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s + +namespace test1 { + +struct A { + A(); + virtual void foo(); +}; + +struct B : A { + virtual void foo(); +}; + +void g(A *a) { a-foo(); } + +// CHECK1-LABEL: define void @_ZN5test14fooAEv() +// CHECK1: call void @_ZN5test11AC1Ev(%struct.test1::A* %a) +// CHECK1: %vtable = load i8**, i8*** %1 +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABEL: } + +void fooA() { + A a; + g(a); +} + +// CHECK1-LABEL: define void @_ZN5test14fooBEv() +// CHECK1: call void @_ZN5test11BC1Ev(%struct.test1::B* %b) +// CHECK1: %vtable = load i8**, i8*** %1 +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABEL: } + +void fooB() { + B b; + g(b); +} +// there should not be any assumes in the ctor that calls base ctor +// CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(%struct.test1::B* %this) +// CHECK1-NOT: @llvm.assume( +// CHECK1-LABEL: } +} +namespace test2 { +struct A { + A(); + virtual void foo(); +}; + +struct B { + B(); + virtual void bar(); +}; +
Re: [PATCH] D11859: Generating vptr assume loads
Prazek marked 3 inline comments as done. Prazek added a comment. http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
rjmccall added inline comments. Comment at: lib/CodeGen/CGClass.cpp:1862 @@ +1861,3 @@ + for (const VPtr Vptr : getVTablePointers(ClassDecl)) +if (CGM.getCXXABI().requiresVPtrInitialization(Vptr)) + EmitVTableAssumptionLoad(Vptr, This); No, it only checks whether VTableClass has novtable. VTableClass is the derived class for which we're initializing subobject v-tables, and it's invariant during getVTablePointers; that's why it's passed separately from BaseSubobject. And if you think about how novtable works as a language feature, you'll see that it has to be that way. The purpose of novtable is to avoid emitting v-tables just for the short-term purposes of construction and destruction. It's not supposed to apply when initializing derived classes: eventually, the complete object does need all the v-tables to be initialized, or else you'll never be able to call virtual methods on it, meaning that it might as well not have any. http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
Prazek marked 3 inline comments as done. Comment at: lib/CodeGen/CGClass.cpp:1862 @@ +1861,3 @@ + for (const VPtr Vptr : getVTablePointers(ClassDecl)) +if (CGM.getCXXABI().requiresVPtrInitialization(Vptr)) + EmitVTableAssumptionLoad(Vptr, This); rjmccall wrote: No, it only checks whether VTableClass has novtable. VTableClass is the derived class for which we're initializing subobject v-tables, and it's invariant during getVTablePointers; that's why it's passed separately from BaseSubobject. And if you think about how novtable works as a language feature, you'll see that it has to be that way. The purpose of novtable is to avoid emitting v-tables just for the short-term purposes of construction and destruction. It's not supposed to apply when initializing derived classes: eventually, the complete object does need all the v-tables to be initialized, or else you'll never be able to call virtual methods on it, meaning that it might as well not have any. You are right. I changed things like You said - I only named it doStructorsInitilizeVPtrs http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
Prazek added a comment. In http://reviews.llvm.org/D11859#225025, @rjmccall wrote: Mostly LGTM. Are you going to emit assumptions for vbptrs in a separate patch? I wasn't planning to. I am focusing now on upgrading GVN for using new invariant.barrier metadata. http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
rjmccall added a comment. In http://reviews.llvm.org/D11859#225384, @Prazek wrote: In http://reviews.llvm.org/D11859#225025, @rjmccall wrote: Mostly LGTM. Are you going to emit assumptions for vbptrs in a separate patch? I wasn't planning to. I am focusing now on upgrading GVN for using new invariant.barrier metadata. I won't argue with prioritizing Itanium over MS work, if that's your motivation, because that's obviously your call to make, and certainly that's how I would weigh things if I were doing this work. If you're interested in both, though, I would guess that vbptr assumptions would be particularly valuable — constructing objects and immediately converting them to a base class is pretty common in a lot of idioms. http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
Prazek marked an inline comment as done. Comment at: lib/CodeGen/CGCXXABI.h:352 @@ +351,3 @@ + isVirtualOffsetNeededForVTableField(CodeGenFunction CGF, + const CXXRecordDecl *NearestVBase) = 0; + rjmccall wrote: This method does not need to be passed a CodeGenFunction, but it should take a complete CodeGenFunction::VPtr, not just this one random field from it. yep, I thought that there will be problem with placing VPtr class, but I haven't noticed that CGCXXAABI includes CodeGenFunction. CodeGenFunction is required for ItaniumABI return NeedsVTTParameter(CGF.CurGD); Comment at: lib/CodeGen/CGClass.cpp:1862 @@ +1861,3 @@ + for (const VPtr vptr : getVTablePointers(ClassDecl)) +if (CGM.getCXXABI().canInitializeVPtr(vptr.VTableClass, vptr.Base.getBase(), + vptr.NearestVBase)) rjmccall wrote: As mentioned elsewhere, you can skip this entire loop if doStructorsInitializeVTables returns false. hmm, I think it is not true. This code checks if each base that we are initilizing/generating vptr assumption don't have novtable specifier. If one base has it, it doesn't mean that we don't have to do it for other base http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
Prazek updated this revision to Diff 32262. http://reviews.llvm.org/D11859 Files: lib/CodeGen/CGCXXABI.h lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/ItaniumCXXABI.cpp lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGen/available-externally-hidden.cpp test/CodeGenCXX/ctor-globalopt.cpp test/CodeGenCXX/template-instantiation.cpp test/CodeGenCXX/thunks.cpp test/CodeGenCXX/virtual-base-ctor.cpp test/CodeGenCXX/vtable-assume-load.cpp test/CodeGenCXX/vtable-available-externally.cpp Index: test/CodeGenCXX/vtable-available-externally.cpp === --- test/CodeGenCXX/vtable-available-externally.cpp +++ test/CodeGenCXX/vtable-available-externally.cpp @@ -182,8 +182,8 @@ namespace Test9 { // all virtual functions are outline, so we can assume that it will // be generated in translation unit where foo is defined -// CHECK-TEST9: @_ZTVN5Test91AE = available_externally unnamed_addr constant -// CHECK-TEST9: @_ZTVN5Test91BE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91AE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91BE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual void bar(); @@ -206,39 +206,39 @@ namespace Test10 { // because A's key function is defined here, vtable is generated in this TU -// CHECK-TEST10: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant struct A { virtual void foo(); virtual void bar(); }; void A::foo() {} // Because key function is inline we will generate vtable as linkonce_odr -// CHECK-TEST10: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; inline void D::bar() {} // because B has outline key function then we can refer to -// CHECK-TEST10: @_ZTVN6Test101BE = available_externally unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101BE = available_externally unnamed_addr constant struct B : A { void foo(); void bar(); }; // C's key function (car) is outline, but C has inline virtual function so we // can't guarantee that we will be able to refer to bar from name // so (at the moment) we can't emit vtable available_externally -// CHECK-TEST10: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant struct C : A { void bar() {} // defined in body - not key function virtual inline void gar(); // inline in body - not key function virtual void car(); }; // no key function, vtable will be generated everywhere it will be used -// CHECK-TEST10: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant struct E : A {}; void g(A a) { Index: test/CodeGenCXX/vtable-assume-load.cpp === --- /dev/null +++ test/CodeGenCXX/vtable-assume-load.cpp @@ -0,0 +1,173 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-optzns -fms-extensions +// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-optzns -fms-extensions + +// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s + +namespace test1 { + +struct A { + A(); + virtual void foo(); +}; + +struct B : A { + virtual void foo(); +}; + +void g(A *a) { a-foo(); } + +// CHECK1-LABEL: define void @_ZN5test14fooAEv() +// CHECK1: call void @_ZN5test11AC1Ev(%struct.test1::A* %a) +// CHECK1: %vtable = load i8**, i8*** %1 +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABEL: } + +void fooA() { + A a; + g(a); +} + +// CHECK1-LABEL: define void @_ZN5test14fooBEv() +// CHECK1: call void @_ZN5test11BC1Ev(%struct.test1::B* %b) +// CHECK1: %vtable = load i8**, i8*** %1 +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABEL: } + +void fooB() { + B b; + g(b); +} +// there should not be any assumes in the ctor that calls base ctor +// CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(%struct.test1::B* %this) +// CHECK1-NOT: @llvm.assume( +// CHECK1-LABEL: } +} +namespace test2 { +struct A { + A(); + virtual void foo(); +}; + +struct B { + B(); + virtual void bar(); +}; + +struct C : A, B { + C(); + virtual void
Re: [PATCH] D11859: Generating vptr assume loads
Prazek updated this revision to Diff 32263. http://reviews.llvm.org/D11859 Files: lib/CodeGen/CGCXXABI.h lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/ItaniumCXXABI.cpp lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGen/available-externally-hidden.cpp test/CodeGenCXX/ctor-globalopt.cpp test/CodeGenCXX/template-instantiation.cpp test/CodeGenCXX/thunks.cpp test/CodeGenCXX/virtual-base-ctor.cpp test/CodeGenCXX/vtable-assume-load.cpp test/CodeGenCXX/vtable-available-externally.cpp Index: test/CodeGenCXX/vtable-available-externally.cpp === --- test/CodeGenCXX/vtable-available-externally.cpp +++ test/CodeGenCXX/vtable-available-externally.cpp @@ -182,8 +182,8 @@ namespace Test9 { // all virtual functions are outline, so we can assume that it will // be generated in translation unit where foo is defined -// CHECK-TEST9: @_ZTVN5Test91AE = available_externally unnamed_addr constant -// CHECK-TEST9: @_ZTVN5Test91BE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91AE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91BE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual void bar(); @@ -206,39 +206,39 @@ namespace Test10 { // because A's key function is defined here, vtable is generated in this TU -// CHECK-TEST10: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant struct A { virtual void foo(); virtual void bar(); }; void A::foo() {} // Because key function is inline we will generate vtable as linkonce_odr -// CHECK-TEST10: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; inline void D::bar() {} // because B has outline key function then we can refer to -// CHECK-TEST10: @_ZTVN6Test101BE = available_externally unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101BE = available_externally unnamed_addr constant struct B : A { void foo(); void bar(); }; // C's key function (car) is outline, but C has inline virtual function so we // can't guarantee that we will be able to refer to bar from name // so (at the moment) we can't emit vtable available_externally -// CHECK-TEST10: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant struct C : A { void bar() {} // defined in body - not key function virtual inline void gar(); // inline in body - not key function virtual void car(); }; // no key function, vtable will be generated everywhere it will be used -// CHECK-TEST10: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant struct E : A {}; void g(A a) { Index: test/CodeGenCXX/vtable-assume-load.cpp === --- /dev/null +++ test/CodeGenCXX/vtable-assume-load.cpp @@ -0,0 +1,173 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-optzns -fms-extensions +// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-optzns -fms-extensions + +// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s + +namespace test1 { + +struct A { + A(); + virtual void foo(); +}; + +struct B : A { + virtual void foo(); +}; + +void g(A *a) { a-foo(); } + +// CHECK1-LABEL: define void @_ZN5test14fooAEv() +// CHECK1: call void @_ZN5test11AC1Ev(%struct.test1::A* %a) +// CHECK1: %vtable = load i8**, i8*** %1 +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABEL: } + +void fooA() { + A a; + g(a); +} + +// CHECK1-LABEL: define void @_ZN5test14fooBEv() +// CHECK1: call void @_ZN5test11BC1Ev(%struct.test1::B* %b) +// CHECK1: %vtable = load i8**, i8*** %1 +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABEL: } + +void fooB() { + B b; + g(b); +} +// there should not be any assumes in the ctor that calls base ctor +// CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(%struct.test1::B* %this) +// CHECK1-NOT: @llvm.assume( +// CHECK1-LABEL: } +} +namespace test2 { +struct A { + A(); + virtual void foo(); +}; + +struct B { + B(); + virtual void bar(); +}; + +struct C : A, B { + C(); + virtual void
Re: [PATCH] D11859: Generating vptr assume loads
rjmccall added a comment. Mostly LGTM. Are you going to emit assumptions for vbptrs in a separate patch? Comment at: lib/CodeGen/CGCXXABI.h:349-357 @@ -348,1 +348,11 @@ + /// Checks if ABI requires extra virtual offset for vtable field. + virtual bool + isVirtualOffsetNeededForVTableField(CodeGenFunction CGF, + const CXXRecordDecl *NearestVBase) = 0; + + /// Checks if ABI allows to initilize vptr for given class. + virtual bool canInitializeVPtr(const CXXRecordDecl *VTableClass, + const CXXRecordDecl *Base, + const CXXRecordDecl *NearestVBase) = 0; + In contrast, this does not need to be as general as it is, and making it this general is actively harmful; just pass the vtable class. Also, I suggest calling it doStructorsInitializeVTables. Comment at: lib/CodeGen/CGCXXABI.h:352 @@ +351,3 @@ + isVirtualOffsetNeededForVTableField(CodeGenFunction CGF, + const CXXRecordDecl *NearestVBase) = 0; + This method does not need to be passed a CodeGenFunction, but it should take a complete CodeGenFunction::VPtr, not just this one random field from it. Comment at: lib/CodeGen/CGClass.cpp:1862 @@ +1861,3 @@ + for (const VPtr vptr : getVTablePointers(ClassDecl)) +if (CGM.getCXXABI().canInitializeVPtr(vptr.VTableClass, vptr.Base.getBase(), + vptr.NearestVBase)) As mentioned elsewhere, you can skip this entire loop if doStructorsInitializeVTables returns false. Comment at: lib/CodeGen/CGClass.cpp:2157 @@ +2156,3 @@ +if (CGM.getCXXABI().canInitializeVPtr(Vptr.VTableClass, Vptr.Base.getBase(), + Vptr.NearestVBase)) + InitializeVTablePointer(Vptr); Please call doStructorsInitializeVTables for RD above the call to getVTablePointers and then just skip the rest of the function if it returns false. http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
majnemer added inline comments. Comment at: test/CodeGenCXX/vtable-assume-load.cpp:40 @@ +39,3 @@ +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABLE: } + This check line looks misspelled. http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
Prazek added inline comments. Comment at: lib/CodeGen/CGClass.cpp:1832 @@ +1831,3 @@ + // Generate vtable assumptions if we are calling dynamic class ctor + // and we are not in another ctor. + if (CGM.getCodeGenOpts().OptimizationLevel 0 hfinkel wrote: I think this comment should be a little more verbose. How about this: // Generate vtable assumptions if we are calling dynamic-class's ctor, except when doing so as part of a derived class's ctor's base-class initialization. Doing so in this latter case would be useless, because the vtable is about to be overwritten by the derived class's vtable. The main point of not calling this function, is because it is useless to have assumption loads inside constructor, when they are generated also outside of ctor. I guess You could have case when You are not overriding base vptr, and You are calling base ctor from dynamic class http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
Prazek marked 5 inline comments as done. Prazek added a comment. http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
Prazek updated this revision to Diff 32122. Prazek marked an inline comment as done. http://reviews.llvm.org/D11859 Files: lib/CodeGen/CGCXXABI.h lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/ItaniumCXXABI.cpp lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGen/available-externally-hidden.cpp test/CodeGenCXX/ctor-globalopt.cpp test/CodeGenCXX/template-instantiation.cpp test/CodeGenCXX/thunks.cpp test/CodeGenCXX/virtual-base-ctor.cpp test/CodeGenCXX/vtable-assume-load.cpp test/CodeGenCXX/vtable-available-externally.cpp Index: test/CodeGenCXX/vtable-available-externally.cpp === --- test/CodeGenCXX/vtable-available-externally.cpp +++ test/CodeGenCXX/vtable-available-externally.cpp @@ -182,8 +182,8 @@ namespace Test9 { // all virtual functions are outline, so we can assume that it will // be generated in translation unit where foo is defined -// CHECK-TEST9: @_ZTVN5Test91AE = available_externally unnamed_addr constant -// CHECK-TEST9: @_ZTVN5Test91BE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91AE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91BE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual void bar(); @@ -206,39 +206,39 @@ namespace Test10 { // because A's key function is defined here, vtable is generated in this TU -// CHECK-TEST10: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant struct A { virtual void foo(); virtual void bar(); }; void A::foo() {} // Because key function is inline we will generate vtable as linkonce_odr -// CHECK-TEST10: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; inline void D::bar() {} // because B has outline key function then we can refer to -// CHECK-TEST10: @_ZTVN6Test101BE = available_externally unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101BE = available_externally unnamed_addr constant struct B : A { void foo(); void bar(); }; // C's key function (car) is outline, but C has inline virtual function so we // can't guarantee that we will be able to refer to bar from name // so (at the moment) we can't emit vtable available_externally -// CHECK-TEST10: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant struct C : A { void bar() {} // defined in body - not key function virtual inline void gar(); // inline in body - not key function virtual void car(); }; // no key function, vtable will be generated everywhere it will be used -// CHECK-TEST10: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant struct E : A {}; void g(A a) { Index: test/CodeGenCXX/vtable-assume-load.cpp === --- /dev/null +++ test/CodeGenCXX/vtable-assume-load.cpp @@ -0,0 +1,173 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-optzns -fms-extensions +// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-optzns -fms-extensions + +// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s + +namespace test1 { + +struct A { + A(); + virtual void foo(); +}; + +struct B : A { + virtual void foo(); +}; + +void g(A *a) { a-foo(); } + +// CHECK1-LABEL: define void @_ZN5test14fooAEv() +// CHECK1: call void @_ZN5test11AC1Ev(%struct.test1::A* %a) +// CHECK1: %vtable = load i8**, i8*** %1 +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABEL: } + +void fooA() { + A a; + g(a); +} + +// CHECK1-LABEL: define void @_ZN5test14fooBEv() +// CHECK1: call void @_ZN5test11BC1Ev(%struct.test1::B* %b) +// CHECK1: %vtable = load i8**, i8*** %1 +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABLE: } + +void fooB() { + B b; + g(b); +} +// there should not be any assumes in the ctor that calls base ctor +// CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(%struct.test1::B* %this) +// CHECK1-NOT: @llvm.assume( +// CHECK1-LABEL: } +} +namespace test2 { +struct A { + A(); + virtual void foo(); +}; + +struct B { + B(); + virtual void bar(); +}; +
Re: [PATCH] D11859: Generating vptr assume loads
Prazek marked an inline comment as done. Comment at: lib/CodeGen/CGClass.cpp:1832 @@ +1831,3 @@ + // Generate vtable assumptions if we are calling dynamic class ctor + // and we are not in another ctor. + if (CGM.getCodeGenOpts().OptimizationLevel 0 rsmith wrote: Prazek wrote: hfinkel wrote: I think this comment should be a little more verbose. How about this: // Generate vtable assumptions if we are calling dynamic-class's ctor, except when doing so as part of a derived class's ctor's base-class initialization. Doing so in this latter case would be useless, because the vtable is about to be overwritten by the derived class's vtable. The main point of not calling this function, is because it is useless to have assumption loads inside constructor, when they are generated also outside of ctor. I guess You could have case when You are not overriding base vptr, and You are calling base ctor from dynamic class It might also be worth including in the comment that it is not correct to call `EmitVTableAssumptionLoads` here, because it assumes the object's vptr points to the complete object vtable; during a constructor call it will probably have a construction vtable instead. Well, it would be correct, but it would be useless. Just after calling base constructor, assume loads would appear, and after there would be new store to vptr. http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
Prazek updated this revision to Diff 31846. http://reviews.llvm.org/D11859 Files: lib/CodeGen/CGCXXABI.h lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/ItaniumCXXABI.cpp lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGen/available-externally-hidden.cpp test/CodeGenCXX/ctor-globalopt.cpp test/CodeGenCXX/template-instantiation.cpp test/CodeGenCXX/thunks.cpp test/CodeGenCXX/virtual-base-ctor.cpp test/CodeGenCXX/vtable-assume-load.cpp test/CodeGenCXX/vtable-available-externally.cpp Index: test/CodeGenCXX/vtable-available-externally.cpp === --- test/CodeGenCXX/vtable-available-externally.cpp +++ test/CodeGenCXX/vtable-available-externally.cpp @@ -182,8 +182,8 @@ namespace Test9 { // all virtual functions are outline, so we can assume that it will // be generated in translation unit where foo is defined -// CHECK-TEST9: @_ZTVN5Test91AE = available_externally unnamed_addr constant -// CHECK-TEST9: @_ZTVN5Test91BE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91AE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91BE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual void bar(); @@ -206,39 +206,39 @@ namespace Test10 { // because A's key function is defined here, vtable is generated in this TU -// CHECK-TEST10: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant struct A { virtual void foo(); virtual void bar(); }; void A::foo() {} // Because key function is inline we will generate vtable as linkonce_odr -// CHECK-TEST10: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; inline void D::bar() {} // because B has outline key function then we can refer to -// CHECK-TEST10: @_ZTVN6Test101BE = available_externally unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101BE = available_externally unnamed_addr constant struct B : A { void foo(); void bar(); }; // C's key function (car) is outline, but C has inline virtual function so we // can't guarantee that we will be able to refer to bar from name // so (at the moment) we can't emit vtable available_externally -// CHECK-TEST10: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant struct C : A { void bar() {} // defined in body - not key function virtual inline void gar(); // inline in body - not key function virtual void car(); }; // no key function, vtable will be generated everywhere it will be used -// CHECK-TEST10: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant struct E : A {}; void g(A a) { Index: test/CodeGenCXX/vtable-assume-load.cpp === --- /dev/null +++ test/CodeGenCXX/vtable-assume-load.cpp @@ -0,0 +1,170 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-optzns -fms-extensions +// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-optzns -fms-extensions + +// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s + +namespace test1 { + +struct A { + A(); + virtual void foo(); +}; + +struct B : A { + virtual void foo(); +}; + +void g(A *a) { a-foo(); } + +void fooA() { + A a; + g(a); +} +void fooB() { + B b; + g(b); +} +// CHECK1-LABEL: define void @_ZN5test14fooAEv() +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABEL: } + +// CHECK1-LABEL: define void @_ZN5test14fooBEv() +// CHECK1: call void @_ZN5test11BC1Ev(%struct.test1::B* %b) +// CHECK1: %vtable = load i8**, i8*** %1, !tbaa !5 +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABLE: } + +// there should not be any assumes in the ctor that calls base ctor +// CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(%struct.test1::B* %this) +// CHECK1-NOT: @llvm.assume( +// CHECK1-LABEL: } +} +namespace test2 { +struct A { + A(); + virtual void foo(); +}; + +struct B { + B(); + virtual void bar(); +}; + +struct C : A, B { + C(); + virtual void foo(); +}; +void g(A *a) { a-foo(); } +void h(B *b) { b-bar(); } + +// CHECK2-LABEL: define void
Re: [PATCH] D11859: Generating vptr assume loads
Prazek updated this revision to Diff 31768. http://reviews.llvm.org/D11859 Files: lib/CodeGen/CGCXXABI.h lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/ItaniumCXXABI.cpp lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGen/available-externally-hidden.cpp test/CodeGenCXX/ctor-globalopt.cpp test/CodeGenCXX/template-instantiation.cpp test/CodeGenCXX/thunks.cpp test/CodeGenCXX/virtual-base-ctor.cpp test/CodeGenCXX/vtable-assume-load.cpp test/CodeGenCXX/vtable-available-externally.cpp Index: test/CodeGenCXX/vtable-available-externally.cpp === --- test/CodeGenCXX/vtable-available-externally.cpp +++ test/CodeGenCXX/vtable-available-externally.cpp @@ -182,8 +182,8 @@ namespace Test9 { // all virtual functions are outline, so we can assume that it will // be generated in translation unit where foo is defined -// CHECK-TEST9: @_ZTVN5Test91AE = available_externally unnamed_addr constant -// CHECK-TEST9: @_ZTVN5Test91BE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91AE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91BE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual void bar(); @@ -206,39 +206,39 @@ namespace Test10 { // because A's key function is defined here, vtable is generated in this TU -// CHECK-TEST10: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant struct A { virtual void foo(); virtual void bar(); }; void A::foo() {} // Because key function is inline we will generate vtable as linkonce_odr -// CHECK-TEST10: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; inline void D::bar() {} // because B has outline key function then we can refer to -// CHECK-TEST10: @_ZTVN6Test101BE = available_externally unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101BE = available_externally unnamed_addr constant struct B : A { void foo(); void bar(); }; // C's key function (car) is outline, but C has inline virtual function so we // can't guarantee that we will be able to refer to bar from name // so (at the moment) we can't emit vtable available_externally -// CHECK-TEST10: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant struct C : A { void bar() {} // defined in body - not key function virtual inline void gar(); // inline in body - not key function virtual void car(); }; // no key function, vtable will be generated everywhere it will be used -// CHECK-TEST10: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant struct E : A {}; void g(A a) { Index: test/CodeGenCXX/vtable-assume-load.cpp === --- /dev/null +++ test/CodeGenCXX/vtable-assume-load.cpp @@ -0,0 +1,170 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-optzns -fms-extensions +// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-optzns -fms-extensions + +// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s + +namespace test1 { + +struct A { + A(); + virtual void foo(); +}; + +struct B : A { + virtual void foo(); +}; + +void g(A* a) { a-foo(); } + +void fooA() { + A a; + g(a); +} +void fooB() { + B b; + g(b); +} +// CHECK1-LABEL: define void @_ZN5test14fooAEv() +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABEL: } + +// CHECK1-LABEL: define void @_ZN5test14fooBEv() +// CHECK1: call void @_ZN5test11BC1Ev(%struct.test1::B* %b) +// CHECK1: %vtable = load i8**, i8*** %1, !tbaa !5 +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABLE: } + +// there should not be any assumes in the ctor that calls base ctor +// CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(%struct.test1::B* %this) +// CHECK1-NOT: @llvm.assume( +// CHECK1-LABEL: } +} +namespace test2 { +struct A { + A(); + virtual void foo(); +}; + +struct B { + B(); + virtual void bar(); +}; + +struct C : A, B { + C(); + virtual void foo(); +}; +void g(A* a) { a-foo(); } +void h(B* b) { b-bar(); } + +// CHECK2-LABEL: define void
Re: [PATCH] D11859: Generating vptr assume loads
nwilson added a subscriber: nwilson. Comment at: lib/CodeGen/CGClass.cpp:1862 @@ +1861,3 @@ +if (CGM.getCXXABI().canInitializeVPtr(vptr.VTableClass, vptr.Base.getBase(), + vptr.NearestVBase)) + EmitVTableAssumptionLoad(vptr, This); Looks like another formatting/tab issue here. Comment at: lib/CodeGen/CGClass.cpp:2155 @@ +2154,3 @@ +if (CGM.getCXXABI().canInitializeVPtr(Vptr.VTableClass, Vptr.Base.getBase(), + Vptr.NearestVBase)) + InitializeVTablePointer(Vptr); Looks like the same formatting/tab as above. This is what I've done when using clang-format, maybe it will fix the issues you've had: ./clang-format -style=llvm -lines=N:M FileToFormat tmp cp tmp FileToFormat (Just don't include the less than and greater around the FileToFormat.) http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
djasper added inline comments. Comment at: lib/CodeGen/CGClass.cpp:2155 @@ +2154,3 @@ +if (CGM.getCXXABI().canInitializeVPtr(Vptr.VTableClass, Vptr.Base.getBase(), + Vptr.NearestVBase)) + InitializeVTablePointer(Vptr); nwilson wrote: Looks like the same formatting/tab as above. This is what I've done when using clang-format, maybe it will fix the issues you've had: ./clang-format -style=llvm -lines=N:M FileToFormat tmp cp tmp FileToFormat (Just don't include the less than and greater around the FileToFormat.) You shouldn't need to do this by hand. There is clang-format-diff.py / git-clang-format for that. http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
nwilson added inline comments. Comment at: lib/CodeGen/CGClass.cpp:2155 @@ +2154,3 @@ +if (CGM.getCXXABI().canInitializeVPtr(Vptr.VTableClass, Vptr.Base.getBase(), + Vptr.NearestVBase)) + InitializeVTablePointer(Vptr); djasper wrote: nwilson wrote: Looks like the same formatting/tab as above. This is what I've done when using clang-format, maybe it will fix the issues you've had: ./clang-format -style=llvm -lines=N:M FileToFormat tmp cp tmp FileToFormat (Just don't include the less than and greater around the FileToFormat.) You shouldn't need to do this by hand. There is clang-format-diff.py / git-clang-format for that. Good to know. Thanks! http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
Prazek added inline comments. Comment at: lib/CodeGen/CodeGenFunction.h:1328-1334 @@ -1320,8 +1327,9 @@ typedef llvm::SmallPtrSetconst CXXRecordDecl *, 4 VisitedVirtualBasesSetTy; - void InitializeVTablePointers(BaseSubobject Base, -const CXXRecordDecl *NearestVBase, -CharUnits OffsetFromNearestVBase, -bool BaseIsNonVirtualPrimaryBase, -const CXXRecordDecl *VTableClass, -VisitedVirtualBasesSetTy VBases); + VPtrsVector getVTablePointers(const CXXRecordDecl *VTableClass); + + void getVTablePointers(BaseSubobject Base, const CXXRecordDecl *NearestVBase, + CharUnits OffsetFromNearestVBase, + bool BaseIsNonVirtualPrimaryBase, + const CXXRecordDecl *VTableClass, + VisitedVirtualBasesSetTy VBases, VPtrsVector vptrs); majnemer wrote: Would it make more sense for these to live in `CGClass` ? What do You mean? These functions are defined in CGClass.cpp Comment at: lib/CodeGen/MicrosoftCXXABI.cpp:223-228 @@ +222,8 @@ + // with the 'novtable' attribute. + bool canInitilizeVPtr(const CXXRecordDecl *VTableClass, +const CXXRecordDecl *Base, +const CXXRecordDecl *NearestVBase) override { +return !VTableClass-hasAttrMSNoVTableAttr() || + (Base != VTableClass Base != NearestVBase); + } + Prazek wrote: majnemer wrote: In the MS ABI, derived classes never share vtables with bases. Why do you need to do anything other than check that the most derived class doesn't have the `__declspec(novtable)` ? I don't know, I just took previous code assuming it is correct. ok, I see. I just took code that suposed to work with microsoft and itanium abi. You are right http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
Prazek updated this revision to Diff 31766. http://reviews.llvm.org/D11859 Files: lib/CodeGen/CGCXXABI.h lib/CodeGen/CGClass.cpp lib/CodeGen/CodeGenFunction.h lib/CodeGen/ItaniumCXXABI.cpp lib/CodeGen/MicrosoftCXXABI.cpp test/CodeGen/available-externally-hidden.cpp test/CodeGenCXX/ctor-globalopt.cpp test/CodeGenCXX/template-instantiation.cpp test/CodeGenCXX/thunks.cpp test/CodeGenCXX/virtual-base-ctor.cpp test/CodeGenCXX/vtable-assume-load.cpp test/CodeGenCXX/vtable-available-externally.cpp Index: test/CodeGenCXX/vtable-available-externally.cpp === --- test/CodeGenCXX/vtable-available-externally.cpp +++ test/CodeGenCXX/vtable-available-externally.cpp @@ -182,8 +182,8 @@ namespace Test9 { // all virtual functions are outline, so we can assume that it will // be generated in translation unit where foo is defined -// CHECK-TEST9: @_ZTVN5Test91AE = available_externally unnamed_addr constant -// CHECK-TEST9: @_ZTVN5Test91BE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91AE = available_externally unnamed_addr constant +// CHECK-TEST9-DAG: @_ZTVN5Test91BE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual void bar(); @@ -206,39 +206,39 @@ namespace Test10 { // because A's key function is defined here, vtable is generated in this TU -// CHECK-TEST10: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant struct A { virtual void foo(); virtual void bar(); }; void A::foo() {} // Because key function is inline we will generate vtable as linkonce_odr -// CHECK-TEST10: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; inline void D::bar() {} // because B has outline key function then we can refer to -// CHECK-TEST10: @_ZTVN6Test101BE = available_externally unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101BE = available_externally unnamed_addr constant struct B : A { void foo(); void bar(); }; // C's key function (car) is outline, but C has inline virtual function so we // can't guarantee that we will be able to refer to bar from name // so (at the moment) we can't emit vtable available_externally -// CHECK-TEST10: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101CE = external unnamed_addr constant struct C : A { void bar() {} // defined in body - not key function virtual inline void gar(); // inline in body - not key function virtual void car(); }; // no key function, vtable will be generated everywhere it will be used -// CHECK-TEST10: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-TEST10-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant struct E : A {}; void g(A a) { Index: test/CodeGenCXX/vtable-assume-load.cpp === --- /dev/null +++ test/CodeGenCXX/vtable-assume-load.cpp @@ -0,0 +1,170 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o %t.ll -O1 -disable-llvm-optzns -fms-extensions +// RUN: %clang_cc1 %s -triple i686-pc-win32 -emit-llvm -o %t.ms.ll -O1 -disable-llvm-optzns -fms-extensions + +// RUN: FileCheck --check-prefix=CHECK1 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK2 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK3 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK4 --input-file=%t.ll %s +// RUN: FileCheck --check-prefix=CHECK-MS --input-file=%t.ms.ll %s + +namespace test1 { + +struct A { + A(); + virtual void foo(); +}; + +struct B : A { + virtual void foo(); +}; + +void g(A* a) { a-foo(); } + +void fooA() { + A a; + g(a); +} +void fooB() { + B b; + g(b); +} +// CHECK1-LABEL: define void @_ZN5test14fooAEv() +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11AE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABEL: } + +// CHECK1-LABEL: define void @_ZN5test14fooBEv() +// CHECK1: call void @_ZN5test11BC1Ev(%struct.test1::B* %b) +// CHECK1: %vtable = load i8**, i8*** %1, !tbaa !5 +// CHECK1: %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTVN5test11BE, i64 0, i64 2) +// CHECK1: call void @llvm.assume(i1 %cmp.vtables) +// CHECK1-LABLE: } + +// there should not be any assumes in the ctor that calls base ctor +// CHECK1-LABEL: define linkonce_odr void @_ZN5test11BC2Ev(%struct.test1::B* %this) +// CHECK1-NOT: @llvm.assume( +// CHECK1-LABEL: } +} +namespace test2 { +struct A { + A(); + virtual void foo(); +}; + +struct B { + B(); + virtual void bar(); +}; + +struct C : A, B { + C(); + virtual void foo(); +}; +void g(A* a) { a-foo(); } +void h(B* b) { b-bar(); } + +// CHECK2-LABEL: define void
Re: [PATCH] D11859: Generating vptr assume loads
Prazek marked 9 inline comments as done. Prazek added a comment. http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
Re: [PATCH] D11859: Generating vptr assume loads
Prazek added inline comments. Comment at: lib/CodeGen/CGClass.cpp:1842 @@ +1841,3 @@ + CGM.getCXXABI().getVTableAddressPoint(vptr.Base, vptr.VTableClass); + if (!VTableGlobal) return; + djasper wrote: Prazek wrote: majnemer wrote: The return should be on it's own line, please clang-format this. Also, under which conditions is this case possible? Unfortunatelly clang-format puts short instructions in the same line Not, it doesn't. At least not if you properly configure LLVM style. So mb I am doing something wrong, but I am using git-clang-format and get things like this http://reviews.llvm.org/D11859 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits