Skip to content

Commit 70938b1

Browse files
committed
Add a stand-alone devirtualizer pass.
Add back a stand-alone devirtualizer pass, running prior to generic specialization. As with the stand-alone generic specializer pass, this may add functions to the pass manager's work list. This is another step in unbundling these passes from the performance inliner.
1 parent 4bb33dc commit 70938b1

File tree

9 files changed

+122
-20
lines changed

9 files changed

+122
-20
lines changed

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ PASS(DeadObjectElimination, "deadobject-elim",
7575
"Eliminate unused objects that do not have destructors with side effects")
7676
PASS(DefiniteInitialization, "definite-init",
7777
"Definite Initialization")
78+
PASS(Devirtualizer, "devirtualizer", "Devirtualize indirect calls")
7879
PASS(DiagnoseUnreachable, "diagnose-unreachable",
7980
"Diagnose Unreachable Code")
8081
PASS(DiagnosticConstantPropagation, "diagnostic-constant-propagation",

lib/SILOptimizer/PassManager/Passes.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ void swift::runSILOptimizationPasses(SILModule &Module) {
251251

252252
// Run two iterations of the high-level SSA passes.
253253
PM.setStageName("HighLevel");
254+
PM.addDevirtualizer();
254255
PM.addGenericSpecializer();
255256
AddSSAPasses(PM, OptimizationLevelKind::HighLevel);
256257
PM.runOneIteration();

lib/SILOptimizer/Transforms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set(TRANSFORMS_SOURCES
77
Transforms/DeadCodeElimination.cpp
88
Transforms/DeadObjectElimination.cpp
99
Transforms/DeadStoreElimination.cpp
10+
Transforms/Devirtualizer.cpp
1011
Transforms/GenericSpecializer.cpp
1112
Transforms/MergeCondFail.cpp
1213
Transforms/RedundantLoadElimination.cpp
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//===-------- Devirtualizer.cpp - Devirtualize indirect calls ------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See http://swift.org/LICENSE.txt for license information
9+
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// Devirtualize indirect calls to functions, turning them into direct function
14+
// references.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
#define DEBUG_TYPE "sil-devirtualizer"
19+
20+
#include "swift/SIL/SILFunction.h"
21+
#include "swift/SIL/SILInstruction.h"
22+
#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h"
23+
#include "swift/SILOptimizer/Utils/Devirtualize.h"
24+
#include "swift/SILOptimizer/PassManager/Transforms.h"
25+
#include "llvm/ADT/SmallVector.h"
26+
27+
using namespace swift;
28+
29+
namespace {
30+
31+
class Devirtualizer : public SILFunctionTransform {
32+
33+
bool devirtualizeAppliesInFunction(SILFunction &F,
34+
ClassHierarchyAnalysis *CHA);
35+
36+
/// The entry point to the transformation.
37+
void run() override {
38+
SILFunction &F = *getFunction();
39+
ClassHierarchyAnalysis *CHA = PM->getAnalysis<ClassHierarchyAnalysis>();
40+
DEBUG(llvm::dbgs() << "***** Devirtualizer on function:" << F.getName()
41+
<< " *****\n");
42+
43+
if (devirtualizeAppliesInFunction(F, CHA))
44+
invalidateAnalysis(SILAnalysis::InvalidationKind::FunctionBody);
45+
}
46+
47+
StringRef getName() override { return "Devirtualizer"; }
48+
};
49+
50+
} // end anonymous namespace
51+
52+
bool Devirtualizer::devirtualizeAppliesInFunction(SILFunction &F,
53+
ClassHierarchyAnalysis *CHA) {
54+
bool Changed = false;
55+
llvm::SmallVector<SILInstruction *, 8> DeadApplies;
56+
57+
for (auto &BB : F) {
58+
for (auto It = BB.begin(), End = BB.end(); It != End;) {
59+
auto &I = *It++;
60+
61+
// Skip non-apply instructions.
62+
63+
auto Apply = FullApplySite::isa(&I);
64+
if (!Apply)
65+
continue;
66+
67+
auto NewInstPair = tryDevirtualizeApply(Apply, CHA);
68+
if (!NewInstPair.second)
69+
continue;
70+
71+
Changed = true;
72+
73+
auto *CalleeFn = NewInstPair.second.getCalleeFunction();
74+
assert(CalleeFn && "Expected devirtualized callee!");
75+
76+
// We may not have optimized these functions yet, and it could
77+
// be beneficial to rerun some earlier passes on the current
78+
// function now that we've made these direct references visible.
79+
if (CalleeFn->isDefinition() && CalleeFn->shouldOptimize())
80+
notifyPassManagerOfFunction(CalleeFn);
81+
82+
auto *AI = Apply.getInstruction();
83+
if (!isa<TryApplyInst>(AI))
84+
AI->replaceAllUsesWith(NewInstPair.first);
85+
86+
DeadApplies.push_back(AI);
87+
}
88+
}
89+
90+
// Remove all the now-dead applies.
91+
while (!DeadApplies.empty()) {
92+
auto *AI = DeadApplies.pop_back_val();
93+
recursivelyDeleteTriviallyDeadInstructions(AI, true);
94+
}
95+
96+
return Changed;
97+
}
98+
99+
SILTransform *swift::createDevirtualizer() { return new Devirtualizer(); }

test/SILOptimizer/devirt_access.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -enable-sil-verify-all %s -inline | FileCheck %s
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -devirtualizer | FileCheck %s
22

33
sil_stage canonical
44

test/SILOptimizer/devirt_alloc_ref_dynamic.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -enable-sil-verify-all %s -sil-combine -inline -dce | FileCheck %s
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -sil-combine -devirtualizer -dce | FileCheck %s
22

33
sil_stage canonical
44

test/SILOptimizer/devirt_try_apply.sil

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -enable-sil-verify-all %s -sil-combine -inline -redundant-load-elim -inline | FileCheck %s --check-prefix=CHECK-INLINE
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -sil-combine -devirtualizer -redundant-load-elim -inline | FileCheck %s --check-prefix=CHECK-DEVIRT
22
// RUN: %target-sil-opt -enable-sil-verify-all %s -early-inline | FileCheck %s --check-prefix=CHECK-EARLY-INLINE
33
// RUN: %target-sil-opt -enable-sil-verify-all %s -specdevirt | FileCheck %s --check-prefix=CHECK-SPECDEVIRT
44
// RUN: %target-sil-opt -enable-sil-verify-all %s -mandatory-inlining | FileCheck %s --check-prefix=CHECK-MANDATORY-INLINING
@@ -615,10 +615,10 @@ bb0:
615615
// CHECK-SPECDEVIRT: checked_cast_br [exact]
616616
// CHECK-SPECDEVIRT: }
617617

618-
// CHECK-INLINE-LABEL: sil @_TF16devirt_try_apply5test4FT_Vs5Int32
619-
// CHECK-INLINE-NOT: checked_cast_br [exact]
620-
// CHECK-INLINE-NOT: class_method
621-
// CHECK-INLINE: }
618+
// CHECK-DEVIRT-LABEL: sil @_TF16devirt_try_apply5test4FT_Vs5Int32
619+
// CHECK-DEVIRT-NOT: checked_cast_br [exact]
620+
// CHECK-DEVIRT-NOT: class_method
621+
// CHECK-DEVIRT: }
622622

623623
// CHECK-EARLY-INLINE-LABEL: sil @_TF16devirt_try_apply5test4FT_Vs5Int32
624624
// CHECK-EARLY-INLINE-NOT: checked_cast_br [exact]
@@ -658,10 +658,10 @@ bb4(%19 : $ErrorType):
658658

659659
// DISABLE THIS TEST CASE FOR NOW. AS RLE GETS BETTER. WILL RE-ENABLE.
660660
//
661-
// DISABLECHECK-INLINE-LABEL: sil @_TF16devirt_try_apply5test5FT_Vs5Int32
662-
// DISABLECHECK-INLINE-NOT: = witness_method
663-
// DISABLECHECK-INLINE-NOT: = class_method
664-
// DISABLECHECK-INLINE: }
661+
// DISABLECHECK-DEVIRT-LABEL: sil @_TF16devirt_try_apply5test5FT_Vs5Int32
662+
// DISABLECHECK-DEVIRT-NOT: = witness_method
663+
// DISABLECHECK-DEVIRT-NOT: = class_method
664+
// DISABLECHECK-DEVIRT: }
665665
sil @_TF16devirt_try_apply5test5FT_Vs5Int32 : $@convention(thin) () -> Int32 {
666666
bb0:
667667
%0 = alloc_stack $Int32
@@ -705,9 +705,9 @@ bb4(%23 : $ErrorType):
705705
// CHECK-SPECDEVIRT: checked_cast_br [exact]
706706
// CHECK-SPECDEVIRT: }
707707

708-
// CHECK-INLINE-LABEL: sil @_TF16devirt_try_apply5test6FT_GSqVs5Int32_
709-
// CHECK-INLINE-NOT: class_method
710-
// CHECK-INLINE: }
708+
// CHECK-DEVIRT-LABEL: sil @_TF16devirt_try_apply5test6FT_GSqVs5Int32_
709+
// CHECK-DEVIRT-NOT: class_method
710+
// CHECK-DEVIRT: }
711711

712712
// CHECK-EARLY-INLINE-LABEL: sil @_TF16devirt_try_apply5test6FT_GSqVs5Int32_
713713
// CHECK-EARLY-INLINE-NOT: class_method
@@ -751,10 +751,10 @@ bb4(%20 : $ErrorType):
751751
// CHECK-SPECDEVIRT: checked_cast_br [exact]
752752
// CHECK-SPECDEVIRT: }
753753

754-
// CHECK-INLINE-LABEL: sil @_TF16devirt_try_apply5test7FT_Vs5Int32
755-
// CHECK-INLINE-NOT: checked_cast_br [exact]
756-
// CHECK-INLINE-NOT: class_method
757-
// CHECK-INLINE: }
754+
// CHECK-DEVIRT-LABEL: sil @_TF16devirt_try_apply5test7FT_Vs5Int32
755+
// CHECK-DEVIRT-NOT: checked_cast_br [exact]
756+
// CHECK-DEVIRT-NOT: class_method
757+
// CHECK-DEVIRT: }
758758

759759
// CHECK-EARLY-INLINE-LABEL: sil @_TF16devirt_try_apply5test7FT_Vs5Int32
760760
// CHECK-EARLY-INLINE-NOT: checked_cast_br [exact]

test/SILOptimizer/devirtualize.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -enable-sil-verify-all %s -inline -dce | FileCheck %s
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -devirtualizer -dce | FileCheck %s
22

33
sil_stage canonical
44

test/SILOptimizer/devirtualize2.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -enable-sil-verify-all %s -inline -dce | FileCheck %s
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -devirtualizer -dce | FileCheck %s
22

33
sil_stage canonical
44

0 commit comments

Comments
 (0)