Skip to content

Commit

Permalink
Merge pull request swiftlang#29472 from eeckstein/delete-dead-wt
Browse files Browse the repository at this point in the history
DeadFunctionElimination: remove externally available witness tables at the end of the pipeline
  • Loading branch information
eeckstein authored Jan 27, 2020
2 parents e3b511d + 03b0a6c commit e8b00a1
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 10 deletions.
2 changes: 2 additions & 0 deletions include/swift/SILOptimizer/PassManager/Passes.def
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ PASS(LICM, "licm",
"Loop Invariant Code Motion")
PASS(LateCodeMotion, "late-codemotion",
"Late Code Motion with Release Hoisting")
PASS(LateDeadFunctionElimination, "late-deadfuncelim",
"Late Dead Function Elimination")
PASS(LateInliner, "late-inline",
"Late Function Inlining")
PASS(LoopCanonicalizer, "loop-canonicalizer",
Expand Down
33 changes: 27 additions & 6 deletions lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ class FunctionLivenessComputation {

llvm::SmallPtrSet<void *, 32> AliveFunctionsAndTables;

bool keepExternalWitnessTablesAlive;

/// Checks is a function is alive, e.g. because it is visible externally.
bool isAnchorFunction(SILFunction *F) {

Expand Down Expand Up @@ -148,6 +150,11 @@ class FunctionLivenessComputation {
/// Marks all contained functions and witness tables of a witness table as
/// alive.
void makeAlive(SILWitnessTable *WT) {
if (isAvailableExternally(WT->getLinkage()) &&
!keepExternalWitnessTablesAlive) {
return;
}

LLVM_DEBUG(llvm::dbgs() << " scan witness table " << WT->getName()
<< '\n');

Expand Down Expand Up @@ -393,8 +400,10 @@ class FunctionLivenessComputation {
}

public:
FunctionLivenessComputation(SILModule *module) :
Module(module) {}
FunctionLivenessComputation(SILModule *module,
bool keepExternalWitnessTablesAlive) :
Module(module),
keepExternalWitnessTablesAlive(keepExternalWitnessTablesAlive) {}

/// The main entry point of the optimization.
bool findAliveFunctions() {
Expand Down Expand Up @@ -635,8 +644,8 @@ class DeadFunctionElimination : FunctionLivenessComputation {
}

public:
DeadFunctionElimination(SILModule *module)
: FunctionLivenessComputation(module) {}
DeadFunctionElimination(SILModule *module, bool keepExternalWitnessTablesAlive)
: FunctionLivenessComputation(module, keepExternalWitnessTablesAlive) {}

/// The main entry point of the optimization.
void eliminateFunctions(SILModuleTransform *DFEPass) {
Expand Down Expand Up @@ -693,6 +702,13 @@ class DeadFunctionElimination : FunctionLivenessComputation {
namespace {

class SILDeadFuncElimination : public SILModuleTransform {

private:
bool isLateDFE;

public:
SILDeadFuncElimination(bool isLateDFE) : isLateDFE(isLateDFE) { }

void run() override {
LLVM_DEBUG(llvm::dbgs() << "Running DeadFuncElimination\n");

Expand All @@ -703,15 +719,20 @@ class SILDeadFuncElimination : public SILModuleTransform {
// can eliminate such functions.
getModule()->invalidateSILLoaderCaches();

DeadFunctionElimination deadFunctionElimination(getModule());
DeadFunctionElimination deadFunctionElimination(getModule(),
/*keepExternalWitnessTablesAlive*/ !isLateDFE);
deadFunctionElimination.eliminateFunctions(this);
}
};

} // end anonymous namespace

SILTransform *swift::createDeadFunctionElimination() {
return new SILDeadFuncElimination();
return new SILDeadFuncElimination(/*isLateDFE*/ false);
}

SILTransform *swift::createLateDeadFunctionElimination() {
return new SILDeadFuncElimination(/*isLateDFE*/ true);
}

void swift::performSILDeadFunctionElimination(SILModule *M) {
Expand Down
4 changes: 3 additions & 1 deletion lib/SILOptimizer/PassManager/PassPipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,9 @@ static void addLateLoopOptPassPipeline(SILPassPipelinePlan &P) {
P.startPipeline("LateLoopOpt");

// Delete dead code and drop the bodies of shared functions.
P.addDeadFunctionElimination();
// Also, remove externally available witness tables. They are not needed
// anymore after the last devirtualizer run.
P.addLateDeadFunctionElimination();

// Perform the final lowering transformations.
P.addCodeSinking();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -sil-inline-threshold 0 %S/Inputs/init_existential_inst_deserializes_witness_tables_input.swift -o %t/Swift.swiftmodule -emit-module -parse-as-library -parse-stdlib -module-link-name swiftCore -module-name Swift -O
// RUN: %target-swift-frontend -I %t -O %s -emit-sil -o - | %FileCheck %s
// RUN: %target-swift-frontend -I %t -O %s -Xllvm -sil-disable-pass=late-deadfuncelim -emit-sil -o - | %FileCheck %s

// CHECK: sil_witness_table public_external X: P module Swift {

Expand Down
2 changes: 1 addition & 1 deletion test/SILOptimizer/devirt_opaque_witness.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/opaque_conformance.swiftmodule -primary-file %S/Inputs/opaque_conformance.swift
// RUN: %target-swift-frontend -O -emit-sil -primary-file %s -I %t | %FileCheck %s
// RUN: %target-swift-frontend -O -emit-sil -primary-file %s -I %t -Xllvm -sil-disable-pass=late-deadfuncelim | %FileCheck %s

import opaque_conformance

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module %S/Inputs/sil_witness_tables_external_input.swift -o %t/Swift.swiftmodule -parse-stdlib -parse-as-library -module-name Swift -module-link-name swiftCore
// RUN: %target-swift-frontend -O -I %t %s -emit-sil | %FileCheck %s
// RUN: %target-swift-frontend -O -I %t %s -Xllvm -sil-disable-pass=late-deadfuncelim -emit-sil | %FileCheck %s
// RUN: %target-swift-frontend -O -I %t %s -emit-sil | %FileCheck -check-prefix=CHECK-DFE %s

import Swift

// Make sure the specializer produces an external witness table.
//
// CHECK: sil_witness_table public_external X: P module Swift {

// Also check that late dead-function-elimination is removing externally
// available witness tables.
//
// CHECK-DFE-NOT: sil_witness_table public_external

func doSomething<T : P>(_ t : T) -> Y {
return t.doSomething()
}
Expand Down

0 comments on commit e8b00a1

Please sign in to comment.