-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[LTO][WPD] Suppress WPD on a class if the LTO unit doesn't have the prevailing definition of this class or any of its superclass #131721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
40f913c
Propagate ExportDynamic from base type to compatible derived types in
mingmingl-llvm 6be4464
implement the fix for hybrid LTO, and update test cases
mingmingl-llvm dfe5970
Look at the Prevailing bit as opposed to ExportDynamic bit, update
mingmingl-llvm 27b1e88
add test coverage for regular LTO
mingmingl-llvm f12edd1
resolve comments
mingmingl-llvm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,158 @@ | ||
| ; RUN: rm -rf %t && mkdir %t && cd %t | ||
|
|
||
| ; Tests that devirtualization is suppressed on a class when the LTO unit doesn't | ||
| ; have the prevailing definition of the base class. | ||
|
|
||
| ; Generate unsplit module with summary for ThinLTO index-based WPD. | ||
| ; RUN: opt -thinlto-bc -o summary.o %s | ||
|
|
||
| ; Index based WPD | ||
| ; The callsite inside @_ZN4Base8dispatchEv gets devirtualized when symbol | ||
| ; resolution shows there is a prevailing definition of `_ZTI7Derived` in the | ||
| ; LTO unit. | ||
| ; RUN: llvm-lto2 run summary.o -save-temps -pass-remarks=. \ | ||
| ; RUN: -thinlto-threads=1 \ | ||
| ; RUN: -o tmp \ | ||
| ; RUN: --whole-program-visibility-enabled-in-lto=true \ | ||
| ; RUN: --validate-all-vtables-have-type-infos=true \ | ||
| ; RUN: --all-vtables-have-type-infos=true \ | ||
| ; RUN: -r=summary.o,_ZN4Base8dispatchEv,px \ | ||
| ; RUN: -r=summary.o,_ZN8DerivedN5printEv,px \ | ||
| ; RUN: -r=summary.o,_ZTV8DerivedN,p \ | ||
| ; RUN: -r=summary.o,_ZTI8DerivedN,p \ | ||
| ; RUN: -r=summary.o,_ZTS8DerivedN,p \ | ||
| ; RUN: -r=summary.o,_ZTI7Derived,p \ | ||
| ; RUN: 2>&1 | FileCheck --allow-empty %s --check-prefix=REMARK | ||
|
|
||
|
|
||
| ; Index based WPD | ||
| ; The callsite inside @_ZN4Base8dispatchEv remains indirect and not de-virtualized | ||
| ; when symbol resolution shows there isn't a prevailing definition of | ||
| ; `_ZTI7Derived` in the LTO unit. | ||
| ; RUN: llvm-lto2 run summary.o -save-temps -pass-remarks=. \ | ||
| ; RUN: -thinlto-threads=1 \ | ||
| ; RUN: -o tmp \ | ||
| ; RUN: --whole-program-visibility-enabled-in-lto=true \ | ||
| ; RUN: --validate-all-vtables-have-type-infos=true \ | ||
| ; RUN: --all-vtables-have-type-infos=true \ | ||
| ; RUN: -r=summary.o,_ZN4Base8dispatchEv,px \ | ||
| ; RUN: -r=summary.o,_ZN8DerivedN5printEv,px \ | ||
| ; RUN: -r=summary.o,_ZTV8DerivedN,p \ | ||
| ; RUN: -r=summary.o,_ZTI8DerivedN,p \ | ||
| ; RUN: -r=summary.o,_ZTS8DerivedN,p \ | ||
| ; RUN: -r=summary.o,_ZTI7Derived, \ | ||
| ; RUN: 2>&1 | FileCheck %s --allow-empty --implicit-check-not='single-impl: devirtualized a call to' | ||
|
|
||
| ; Repeat the above tests for WPD in hybrid LTO. | ||
| ; RUN: opt --thinlto-bc --thinlto-split-lto-unit -o hybrid.o %s | ||
|
|
||
| ; RUN: llvm-lto2 run hybrid.o -save-temps -pass-remarks=. \ | ||
| ; RUN: -thinlto-threads=1 \ | ||
| ; RUN: -o hybrid-tmp \ | ||
| ; RUN: --whole-program-visibility-enabled-in-lto=true \ | ||
| ; RUN: --validate-all-vtables-have-type-infos=true \ | ||
| ; RUN: --all-vtables-have-type-infos=true \ | ||
| ; RUN: -r=hybrid.o,_ZN4Base8dispatchEv,px \ | ||
| ; RUN: -r=hybrid.o,_ZN8DerivedN5printEv,px \ | ||
| ; RUN: -r=hybrid.o,_ZTV8DerivedN, \ | ||
| ; RUN: -r=hybrid.o,_ZTI8DerivedN, \ | ||
| ; RUN: -r=hybrid.o,_ZTS8DerivedN,p \ | ||
| ; RUN: -r=hybrid.o,_ZTI7Derived,p \ | ||
| ; RUN: -r=hybrid.o,_ZN8DerivedN5printEv, \ | ||
| ; RUN: -r=hybrid.o,_ZTV8DerivedN,p \ | ||
| ; RUN: -r=hybrid.o,_ZTI8DerivedN,p \ | ||
| ; RUN: 2>&1 | FileCheck --allow-empty %s --check-prefix=REMARK | ||
|
|
||
|
|
||
| ; RUN: llvm-lto2 run hybrid.o -save-temps -pass-remarks=. \ | ||
| ; RUN: -thinlto-threads=1 \ | ||
| ; RUN: -o hybrid-tmp \ | ||
| ; RUN: --whole-program-visibility-enabled-in-lto=true \ | ||
| ; RUN: --validate-all-vtables-have-type-infos=true \ | ||
| ; RUN: --all-vtables-have-type-infos=true \ | ||
| ; RUN: -r=hybrid.o,_ZN4Base8dispatchEv,px \ | ||
| ; RUN: -r=hybrid.o,_ZN8DerivedN5printEv,px \ | ||
| ; RUN: -r=hybrid.o,_ZTV8DerivedN, \ | ||
| ; RUN: -r=hybrid.o,_ZTI8DerivedN, \ | ||
| ; RUN: -r=hybrid.o,_ZTS8DerivedN,p \ | ||
| ; RUN: -r=hybrid.o,_ZTI7Derived, \ | ||
| ; RUN: -r=hybrid.o,_ZN8DerivedN5printEv, \ | ||
| ; RUN: -r=hybrid.o,_ZTV8DerivedN,p \ | ||
| ; RUN: -r=hybrid.o,_ZTI8DerivedN,p \ | ||
| ; RUN: 2>&1 | FileCheck --allow-empty %s --implicit-check-not='single-impl: devirtualized a call to' | ||
|
|
||
|
|
||
| ; Repeat the above tests for WPD in regular LTO. | ||
| ; RUN: opt -module-summary -o regular.o %s | ||
|
|
||
| ; RUN: llvm-lto2 run regular.o -save-temps -pass-remarks=. \ | ||
| ; RUN: -thinlto-threads=1 \ | ||
| ; RUN: -o regular-temp \ | ||
| ; RUN: --whole-program-visibility-enabled-in-lto=true \ | ||
| ; RUN: --validate-all-vtables-have-type-infos=true \ | ||
| ; RUN: --all-vtables-have-type-infos=true \ | ||
| ; RUN: -r=regular.o,_ZN4Base8dispatchEv,px \ | ||
| ; RUN: -r=regular.o,_ZN8DerivedN5printEv,px \ | ||
| ; RUN: -r=regular.o,_ZTS8DerivedN,p \ | ||
| ; RUN: -r=regular.o,_ZTI7Derived,p \ | ||
| ; RUN: -r=regular.o,_ZTV8DerivedN,p \ | ||
| ; RUN: -r=regular.o,_ZTI8DerivedN,p \ | ||
| ; RUN: 2>&1 | FileCheck --allow-empty %s --check-prefix=REMARK | ||
|
|
||
| ; RUN: llvm-lto2 run regular.o -save-temps -pass-remarks=. \ | ||
| ; RUN: -thinlto-threads=1 \ | ||
| ; RUN: -o regular-temp \ | ||
| ; RUN: --whole-program-visibility-enabled-in-lto=true \ | ||
| ; RUN: --validate-all-vtables-have-type-infos=true \ | ||
| ; RUN: --all-vtables-have-type-infos=true \ | ||
| ; RUN: -r=regular.o,_ZN4Base8dispatchEv,px \ | ||
| ; RUN: -r=regular.o,_ZN8DerivedN5printEv,px \ | ||
| ; RUN: -r=regular.o,_ZTS8DerivedN,p \ | ||
| ; RUN: -r=regular.o,_ZTI7Derived, \ | ||
| ; RUN: -r=regular.o,_ZTV8DerivedN,p \ | ||
| ; RUN: -r=regular.o,_ZTI8DerivedN,p \ | ||
| ; RUN: 2>&1 | FileCheck --allow-empty %s --implicit-check-not='single-impl: devirtualized a call to' | ||
|
|
||
| ; REMARK: single-impl: devirtualized a call to _ZN8DerivedN5printEv | ||
|
|
||
| target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" | ||
| target triple = "x86_64-unknown-linux-gnu" | ||
|
|
||
| @_ZTV8DerivedN = linkonce_odr hidden constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr @_ZTI8DerivedN, ptr @_ZN8DerivedN5printEv] }, !type !0, !type !1, !type !2, !type !3, !vcall_visibility !4 | ||
| @_ZTI8DerivedN = linkonce_odr hidden constant { ptr, ptr, ptr } { ptr null, ptr @_ZTS8DerivedN, ptr @_ZTI7Derived } | ||
| @_ZTS8DerivedN = linkonce_odr hidden constant [10 x i8] c"8DerivedN\00", align 1 | ||
| @_ZTI7Derived = external constant ptr | ||
|
|
||
| ; Whole program devirtualization will ignore summaries that are not live. | ||
| ; Mark '_ZTV8DerivedN' as used so it remains live. | ||
| @llvm.used = appending global [1 x ptr] [ptr @_ZTV8DerivedN], section "llvm.metadata" | ||
|
|
||
| define hidden void @_ZN4Base8dispatchEv(ptr %this) { | ||
| entry: | ||
| %this.addr = alloca ptr | ||
| store ptr %this, ptr %this.addr | ||
| %this1 = load ptr, ptr %this.addr | ||
| %vtable = load ptr, ptr %this1 | ||
| %0 = call i1 @llvm.type.test(ptr %vtable, metadata !"_ZTS7Derived") | ||
| call void @llvm.assume(i1 %0) | ||
| %vfn = getelementptr inbounds ptr, ptr %vtable, i64 0 | ||
| %1 = load ptr, ptr %vfn | ||
| call void %1(ptr %this1) | ||
| ret void | ||
| } | ||
|
|
||
| define linkonce_odr hidden void @_ZN8DerivedN5printEv(ptr %this) #0 { | ||
| entry: | ||
| ret void | ||
| } | ||
|
|
||
| attributes #0 = { noinline optnone } | ||
|
|
||
| declare i1 @llvm.type.test(ptr, metadata) | ||
| declare void @llvm.assume(i1) | ||
|
|
||
| !0 = !{i64 16, !"_ZTS7Derived"} | ||
| !1 = !{i64 16, !"_ZTSM7DerivedFvvE.virtual"} | ||
| !2 = !{i64 16, !"_ZTS8DerivedN"} | ||
| !3 = !{i64 16, !"_ZTSM8DerivedNFvvE.virtual"} | ||
| !4 = !{i64 0} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -187,6 +187,18 @@ static cl::opt<bool> EnableFreestanding( | |
| cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"), | ||
| cl::Hidden); | ||
|
|
||
| static cl::opt<bool> WholeProgramVisibilityEnabledInLTO( | ||
| "whole-program-visibility-enabled-in-lto", | ||
| cl::desc("Enable whole program visibility during LTO"), cl::Hidden); | ||
|
|
||
| static cl::opt<bool> ValidateAllVtablesHaveTypeInfos( | ||
| "validate-all-vtables-have-type-infos", | ||
| cl::desc("Validate that all vtables have type infos in LTO"), cl::Hidden); | ||
|
|
||
| static cl::opt<bool> | ||
| AllVtablesHaveTypeInfos("all-vtables-have-type-infos", cl::Hidden, | ||
| cl::desc("All vtables have type infos")); | ||
|
|
||
| extern cl::opt<cl::boolOrDefault> LoadBitcodeIntoNewDbgInfoFormat; | ||
| extern cl::opt<cl::boolOrDefault> PreserveInputDbgFormat; | ||
|
|
||
|
|
@@ -332,6 +344,13 @@ static int run(int argc, char **argv) { | |
| Conf.PTO.LoopVectorization = Conf.OptLevel > 1; | ||
| Conf.PTO.SLPVectorization = Conf.OptLevel > 1; | ||
|
|
||
| if (WholeProgramVisibilityEnabledInLTO.getNumOccurrences() > 0) | ||
| Conf.HasWholeProgramVisibility = WholeProgramVisibilityEnabledInLTO; | ||
| if (ValidateAllVtablesHaveTypeInfos.getNumOccurrences() > 0) | ||
| Conf.ValidateAllVtablesHaveTypeInfos = ValidateAllVtablesHaveTypeInfos; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think either of these are needed for the test as ValidateAllVtablesHaveTypeInfos defaults to false, meaning we don't do this validation, and AllVtablesHaveTypeInfos is only checked if ValidateAllVtablesHaveTypeInfos is true. |
||
| if (AllVtablesHaveTypeInfos.getNumOccurrences() > 0) | ||
| Conf.AllVtablesHaveTypeInfos = AllVtablesHaveTypeInfos; | ||
|
|
||
| ThinBackend Backend; | ||
| if (ThinLTODistributedIndexes) | ||
| Backend = createWriteIndexesThinBackend(llvm::hardware_concurrency(Threads), | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the test can just use the existing
-whole-program-visibilityflag (defined in WholeProgramDevirt.cpp) which is OR'ed with this config value, instead of adding a new llvm-lto2 flag.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I spent some time looking into reusing
-whole-program-visibilityflag before introducing new options inllvm-lto2, but-whole-program-visibilityitself doesn't initialize theVisibleToRegularObjSymbolsset, which are used to skip vtable visibility upgrade.Basically, the condition (
llvm-project/llvm/lib/LTO/LTO.cpp
Lines 1901 to 1902 in d0d33d2
WholeProgramVisibilityEnabledInLTOandConf.ValidateAllVtablesHaveTypeInfosto getDenseSet<GlobalValue::GUID> VisibleToRegularObjSymbols, andWholeProgramVisibilityEnabledInLTOvalue is based on configuration value (llvm-project/llvm/lib/LTO/LTO.cpp
Lines 1889 to 1893 in d0d33d2
I tried to use
-whole-program-visibility[1] flag in the secondllvm-lto2RUN command (which is expected to see no devirtualization), and the test failed..[1]