Skip to content

Commit bfc2dac

Browse files
committed
[func-sig-opts] Split FunctionSignatureOpts.cpp into 3 files one for each of the operations it employs now.
This is one step along the way to splitting FSO into sub-transforms.
1 parent 30d4f45 commit bfc2dac

File tree

5 files changed

+505
-459
lines changed

5 files changed

+505
-459
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
//===--- ArgumentExplosionTransform.cpp -----------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#define DEBUG_TYPE "fso-argument-explosion-transform"
14+
#include "FunctionSignatureOpts.h"
15+
#include "llvm/Support/CommandLine.h"
16+
17+
using namespace swift;
18+
19+
static llvm::cl::opt<bool> FSODisableArgExplosion(
20+
"sil-fso-disable-arg-explosion",
21+
llvm::cl::desc("Do not perform argument explosion during FSO. Intended "
22+
"only for testing purposes"));
23+
24+
bool FunctionSignatureTransform::ArgumentExplosionAnalyzeParameters() {
25+
// If we are not supposed to perform argument explosion, bail.
26+
if (FSODisableArgExplosion)
27+
return false;
28+
29+
SILFunction *F = TransformDescriptor.OriginalFunction;
30+
// Did we decide we should optimize any parameter?
31+
bool SignatureOptimize = false;
32+
auto Args = F->begin()->getFunctionArguments();
33+
ConsumedArgToEpilogueReleaseMatcher ArgToReturnReleaseMap(
34+
RCIA->get(F), F, {SILArgumentConvention::Direct_Owned});
35+
36+
// Analyze the argument information.
37+
for (unsigned i : indices(Args)) {
38+
ArgumentDescriptor &A = TransformDescriptor.ArgumentDescList[i];
39+
// If the argument is dead, there is no point in trying to explode it. The
40+
// dead argument pass will get it.
41+
if (A.IsEntirelyDead) {
42+
continue;
43+
}
44+
45+
// Do not optimize argument.
46+
if (!A.canOptimizeLiveArg()) {
47+
continue;
48+
}
49+
50+
// Explosion of generic parameters is not supported yet.
51+
if (A.Arg->getType().hasArchetype())
52+
continue;
53+
54+
A.ProjTree.computeUsesAndLiveness(A.Arg);
55+
A.Explode = A.shouldExplode(ArgToReturnReleaseMap);
56+
57+
// Modified self argument.
58+
if (A.Explode && Args[i]->isSelf()) {
59+
TransformDescriptor.shouldModifySelfArgument = true;
60+
}
61+
62+
SignatureOptimize |= A.Explode;
63+
}
64+
return SignatureOptimize;
65+
}
66+
67+
void FunctionSignatureTransform::ArgumentExplosionFinalizeOptimizedFunction() {
68+
SILFunction *NewF = TransformDescriptor.OptimizedFunction.get();
69+
SILBasicBlock *BB = &*NewF->begin();
70+
SILBuilder Builder(BB->begin());
71+
Builder.setCurrentDebugScope(BB->getParent()->getDebugScope());
72+
unsigned TotalArgIndex = 0;
73+
for (ArgumentDescriptor &AD : TransformDescriptor.ArgumentDescList) {
74+
// If this argument descriptor was dead and we removed it, just skip it. Do
75+
// not increment the argument index.
76+
if (AD.WasErased) {
77+
continue;
78+
}
79+
80+
// Simply continue if do not explode.
81+
if (!AD.Explode) {
82+
TransformDescriptor.AIM[TotalArgIndex] = AD.Index;
83+
++TotalArgIndex;
84+
continue;
85+
}
86+
87+
assert(!AD.IsEntirelyDead &&
88+
"Should never see completely dead values here");
89+
90+
// OK, we need to explode this argument.
91+
unsigned ArgOffset = ++TotalArgIndex;
92+
unsigned OldArgIndex = ArgOffset - 1;
93+
llvm::SmallVector<SILValue, 8> LeafValues;
94+
95+
// We do this in the same order as leaf types since ProjTree expects that
96+
// the order of leaf values matches the order of leaf types.
97+
llvm::SmallVector<const ProjectionTreeNode *, 8> LeafNodes;
98+
AD.ProjTree.getLiveLeafNodes(LeafNodes);
99+
100+
for (auto *Node : LeafNodes) {
101+
auto OwnershipKind = *AD.getTransformedOwnershipKind(Node->getType());
102+
LeafValues.push_back(
103+
BB->insertFunctionArgument(ArgOffset, Node->getType(), OwnershipKind,
104+
BB->getArgument(OldArgIndex)->getDecl()));
105+
TransformDescriptor.AIM[TotalArgIndex - 1] = AD.Index;
106+
++ArgOffset;
107+
++TotalArgIndex;
108+
}
109+
110+
// Then go through the projection tree constructing aggregates and replacing
111+
// uses.
112+
AD.ProjTree.replaceValueUsesWithLeafUses(
113+
Builder, BB->getParent()->getLocation(), LeafValues);
114+
115+
// We ignored debugvalue uses when we constructed the new arguments, in
116+
// order to preserve as much information as possible, we construct a new
117+
// value for OrigArg from the leaf values and use that in place of the
118+
// OrigArg.
119+
SILValue NewOrigArgValue = AD.ProjTree.computeExplodedArgumentValue(
120+
Builder, BB->getParent()->getLocation(), LeafValues);
121+
122+
// Replace all uses of the original arg with the new value.
123+
SILArgument *OrigArg = BB->getArgument(OldArgIndex);
124+
OrigArg->replaceAllUsesWith(NewOrigArgValue);
125+
126+
// Now erase the old argument since it does not have any uses. We also
127+
// decrement ArgOffset since we have one less argument now.
128+
BB->eraseArgument(OldArgIndex);
129+
--TotalArgIndex;
130+
}
131+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
set(FUNCTIONSIGNATURETRANSFORMS_SOURCES
22
FunctionSignatureTransforms/FunctionSignatureOpts.cpp
3+
FunctionSignatureTransforms/DeadArgumentTransform.cpp
4+
FunctionSignatureTransforms/ArgumentExplosionTransform.cpp
5+
FunctionSignatureTransforms/OwnedToGuaranteedTransform.cpp
36
PARENT_SCOPE)
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//===--- DeadArgumentTransform.cpp ----------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#define DEBUG_TYPE "fso-dead-argument-transform"
14+
#include "FunctionSignatureOpts.h"
15+
#include "swift/SIL/DebugUtils.h"
16+
#include "llvm/Support/CommandLine.h"
17+
18+
using namespace swift;
19+
20+
static llvm::cl::opt<bool> FSODisableDeadArgument(
21+
"sil-fso-disable-dead-argument",
22+
llvm::cl::desc("Do not perform dead argument elimination during FSO. "
23+
"Intended only for testing purposes"));
24+
25+
bool FunctionSignatureTransform::DeadArgumentAnalyzeParameters() {
26+
if (FSODisableDeadArgument)
27+
return false;
28+
29+
// Did we decide we should optimize any parameter?
30+
SILFunction *F = TransformDescriptor.OriginalFunction;
31+
bool SignatureOptimize = false;
32+
auto Args = F->begin()->getFunctionArguments();
33+
auto OrigShouldModifySelfArgument =
34+
TransformDescriptor.shouldModifySelfArgument;
35+
// Analyze the argument information.
36+
for (unsigned i : indices(Args)) {
37+
ArgumentDescriptor &A = TransformDescriptor.ArgumentDescList[i];
38+
if (!A.PInfo.hasValue()) {
39+
// It is not an argument. It could be an indirect result.
40+
continue;
41+
}
42+
43+
if (!A.canOptimizeLiveArg()) {
44+
continue;
45+
}
46+
47+
// Check whether argument is dead.
48+
if (!hasNonTrivialNonDebugTransitiveUsers(Args[i])) {
49+
A.IsEntirelyDead = true;
50+
SignatureOptimize = true;
51+
if (Args[i]->isSelf())
52+
TransformDescriptor.shouldModifySelfArgument = true;
53+
}
54+
}
55+
56+
if (F->getLoweredFunctionType()->isPolymorphic()) {
57+
// If the set of dead arguments contains only type arguments,
58+
// don't remove them, because it would produce a slower code
59+
// for generic functions.
60+
bool HasNonTypeDeadArguments = false;
61+
for (auto &AD : TransformDescriptor.ArgumentDescList) {
62+
if (AD.IsEntirelyDead &&
63+
!isa<AnyMetatypeType>(AD.Arg->getType().getASTType())) {
64+
HasNonTypeDeadArguments = true;
65+
break;
66+
}
67+
}
68+
69+
if (!HasNonTypeDeadArguments) {
70+
for (auto &AD : TransformDescriptor.ArgumentDescList) {
71+
if (AD.IsEntirelyDead) {
72+
AD.IsEntirelyDead = false;
73+
break;
74+
}
75+
}
76+
TransformDescriptor.shouldModifySelfArgument =
77+
OrigShouldModifySelfArgument;
78+
SignatureOptimize = false;
79+
}
80+
}
81+
82+
return SignatureOptimize;
83+
}
84+
85+
void FunctionSignatureTransform::DeadArgumentTransformFunction() {
86+
SILFunction *F = TransformDescriptor.OriginalFunction;
87+
SILBasicBlock *BB = &*F->begin();
88+
for (const ArgumentDescriptor &AD : TransformDescriptor.ArgumentDescList) {
89+
if (!AD.IsEntirelyDead)
90+
continue;
91+
eraseUsesOfValue(BB->getArgument(AD.Index));
92+
}
93+
}
94+
95+
void FunctionSignatureTransform::DeadArgumentFinalizeOptimizedFunction() {
96+
auto *BB = &*TransformDescriptor.OptimizedFunction.get()->begin();
97+
// Remove any dead argument starting from the last argument to the first.
98+
for (ArgumentDescriptor &AD : reverse(TransformDescriptor.ArgumentDescList)) {
99+
if (!AD.IsEntirelyDead)
100+
continue;
101+
AD.WasErased = true;
102+
BB->eraseArgument(AD.Arg->getIndex());
103+
}
104+
}

0 commit comments

Comments
 (0)