Skip to content

Commit d729e6d

Browse files
committed
Resolve review comments
Change-Id: Icaebe5ea54b51d025602c1367b2eac7f4db1d71e
1 parent 77d16b2 commit d729e6d

File tree

3 files changed

+42
-52
lines changed

3 files changed

+42
-52
lines changed

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7837,28 +7837,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
78377837
// ThinLTO mode.
78387838
bool IsPS4 = getToolChain().getTriple().isPS4();
78397839

7840-
// Check if we passed LTO options but they were suppressed because this is a
7841-
// device offloading action, or we passed device offload LTO options which
7842-
// were suppressed because this is not the device offload action.
78437840
// Check if we are using PS4 in regular LTO mode.
78447841
// Otherwise, issue an error.
78457842

7846-
auto OtherLTOMode =
7847-
IsDeviceOffloadAction ? D.getLTOMode() : D.getOffloadLTOMode();
7848-
auto OtherIsUsingLTO = OtherLTOMode != LTOK_None;
7849-
7850-
if (!IsUsingLTO && !OtherIsUsingLTO && !UnifiedLTO) {
7851-
if (const Arg *A = Args.getLastArg(options::OPT_O_Group))
7852-
if (!A->getOption().matches(options::OPT_O0))
7853-
CmdArgs.push_back("-fwhole-program-vtables");
7854-
} else if ((!IsUsingLTO && !OtherIsUsingLTO) ||
7855-
(IsPS4 && !UnifiedLTO && (D.getLTOMode() != LTOK_Full)))
7843+
if (IsPS4 && !UnifiedLTO && (D.getLTOMode() != LTOK_Full))
78567844
D.Diag(diag::err_drv_argument_only_allowed_with)
78577845
<< "-fwhole-program-vtables"
78587846
<< ((IsPS4 && !UnifiedLTO) ? "-flto=full" : "-flto");
78597847

7860-
// Propagate -fwhole-program-vtables if this is an LTO compile.
7861-
if (IsUsingLTO)
7848+
// Propagate -fwhole-program-vtables if this is an LTO compile or at least
7849+
// optimization level is O1 so that the devirtualization be effective
7850+
// outside LTO.
7851+
if (const Arg *A = Args.getLastArg(options::OPT_O_Group);
7852+
(A && !A->getOption().matches(options::OPT_O0)) || IsUsingLTO)
78627853
CmdArgs.push_back("-fwhole-program-vtables");
78637854
}
78647855

llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,11 @@
5050
// - Import phase: (same as with hybrid case above).
5151
//
5252
// In non-LTO mode:
53-
// - The pass apply speculative devirtualization without requiring any type of
53+
// - The pass applies speculative devirtualization without requiring any type of
5454
// visibility.
5555
// - Skips other features like virtual constant propagation, uniform return
56-
// value
57-
// optimization, unique return value optimization, branch funnels to minimize
58-
// the drawbacks of wrong speculation.
56+
// value optimization, unique return value optimization, branch funnels as they
57+
// need LTO.
5958
//===----------------------------------------------------------------------===//
6059

6160
#include "llvm/Transforms/IPO/WholeProgramDevirt.h"
@@ -629,11 +628,13 @@ struct DevirtModule {
629628
std::map<CallInst *, unsigned> NumUnsafeUsesForTypeTest;
630629
PatternList FunctionsToSkip;
631630

631+
const bool InLTOMode;
632+
632633
DevirtModule(Module &M, function_ref<AAResults &(Function &)> AARGetter,
633634
function_ref<OptimizationRemarkEmitter &(Function *)> OREGetter,
634635
function_ref<DominatorTree &(Function &)> LookupDomTree,
635636
ModuleSummaryIndex *ExportSummary,
636-
const ModuleSummaryIndex *ImportSummary)
637+
const ModuleSummaryIndex *ImportSummary, bool InLTOMode)
637638
: M(M), AARGetter(AARGetter), LookupDomTree(LookupDomTree),
638639
ExportSummary(ExportSummary), ImportSummary(ImportSummary),
639640
Int8Ty(Type::getInt8Ty(M.getContext())),
@@ -642,7 +643,8 @@ struct DevirtModule {
642643
Int64Ty(Type::getInt64Ty(M.getContext())),
643644
IntPtrTy(M.getDataLayout().getIntPtrType(M.getContext(), 0)),
644645
Int8Arr0Ty(ArrayType::get(Type::getInt8Ty(M.getContext()), 0)),
645-
RemarksEnabled(areRemarksEnabled()), OREGetter(OREGetter) {
646+
RemarksEnabled(areRemarksEnabled()), OREGetter(OREGetter),
647+
InLTOMode(InLTOMode) {
646648
assert(!(ExportSummary && ImportSummary));
647649
FunctionsToSkip.init(SkipFunctionNames);
648650
}
@@ -759,7 +761,8 @@ struct DevirtModule {
759761
static bool
760762
runForTesting(Module &M, function_ref<AAResults &(Function &)> AARGetter,
761763
function_ref<OptimizationRemarkEmitter &(Function *)> OREGetter,
762-
function_ref<DominatorTree &(Function &)> LookupDomTree);
764+
function_ref<DominatorTree &(Function &)> LookupDomTree,
765+
bool InLTOMode);
763766
};
764767

765768
struct DevirtIndex {
@@ -815,7 +818,8 @@ PreservedAnalyses WholeProgramDevirtPass::run(Module &M,
815818
if (TestNoLTOMode)
816819
// we are outside LTO mode. enable speculative devirtualization:
817820
DevirtCheckMode = WPDCheckMode::Fallback;
818-
if (!DevirtModule::runForTesting(M, AARGetter, OREGetter, LookupDomTree))
821+
if (!DevirtModule::runForTesting(M, AARGetter, OREGetter, LookupDomTree,
822+
!TestNoLTOMode))
819823
return PreservedAnalyses::all();
820824
return PreservedAnalyses::none();
821825
}
@@ -828,14 +832,12 @@ PreservedAnalyses WholeProgramDevirtPass::run(Module &M,
828832
// build the ExportSummary from the module.
829833
assert(!ExportSummary &&
830834
"ExportSummary is expected to be empty in non-LTO mode");
831-
if (DevirtCheckMode == WPDCheckMode::Fallback && !ExportSummary) {
832-
ProfileSummaryInfo PSI(M);
833-
Index.emplace(buildModuleSummaryIndex(M, nullptr, &PSI));
834-
ExportSummary = Index.has_value() ? &Index.value() : nullptr;
835-
}
835+
ProfileSummaryInfo PSI(M);
836+
Index.emplace(buildModuleSummaryIndex(M, nullptr, &PSI));
837+
ExportSummary = Index.has_value() ? &Index.value() : nullptr;
836838
}
837839
if (!DevirtModule(M, AARGetter, OREGetter, LookupDomTree, ExportSummary,
838-
ImportSummary)
840+
ImportSummary, InLTOMode)
839841
.run())
840842
return PreservedAnalyses::all();
841843
return PreservedAnalyses::none();
@@ -1034,7 +1036,7 @@ static Error checkCombinedSummaryForTesting(ModuleSummaryIndex *Summary) {
10341036
bool DevirtModule::runForTesting(
10351037
Module &M, function_ref<AAResults &(Function &)> AARGetter,
10361038
function_ref<OptimizationRemarkEmitter &(Function *)> OREGetter,
1037-
function_ref<DominatorTree &(Function &)> LookupDomTree) {
1039+
function_ref<DominatorTree &(Function &)> LookupDomTree, bool InLTOMode) {
10381040
std::unique_ptr<ModuleSummaryIndex> Summary =
10391041
std::make_unique<ModuleSummaryIndex>(/*HaveGVs=*/false);
10401042

@@ -1063,7 +1065,8 @@ bool DevirtModule::runForTesting(
10631065
ClSummaryAction == PassSummaryAction::Export ? Summary.get()
10641066
: nullptr,
10651067
ClSummaryAction == PassSummaryAction::Import ? Summary.get()
1066-
: nullptr)
1068+
: nullptr,
1069+
InLTOMode)
10671070
.run();
10681071

10691072
if (!ClWriteSummary.empty()) {
@@ -1127,12 +1130,10 @@ bool DevirtModule::tryFindVirtualCallTargets(
11271130
if (!TM.Bits->GV->isConstant())
11281131
return false;
11291132

1130-
// If speculative devirtualization is NOT enabled, it's not safe to perform
1131-
// whole program devirtualization
1132-
// analysis on a vtable with public LTO visibility.
1133-
if (DevirtCheckMode != WPDCheckMode::Fallback &&
1134-
TM.Bits->GV->getVCallVisibility() ==
1135-
GlobalObject::VCallVisibilityPublic)
1133+
// In LTO mode, it's not safe to perform whole program devirtualization
1134+
// analysis on a vtable with public LTO visibility.
1135+
if (InLTOMode && TM.Bits->GV->getVCallVisibility() ==
1136+
GlobalObject::VCallVisibilityPublic)
11361137
return false;
11371138

11381139
Function *Fn = nullptr;
@@ -1150,10 +1151,10 @@ bool DevirtModule::tryFindVirtualCallTargets(
11501151
// calls to pure virtuals are UB.
11511152
if (Fn->getName() == "__cxa_pure_virtual")
11521153
continue;
1153-
// In Most cases empty functions will be overridden by the
1154+
// In most cases empty functions will be overridden by the
11541155
// implementation of the derived class, so we can skip them.
1155-
if (DevirtCheckMode == WPDCheckMode::Fallback &&
1156-
Fn->getReturnType()->isVoidTy() && Fn->getInstructionCount() <= 1)
1156+
if (!InLTOMode && Fn->getReturnType()->isVoidTy() &&
1157+
Fn->getInstructionCount() <= 1)
11571158
continue;
11581159

11591160
// We can disregard unreachable functions as possible call targets, as
@@ -1376,11 +1377,10 @@ bool DevirtModule::trySingleImplDevirt(
13761377
if (!IsExported)
13771378
return false;
13781379

1379-
// In case of non-speculative devirtualization, If the only implementation has
1380-
// local linkage, we must promote to external
1381-
// to make it visible to thin LTO objects. We can only get here during the
1382-
// ThinLTO export phase.
1383-
if (DevirtCheckMode != WPDCheckMode::Fallback && TheFn->hasLocalLinkage()) {
1380+
// In LTO mode, if the only implementation has local linkage, we must promote
1381+
// to external to make it visible to thin LTO objects. We can only get here
1382+
// during the ThinLTO export phase.
1383+
if (InLTOMode && TheFn->hasLocalLinkage()) {
13841384
std::string NewName = (TheFn->getName() + ".llvm.merged").str();
13851385

13861386
// Since we are renaming the function, any comdats with the same name must
@@ -2359,9 +2359,9 @@ bool DevirtModule::run() {
23592359

23602360
Function *TypeTestFunc =
23612361
Intrinsic::getDeclarationIfExists(&M, Intrinsic::type_test);
2362-
// If we are applying speculative devirtualization, we can work on the public
2362+
// If we are out of LTO mode, we can work on the public
23632363
// type test intrinsics.
2364-
if (!TypeTestFunc && DevirtCheckMode == WPDCheckMode::Fallback)
2364+
if (!TypeTestFunc && !InLTOMode)
23652365
TypeTestFunc =
23662366
Intrinsic::getDeclarationIfExists(&M, Intrinsic::public_type_test);
23672367
Function *TypeCheckedLoadFunc =
@@ -2488,10 +2488,9 @@ bool DevirtModule::run() {
24882488
S.first.ByteOffset, ExportSummary)) {
24892489
bool SingleImplDevirt =
24902490
trySingleImplDevirt(ExportSummary, TargetsForSlot, S.second, Res);
2491-
// In Speculative devirt mode, we skip virtual constant propagation
2492-
// and branch funneling to minimize the drawback if we got wrong
2493-
// speculation during devirtualization.
2494-
if (!SingleImplDevirt && DevirtCheckMode != WPDCheckMode::Fallback) {
2491+
// We apply virtual constant propagation and branch funneling only in LTO
2492+
// mode.
2493+
if (!SingleImplDevirt && InLTOMode) {
24952494
DidVirtualConstProp |=
24962495
tryVirtualConstProp(TargetsForSlot, S.second, Res, S.first);
24972496

llvm/test/Transforms/WholeProgramDevirt/devirt-single-impl-nolto.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ define i1 @vf(ptr %this) #0 !dbg !7 {
2222
ret i1 true
2323
}
2424

25-
; This should NOT be devietualized because during non-lto empty functions
25+
; This should NOT be devirtualized because during non-lto empty functions
2626
; are skipped.
2727
define void @vf_empty(ptr %this) !dbg !11 {
2828
ret void

0 commit comments

Comments
 (0)