mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Mostly functionally neutral: - may fix latent bugs. - may reduce useless basic blocks after inlining. This rewrite encapsulates the cloner's internal state, providing a clean API for the CRTP subclasses. The subclasses are rewritten to use the exposed API and extension points. This makes it much easier to understand, work with, and extend SIL cloners, which are central to many optimization passes. Basic SIL invariants are now clearly expressed and enforced. There is no longer a intricate dance between multiple levels of subclasses operating on underlying low-level data structures. All of the logic needed to keep the original SIL in a consistent state is contained within the SILCloner itself. Subclasses only need to be responsible for their own modifications. The immediate motiviation is to make CFG updates self-contained so that SIL remains in a valid state. This will allow the removal of critical edge splitting hacks and will allow general SIL utilities to take advantage of the fact that we don't allow critical edges. This rewrite establishes a simple principal that should be followed everywhere: aside from the primitive mutation APIs on SIL data types, each SIL utility is responsibile for leaving SIL in a valid state and the logic for doing so should exist in one central location. This includes, for example: - Generating a valid CFG, splitting edges if needed. - Returning a valid instruction iterator if any instructions are removed. - Updating dominance. - Updating SSA (block arguments). (Dominance info and SSA properties are fundamental to SIL verification). LoopInfo is also somewhat fundamental to SIL, and should generally be updated, but it isn't required. This also fixes some latent bugs related to iterator invalidation in recursivelyDeleteTriviallyDeadInstructions and SILInliner. Note that the SILModule deletion callback should be avoided. It can be useful as a simple cache invalidation mechanism, but it is otherwise bug prone, too limited to be very useful, and basically bad design. Utilities that mutate should return a valid instruction iterator and provide their own deletion callbacks.
114 lines
4.1 KiB
C++
114 lines
4.1 KiB
C++
//===--- GenericCloner.h - Specializes generic functions -------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This contains the definition of a cloner class for creating specialized
|
|
// versions of generic functions by substituting concrete types.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_SIL_GENERICCLONER_H
|
|
#define SWIFT_SIL_GENERICCLONER_H
|
|
|
|
#include "swift/AST/Type.h"
|
|
#include "swift/SIL/SILFunction.h"
|
|
#include "swift/SIL/SILInstruction.h"
|
|
#include "swift/SIL/TypeSubstCloner.h"
|
|
#include "swift/SILOptimizer/Utils/Local.h"
|
|
#include "swift/SILOptimizer/Utils/Generics.h"
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include <functional>
|
|
|
|
namespace swift {
|
|
|
|
class GenericCloner
|
|
: public TypeSubstCloner<GenericCloner, SILOptFunctionBuilder> {
|
|
using SuperTy = TypeSubstCloner<GenericCloner, SILOptFunctionBuilder>;
|
|
|
|
SILOptFunctionBuilder &FuncBuilder;
|
|
IsSerialized_t Serialized;
|
|
const ReabstractionInfo &ReInfo;
|
|
CloneCollector::CallbackType Callback;
|
|
llvm::SmallDenseMap<const SILDebugScope *, const SILDebugScope *, 8>
|
|
RemappedScopeCache;
|
|
|
|
llvm::SmallVector<AllocStackInst *, 8> AllocStacks;
|
|
AllocStackInst *ReturnValueAddr = nullptr;
|
|
|
|
public:
|
|
friend class SILCloner<GenericCloner>;
|
|
|
|
GenericCloner(SILOptFunctionBuilder &FuncBuilder,
|
|
SILFunction *F,
|
|
IsSerialized_t Serialized,
|
|
const ReabstractionInfo &ReInfo,
|
|
SubstitutionMap ParamSubs,
|
|
StringRef NewName,
|
|
CloneCollector::CallbackType Callback)
|
|
: SuperTy(*initCloned(FuncBuilder, F, Serialized, ReInfo, NewName), *F,
|
|
ParamSubs), FuncBuilder(FuncBuilder), ReInfo(ReInfo), Callback(Callback) {
|
|
assert(F->getDebugScope()->Parent != getCloned()->getDebugScope()->Parent);
|
|
}
|
|
/// Clone and remap the types in \p F according to the substitution
|
|
/// list in \p Subs. Parameters are re-abstracted (changed from indirect to
|
|
/// direct) according to \p ReInfo.
|
|
static SILFunction *
|
|
cloneFunction(SILOptFunctionBuilder &FuncBuilder,
|
|
SILFunction *F,
|
|
IsSerialized_t Serialized,
|
|
const ReabstractionInfo &ReInfo,
|
|
SubstitutionMap ParamSubs,
|
|
StringRef NewName,
|
|
CloneCollector::CallbackType Callback =nullptr) {
|
|
// Clone and specialize the function.
|
|
GenericCloner SC(FuncBuilder, F, Serialized, ReInfo, ParamSubs,
|
|
NewName, Callback);
|
|
SC.populateCloned();
|
|
return SC.getCloned();
|
|
}
|
|
|
|
protected:
|
|
void visitTerminator(SILBasicBlock *BB);
|
|
|
|
// FIXME: We intentionally call SILClonerWithScopes here to ensure
|
|
// the debug scopes are set correctly for cloned
|
|
// functions. TypeSubstCloner, SILClonerWithScopes, and
|
|
// SILCloner desperately need refactoring and/or combining so
|
|
// that the obviously right things are happening for cloning
|
|
// vs. inlining.
|
|
void postProcess(SILInstruction *Orig, SILInstruction *Cloned) {
|
|
// Call client-supplied callback function.
|
|
if (Callback)
|
|
Callback(Orig, Cloned);
|
|
|
|
SILClonerWithScopes<GenericCloner>::postProcess(Orig, Cloned);
|
|
}
|
|
|
|
private:
|
|
static SILFunction *initCloned(SILOptFunctionBuilder &FuncBuilder,
|
|
SILFunction *Orig,
|
|
IsSerialized_t Serialized,
|
|
const ReabstractionInfo &ReInfo,
|
|
StringRef NewName);
|
|
/// Clone the body of the function into the empty function that was created
|
|
/// by initCloned.
|
|
void populateCloned();
|
|
SILFunction *getCloned() { return &getBuilder().getFunction(); }
|
|
|
|
const SILDebugScope *remapScope(const SILDebugScope *DS);
|
|
|
|
};
|
|
|
|
} // end namespace swift
|
|
|
|
#endif
|