Skip to content

[SILOptimizer] Alter FSO arg explosion heuristic. #27239

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
41 changes: 32 additions & 9 deletions include/swift/SIL/Projection.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@
#ifndef SWIFT_SIL_PROJECTION_H
#define SWIFT_SIL_PROJECTION_H

#include "swift/AST/TypeAlignments.h"
#include "swift/Basic/NullablePtr.h"
#include "swift/Basic/PointerIntEnum.h"
#include "swift/AST/TypeAlignments.h"
#include "swift/SIL/SILValue.h"
#include "swift/Basic/STLExtras.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILValue.h"
#include "swift/SILOptimizer/Analysis/ARCAnalysis.h"
#include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h"
#include "llvm/ADT/Hashing.h"
Expand Down Expand Up @@ -751,15 +752,17 @@ class ProjectionTreeNode {
~ProjectionTreeNode() = default;
ProjectionTreeNode(const ProjectionTreeNode &) = default;

llvm::ArrayRef<unsigned> getChildProjections() {
return llvm::makeArrayRef(ChildProjections);
bool isLeaf() const { return ChildProjections.empty(); }

ArrayRef<unsigned> getChildProjections() const {
return llvm::makeArrayRef(ChildProjections);
}

llvm::Optional<Projection> &getProjection() { return Proj; }
Optional<Projection> &getProjection() { return Proj; }

llvm::SmallVector<Operand *, 4> getNonProjUsers() const {
return NonProjUsers;
};
const ArrayRef<Operand *> getNonProjUsers() const {
return llvm::makeArrayRef(NonProjUsers);
}

SILType getType() const { return NodeType; }

Expand Down Expand Up @@ -914,6 +917,24 @@ class ProjectionTree {
return false;
}

void getAllLeafTypes(llvm::SmallVectorImpl<SILType> &outArray) const {
llvm::SmallVector<const ProjectionTreeNode *, 32> worklist;
worklist.push_back(getRoot());

while (!worklist.empty()) {
auto *node = worklist.pop_back_val();
// If we have a leaf node, add its type.
if (node->isLeaf()) {
outArray.push_back(node->getType());
continue;
}

// Otherwise, add the nodes children to the worklist.
transform(node->getChildProjections(), std::back_inserter(worklist),
[&](unsigned idx) { return getNode(idx); });
}
}

void getLiveLeafTypes(llvm::SmallVectorImpl<SILType> &OutArray) const {
for (unsigned LeafIndex : LiveLeafIndices) {
const ProjectionTreeNode *Node = getNode(LeafIndex);
Expand All @@ -940,7 +961,9 @@ class ProjectionTree {
void
replaceValueUsesWithLeafUses(SILBuilder &B, SILLocation Loc,
llvm::SmallVectorImpl<SILValue> &Leafs);


void getUsers(SmallPtrSetImpl<SILInstruction *> &users) const;

private:
void createRoot(SILType BaseTy) {
assert(ProjectionTreeNodes.empty() &&
Expand Down
11 changes: 11 additions & 0 deletions include/swift/SILOptimizer/Analysis/ARCAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,17 @@ class ConsumedArgToEpilogueReleaseMatcher {
return completeList.getValue();
}

Optional<ArrayRef<SILInstruction *>>
getPartiallyPostDomReleaseSet(SILArgument *arg) const {
auto iter = ArgInstMap.find(arg);
if (iter == ArgInstMap.end())
return None;
auto partialList = iter->second.getPartiallyPostDomReleases();
if (!partialList)
return None;
return partialList;
}

ArrayRef<SILInstruction *> getReleasesForArgument(SILValue value) const {
auto *arg = dyn_cast<SILArgument>(value);
if (!arg)
Expand Down
7 changes: 6 additions & 1 deletion include/swift/SILOptimizer/Analysis/CallerAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,10 @@ class CallerAnalysis::FunctionInfo {
/// visibility of a protocol conformance or class.
bool mayHaveIndirectCallers : 1;

/// Whether the function is sufficiently visible to be called by a different
/// module.
bool mayHaveExternalCallers : 1;

public:
FunctionInfo(SILFunction *f);

Expand All @@ -289,7 +293,8 @@ class CallerAnalysis::FunctionInfo {
/// function (e.g. a specialized function) without needing to introduce a
/// thunk since we can rewrite all of the callers to call the new function.
bool foundAllCallers() const {
return hasOnlyCompleteDirectCallerSets() && !mayHaveIndirectCallers;
return hasOnlyCompleteDirectCallerSets() && !mayHaveIndirectCallers &&
!mayHaveExternalCallers;
}

/// Returns true if this function has at least one direct caller.
Expand Down
8 changes: 8 additions & 0 deletions lib/SIL/Projection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1514,3 +1514,11 @@ replaceValueUsesWithLeafUses(SILBuilder &Builder, SILLocation Loc,
NewNodes.clear();
}
}

void ProjectionTree::getUsers(SmallPtrSetImpl<SILInstruction *> &users) const {
for (auto *node : ProjectionTreeNodes) {
for (auto *op : node->getNonProjUsers()) {
users.insert(op->getUser());
}
}
}
4 changes: 3 additions & 1 deletion lib/SILOptimizer/Analysis/CallerAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ CallerAnalysis::FunctionInfo::FunctionInfo(SILFunction *f)
// TODO: Make this more aggressive by considering
// final/visibility/etc.
mayHaveIndirectCallers(f->getDynamicallyReplacedFunction() ||
canBeCalledIndirectly(f->getRepresentation())) {}
canBeCalledIndirectly(f->getRepresentation())),
mayHaveExternalCallers(f->isPossiblyUsedExternally() ||
f->isAvailableExternally()) {}

//===----------------------------------------------------------------------===//
// CallerAnalysis::ApplySiteFinderVisitor
Expand Down
Loading