Skip to content

Commit c47946a

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents 5c04790 + 9209e23 commit c47946a

22 files changed

+1268
-596
lines changed

include/swift/SIL/ApplySite.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ class ApplySite {
116116

117117
ApplySiteKind getKind() const { return ApplySiteKind(Inst->getKind()); }
118118

119+
SILInstruction *operator*() const { return Inst; }
120+
SILInstruction *operator->() const { return Inst; }
121+
119122
explicit operator bool() const { return Inst != nullptr; }
120123

121124
SILInstruction *getInstruction() const { return Inst; }

include/swift/SIL/OwnershipUtils.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,13 +189,13 @@ struct BorrowingOperand {
189189

190190
// A set of operators so that a BorrowingOperand can be used like a normal
191191
// operand in a light weight way.
192-
operator const Operand *() const { return op; }
193-
operator Operand *() { return op; }
194192
const Operand *operator*() const { return op; }
195193
Operand *operator*() { return op; }
196194
const Operand *operator->() const { return op; }
197195
Operand *operator->() { return op; }
198196

197+
operator bool() const { return kind != BorrowingOperandKind::Invalid && op; }
198+
199199
/// If \p op is a borrow introducing operand return it after doing some
200200
/// checks.
201201
static BorrowingOperand get(Operand *op) {

include/swift/SIL/SILType.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,13 @@ class SILType {
429429
SILType getEnumElementType(EnumElementDecl *elt, SILModule &M,
430430
TypeExpansionContext context) const;
431431

432+
/// Given that this is an enum type, return the lowered type of the
433+
/// data for the given element. Applies substitutions as necessary.
434+
/// The result will have the same value category as the base type.
435+
///
436+
/// NOTE: Takes the type expansion context from \p fn.
437+
SILType getEnumElementType(EnumElementDecl *elt, SILFunction *fn) const;
438+
432439
/// Given that this is an enum type, return true if this type is effectively
433440
/// exhausted.
434441
bool isEffectivelyExhaustiveEnumType(SILFunction *f);

include/swift/SILOptimizer/Utils/InstOptUtils.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,11 @@ SILValue
705705
makeNewValueAvailable(SILValue value, SILBasicBlock *inBlock,
706706
JointPostDominanceSetComputer *jointPostDomComputer);
707707

708+
/// Given a forwarding instruction, eliminate it if all of its users are debug
709+
/// instructions and ownership uses.
710+
bool tryEliminateOnlyOwnershipUsedForwardingInst(
711+
SingleValueInstruction *forwardingInst, InstModCallbacks &callbacks);
712+
708713
} // end namespace swift
709714

710715
#endif

include/swift/SILOptimizer/Utils/OwnershipOptUtils.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#ifndef SWIFT_SILOPTIMIZER_UTILS_OWNERSHIPOPTUTILS_H
2020
#define SWIFT_SILOPTIMIZER_UTILS_OWNERSHIPOPTUTILS_H
2121

22+
#include "swift/Basic/Defer.h"
2223
#include "swift/SIL/BasicBlockUtils.h"
2324
#include "swift/SIL/OwnershipUtils.h"
2425
#include "swift/SIL/SILModule.h"
@@ -76,6 +77,17 @@ struct OwnershipFixupContext {
7677
extraAddressFixupInfo.intPtrOp = InteriorPointerOperand();
7778
}
7879

80+
/// Gets access to the joint post dominance computer and clears it after \p
81+
/// callback.
82+
template <typename ResultTy>
83+
ResultTy withJointPostDomComputer(
84+
function_ref<ResultTy(JointPostDominanceSetComputer &)> callback) {
85+
// Make sure we clear the joint post dom computer after callback.
86+
SWIFT_DEFER { jointPostDomSetComputer.clear(); };
87+
// Then return callback passing in the computer.
88+
return callback(jointPostDomSetComputer);
89+
}
90+
7991
private:
8092
/// Helper method called to determine if we discovered we needed interior
8193
/// pointer fixups while simplifying.
@@ -129,6 +141,37 @@ class OwnershipRAUWHelper {
129141
SILValue newValue);
130142
};
131143

144+
/// A utility composed ontop of OwnershipFixupContext that knows how to replace
145+
/// a single use of a value with another value with a different ownership. We
146+
/// allow for the values to have different types.
147+
///
148+
/// NOTE: When not in OSSA, this just performs a normal set use, so this code is
149+
/// safe to use with all code.
150+
class OwnershipReplaceSingleUseHelper {
151+
OwnershipFixupContext *ctx;
152+
Operand *use;
153+
SILValue newValue;
154+
155+
public:
156+
OwnershipReplaceSingleUseHelper()
157+
: ctx(nullptr), use(nullptr), newValue(nullptr) {}
158+
159+
/// Return an instance of this class if we support replacing \p use->get()
160+
/// with \p newValue.
161+
///
162+
/// NOTE: For now we only support objects, not addresses so addresses will
163+
/// always yield an invalid helper.
164+
OwnershipReplaceSingleUseHelper(OwnershipFixupContext &ctx, Operand *use,
165+
SILValue newValue);
166+
167+
/// Returns true if this helper was initialized into a valid state.
168+
operator bool() const { return isValid(); }
169+
bool isValid() const { return bool(ctx) && bool(use) && bool(newValue); }
170+
171+
/// Perform the actual RAUW.
172+
SILBasicBlock::iterator perform();
173+
};
174+
132175
} // namespace swift
133176

134177
#endif

lib/SIL/IR/SILType.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,12 @@ SILType SILType::getEnumElementType(EnumElementDecl *elt, SILModule &M,
195195
return getEnumElementType(elt, M.Types, context);
196196
}
197197

198+
SILType SILType::getEnumElementType(EnumElementDecl *elt,
199+
SILFunction *fn) const {
200+
return getEnumElementType(elt, fn->getModule(),
201+
fn->getTypeExpansionContext());
202+
}
203+
198204
bool SILType::isLoadableOrOpaque(const SILFunction &F) const {
199205
SILModule &M = F.getModule();
200206
return isLoadable(F) || !SILModuleConventions(M).useLoweredAddresses();

lib/SIL/Verifier/MemoryLifetime.cpp

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,36 @@ int MemoryLocations::getLocationIdx(SILValue addr) const {
132132
return iter->second;
133133
}
134134

135+
static bool canHandleAllocStack(AllocStackInst *asi) {
136+
assert(asi);
137+
138+
// An alloc_stack with dynamic lifetime set has a lifetime that relies on
139+
// unrelated conditional control flow for correctness. This means that we may
140+
// statically leak along paths that were known by the emitter to never be
141+
// taken if the value is live. So bail since we can't verify this.
142+
if (asi->hasDynamicLifetime())
143+
return false;
144+
145+
// Currently in this verifier, we stop verifying if we find a switch_enum_addr
146+
// use. This creates a problem since no one has gone through and changed the
147+
// frontend/optimizer to understand that it needs to insert destroy_addr on
148+
// alloc_stack even if dynamically we know that the enum has a trivial case or
149+
// non-payloaded case due to a switch_enum_addr. So if one then performs the
150+
// completely unrelated, valid optimization of promoting the switch_enum_addr
151+
// to a switch_enum (lets say using a load_borrow), then this verifier will
152+
// see a leaked value along the non-payloaded path.
153+
//
154+
// Disable this verification for now until a complete analysis of enums is
155+
// implemented.
156+
//
157+
// https://bugs.swift.org/browse/SR-14123
158+
if (asi->getType().getEnumOrBoundGenericEnum())
159+
return false;
160+
161+
// Otherwise we can optimize!
162+
return true;
163+
}
164+
135165
void MemoryLocations::analyzeLocations(SILFunction *function) {
136166
// As we have to limit the set of handled locations to memory, which is
137167
// guaranteed to be not aliased, we currently only handle indirect function
@@ -152,12 +182,13 @@ void MemoryLocations::analyzeLocations(SILFunction *function) {
152182
}
153183
for (SILBasicBlock &BB : *function) {
154184
for (SILInstruction &I : BB) {
155-
auto *ASI = dyn_cast<AllocStackInst>(&I);
156-
if (ASI && !ASI->hasDynamicLifetime()) {
157-
if (allUsesInSameBlock(ASI)) {
158-
singleBlockLocations.push_back(ASI);
159-
} else {
160-
analyzeLocation(ASI);
185+
if (auto *ASI = dyn_cast<AllocStackInst>(&I)) {
186+
if (canHandleAllocStack(ASI)) {
187+
if (allUsesInSameBlock(ASI)) {
188+
singleBlockLocations.push_back(ASI);
189+
} else {
190+
analyzeLocation(ASI);
191+
}
161192
}
162193
}
163194
}

lib/SILOptimizer/Analysis/SimplifyInstruction.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ namespace {
7070
SILValue visitPointerToThinFunctionInst(PointerToThinFunctionInst *PTTFI);
7171
SILValue visitBeginAccessInst(BeginAccessInst *BAI);
7272
SILValue visitMetatypeInst(MetatypeInst *MTI);
73+
SILValue visitConvertFunctionInst(ConvertFunctionInst *cfi);
7374

7475
SILValue simplifyOverflowBuiltin(BuiltinInst *BI);
7576
};
@@ -482,6 +483,19 @@ SILValue InstSimplifier::visitBeginAccessInst(BeginAccessInst *BAI) {
482483
return SILValue();
483484
}
484485

486+
SILValue InstSimplifier::visitConvertFunctionInst(ConvertFunctionInst *cfi) {
487+
// Eliminate round trip convert_function. Non round-trip is performed in
488+
// SILCombine.
489+
//
490+
// (convert_function Y->X (convert_function x X->Y)) -> x
491+
SILValue convertedValue = lookThroughOwnershipInsts(cfi->getConverted());
492+
if (auto *subCFI = dyn_cast<ConvertFunctionInst>(convertedValue))
493+
if (subCFI->getConverted()->getType() == cfi->getType())
494+
return lookThroughOwnershipInsts(subCFI->getConverted());
495+
496+
return SILValue();
497+
}
498+
485499
SILValue InstSimplifier::visitMetatypeInst(MetatypeInst *MI) {
486500
auto metaType = MI->getType().castTo<MetatypeType>();
487501
auto instanceType = metaType.getInstanceType();

lib/SILOptimizer/SILCombiner/SILCombiner.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#ifndef SWIFT_SILOPTIMIZER_PASSMANAGER_SILCOMBINER_H
2222
#define SWIFT_SILOPTIMIZER_PASSMANAGER_SILCOMBINER_H
2323

24+
#include "swift/Basic/Defer.h"
2425
#include "swift/SIL/BasicBlockUtils.h"
2526
#include "swift/SIL/SILBuilder.h"
2627
#include "swift/SIL/SILInstruction.h"
@@ -433,6 +434,21 @@ class SILCombiner :
433434
/// Returns true if the results of a try_apply are not used.
434435
static bool isTryApplyResultNotUsed(UserListTy &AcceptedUses,
435436
TryApplyInst *TAI);
437+
438+
bool hasOwnership() const {
439+
return Builder.hasOwnership();
440+
}
441+
442+
/// Gets access to the joint post dominance computer and clears it after \p
443+
/// callback.
444+
template <typename ResultTy>
445+
ResultTy withJointPostDomComputer(
446+
function_ref<ResultTy(JointPostDominanceSetComputer &)> callback) {
447+
// Make sure we clear the joint post dom computer after callback.
448+
SWIFT_DEFER { jPostDomComputer.clear(); };
449+
// Then return callback passing in the computer.
450+
return callback(jPostDomComputer);
451+
}
436452
};
437453

438454
} // end namespace swift

0 commit comments

Comments
 (0)