[SILOptimizer] Generalize optimization of static keypaths

We have an optimization in SILCombiner that "inlines" the use of compile-time constant key paths by performing the property access directly instead of calling a runtime function (leading to huge performance gains e.g. for heavy use of @dynamicMemberLookup). However, this optimization previously only supported key paths which solely access stored properties, so computed properties, optional chaining, etc. still had to call a runtime function. This commit generalizes the optimization to support all types of key paths.
This commit is contained in:
Jonathan Keller
2019-12-15 13:57:42 -08:00
parent 9f09add09b
commit 44d211fa17
5 changed files with 1033 additions and 112 deletions

View File

@@ -0,0 +1,81 @@
//===-- KeyPathProjector.h - Project a static key path ----------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2019 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Utility class to project a statically known key path
/// expression to a direct property access sequence.
///
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SILOPTIMIZER_UTILS_KEYPATHPROJECTOR_H
#define SWIFT_SILOPTIMIZER_UTILS_KEYPATHPROJECTOR_H
#include "swift/SIL/SILBuilder.h"
#include <memory>
namespace swift {
/// Projects a statically known key path expression to
/// a direct property access.
class KeyPathProjector {
public:
/// The type of a key path access.
enum class AccessType {
/// A get-only access (i.e. swift_getAtKeyPath).
Get,
/// A set-only access (i.e. swift_setAtWritableKeyPath).
Set,
/// A modification (i.e. swift_modifyAtWritableKeyPath).
Modify
};
/// Creates a key path projector for a key path.
///
/// Returns nullptr if \p keyPath is not a keypath instruction or if there is
/// any other reason why the optimization cannot be done.
///
/// \param keyPath The key path to project. Must be the result of either
/// a keypath instruction or an upcast of a key path instruction.
/// \param root The address of the object the key path is applied to.
/// \param loc The location of the key path application.
/// \param builder The SILBuilder to use.
static std::unique_ptr<KeyPathProjector>
create(SILValue keyPath, SILValue root, SILLocation loc, SILBuilder &builder);
/// Projects the key path to an address. Sets up the projection,
/// invokes the callback, then tears down the projection.
/// \param accessType The access type of the projected address.
/// \param callback A callback to invoke with the projected adddress.
/// The projected address is only valid from within \p callback.
virtual void project(AccessType accessType,
std::function<void(SILValue addr)> callback) = 0;
virtual ~KeyPathProjector() {};
/// Whether this projection returns a struct.
virtual bool isStruct() = 0;
protected:
KeyPathProjector(SILLocation loc, SILBuilder &builder)
: loc(loc), builder(builder) {}
/// The location of the key path application.
SILLocation loc;
/// The SILBuilder to use.
SILBuilder &builder;
};
} // end namespace swift
#endif /* KeyPathProjector_h */