Skip to content

[5.3] parse COW support builtins as no-ops #32600

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
merged 2 commits into from
Jul 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions include/swift/AST/Builtins.def
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,35 @@ BUILTIN_SIL_OPERATION(IsUnique, "isUnique", Special)
/// BridgeObject to be treated as a native object by the runtime.
BUILTIN_SIL_OPERATION(IsUnique_native, "isUnique_native", Special)

/// beginCOWMutation<T : AnyObject>(inout T) -> Int1
///
/// Begins a copy-on-write mutation for a buffer reference which is passed as
/// inout argument. It returns a true if the buffer is uniquely referenced.
/// In this case the buffer may be mutated after calling this builtin.
///
/// The beginCOWMutation builtin is very similar to isUnique. It just translates
/// to a different SIL instruction (begin_cow_mutation), which is the preferred
/// representation of COW in SIL.
BUILTIN_SIL_OPERATION(BeginCOWMutation, "beginCOWMutation", Special)

/// beginCOWMutation_native<T : AnyObject>(inout T) -> Int1
///
/// Like beginCOWMutation, but it's assumed that T has native Swift reference
/// counting.
BUILTIN_SIL_OPERATION(BeginCOWMutation_native, "beginCOWMutation_native", Special)

/// endCOWMutation<T : AnyObject>(inout T)
///
/// Ends a copy-on-write mutation for a buffer reference which is passed as
/// inout argument. After calling this builtin, the buffer must not be mutated.
BUILTIN_SIL_OPERATION(EndCOWMutation, "endCOWMutation", Special)

/// COWBufferForReading has type <T: AnyObject> T -> T
///
/// Returns the buffer reference which is passed as argument.
/// This builtin indicates to the optimizer that the buffer is not mutable.
BUILTIN_SIL_OPERATION(COWBufferForReading, "COWBufferForReading", Special)

/// bindMemory : <T> (Builtin.RawPointer, Builtin.Word, T.Type) -> ()
BUILTIN_SIL_OPERATION(BindMemory, "bindMemory", Special)

Expand Down
49 changes: 46 additions & 3 deletions lib/AST/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,13 +431,26 @@ createGenericParam(ASTContext &ctx, const char *name, unsigned index) {

/// Create a generic parameter list with multiple generic parameters.
static GenericParamList *getGenericParams(ASTContext &ctx,
unsigned numParameters) {
unsigned numParameters,
bool isAnyObject) {
assert(numParameters <= llvm::array_lengthof(GenericParamNames));

SmallVector<GenericTypeParamDecl*, 2> genericParams;
for (unsigned i = 0; i != numParameters; ++i)
genericParams.push_back(createGenericParam(ctx, GenericParamNames[i], i));


if (isAnyObject) {
CanType ao = ctx.getAnyObjectType();
SmallVector<RequirementRepr, 1> req;
req.push_back(RequirementRepr::getTypeConstraint(TypeLoc::withoutLoc(genericParams[0]->getInterfaceType()), SourceLoc(),
TypeLoc::withoutLoc(ao)));

auto paramList = GenericParamList::create(ctx, SourceLoc(), genericParams,
SourceLoc(), req, SourceLoc());
return paramList;
}

auto paramList = GenericParamList::create(ctx, SourceLoc(), genericParams,
SourceLoc());
return paramList;
Expand All @@ -460,9 +473,10 @@ namespace {
SmallVector<Requirement, 2> addedRequirements;

public:
BuiltinFunctionBuilder(ASTContext &ctx, unsigned numGenericParams = 1)
BuiltinFunctionBuilder(ASTContext &ctx, unsigned numGenericParams = 1,
bool isAnyObject = false)
: Context(ctx) {
TheGenericParamList = getGenericParams(ctx, numGenericParams);
TheGenericParamList = getGenericParams(ctx, numGenericParams, isAnyObject);
for (auto gp : TheGenericParamList->getParams()) {
genericParamTypes.push_back(
gp->getDeclaredInterfaceType()->castTo<GenericTypeParamType>());
Expand Down Expand Up @@ -645,6 +659,14 @@ static ValueDecl *getIsUniqueOperation(ASTContext &Context, Identifier Id) {
return builder.build(Id);
}

static ValueDecl *getEndCOWMutation(ASTContext &Context, Identifier Id) {
// <T> (@inout T) -> ()
BuiltinFunctionBuilder builder(Context);
builder.addParameter(makeGenericParam(), ValueOwnership::InOut);
builder.setResult(makeConcrete(TupleType::getEmpty(Context)));
return builder.build(Id);
}

static ValueDecl *getBindMemoryOperation(ASTContext &Context, Identifier Id) {
BuiltinFunctionBuilder builder(Context);
builder.addParameter(makeConcrete(Context.TheRawPointerType));
Expand Down Expand Up @@ -908,6 +930,16 @@ static ValueDecl *getValueToBridgeObject(ASTContext &C, Identifier Id) {
return builder.build(Id);
}

static ValueDecl *getCOWBufferForReading(ASTContext &C, Identifier Id) {
// <T : AnyObject> T -> T
//
BuiltinFunctionBuilder builder(C, 1, true);
auto T = makeGenericParam();
builder.addParameter(T);
builder.setResult(T);
return builder.build(Id);
}

static ValueDecl *getUnsafeGuaranteed(ASTContext &C, Identifier Id) {
// <T : AnyObject> T -> (T, Int8Ty)
//
Expand Down Expand Up @@ -2249,9 +2281,16 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {

case BuiltinValueKind::IsUnique:
case BuiltinValueKind::IsUnique_native:
case BuiltinValueKind::BeginCOWMutation:
case BuiltinValueKind::BeginCOWMutation_native:
if (!Types.empty()) return nullptr;
// BeginCOWMutation has the same signature as IsUnique.
return getIsUniqueOperation(Context, Id);

case BuiltinValueKind::EndCOWMutation:
if (!Types.empty()) return nullptr;
return getEndCOWMutation(Context, Id);

case BuiltinValueKind::BindMemory:
if (!Types.empty()) return nullptr;
return getBindMemoryOperation(Context, Id);
Expand Down Expand Up @@ -2380,6 +2419,10 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
if (!Types.empty())
return nullptr;
return getValueToBridgeObject(Context, Id);

case BuiltinValueKind::COWBufferForReading:
return getCOWBufferForReading(Context, Id);

case BuiltinValueKind::UnsafeGuaranteed:
return getUnsafeGuaranteed(Context, Id);

Expand Down
39 changes: 39 additions & 0 deletions lib/SILGen/SILGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,45 @@ emitBuiltinIsUnique_native(SILGenFunction &SGF,
return ManagedValue::forUnmanaged(result);
}

static ManagedValue
emitBuiltinBeginCOWMutation(SILGenFunction &SGF,
SILLocation loc,
SubstitutionMap subs,
ArrayRef<ManagedValue> args,
SGFContext C) {
return emitBuiltinIsUnique(SGF, loc, subs, args, C);
}

static ManagedValue
emitBuiltinBeginCOWMutation_native(SILGenFunction &SGF,
SILLocation loc,
SubstitutionMap subs,
ArrayRef<ManagedValue> args,
SGFContext C) {
return emitBuiltinIsUnique_native(SGF, loc, subs, args, C);
}

static ManagedValue
emitBuiltinEndCOWMutation(SILGenFunction &SGF,
SILLocation loc,
SubstitutionMap subs,
ArrayRef<ManagedValue> args,
SGFContext C) {
return ManagedValue::forUnmanaged(SGF.emitEmptyTuple(loc));
}

static ManagedValue
emitBuiltinCOWBufferForReading(SILGenFunction &SGF,
SILLocation loc,
SubstitutionMap subs,
ArrayRef<ManagedValue> args,
SGFContext C) {


assert(args.size() == 1 && "isUnique_native should have one arg.");
return args[0];
}

static ManagedValue emitBuiltinBindMemory(SILGenFunction &SGF,
SILLocation loc,
SubstitutionMap subs,
Expand Down
8 changes: 7 additions & 1 deletion lib/SILOptimizer/Analysis/ArraySemantic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,13 @@ void ArraySemanticsCall::initialize(ApplyInst *AI, StringRef semanticName,

// Need a 'self' argument otherwise this is not a semantic call that
// we recognize.
if (getKind() < ArrayCallKind::kArrayInit && !hasSelf())
ArrayCallKind kind = getKind();
if (kind == ArrayCallKind::kNone) {
SemanticsCall = nullptr;
return;
}

if (kind < ArrayCallKind::kArrayInit && !hasSelf())
SemanticsCall = nullptr;

// A arguments must be passed reference count neutral except for self.
Expand Down
6 changes: 6 additions & 0 deletions test/IRGen/builtins.swift
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,12 @@ func isUniqueIUO(_ ref: inout Builtin.NativeObject?) -> Bool {
return Builtin.isUnique(&iuo)
}

// CHECK-LABEL: define hidden {{.*}} @"$s8builtins19COWBufferForReadingyAA1CCADnF"
// CHECK: ret %T8builtins1CC* %0
func COWBufferForReading(_ ref: __owned C) -> C {
return Builtin.COWBufferForReading(ref)
}

// CHECK-LABEL: define {{.*}} @{{.*}}generic_ispod_test
func generic_ispod_test<T>(_: T) {
// CHECK: [[T0:%.*]] = getelementptr inbounds %swift.vwtable, %swift.vwtable* [[T:%.*]], i32 10
Expand Down
25 changes: 25 additions & 0 deletions test/SILGen/builtins.swift
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,31 @@ func castBitPatternFromBridgeObject(_ bo: Builtin.BridgeObject) -> Builtin.Word
return Builtin.castBitPatternFromBridgeObject(bo)
}

// CHECK-LABEL: sil hidden [ossa] @$s8builtins16beginCOWMutationySbAA1CCzF
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*C
// CHECK: [[BUILTIN:%.*]] = is_unique [[WRITE]] : $*C
// CHECK: return
func beginCOWMutation(_ c: inout C) -> Bool {
return Bool(_builtinBooleanLiteral: Builtin.beginCOWMutation(&c))
}

// CHECK-LABEL: sil hidden [ossa] @$s8builtins23beginCOWMutation_nativeySbAA1CCzF
// CHECK: [[WRITE:%.*]] = begin_access [modify] [unknown] %0 : $*C
// CHECK: [[CAST:%.*]] = unchecked_addr_cast [[WRITE]] : $*C to $*Builtin.NativeObject
// CHECK: [[BUILTIN:%.*]] = is_unique [[CAST]] : $*Builtin.NativeObject
// CHECK: return
func beginCOWMutation_native(_ c: inout C) -> Bool {
return Bool(_builtinBooleanLiteral: Builtin.beginCOWMutation_native(&c))
}

// CHECK-LABEL: sil hidden [ossa] @$s8builtins14endCOWMutationyyAA1CCzF
// CHECK: begin_access
// CHECK-NEXT: tuple ()
// CHECK-NEXT: end_access
func endCOWMutation(_ c: inout C) {
Builtin.endCOWMutation(&c)
}

// ----------------------------------------------------------------------------
// isUnique variants
// ----------------------------------------------------------------------------
Expand Down