Skip to content

Commit 4792d68

Browse files
authored
Merge pull request #2204 from swiftwasm/main
[pull] swiftwasm from main
2 parents 315fb7a + f677d19 commit 4792d68

21 files changed

+238
-46
lines changed

include/swift/AST/DeclContext.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -873,8 +873,6 @@ class IterableDeclContext {
873873
/// available.
874874
Optional<std::string> getBodyFingerprint() const;
875875

876-
bool areTokensHashedForThisBodyInsteadOfInterfaceHash() const;
877-
878876
private:
879877
/// Add a member to the list for iteration purposes, but do not notify the
880878
/// subclass that we have done so.

include/swift/SIL/Dominance.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ class PostDominanceInfo : public PostDominatorTreeBase {
149149
PostDominanceInfo(SILFunction *F);
150150

151151
bool properlyDominates(SILInstruction *A, SILInstruction *B);
152+
bool properlyDominates(SILValue A, SILInstruction *B);
152153

153154
void verify() const;
154155

include/swift/SIL/SILNodes.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
592592

593593
// Accessing memory
594594
SINGLE_VALUE_INST(LoadInst, load,
595-
SingleValueInstruction, MayRead, DoesNotRelease)
595+
SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
596596
SINGLE_VALUE_INST(LoadBorrowInst, load_borrow,
597597
SingleValueInstruction, MayRead, DoesNotRelease)
598598
SINGLE_VALUE_INST(BeginBorrowInst, begin_borrow,
@@ -852,7 +852,7 @@ NON_VALUE_INST(BeginUnpairedAccessInst, begin_unpaired_access,
852852
NON_VALUE_INST(EndUnpairedAccessInst, end_unpaired_access,
853853
SILInstruction, MayHaveSideEffects, DoesNotRelease)
854854
NON_VALUE_INST(StoreInst, store,
855-
SILInstruction, MayWrite, DoesNotRelease)
855+
SILInstruction, MayHaveSideEffects, MayRelease)
856856
NON_VALUE_INST(AssignInst, assign,
857857
SILInstruction, MayWrite, DoesNotRelease)
858858
NON_VALUE_INST(AssignByWrapperInst, assign_by_wrapper,

lib/AST/DeclContext.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,16 +1022,6 @@ Optional<std::string> IterableDeclContext::getBodyFingerprint() const {
10221022
.fingerprint;
10231023
}
10241024

1025-
bool IterableDeclContext::areTokensHashedForThisBodyInsteadOfInterfaceHash()
1026-
const {
1027-
// Do not keep separate hashes for extension bodies because the dependencies
1028-
// can miss the addition of a member in an extension because there is nothing
1029-
// corresponding to the fingerprinted nominal dependency node.
1030-
if (isa<ExtensionDecl>(this))
1031-
return false;
1032-
return true;
1033-
}
1034-
10351025
/// Return the DeclContext to compare when checking private access in
10361026
/// Swift 4 mode. The context returned is the type declaration if the context
10371027
/// and the type declaration are in the same file, otherwise it is the types

lib/Parse/ParseDecl.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4765,12 +4765,9 @@ Parser::parseDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, Diag<> ErrorDiag,
47654765

47664766
// If we're hashing the type body separately, record the curly braces but
47674767
// nothing inside for the interface hash.
4768-
Optional<llvm::SaveAndRestore<Optional<llvm::MD5>>> MemberHashingScope;
4769-
if (IDC->areTokensHashedForThisBodyInsteadOfInterfaceHash()) {
4770-
recordTokenHash("{");
4771-
recordTokenHash("}");
4772-
MemberHashingScope.emplace(CurrentTokenHash, llvm::MD5());
4773-
}
4768+
llvm::SaveAndRestore<Optional<llvm::MD5>> MemberHashingScope{CurrentTokenHash, llvm::MD5()};
4769+
recordTokenHash("{");
4770+
recordTokenHash("}");
47744771

47754772
std::vector<Decl *> decls;
47764773
ParserStatus Status;
@@ -4802,8 +4799,7 @@ Parser::parseDeclList(SourceLoc LBLoc, SourceLoc &RBLoc, Diag<> ErrorDiag,
48024799
hadError = true;
48034800

48044801
llvm::MD5::MD5Result result;
4805-
auto declListHash = MemberHashingScope ? *CurrentTokenHash : llvm::MD5();
4806-
declListHash.final(result);
4802+
CurrentTokenHash->final(result);
48074803
llvm::SmallString<32> tokenHashString;
48084804
llvm::MD5::stringifyResult(result, tokenHashString);
48094805
return std::make_pair(decls, tokenHashString.str().str());

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,19 @@ OwnershipConstraintClassifier::visitBuiltinInst(BuiltinInst *bi) {
913913
Optional<OwnershipConstraint> Operand::getOwnershipConstraint() const {
914914
if (isTypeDependent())
915915
return None;
916+
917+
// If we do not have ownership enabled, just return any. This ensures that we
918+
// do not have any consuming uses and everything from an ownership perspective
919+
// is just a liveness use short-circuiting many of the optimizations.
920+
//
921+
// We do not ever call this function when an instruction isn't in a block.
922+
assert(getUser()->getParent() &&
923+
"Can not lookup ownership constraint unless inserted into block");
924+
if (auto *block = getUser()->getParent())
925+
if (auto *func = block->getParent())
926+
if (!func->hasOwnership())
927+
return {{OwnershipKind::Any, UseLifetimeConstraint::NonLifetimeEnding}};
928+
916929
OwnershipConstraintClassifier classifier(getUser()->getModule(), *this);
917930
return classifier.visit(const_cast<SILInstruction *>(getUser()));
918931
}

lib/SIL/IR/SILInstruction.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,36 @@ SILInstruction::MemoryBehavior SILInstruction::getMemoryBehavior() const {
10291029
MemoryBehavior::MayHaveSideEffects;
10301030
}
10311031

1032+
if (auto *li = dyn_cast<LoadInst>(this)) {
1033+
switch (li->getOwnershipQualifier()) {
1034+
case LoadOwnershipQualifier::Unqualified:
1035+
case LoadOwnershipQualifier::Trivial:
1036+
return MemoryBehavior::MayRead;
1037+
case LoadOwnershipQualifier::Take:
1038+
// Take deinitializes the underlying memory. Until we separate notions of
1039+
// memory writing from deinitialization (since a take doesn't actually
1040+
// write to the memory), lets be conservative and treat it as may read
1041+
// write.
1042+
return MemoryBehavior::MayReadWrite;
1043+
case LoadOwnershipQualifier::Copy:
1044+
return MemoryBehavior::MayHaveSideEffects;
1045+
}
1046+
llvm_unreachable("Covered switch isn't covered?!");
1047+
}
1048+
1049+
if (auto *si = dyn_cast<StoreInst>(this)) {
1050+
switch (si->getOwnershipQualifier()) {
1051+
case StoreOwnershipQualifier::Unqualified:
1052+
case StoreOwnershipQualifier::Trivial:
1053+
case StoreOwnershipQualifier::Init:
1054+
return MemoryBehavior::MayWrite;
1055+
case StoreOwnershipQualifier::Assign:
1056+
// For the release.
1057+
return MemoryBehavior::MayHaveSideEffects;
1058+
}
1059+
llvm_unreachable("Covered switch isn't covered?!");
1060+
}
1061+
10321062
switch (getKind()) {
10331063
#define FULL_INST(CLASS, TEXTUALNAME, PARENT, MEMBEHAVIOR, RELEASINGBEHAVIOR) \
10341064
case SILInstructionKind::CLASS: \
@@ -1138,6 +1168,18 @@ bool SILInstruction::mayRelease() const {
11381168
}
11391169
return true;
11401170
}
1171+
case SILInstructionKind::StoreInst:
1172+
switch (cast<StoreInst>(this)->getOwnershipQualifier()) {
1173+
case StoreOwnershipQualifier::Unqualified:
1174+
case StoreOwnershipQualifier::Init:
1175+
case StoreOwnershipQualifier::Trivial:
1176+
return false;
1177+
case StoreOwnershipQualifier::Assign:
1178+
// Assign destroys the old value that was in the memory location before we
1179+
// write the new value into the location.
1180+
return true;
1181+
}
1182+
llvm_unreachable("Covered switch isn't covered?!");
11411183
}
11421184
}
11431185

lib/SIL/IR/SILUndef.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
using namespace swift;
1717

1818
static ValueOwnershipKind getOwnershipKindForUndef(SILType type, const SILFunction &f) {
19+
if (!f.hasOwnership())
20+
return OwnershipKind::None;
1921
if (type.isAddress() || type.isTrivial(f))
2022
return OwnershipKind::None;
2123
return OwnershipKind::Owned;

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,19 @@ ValueOwnershipKindClassifier::visitBuiltinInst(BuiltinInst *BI) {
583583
//===----------------------------------------------------------------------===//
584584

585585
ValueOwnershipKind SILValue::getOwnershipKind() const {
586+
// If we do not have an undef, we should always be able to get to our function
587+
// here. If we do not have ownership enabled, just return none for everything
588+
// to short circuit ownership optimizations. If we have an undef we may still
589+
// get some results that are slightly wonky but hopefully when we lower
590+
// ownership we remove that.
591+
//
592+
// We assume that any time we are in SILBuilder and call this without having a
593+
// value in a block yet, ossa is enabled.
594+
if (auto *block = Value->getParentBlock())
595+
if (auto *f = block->getParent())
596+
if (!f->hasOwnership())
597+
return OwnershipKind::None;
598+
586599
ValueOwnershipKindClassifier Classifier;
587600
auto result = Classifier.visit(const_cast<ValueBase *>(Value));
588601
assert(result && "Returned ownership kind invalid on values");

lib/SIL/Utils/Dominance.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,16 @@ properlyDominates(SILInstruction *I1, SILInstruction *I2) {
114114
return true;
115115
}
116116

117+
bool PostDominanceInfo::properlyDominates(SILValue A, SILInstruction *B) {
118+
if (auto *Inst = A->getDefiningInstruction()) {
119+
return properlyDominates(Inst, B);
120+
}
121+
if (auto *Arg = dyn_cast<SILArgument>(A)) {
122+
return dominates(Arg->getParent(), B->getParent());
123+
}
124+
return false;
125+
}
126+
117127
void PostDominanceInfo::verify() const {
118128
// Recompute.
119129
//

lib/SIL/Verifier/LoadBorrowImmutabilityChecker.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,17 @@ bool GatherWritesVisitor::visitUse(Operand *op, AccessUseType useTy) {
243243
return false;
244244
}
245245

246+
if (auto *pa = dyn_cast<PartialApplyInst>(user)) {
247+
auto argConv = ApplySite(user).getArgumentConvention(*op);
248+
if (argConv == SILArgumentConvention::Indirect_In_Guaranteed) {
249+
return true;
250+
}
251+
252+
// For all other conventions, the underlying address could be mutated
253+
writeAccumulator.push_back(op);
254+
return true;
255+
}
256+
246257
// Handle a capture-by-address like a write.
247258
if (auto as = ApplySite::isa(user)) {
248259
writeAccumulator.push_back(op);

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,8 +1022,11 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
10221022
assert(F && "Expected value base with parent function");
10231023
// If we do not have qualified ownership, then do not verify value base
10241024
// ownership.
1025-
if (!F->hasOwnership())
1025+
if (!F->hasOwnership()) {
1026+
require(SILValue(V).getOwnershipKind() == OwnershipKind::None,
1027+
"Once ownership is gone, all values should have none ownership");
10261028
return;
1029+
}
10271030
SILValue(V).verifyOwnership(&DEBlocks);
10281031
}
10291032

@@ -1100,14 +1103,36 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
11001103
"instruction's operand's owner isn't the instruction");
11011104
require(isInValueUses(&operand), "operand value isn't used by operand");
11021105

1103-
if (I->isTypeDependentOperand(operand)) {
1106+
if (operand.isTypeDependent()) {
11041107
require(isa<SILInstruction>(I),
11051108
"opened archetype operand should refer to a SILInstruction");
11061109
}
11071110

11081111
// Make sure that if operand is generic that its primary archetypes match
11091112
// the function context.
11101113
checkLegalType(I->getFunction(), operand.get(), I);
1114+
1115+
// If we are not in OSSA, our operand constraint should be invalid for a
1116+
// type dependent operand (that is Optional::None) and if we have a non
1117+
// type dependent operand then we should have a constraint of
1118+
// OwnershipKind::Any, UseLifetimeConstraint::NonLifetimeEnding.
1119+
if (!I->getFunction()->hasOwnership()) {
1120+
if (operand.isTypeDependent()) {
1121+
require(
1122+
!operand.getOwnershipConstraint(),
1123+
"Non Optional::None constraint for a type dependent operand?!");
1124+
} else {
1125+
auto constraint = operand.getOwnershipConstraint();
1126+
require(constraint.hasValue(),
1127+
"All non-type dependent operands must have a "
1128+
"non-Optional::None constraint?!");
1129+
require(constraint->getPreferredKind() == OwnershipKind::Any &&
1130+
constraint->getLifetimeConstraint() ==
1131+
UseLifetimeConstraint::NonLifetimeEnding,
1132+
"In non-ossa all non-type dependent operands must have a "
1133+
"constraint of Any, NonLifetimeEnding");
1134+
}
1135+
}
11111136
}
11121137

11131138
// TODO: There should be a use of an opened archetype inside the instruction for

lib/SILOptimizer/Analysis/MemoryBehavior.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,15 @@ MemBehavior MemoryBehaviorVisitor::visitLoadInst(LoadInst *LI) {
242242
if (!mayAlias(LI->getOperand()))
243243
return MemBehavior::None;
244244

245-
// A take is modelled as a write. See MemoryBehavior::MayWrite.
246-
if (LI->getOwnershipQualifier() == LoadOwnershipQualifier::Take)
247-
return MemBehavior::MayReadWrite;
248-
249245
LLVM_DEBUG(llvm::dbgs() << " Could not prove that load inst does not alias "
250-
"pointer. Returning may read.\n");
246+
"pointer. ");
247+
248+
if (LI->getOwnershipQualifier() == LoadOwnershipQualifier::Take) {
249+
LLVM_DEBUG(llvm::dbgs() << "Is a take so return MayReadWrite.\n");
250+
return MemBehavior::MayReadWrite;
251+
}
252+
253+
LLVM_DEBUG(llvm::dbgs() << "Not a take so returning MayRead.\n");
251254
return MemBehavior::MayRead;
252255
}
253256

@@ -257,15 +260,17 @@ MemBehavior MemoryBehaviorVisitor::visitStoreInst(StoreInst *SI) {
257260
if (isLetValue() && (getAccessBase(SI->getDest()) != getValueAddress())) {
258261
return MemBehavior::None;
259262
}
260-
// If the store dest cannot alias the pointer in question, then the
261-
// specified value cannot be modified by the store.
262-
if (!mayAlias(SI->getDest()))
263+
// If the store dest cannot alias the pointer in question and we are not
264+
// releasing anything due to an assign, then the specified value cannot be
265+
// modified by the store.
266+
if (!mayAlias(SI->getDest()) &&
267+
SI->getOwnershipQualifier() != StoreOwnershipQualifier::Assign)
263268
return MemBehavior::None;
264269

265270
// Otherwise, a store just writes.
266271
LLVM_DEBUG(llvm::dbgs() << " Could not prove store does not alias inst. "
267-
"Returning MayWrite.\n");
268-
return MemBehavior::MayWrite;
272+
"Returning default mem behavior.\n");
273+
return SI->getMemoryBehavior();
269274
}
270275

271276
MemBehavior MemoryBehaviorVisitor::visitCopyAddrInst(CopyAddrInst *CAI) {

lib/SILOptimizer/Analysis/SideEffectAnalysis.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -539,12 +539,29 @@ void FunctionSideEffects::analyzeInstruction(SILInstruction *I) {
539539
true;
540540
Traps = true;
541541
return;
542-
case SILInstructionKind::LoadInst:
543-
getEffectsOn(cast<LoadInst>(I)->getOperand())->Reads = true;
542+
case SILInstructionKind::LoadBorrowInst: {
543+
auto *effects = getEffectsOn(cast<LoadBorrowInst>(I)->getOperand());
544+
effects->Reads = true;
544545
return;
545-
case SILInstructionKind::StoreInst:
546-
getEffectsOn(cast<StoreInst>(I)->getDest())->Writes = true;
546+
}
547+
case SILInstructionKind::LoadInst: {
548+
auto *li = cast<LoadInst>(I);
549+
auto *effects = getEffectsOn(cast<LoadInst>(I)->getOperand());
550+
effects->Reads = true;
551+
if (li->getOwnershipQualifier() == LoadOwnershipQualifier::Take)
552+
effects->Writes = true;
553+
if (li->getOwnershipQualifier() == LoadOwnershipQualifier::Copy)
554+
effects->Retains = true;
555+
return;
556+
}
557+
case SILInstructionKind::StoreInst: {
558+
auto *si = cast<StoreInst>(I);
559+
auto *effects = getEffectsOn(si->getDest());
560+
effects->Writes = true;
561+
if (si->getOwnershipQualifier() == StoreOwnershipQualifier::Assign)
562+
effects->Releases = true;
547563
return;
564+
}
548565
case SILInstructionKind::CondFailInst:
549566
Traps = true;
550567
return;

test/AutoDiff/SILOptimizer/differentiation_function_canonicalization.sil

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@ bb0(%0 : $@differentiable @callee_guaranteed (Float) -> Float):
4545
// CHECK: bb0([[ARG:%.*]] : $@differentiable @callee_guaranteed (Float) -> Float):
4646
// CHECK: [[ORIG_FN:%.*]] = differentiable_function_extract [original] [[ARG]]
4747
// CHECK: [[JVP_FN:%.*]] = differentiable_function_extract [jvp] [[ARG]]
48-
// CHECK: strong_retain [[JVP_FN]]
4948
// CHECK: [[VJP_FN:%.*]] = differentiable_function_extract [vjp] [[ARG]]
50-
// CHECK: strong_retain [[VJP_FN]]
5149
// CHECK: differentiable_function [parameters 0] [results 0] [[ORIG_FN]] : {{.*}} with_derivative {[[JVP_FN]] : {{.*}}, [[VJP_FN]] : {{.*}}}
5250
// CHECK: }
5351

@@ -134,8 +132,6 @@ bb0(%0 : $Class):
134132
// CHECK-LABEL: sil @test_class_method_partial_apply
135133
// CHECK: bb0([[ARG:%.*]] : $Class):
136134
// CHECK: [[ORIG_FN:%.*]] = class_method [[ARG]] : $Class, #Class.method
137-
// CHECK: strong_retain [[ARG]]
138-
// CHECK: strong_retain [[ARG]]
139135
// CHECK: [[ORIG_FN_PARTIALLY_APPLIED:%.*]] = partial_apply [callee_guaranteed] [[ORIG_FN]]([[ARG]])
140136
// CHECK: [[JVP_FN:%.*]] = class_method [[ARG]] : $Class, #Class.method!jvp.SU
141137
// CHECK: [[JVP_FN_PARTIALLY_APPLIED:%.*]] = partial_apply [callee_guaranteed] [[JVP_FN]]([[ARG]])

test/Incremental/CrossModule/external-cascade.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// RUN: %empty-directory(%t)
22
// RUN: cp -r %S/Inputs/external-cascade/* %t
33

4+
// rdar://70772320
5+
// REQUIRES: !(optimized_stdlib)
6+
47
//
58
// This test establishes a chain of modules that all depend on a set of
69
// bridging headers. This test ensures that changes to external dependencies -

test/Incremental/CrossModule/linear.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// RUN: %empty-directory(%t)
22
// RUN: cp -r %S/Inputs/linear/* %t
33

4+
// rdar://70772320
5+
// REQUIRES: !(optimized_stdlib)
6+
47
//
58
// This test establishes a "linear" chain of modules that import one another
69
// and ensures that a cross-module incremental build does not needlessly

test/Incremental/CrossModule/transitive.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// RUN: %empty-directory(%t)
22
// RUN: cp -r %S/Inputs/transitive/* %t
33

4+
// rdar://70772320
5+
// REQUIRES: !(optimized_stdlib)
6+
47
//
58
// This test establishes a "transitive" chain of modules that import one another
69
// and ensures that a cross-module incremental build rebuilds all modules

0 commit comments

Comments
 (0)