Skip to content

Commit b581a6e

Browse files
committed
---
yaml --- r: 322423 b: refs/heads/tensorflow-next c: f3f9f84 h: refs/heads/master i: 322421: 4ab29ea 322419: fd44484 322415: 432eee1
1 parent 915e5b9 commit b581a6e

26 files changed

+555
-64
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1461,4 +1461,4 @@ refs/heads/master-rebranch: 86e95c23aa0d37f24ec138b7853146c1cead2e40
14611461
refs/heads/rdar-53901732: 9bd06af3284e18a109cdbf9aa59d833b24eeca7b
14621462
refs/heads/revert-26776-subst-always-returns-a-type: 1b8e18fdd391903a348970a4c848995d4cdd789c
14631463
refs/heads/tensorflow-merge: 8b854f62f80d4476cb383d43c4aac2001dde3cec
1464-
refs/heads/tensorflow-next: e2380b869943e1e05dfddace715f2456c6c721da
1464+
refs/heads/tensorflow-next: f3f9f84b1b34f66ee9813d58817e73898a3dee94

branches/tensorflow-next/include/swift/SIL/SILInstruction.h

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,16 @@ class SILInstruction
505505
return isTypeDependentOperand(Op.getOperandNumber());
506506
}
507507

508+
private:
509+
/// Predicate used to filter OperandValueRange.
510+
struct OperandToValue;
511+
512+
public:
513+
using OperandValueRange =
514+
OptionalTransformRange<ArrayRef<Operand>, OperandToValue>;
515+
OperandValueRange
516+
getOperandValues(bool skipTypeDependentOperands = false) const;
517+
508518
SILValue getOperand(unsigned Num) const {
509519
return getAllOperands()[Num].get();
510520
}
@@ -514,6 +524,7 @@ class SILInstruction
514524
}
515525

516526
/// Return the list of results produced by this instruction.
527+
bool hasResults() const { return !getResults().empty(); }
517528
SILInstructionResultArray getResults() const { return getResultsImpl(); }
518529
unsigned getNumResults() const { return getResults().size(); }
519530

@@ -668,6 +679,27 @@ class SILInstruction
668679
static bool classof(const ValueBase *) = delete;
669680
};
670681

682+
struct SILInstruction::OperandToValue {
683+
const SILInstruction &i;
684+
bool skipTypeDependentOps;
685+
686+
OperandToValue(const SILInstruction &i, bool skipTypeDependentOps)
687+
: i(i), skipTypeDependentOps(skipTypeDependentOps) {}
688+
689+
Optional<SILValue> operator()(const Operand &use) const {
690+
if (skipTypeDependentOps && i.isTypeDependentOperand(use))
691+
return None;
692+
return use.get();
693+
}
694+
};
695+
696+
inline auto
697+
SILInstruction::getOperandValues(bool skipTypeDependentOperands) const
698+
-> OperandValueRange {
699+
return OperandValueRange(getAllOperands(),
700+
OperandToValue(*this, skipTypeDependentOperands));
701+
}
702+
671703
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
672704
const SILInstruction &I) {
673705
I.print(OS);
@@ -801,6 +833,9 @@ class OwnershipForwardingSingleValueInst : public SingleValueInstruction {
801833

802834
public:
803835
ValueOwnershipKind getOwnershipKind() const { return ownershipKind; }
836+
void setOwnershipKind(ValueOwnershipKind newOwnershipKind) {
837+
ownershipKind = newOwnershipKind;
838+
}
804839
};
805840

806841
/// A value base result of a multiple value instruction.
@@ -838,6 +873,11 @@ class MultipleValueInstructionResult : public ValueBase {
838873
/// This is stored in the bottom 3 bits of ValueBase's subclass data.
839874
ValueOwnershipKind getOwnershipKind() const;
840875

876+
/// Set the ownership kind assigned to this result.
877+
///
878+
/// This is stored in SILNode in the subclass data.
879+
void setOwnershipKind(ValueOwnershipKind Kind);
880+
841881
static bool classof(const SILInstruction *) = delete;
842882
static bool classof(const SILUndef *) = delete;
843883
static bool classof(const SILArgument *) = delete;
@@ -851,11 +891,6 @@ class MultipleValueInstructionResult : public ValueBase {
851891
}
852892

853893
protected:
854-
/// Set the ownership kind assigned to this result.
855-
///
856-
/// This is stored in SILNode in the subclass data.
857-
void setOwnershipKind(ValueOwnershipKind Kind);
858-
859894
/// Set the index of this result.
860895
void setIndex(unsigned NewIndex);
861896
};
@@ -4077,6 +4112,9 @@ class OwnershipForwardingConversionInst : public ConversionInst {
40774112

40784113
public:
40794114
ValueOwnershipKind getOwnershipKind() const { return ownershipKind; }
4115+
void setOwnershipKind(ValueOwnershipKind newOwnershipKind) {
4116+
ownershipKind = newOwnershipKind;
4117+
}
40804118
};
40814119

40824120
/// ConvertFunctionInst - Change the type of a function value without
@@ -5305,6 +5343,9 @@ class OwnershipForwardingSelectEnumInstBase : public SelectEnumInstBase {
53055343

53065344
public:
53075345
ValueOwnershipKind getOwnershipKind() const { return ownershipKind; }
5346+
void setOwnershipKind(ValueOwnershipKind newOwnershipKind) {
5347+
ownershipKind = newOwnershipKind;
5348+
}
53085349
};
53095350

53105351
/// Select one of a set of values based on the case of an enum.
@@ -7849,6 +7890,11 @@ inline void SILSuccessor::pred_iterator::cacheBasicBlock() {
78497890
}
78507891
}
78517892

7893+
// Declared in SILValue.h
7894+
inline bool Operand::isTypeDependent() const {
7895+
return getUser()->isTypeDependentOperand(*this);
7896+
}
7897+
78527898
} // end swift namespace
78537899

78547900
//===----------------------------------------------------------------------===//

branches/tensorflow-next/include/swift/SIL/SILValue.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,11 @@ class Operand {
586586
SILInstruction *getUser() { return Owner; }
587587
const SILInstruction *getUser() const { return Owner; }
588588

589+
/// Return true if this operand is a type dependent operand.
590+
///
591+
/// Implemented in SILInstruction.h
592+
bool isTypeDependent() const;
593+
589594
/// Return which operand this is in the operand list of the using instruction.
590595
unsigned getOperandNumber() const;
591596

branches/tensorflow-next/lib/AST/USRGeneration.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ static bool shouldUseObjCUSR(const Decl *D) {
167167
llvm::Expected<std::string>
168168
swift::USRGenerationRequest::evaluate(Evaluator &evaluator,
169169
const ValueDecl *D) const {
170+
if (auto *VD = dyn_cast<VarDecl>(D))
171+
D = VD->getCanonicalVarDecl();
172+
170173
if (!D->hasName() && !isa<ParamDecl>(D) && !isa<AccessorDecl>(D))
171174
return std::string(); // Ignore.
172175
if (D->getModuleContext()->isBuiltinModule())

branches/tensorflow-next/lib/IDE/SwiftSourceDocInfo.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,19 @@ bool CursorInfoResolver::tryResolve(ValueDecl *D, TypeDecl *CtorTyRef,
7979
if (!D->hasName())
8080
return false;
8181

82-
if (Loc == LocToResolve) {
83-
CursorInfo.setValueRef(D, CtorTyRef, ExtTyRef, IsRef, Ty, ContainerType);
84-
return true;
82+
if (Loc != LocToResolve)
83+
return false;
84+
85+
if (auto *VD = dyn_cast<VarDecl>(D)) {
86+
// Handle references to the implicitly generated vars in case statements
87+
// matching multiple patterns
88+
if (VD->isImplicit()) {
89+
if (auto * Parent = VD->getParentVarDecl())
90+
D = Parent;
91+
}
8592
}
86-
return false;
93+
CursorInfo.setValueRef(D, CtorTyRef, ExtTyRef, IsRef, Ty, ContainerType);
94+
return true;
8795
}
8896

8997
bool CursorInfoResolver::tryResolve(ModuleEntity Mod, SourceLoc Loc) {

branches/tensorflow-next/lib/Index/Index.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,12 @@ class IndexSwiftASTWalker : public SourceEntityWalker {
516516
}
517517

518518
bool shouldIndex(ValueDecl *D, bool IsRef) const {
519+
if (D->isImplicit() && isa<VarDecl>(D) && IsRef) {
520+
// Bypass the implicit VarDecls introduced in CaseStmt bodies by using the
521+
// canonical VarDecl for these checks instead.
522+
D = cast<VarDecl>(D)->getCanonicalVarDecl();
523+
}
524+
519525
if (D->isImplicit() && !isa<ConstructorDecl>(D))
520526
return false;
521527

@@ -1151,6 +1157,11 @@ bool IndexSwiftASTWalker::reportImplicitConformance(ValueDecl *witness, ValueDec
11511157
bool IndexSwiftASTWalker::initIndexSymbol(ValueDecl *D, SourceLoc Loc,
11521158
bool IsRef, IndexSymbol &Info) {
11531159
assert(D);
1160+
if (auto *VD = dyn_cast<VarDecl>(D)) {
1161+
// Always base the symbol information on the canonical VarDecl
1162+
D = VD->getCanonicalVarDecl();
1163+
}
1164+
11541165
Info.decl = D;
11551166
Info.symInfo = getSymbolInfoForDecl(D);
11561167
if (Info.symInfo.Kind == SymbolKind::Unknown)

branches/tensorflow-next/lib/Parse/ParseStmt.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,6 @@ static void parseGuardedPattern(Parser &P, GuardedPattern &result,
12061206

12071207
for (auto VD : repeatedDecls) {
12081208
VD->setHasNonPatternBindingInit();
1209-
VD->setImplicit();
12101209
}
12111210

12121211
// Parse the optional 'where' guard, with this particular pattern's bound

branches/tensorflow-next/lib/SIL/OperandOwnership.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,10 @@ OperandOwnershipKindClassifier::visitFullApply(FullApplySite apply) {
719719
return Map::allLive();
720720
}
721721

722+
// If we have a type dependent operand, return an empty map.
723+
if (apply.getInstruction()->isTypeDependentOperand(op))
724+
return Map();
725+
722726
unsigned argIndex = apply.getCalleeArgIndex(op);
723727
auto conv = apply.getSubstCalleeConv();
724728
SILParameterInfo paramInfo = conv.getParamInfoForSILArg(argIndex);

branches/tensorflow-next/lib/SILOptimizer/Mandatory/SemanticARCOpts.cpp

Lines changed: 107 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -40,36 +40,73 @@ STATISTIC(NumLoadCopyConvertedToLoadBorrow,
4040
///
4141
/// Semantically this implies that a value is never passed off as +1 to memory
4242
/// or another function implying it can be used everywhere at +0.
43-
static bool isConsumed(SILValue v,
44-
SmallVectorImpl<DestroyValueInst *> &destroys) {
43+
static bool isConsumed(
44+
SILValue v, SmallVectorImpl<DestroyValueInst *> &destroys,
45+
NullablePtr<SmallVectorImpl<SILInstruction *>> forwardingInsts = nullptr) {
4546
assert(v.getOwnershipKind() == ValueOwnershipKind::Owned);
46-
return !all_of(v->getUses(), [&destroys](Operand *op) {
47-
// We know that a copy_value produces an @owned value. Look
48-
// through all of our uses and classify them as either
49-
// invalidating or not invalidating. Make sure that all of the
50-
// invalidating ones are destroy_value since otherwise the
51-
// live_range is not complete.
47+
SmallVector<Operand *, 32> worklist(v->use_begin(), v->use_end());
48+
while (!worklist.empty()) {
49+
auto *op = worklist.pop_back_val();
50+
51+
// Skip type dependent operands.
52+
if (op->isTypeDependent())
53+
continue;
54+
55+
auto *user = op->getUser();
56+
57+
// We know that a copy_value produces an @owned value. Look through all of
58+
// our uses and classify them as either invalidating or not
59+
// invalidating. Make sure that all of the invalidating ones are
60+
// destroy_value since otherwise the live_range is not complete.
5261
auto map = op->getOwnershipKindMap();
5362
auto constraint = map.getLifetimeConstraint(ValueOwnershipKind::Owned);
5463
switch (constraint) {
5564
case UseLifetimeConstraint::MustBeInvalidated: {
5665
// See if we have a destroy value. If we don't we have an
5766
// unknown consumer. Return false, we need this live range.
58-
auto *dvi = dyn_cast<DestroyValueInst>(op->getUser());
59-
if (!dvi)
60-
return false;
67+
if (auto *dvi = dyn_cast<DestroyValueInst>(user)) {
68+
destroys.push_back(dvi);
69+
continue;
70+
}
71+
72+
// Otherwise, see if we have a forwarding value that has a single
73+
// non-trivial operand that can accept a guaranteed value. If so, at its
74+
// users to the worklist and continue.
75+
//
76+
// DISCUSSION: For now we do not support forwarding instructions with
77+
// multiple non-trivial arguments since we would need to optimize all of
78+
// the non-trivial arguments at the same time.
79+
//
80+
// NOTE: Today we do not support TermInsts for simplicity... we /could/
81+
// support it though if we need to.
82+
if (forwardingInsts.isNonNull() && !isa<TermInst>(user) &&
83+
isGuaranteedForwardingInst(user) &&
84+
1 == count_if(user->getOperandValues(
85+
true /*ignore type dependent operands*/),
86+
[&](SILValue v) {
87+
return v.getOwnershipKind() ==
88+
ValueOwnershipKind::Owned;
89+
})) {
90+
forwardingInsts.get()->push_back(user);
91+
for (SILValue v : user->getResults()) {
92+
copy(v->getUses(), std::back_inserter(worklist));
93+
}
94+
continue;
95+
}
6196

62-
// Otherwise, return true and stash this destroy value.
63-
destroys.push_back(dvi);
97+
// Otherwise be conservative and assume that we /may consume/ the value.
6498
return true;
6599
}
66100
case UseLifetimeConstraint::MustBeLive:
67101
// Ok, this constraint can take something owned as live. Lets
68102
// see if it can also take something that is guaranteed. If it
69103
// can not, then we bail.
70-
return map.canAcceptKind(ValueOwnershipKind::Guaranteed);
104+
map.canAcceptKind(ValueOwnershipKind::Guaranteed);
105+
continue;
71106
}
72-
});
107+
}
108+
109+
return false;
73110
}
74111

75112
//===----------------------------------------------------------------------===//
@@ -168,13 +205,14 @@ static bool performGuaranteedCopyValueOptimization(CopyValueInst *cvi) {
168205
if (!canHandleOperand(cvi->getOperand(), borrowIntroducers))
169206
return false;
170207

171-
// Then go over all of our uses. Find our destroying instructions
172-
// and make sure all of them are destroy_value. For our
173-
// non-destroying instructions, make sure that they accept a
174-
// guaranteed value. After that, make sure that our destroys are
175-
// within the lifetime of our borrowed values.
208+
// Then go over all of our uses. Find our destroying instructions (ignoring
209+
// forwarding instructions that can forward both owned and guaranteed) and
210+
// make sure all of them are destroy_value. For our non-destroying
211+
// instructions, make sure that they accept a guaranteed value. After that,
212+
// make sure that our destroys are within the lifetime of our borrowed values.
176213
SmallVector<DestroyValueInst *, 16> destroys;
177-
if (isConsumed(cvi, destroys))
214+
SmallVector<SILInstruction *, 16> guaranteedForwardingInsts;
215+
if (isConsumed(cvi, destroys, &guaranteedForwardingInsts))
178216
return false;
179217

180218
// If we reached this point, then we know that all of our users can
@@ -189,15 +227,56 @@ static bool performGuaranteedCopyValueOptimization(CopyValueInst *cvi) {
189227
assert(all_of(borrowIntroducers,
190228
[](SILValue v) { return isa<SILFunctionArgument>(v); }));
191229

192-
// Otherwise, we know that our copy_value/destroy_values are all
193-
// completely within the guaranteed value scope.
230+
// Otherwise, we know that our copy_value/destroy_values are all completely
231+
// within the guaranteed value scope. First delete the destroys/copies.
194232
while (!destroys.empty()) {
195233
auto *dvi = destroys.pop_back_val();
196234
dvi->eraseFromParent();
197235
++NumEliminatedInsts;
198236
}
199237
cvi->replaceAllUsesWith(cvi->getOperand());
200238
cvi->eraseFromParent();
239+
240+
// Then change all of our guaranteed forwarding insts to have guaranteed
241+
// ownership kind instead of what ever they previously had (ignoring trivial
242+
// results);
243+
while (!guaranteedForwardingInsts.empty()) {
244+
auto *i = guaranteedForwardingInsts.pop_back_val();
245+
246+
assert(i->hasResults());
247+
248+
for (SILValue result : i->getResults()) {
249+
if (auto *svi = dyn_cast<OwnershipForwardingSingleValueInst>(result)) {
250+
if (svi->getOwnershipKind() == ValueOwnershipKind::Owned) {
251+
svi->setOwnershipKind(ValueOwnershipKind::Guaranteed);
252+
}
253+
continue;
254+
}
255+
256+
if (auto *ofci = dyn_cast<OwnershipForwardingConversionInst>(result)) {
257+
if (ofci->getOwnershipKind() == ValueOwnershipKind::Owned) {
258+
ofci->setOwnershipKind(ValueOwnershipKind::Guaranteed);
259+
}
260+
continue;
261+
}
262+
263+
if (auto *sei = dyn_cast<OwnershipForwardingSelectEnumInstBase>(result)) {
264+
if (sei->getOwnershipKind() == ValueOwnershipKind::Owned) {
265+
sei->setOwnershipKind(ValueOwnershipKind::Guaranteed);
266+
}
267+
continue;
268+
}
269+
270+
if (auto *mvir = dyn_cast<MultipleValueInstructionResult>(result)) {
271+
if (mvir->getOwnershipKind() == ValueOwnershipKind::Owned) {
272+
mvir->setOwnershipKind(ValueOwnershipKind::Guaranteed);
273+
}
274+
continue;
275+
}
276+
277+
llvm_unreachable("unhandled forwarding instruction?!");
278+
}
279+
}
201280
++NumEliminatedInsts;
202281
return true;
203282
}
@@ -350,6 +429,11 @@ bool SemanticARCOptVisitor::visitLoadInst(LoadInst *li) {
350429
// load_borrow.
351430
auto *lbi =
352431
SILBuilderWithScope(li).createLoadBorrow(li->getLoc(), li->getOperand());
432+
433+
// Since we are looking through forwarding uses that can accept guaranteed
434+
// parameters, we can have multiple destroy_value along the same path. We need
435+
// to find the post-dominating block set of these destroy value to ensure that
436+
// we do not insert multiple end_borrow.
353437
while (!destroyValues.empty()) {
354438
auto *dvi = destroyValues.pop_back_val();
355439
SILBuilderWithScope(dvi).createEndBorrow(dvi->getLoc(), lbi);

0 commit comments

Comments
 (0)