[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables
This revision was automatically updated to reflect the committed changes. Prazek marked an inline comment as done. Closed by commit rC334600: Add -fforce-emit-vtables (authored by Prazek, committed by ). Changed prior to commit: https://reviews.llvm.org/D47108?vs=150735&id=151154#toc Repository: rC Clang https://reviews.llvm.org/D47108 Files: docs/ClangCommandLineReference.rst docs/ReleaseNotes.rst docs/UsersManual.rst include/clang/Basic/LangOptions.def include/clang/Driver/Options.td include/clang/Frontend/CodeGenOptions.def lib/CodeGen/ItaniumCXXABI.cpp lib/Driver/ToolChains/Clang.cpp lib/Frontend/CompilerInvocation.cpp lib/Sema/SemaDeclCXX.cpp test/CodeGenCXX/vtable-available-externally.cpp Index: docs/ClangCommandLineReference.rst === --- docs/ClangCommandLineReference.rst +++ docs/ClangCommandLineReference.rst @@ -1934,6 +1934,12 @@ Enables whole-program vtable optimization. Requires -flto +.. option:: -fforce-emit-vtables, -fno-force-emit-vtables + +In order to improve devirtualization, forces emitting of vtables even in +modules where it isn't necessary. It causes more inline virtual functions +to be emitted. + .. option:: -fwrapv, -fno-wrapv Treat signed integer overflow as two's complement Index: docs/UsersManual.rst === --- docs/UsersManual.rst +++ docs/UsersManual.rst @@ -1269,6 +1269,12 @@ devirtualization and virtual constant propagation, for classes with :doc:`hidden LTO visibility `. Requires ``-flto``. +.. option:: -fforce-emit-vtables + + In order to improve devirtualization, forces emitting of vtables even in + modules where it isn't necessary. It causes more inline virtual functions + to be emitted. + .. option:: -fno-assume-sane-operator-new Don't assume that the C++'s new operator is sane. Index: docs/ReleaseNotes.rst === --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -112,6 +112,12 @@ 'no-strict' option, Clang attempts to match the overflowing behavior of the target's native float-to-int conversion instructions. +- :option: `-fforce-emit-vtables` and `-fno-force-emit-vtables`. + + In order to improve devirtualization, forces emitting of vtables even in + modules where it isn't necessary. It causes more inline virtual functions + to be emitted. + - ... Deprecated Compiler Flags Index: include/clang/Basic/LangOptions.def === --- include/clang/Basic/LangOptions.def +++ include/clang/Basic/LangOptions.def @@ -293,6 +293,8 @@ "controls whether to always emit intrinsic calls to " "__xray_typedevent(...) builtin.") +LANGOPT(ForceEmitVTables, 1, 0, "whether to emit all vtables") + BENIGN_LANGOPT(AllowEditorPlaceholders, 1, 0, "allow editor placeholders in source") Index: include/clang/Frontend/CodeGenOptions.def === --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -332,6 +332,10 @@ /// Whether to embed source in DWARF debug line section. CODEGENOPT(EmbedSource, 1, 0) +/// Whether to emit all vtables +CODEGENOPT(ForceEmitVTables, 1, 0) + + #undef CODEGENOPT #undef ENUM_CODEGENOPT #undef VALUE_CODEGENOPT Index: include/clang/Driver/Options.td === --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1688,6 +1688,11 @@ HelpText<"Enables whole-program vtable optimization. Requires -flto">; def fno_whole_program_vtables : Flag<["-"], "fno-whole-program-vtables">, Group, Flags<[CoreOption]>; +def fforce_emit_vtables : Flag<["-"], "fforce-emit-vtables">, Group, +Flags<[CC1Option]>, +HelpText<"Emits more virtual tables to improve devirtualization">; +def fno_force_emit_vtables : Flag<["-"], "fno-force-emit-vtables">, Group, + Flags<[CoreOption]>; def fwrapv : Flag<["-"], "fwrapv">, Group, Flags<[CC1Option]>, HelpText<"Treat signed integer overflow as two's complement">; def fwritable_strings : Flag<["-"], "fwritable-strings">, Group, Flags<[CC1Option]>, Index: test/CodeGenCXX/vtable-available-externally.cpp === --- test/CodeGenCXX/vtable-available-externally.cpp +++ test/CodeGenCXX/vtable-available-externally.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables -fstrict-vtable-pointers -mconstructor-aliases // RUN: FileCheck --check-pref
[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables
rsmith accepted this revision. rsmith added a comment. LGTM with one change. Comment at: clang/include/clang/Basic/LangOptions.def:292 +BENIGN_LANGOPT(ForceEmitVTables, 1, 0, + "whether to emit all vtables") I don't think this is benign or even compatible: if we compile a PCH with this turned off, and then try to emit code using that PCH, we can miscompile due to having not marked the contents of a vtable as used. Please change this from `BENIGN_LANGOPT` to just `LANGOPT`. Repository: rL LLVM https://reviews.llvm.org/D47108 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables
Prazek updated this revision to Diff 150735. Prazek added a comment. - Fixed templates Repository: rL LLVM https://reviews.llvm.org/D47108 Files: clang/docs/ClangCommandLineReference.rst clang/docs/ReleaseNotes.rst clang/docs/UsersManual.rst clang/include/clang/Basic/LangOptions.def clang/include/clang/Driver/Options.td clang/include/clang/Frontend/CodeGenOptions.def clang/lib/CodeGen/ItaniumCXXABI.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/test/CodeGenCXX/vtable-available-externally.cpp Index: clang/test/CodeGenCXX/vtable-available-externally.cpp === --- clang/test/CodeGenCXX/vtable-available-externally.cpp +++ clang/test/CodeGenCXX/vtable-available-externally.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables -fstrict-vtable-pointers -mconstructor-aliases // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t @@ -13,10 +14,13 @@ // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable + #include // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant namespace Test1 { struct A { @@ -213,14 +217,16 @@ // because A's key function is defined here, vtable is generated in this TU // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-FORCE-EMIT-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-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; @@ -237,14 +243,17 @@ // 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-DAG: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally 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-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant + struct E : A {}; void g(A& a) { @@ -298,11 +307,13 @@ namespace Test12 { // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual ~A() {} }; // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant struct B : A { void foo(); }; @@ -319,6 +330,9 @@ // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant + struct A { virtual ~A(); }; @@ -371,6 +385,8 @@ // generate available_externally vtable for it. // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally struct S { __attribute__((visibility("hidden"))) virtual void doStuff(); @@ -395,6 +411,10 @@ // This test checks if we emit vtables opportunistically. // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD2Ev( +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev( struct A { virtual void key(); @@ -418,3 +43
[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables
rsmith accepted this revision. rsmith added a comment. I would like to see a test that virtual function definitions are properly emitted for classes instantiated from templates (and in particular, that this triggers instantiation of such virtual member functions so they can be emitted). Other than that, this looks good to me. Repository: rL LLVM https://reviews.llvm.org/D47108 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables
amharc accepted this revision. amharc added a comment. This revision is now accepted and ready to land. Looks good to me. Obviously, you should wait for someone more competent than me to accept it, too. Repository: rL LLVM https://reviews.llvm.org/D47108 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables
Prazek updated this revision to Diff 148839. Prazek marked an inline comment as done. Prazek added a comment. fixed test Repository: rL LLVM https://reviews.llvm.org/D47108 Files: clang/docs/ClangCommandLineReference.rst clang/docs/ReleaseNotes.rst clang/docs/UsersManual.rst clang/include/clang/Basic/LangOptions.def clang/include/clang/Driver/Options.td clang/include/clang/Frontend/CodeGenOptions.def clang/lib/CodeGen/ItaniumCXXABI.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/test/CodeGenCXX/vtable-available-externally.cpp Index: clang/test/CodeGenCXX/vtable-available-externally.cpp === --- clang/test/CodeGenCXX/vtable-available-externally.cpp +++ clang/test/CodeGenCXX/vtable-available-externally.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables -fstrict-vtable-pointers -mconstructor-aliases // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t @@ -13,10 +14,13 @@ // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable + #include // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant namespace Test1 { struct A { @@ -213,14 +217,16 @@ // because A's key function is defined here, vtable is generated in this TU // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-FORCE-EMIT-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-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; @@ -237,14 +243,17 @@ // 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-DAG: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally 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-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant + struct E : A {}; void g(A& a) { @@ -298,11 +307,13 @@ namespace Test12 { // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual ~A() {} }; // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant struct B : A { void foo(); }; @@ -319,6 +330,9 @@ // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant + struct A { virtual ~A(); }; @@ -371,6 +385,8 @@ // generate available_externally vtable for it. // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally struct S { __attribute__((visibility("hidden"))) virtual void doStuff(); @@ -395,6 +411,10 @@ // This test checks if we emit vtables opportunistically. // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD2Ev( +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev( struct A {
[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables
amharc requested changes to this revision. amharc added inline comments. This revision now requires changes to proceed. Comment at: clang/test/CodeGenCXX/vtable-available-externally.cpp:445 +// after the Derived construction. +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test187DerivedE = linkonce_odr unnamed_addr constant {{.*}} @_ZTIN6Test187DerivedE {{.*}} @_ZN6Test184Base3funEv {{.*}} @_ZN6Test187DerivedD1Ev {{.*}} @_ZN6Test187DerivedD0Ev +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test187DerivedD0Ev This still uses `_ZN6Test187DerivedD1Ev` instead of `_ZN6Test184BaseD2Ev`, because the triple you selected is `x86_64-apple-darwin10` and `-mconstructor-aliases` is off by default on Darwin. I suggest you either add `-mconstructor-aliases` to the compiler invocation or change the triple to literally everything else than Darwin (or CUDA). Preferably the former, as it shows clearly what we want to test here. Repository: rL LLVM https://reviews.llvm.org/D47108 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables
Prazek updated this revision to Diff 148764. Prazek added a comment. small update Repository: rL LLVM https://reviews.llvm.org/D47108 Files: clang/docs/ClangCommandLineReference.rst clang/docs/ReleaseNotes.rst clang/docs/UsersManual.rst clang/include/clang/Basic/LangOptions.def clang/include/clang/Driver/Options.td clang/include/clang/Frontend/CodeGenOptions.def clang/lib/CodeGen/ItaniumCXXABI.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/test/CodeGenCXX/vtable-available-externally.cpp Index: clang/test/CodeGenCXX/vtable-available-externally.cpp === --- clang/test/CodeGenCXX/vtable-available-externally.cpp +++ clang/test/CodeGenCXX/vtable-available-externally.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables -fstrict-vtable-pointers // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t @@ -13,10 +14,13 @@ // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable + #include // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant namespace Test1 { struct A { @@ -213,14 +217,16 @@ // because A's key function is defined here, vtable is generated in this TU // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-FORCE-EMIT-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-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; @@ -237,14 +243,17 @@ // 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-DAG: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally 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-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant + struct E : A {}; void g(A& a) { @@ -298,11 +307,13 @@ namespace Test12 { // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual ~A() {} }; // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant struct B : A { void foo(); }; @@ -319,6 +330,9 @@ // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant + struct A { virtual ~A(); }; @@ -371,6 +385,8 @@ // generate available_externally vtable for it. // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally struct S { __attribute__((visibility("hidden"))) virtual void doStuff(); @@ -395,6 +411,10 @@ // This test checks if we emit vtables opportunistically. // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD1Ev( +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev( struct A { virtual void key(); @@ -418,3 +438,27 @@ } } // namespac
[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables
Prazek updated this revision to Diff 148762. Prazek added a comment. Fixed missing vtable commponents Repository: rL LLVM https://reviews.llvm.org/D47108 Files: clang/docs/ClangCommandLineReference.rst clang/docs/ReleaseNotes.rst clang/docs/UsersManual.rst clang/include/clang/Basic/LangOptions.def clang/include/clang/Driver/Options.td clang/include/clang/Frontend/CodeGenOptions.def clang/lib/CodeGen/ItaniumCXXABI.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/lib/Sema/SemaDeclCXX.cpp clang/test/CodeGenCXX/vtable-available-externally.cpp Index: clang/test/CodeGenCXX/vtable-available-externally.cpp === --- clang/test/CodeGenCXX/vtable-available-externally.cpp +++ clang/test/CodeGenCXX/vtable-available-externally.cpp @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -emit-llvm -o %t // RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.opt +// RUN: %clang_cc1 %s -I%S -triple=x86_64-apple-darwin10 -std=c++98 -O2 -disable-llvm-passes -emit-llvm -o %t.vtable -fforce-emit-vtables -fstrict-vtable-pointers // RUN: FileCheck --check-prefix=CHECK-TEST1 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST2 %s < %t // RUN: FileCheck --check-prefix=CHECK-TEST5 %s < %t @@ -13,10 +14,13 @@ // RUN: FileCheck --check-prefix=CHECK-TEST15 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST16 %s < %t.opt // RUN: FileCheck --check-prefix=CHECK-TEST17 %s < %t.opt +// RUN: FileCheck --check-prefix=CHECK-FORCE-EMIT %s < %t.vtable + #include // CHECK-TEST1: @_ZTVN5Test11AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN5Test11AE = available_externally unnamed_addr constant namespace Test1 { struct A { @@ -213,14 +217,16 @@ // because A's key function is defined here, vtable is generated in this TU // CHECK-TEST10-DAG: @_ZTVN6Test101AE = unnamed_addr constant +// CHECK-FORCE-EMIT-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-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101DE = linkonce_odr unnamed_addr constant struct D : A { void bar(); }; @@ -237,14 +243,17 @@ // 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-DAG: @_ZTVN6Test101CE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101CE = available_externally 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-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test101EE = linkonce_odr unnamed_addr constant + struct E : A {}; void g(A& a) { @@ -298,11 +307,13 @@ namespace Test12 { // CHECK-TEST12: @_ZTVN6Test121AE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121AE = available_externally unnamed_addr constant struct A { virtual void foo(); virtual ~A() {} }; // CHECK-TEST12: @_ZTVN6Test121BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test121BE = available_externally unnamed_addr constant struct B : A { void foo(); }; @@ -319,6 +330,9 @@ // CHECK-TEST13-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant // CHECK-TEST13-DAG: @_ZTVN6Test131BE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131AE = available_externally unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test131BE = available_externally unnamed_addr constant + struct A { virtual ~A(); }; @@ -371,6 +385,8 @@ // generate available_externally vtable for it. // CHECK-TEST16-DAG: @_ZTVN6Test161SE = external unnamed_addr constant // CHECK-TEST16-DAG: @_ZTVN6Test162S2E = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test161SE = external unnamed_addr constant +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test162S2E = available_externally struct S { __attribute__((visibility("hidden"))) virtual void doStuff(); @@ -395,6 +411,10 @@ // This test checks if we emit vtables opportunistically. // CHECK-TEST17-DAG: @_ZTVN6Test171AE = available_externally // CHECK-TEST17-DAG: @_ZTVN6Test171BE = external +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171AE = available_externally +// CHECK-FORCE-EMIT-DAG: @_ZTVN6Test171BE = available_externally +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD1Ev( +// CHECK-FORCE-EMIT-DAG: define linkonce_odr void @_ZN6Test171BD0Ev( struct A { virtual void key(); @@ -418,3 +438,27 @@
[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables
rjmccall added a comment. In https://reviews.llvm.org/D47108#1109145, @Prazek wrote: > In https://reviews.llvm.org/D47108#1109014, @rjmccall wrote: > > > I thought we already had places in Sema that marked inline virtual methods > > as used, instantiated templates, etc. for devirtualization purposes when > > optimization was enabled. Did we rip that out? > > > I only recall the emitting available_externally vtables opportunistically, > that is emitting it only if all the inline virtual functions are present (and > they are not hidden). > (https://reviews.llvm.org/D33437) > > > The problem we've had over and over with devirtualization is that we have > > to emit a perfect v-table because LLVM lacks a lot of the key vocabulary > > for talking about incomplete information. For example, if something weird > > happens and we don't have a definition for an inline virtual method, > > ideally we'd just say "well, you can't devirtualize this slot", then try to > > fix that as incremental progress; but instead we have to get everything > > just right or else disable the whole optimization. Note that vague-linkage > > v-tables mean that we'd also need to be able to say things like "there is > > an object with a definition that looks like this, but its symbol is not > > available and you can't emit it yourself". > > That is correcty, my intention was that this flag would cause all inline > virtual functions to be emitted. Can you give a hint how to achieve this in > the sane way? Well, this paragraph was really a call for extending LLVM IR, which might be outside a reasonable scope for your summer project. Building a v-table should itself cause inline functions to be emitted in IRGen as long as they've been properly marked for instantiation and use by Sema. I don't know the right place to ensure that that happens. Repository: rL LLVM https://reviews.llvm.org/D47108 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables
Prazek added a comment. In https://reviews.llvm.org/D47108#1109014, @rjmccall wrote: > I thought we already had places in Sema that marked inline virtual methods as > used, instantiated templates, etc. for devirtualization purposes when > optimization was enabled. Did we rip that out? I only recall the emitting available_externally vtables opportunistically, that is emitting it only if all the inline virtual functions are present (and they are not hidden). (https://reviews.llvm.org/D33437) > The problem we've had over and over with devirtualization is that we have to > emit a perfect v-table because LLVM lacks a lot of the key vocabulary for > talking about incomplete information. For example, if something weird > happens and we don't have a definition for an inline virtual method, ideally > we'd just say "well, you can't devirtualize this slot", then try to fix that > as incremental progress; but instead we have to get everything just right or > else disable the whole optimization. Note that vague-linkage v-tables mean > that we'd also need to be able to say things like "there is an object with a > definition that looks like this, but its symbol is not available and you > can't emit it yourself". That is correcty, my intention was that this flag would cause all inline virtual functions to be emitted. Can you give a hint how to achieve this in the sane way? Repository: rL LLVM https://reviews.llvm.org/D47108 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables
rjmccall added a comment. I thought we already had places in Sema that marked inline virtual methods as used, instantiated templates, etc. for devirtualization purposes when optimization was enabled. Did we rip that out? The problem we've had over and over with devirtualization is that we have to emit a perfect v-table because LLVM lacks a lot of the key vocabulary for talking about incomplete information. For example, if something weird happens and we don't have a definition for an inline virtual method, ideally we'd just say "well, you can't devirtualize this slot", then try to fix that as incremental progress; but instead we have to get everything just right or else disable the whole optimization. Note that vague-linkage v-tables mean that we'd also need to be able to say things like "there is an object with a definition that looks like this, but its symbol is not available and you can't emit it yourself". Repository: rL LLVM https://reviews.llvm.org/D47108 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D47108: [CodeGenCXX] Add -fforce-emit-vtables
Prazek added a comment. @rjmccall do you have any thoughts on the best way to solve it? Repository: rL LLVM https://reviews.llvm.org/D47108 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits