Skip to content

Commit afde39d

Browse files
authored
Merge pull request #41366 from atrick/addrlower-silapi
Many minor/obvious SIL API improvements that address lowering depends on
2 parents 9339316 + d9ba9f3 commit afde39d

31 files changed

+373
-127
lines changed

include/swift/SIL/ApplySite.h

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -580,18 +580,19 @@ class FullApplySite : public ApplySite {
580580
return getSubstCalleeConv().hasIndirectSILResults();
581581
}
582582

583-
/// If our apply site has a single direct result SILValue, return that
584-
/// SILValue. Return SILValue() otherwise.
583+
/// Get the SIL value that represents all of the given call's results. For a
584+
/// single direct result, returns the result. For multiple results, returns a
585+
/// fake tuple value. The tuple has no storage of its own. The real results
586+
/// must be extracted from it.
585587
///
586-
/// This means that:
588+
/// For ApplyInst, returns the single-value instruction itself.
587589
///
588-
/// 1. If we have an ApplyInst, we just visit the apply.
589-
/// 2. If we have a TryApplyInst, we visit the first argument of the normal
590-
/// block.
591-
/// 3. If we have a BeginApplyInst, we return SILValue() since the begin_apply
592-
/// yields values instead of returning them. A returned value should only
593-
/// be valid after a full apply site has completely finished executing.
594-
SILValue getSingleDirectResult() const {
590+
/// For TryApplyInst returns the continuation block argument.
591+
///
592+
/// For BeginApplyInst, returns an invalid value. For coroutines, there is no
593+
/// single value representing all results. Yielded values are generally
594+
/// handled differently since they have the convention of incoming arguments.
595+
SILValue getPseudoResult() const {
595596
switch (getKind()) {
596597
case FullApplySiteKind::ApplyInst:
597598
return SILValue(cast<ApplyInst>(getInstruction()));

include/swift/SIL/Dominance.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,19 @@ class DominanceInfo : public DominatorTreeBase {
8888
}
8989
};
9090

91+
/// Compute a single block's dominance frontier.
92+
///
93+
/// Precondition: no critical edges (OSSA)
94+
///
95+
/// Postcondition: each block in \p frontier is dominated by \p root and either
96+
/// exits the function or has a single successor that is not dominated by \p
97+
/// root.
98+
///
99+
/// With no critical edges, the dominance frontier is identified simply by leaf
100+
/// blocks in the dominance subtree.
101+
void computeDominanceFrontier(SILBasicBlock *root, DominanceInfo *domTree,
102+
SmallVectorImpl<SILBasicBlock *> &frontier);
103+
91104
/// Helper class for visiting basic blocks in dominance order, based on a
92105
/// worklist algorithm. Example usage:
93106
/// \code

include/swift/SIL/MemAccessUtils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1689,7 +1689,7 @@ Result AccessUseDefChainVisitor<Impl, Result>::visit(SILValue sourceAddr) {
16891689

16901690
case ValueKind::SILPhiArgument: {
16911691
auto *phiArg = cast<SILPhiArgument>(sourceAddr);
1692-
if (phiArg->isPhiArgument()) {
1692+
if (phiArg->isPhi()) {
16931693
return asImpl().visitPhi(phiArg);
16941694
}
16951695

include/swift/SIL/OwnershipUtils.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,7 @@ inline bool isForwardingConsume(SILValue value) {
7979
}
8080

8181
/// Find leaf "use points" of \p guaranteedValue that determine its lifetime
82-
/// requirement. If \p usePoints is nullptr, then the simply returns true if no
83-
/// PointerEscape use was found.
82+
/// requirement. Return true if no PointerEscape use was found.
8483
///
8584
/// Precondition: \p guaranteedValue is not a BorrowedValue.
8685
///

include/swift/SIL/SILArgument.h

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ namespace swift {
2222

2323
class SILBasicBlock;
2424
class SILModule;
25+
class SILPhiArgument;
2526
class SILUndef;
2627
class TermInst;
2728

@@ -115,9 +116,15 @@ class SILArgument : public ValueBase {
115116

116117
unsigned getIndex() const;
117118

118-
/// Return true if this block argument is actually a phi argument as
119-
/// opposed to a cast or projection.
120-
bool isPhiArgument() const;
119+
/// Return non-null if \p value is a phi.
120+
static SILPhiArgument *isPhi(SILValue value);
121+
122+
/// Return non-null if \p value is a terminator result.
123+
static SILPhiArgument *isTerminatorResult(SILValue value);
124+
125+
/// Return true if this block argument is a phi as opposed to a terminator
126+
/// result.
127+
bool isPhi() const;
121128

122129
/// Return true if this block argument is a terminator result.
123130
bool isTerminatorResult() const;
@@ -217,12 +224,12 @@ class SILPhiArgument : public SILArgument {
217224
: SILArgument(ValueKind::SILPhiArgument, type, ownershipKind, decl) {}
218225

219226
public:
220-
/// Return true if this is block argument is actually a phi argument as
221-
/// opposed to a cast or projection.
222-
bool isPhiArgument() const;
227+
/// Return true if this is block argument is a phi, as opposed to a terminator
228+
/// result.
229+
bool isPhi() const;
223230

224231
/// Return true if this block argument is a terminator result.
225-
bool isTerminatorResult() const { return !isPhiArgument(); }
232+
bool isTerminatorResult() const { return !isPhi(); }
226233

227234
/// If this argument is a phi, return the incoming phi value for the given
228235
/// predecessor BB. If this argument is not a phi, return an invalid SILValue.
@@ -365,16 +372,34 @@ class SILFunctionArgument : public SILArgument {
365372
// Out of line Definitions for SILArgument to avoid Forward Decl issues
366373
//===----------------------------------------------------------------------===//
367374

368-
inline bool SILArgument::isPhiArgument() const {
375+
/// Return non-null if \p value is a real phi argument.
376+
inline SILPhiArgument *SILArgument::isPhi(SILValue value) {
377+
if (auto *arg = dyn_cast<SILPhiArgument>(value)) {
378+
if (arg->isPhi())
379+
return arg;
380+
}
381+
return nullptr;
382+
}
383+
384+
inline bool SILArgument::isPhi() const {
369385
switch (getKind()) {
370386
case SILArgumentKind::SILPhiArgument:
371-
return cast<SILPhiArgument>(this)->isPhiArgument();
387+
return cast<SILPhiArgument>(this)->isPhi();
372388
case SILArgumentKind::SILFunctionArgument:
373389
return false;
374390
}
375391
llvm_unreachable("Covered switch is not covered?!");
376392
}
377393

394+
/// Return non-null if \p value is a terminator result.
395+
inline SILPhiArgument *SILArgument::isTerminatorResult(SILValue value) {
396+
if (auto *arg = dyn_cast<SILPhiArgument>(value)) {
397+
if (arg->isTerminatorResult())
398+
return arg;
399+
}
400+
return nullptr;
401+
}
402+
378403
inline bool SILArgument::isNoImplicitCopy() const {
379404
if (auto *fArg = dyn_cast<SILFunctionArgument>(this))
380405
return fArg->isNoImplicitCopy();

include/swift/SIL/SILBasicBlock.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ struct PhiValue {
581581

582582
PhiValue(SILValue value) {
583583
auto *blockArg = dyn_cast<SILPhiArgument>(value);
584-
if (!blockArg || !blockArg->isPhiArgument())
584+
if (!blockArg || !blockArg->isPhi())
585585
return;
586586

587587
phiBlock = blockArg->getParent();
@@ -600,6 +600,11 @@ struct PhiValue {
600600
return cast<SILPhiArgument>(phiBlock->getArgument(argIndex));
601601
}
602602

603+
Operand *getOperand(SILBasicBlock *predecessor) {
604+
auto *branch = cast<BranchInst>(predecessor->getTerminator());
605+
return &branch->getAllOperands()[argIndex];
606+
}
607+
603608
operator SILValue() const { return getValue(); }
604609
SILValue operator*() const { return getValue(); }
605610
SILValue operator->() const { return getValue(); }

include/swift/SIL/SILBuilder.h

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -896,19 +896,18 @@ class SILBuilder {
896896
/// [trivial].
897897
///
898898
/// * Otherwise, emit an actual store_borrow.
899-
void emitStoreBorrowOperation(SILLocation loc, SILValue src,
900-
SILValue destAddr) {
899+
SILInstruction *emitStoreBorrowOperation(SILLocation loc, SILValue src,
900+
SILValue destAddr) {
901901
if (!hasOwnership()) {
902-
return emitStoreValueOperation(loc, src, destAddr,
903-
StoreOwnershipQualifier::Unqualified);
904-
}
905-
906-
if (src->getType().isTrivial(getFunction())) {
907-
return emitStoreValueOperation(loc, src, destAddr,
908-
StoreOwnershipQualifier::Trivial);
902+
emitStoreValueOperation(loc, src, destAddr,
903+
StoreOwnershipQualifier::Unqualified);
904+
} else if (src->getType().isTrivial(getFunction())) {
905+
emitStoreValueOperation(loc, src, destAddr,
906+
StoreOwnershipQualifier::Trivial);
907+
} else {
908+
createStoreBorrow(loc, src, destAddr);
909909
}
910-
911-
createStoreBorrow(loc, src, destAddr);
910+
return &*std::prev(getInsertionPoint());
912911
}
913912

914913
MarkUninitializedInst *
@@ -2691,7 +2690,7 @@ class SILBuilder {
26912690
// sync. We don't care if an instruction is used in global_addr.
26922691
if (F)
26932692
TheInst->verifyDebugInfo();
2694-
TheInst->verifyOperandOwnership();
2693+
TheInst->verifyOperandOwnership(&C.silConv);
26952694
#endif
26962695
}
26972696

include/swift/SIL/SILInstruction.h

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -567,19 +567,30 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
567567
bool maySuspend() const;
568568

569569
private:
570-
/// Predicate used to filter OperandValueRange.
570+
/// Functor for Operand::get()
571571
struct OperandToValue;
572-
/// Predicate used to filter TransformedOperandValueRange.
572+
/// Functor for Operand::get()
573+
struct OperandRefToValue;
574+
/// Predicate to filter NonTypeDependentOperandValueRange
575+
struct NonTypeDependentOperandToValue;
576+
/// Predicate to filter TransformedOperandValueRange.
573577
struct OperandToTransformedValue;
574578

575579
public:
576-
using OperandValueRange =
577-
OptionalTransformRange<ArrayRef<Operand>, OperandToValue>;
580+
using OperandValueRange = TransformRange<ArrayRef<Operand*>, OperandToValue>;
581+
using OperandRefValueRange =
582+
TransformRange<ArrayRef<Operand>, OperandRefToValue>;
583+
using NonTypeDependentOperandValueRange =
584+
OptionalTransformRange<ArrayRef<Operand>, NonTypeDependentOperandToValue>;
578585
using TransformedOperandValueRange =
579-
OptionalTransformRange<ArrayRef<Operand>, OperandToTransformedValue>;
586+
OptionalTransformRange<ArrayRef<Operand>, OperandToTransformedValue>;
587+
588+
static OperandValueRange getOperandValues(ArrayRef<Operand*> operands);
589+
590+
OperandRefValueRange getOperandValues() const;
591+
592+
NonTypeDependentOperandValueRange getNonTypeDependentOperandValues() const;
580593

581-
OperandValueRange
582-
getOperandValues(bool skipTypeDependentOperands = false) const;
583594
TransformedOperandValueRange
584595
getOperandValues(std::function<SILValue(SILValue)> transformFn,
585596
bool skipTypeDependentOperands) const;
@@ -762,7 +773,7 @@ class SILInstruction : public llvm::ilist_node<SILInstruction> {
762773

763774
/// Verify that all operands of this instruction have compatible ownership
764775
/// with this instruction.
765-
void verifyOperandOwnership() const;
776+
void verifyOperandOwnership(SILModuleConventions *silConv = nullptr) const;
766777

767778
/// Verify that this instruction and its associated debug information follow
768779
/// all SIL debug info invariants.
@@ -879,14 +890,24 @@ inline const SILNode *SILNode::instAsNode(const SILInstruction *inst) {
879890

880891

881892
struct SILInstruction::OperandToValue {
893+
SILValue operator()(const Operand *use) const {
894+
return use->get();
895+
}
896+
};
897+
898+
struct SILInstruction::OperandRefToValue {
899+
SILValue operator()(const Operand &use) const {
900+
return use.get();
901+
}
902+
};
903+
904+
struct SILInstruction::NonTypeDependentOperandToValue {
882905
const SILInstruction &i;
883-
bool skipTypeDependentOps;
884906

885-
OperandToValue(const SILInstruction &i, bool skipTypeDependentOps)
886-
: i(i), skipTypeDependentOps(skipTypeDependentOps) {}
907+
NonTypeDependentOperandToValue(const SILInstruction &i): i(i) {}
887908

888909
Optional<SILValue> operator()(const Operand &use) const {
889-
if (skipTypeDependentOps && i.isTypeDependentOperand(use))
910+
if (i.isTypeDependentOperand(use))
890911
return None;
891912
return use.get();
892913
}
@@ -910,11 +931,21 @@ struct SILInstruction::OperandToTransformedValue {
910931
}
911932
};
912933

934+
inline SILInstruction::OperandValueRange
935+
SILInstruction::getOperandValues(ArrayRef<Operand*> operands) {
936+
return OperandValueRange(operands, OperandToValue());
937+
}
938+
913939
inline auto
914-
SILInstruction::getOperandValues(bool skipTypeDependentOperands) const
915-
-> OperandValueRange {
916-
return OperandValueRange(getAllOperands(),
917-
OperandToValue(*this, skipTypeDependentOperands));
940+
SILInstruction::getOperandValues() const -> OperandRefValueRange {
941+
return OperandRefValueRange(getAllOperands(), OperandRefToValue());
942+
}
943+
944+
inline auto
945+
SILInstruction::getNonTypeDependentOperandValues() const
946+
-> NonTypeDependentOperandValueRange {
947+
return NonTypeDependentOperandValueRange(getAllOperands(),
948+
NonTypeDependentOperandToValue(*this));
918949
}
919950

920951
inline auto
@@ -1145,6 +1176,18 @@ class OwnershipForwardingMixin {
11451176
return isa(i);
11461177
return false;
11471178
}
1179+
1180+
/// Return true if the forwarded value has the same representation. If true,
1181+
/// then the result can be mapped to the same storage without a move or copy.
1182+
///
1183+
/// \p inst is an OwnershipForwardingMixin
1184+
static bool hasSameRepresentation(SILInstruction *inst);
1185+
1186+
/// Return true if the forwarded value is address-only either before or after
1187+
/// forwarding.
1188+
///
1189+
/// \p inst is an OwnershipForwardingMixin
1190+
static bool isAddressOnly(SILInstruction *inst);
11481191
};
11491192

11501193
/// A single value inst that forwards a static ownership from its first operand.

include/swift/SIL/SILValue.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class ConsumingUseIterator;
4646
class NonConsumingUseIterator;
4747
class NonTypeDependentUseIterator;
4848
class SILValue;
49+
class SILModuleConventions;
4950

5051
/// An enumeration which contains values for all the concrete ValueBase
5152
/// subclasses.
@@ -922,7 +923,8 @@ inline bool canAcceptUnownedValue(OperandOwnership operandOwnership) {
922923
}
923924

924925
/// Return true if all OperandOwnership invariants hold.
925-
bool checkOperandOwnershipInvariants(const Operand *operand);
926+
bool checkOperandOwnershipInvariants(const Operand *operand,
927+
SILModuleConventions *silConv = nullptr);
926928

927929
/// Return the OperandOwnership for a forwarded operand when the forwarding
928930
/// operation has this "forwarding ownership" (as returned by
@@ -1039,22 +1041,25 @@ class Operand {
10391041
/// Return the use ownership of this operand.
10401042
///
10411043
/// NOTE: This is implemented in OperandOwnership.cpp.
1042-
OperandOwnership getOperandOwnership() const;
1044+
OperandOwnership
1045+
getOperandOwnership(SILModuleConventions *silConv = nullptr) const;
10431046

10441047
/// Return the ownership constraint that restricts what types of values this
10451048
/// Operand can contain.
1046-
OwnershipConstraint getOwnershipConstraint() const {
1047-
return getOperandOwnership().getOwnershipConstraint();
1049+
OwnershipConstraint
1050+
getOwnershipConstraint(SILModuleConventions *silConv = nullptr) const {
1051+
return getOperandOwnership(silConv).getOwnershipConstraint();
10481052
}
10491053

10501054
/// Returns true if changing the operand to use a value with the given
10511055
/// ownership kind, without rewriting the instruction, would not cause the
10521056
/// operand to violate the operand's ownership constraints.
1053-
bool canAcceptKind(ValueOwnershipKind kind) const;
1057+
bool canAcceptKind(ValueOwnershipKind kind,
1058+
SILModuleConventions *silConv = nullptr) const;
10541059

10551060
/// Returns true if this operand and its value satisfy the operand's
10561061
/// operand constraint.
1057-
bool satisfiesConstraints() const;
1062+
bool satisfiesConstraints(SILModuleConventions *silConv = nullptr) const;
10581063

10591064
/// Returns true if this operand acts as a use that ends the lifetime its
10601065
/// associated value, either by consuming the owned value or ending the

include/swift/SILOptimizer/Utils/OwnershipOptUtils.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,16 @@ makeGuaranteedValueAvailable(SILValue value, SILInstruction *user,
7878
DeadEndBlocks &deBlocks,
7979
InstModCallbacks callbacks = InstModCallbacks());
8080

81+
/// Compute the liveness boundary for a guaranteed value. Returns true if no
82+
/// uses are pointer escapes. If pointer escapes are present, the liveness
83+
/// boundary is still valid for all known uses.
84+
///
85+
/// Precondition: \p value has guaranteed ownership and no reborrows. It is
86+
/// either an "inner" guaranteed value or a simple borrow introducer whose
87+
/// end_borrows have not yet been inserted.
88+
bool computeGuaranteedBoundary(SILValue value,
89+
PrunedLivenessBoundary &boundary);
90+
8191
//===----------------------------------------------------------------------===//
8292
// GuaranteedOwnershipExtension
8393
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)