Skip to content

Commit 63f79b6

Browse files
authored
Merge pull request #32962 from atrick/5.3-templvalue
[5.3] SILOptimizer: A new "TempLValueOpt" optimization for copy_addr
2 parents c22f010 + ed2e6fb commit 63f79b6

File tree

12 files changed

+868
-3
lines changed

12 files changed

+868
-3
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,12 @@ class SILInstruction
375375
/// The instruction may read memory.
376376
MayRead,
377377
/// The instruction may write to memory.
378+
/// This includes destroying or taking from memory (e.g. destroy_addr,
379+
/// copy_addr [take], load [take]).
380+
/// Although, physically, destroying or taking does not modify the memory,
381+
/// it is important to model it is a write. Optimizations must not assume
382+
/// that the value stored in memory is still available for loading after
383+
/// the memory is destroyed or taken.
378384
MayWrite,
379385
/// The instruction may read or write memory.
380386
MayReadWrite,

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ PASS(PerformanceSILLinker, "performance-linker",
273273
"Deserialize all referenced SIL functions")
274274
PASS(RawSILInstLowering, "raw-sil-inst-lowering",
275275
"Lower all raw SIL instructions to canonical equivalents.")
276+
PASS(TempLValueOpt, "temp-lvalue-opt",
277+
"Remove short-lived immutable temporary l-values")
276278
PASS(TempRValueOpt, "temp-rvalue-opt",
277279
"Remove short-lived immutable temporary copies")
278280
PASS(SideEffectsDumper, "side-effects-dump",

lib/SILOptimizer/Analysis/AliasAnalysis.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,15 @@ AliasResult AliasAnalysis::alias(SILValue V1, SILValue V2,
569569
return Result;
570570
}
571571

572+
/// Get the underlying object, looking through init_enum_data_addr and
573+
/// init_existential_addr.
574+
static SILValue stripInitEnumAndExistentialAddr(SILValue v) {
575+
while (isa<InitEnumDataAddrInst>(v) || isa<InitExistentialAddrInst>(v)) {
576+
v = getUnderlyingObject(cast<SingleValueInstruction>(v)->getOperand(0));
577+
}
578+
return v;
579+
}
580+
572581
/// The main AA entry point. Performs various analyses on V1, V2 in an attempt
573582
/// to disambiguate the two values.
574583
AliasResult AliasAnalysis::aliasInner(SILValue V1, SILValue V2,
@@ -614,9 +623,12 @@ AliasResult AliasAnalysis::aliasInner(SILValue V1, SILValue V2,
614623
LLVM_DEBUG(llvm::dbgs() << " Underlying V1:" << *O1);
615624
LLVM_DEBUG(llvm::dbgs() << " Underlying V2:" << *O2);
616625

617-
// If O1 and O2 do not equal, see if we can prove that they cannot be the
618-
// same object. If we can, return No Alias.
619-
if (O1 != O2 && aliasUnequalObjects(O1, O2))
626+
// If the underlying objects are not equal, see if we can prove that they
627+
// cannot be the same object. If we can, return No Alias.
628+
// For this we even look through init_enum_data_addr and init_existential_addr.
629+
SILValue StrippedO1 = stripInitEnumAndExistentialAddr(O1);
630+
SILValue StrippedO2 = stripInitEnumAndExistentialAddr(O2);
631+
if (StrippedO1 != StrippedO2 && aliasUnequalObjects(StrippedO1, StrippedO2))
620632
return AliasResult::NoAlias;
621633

622634
// Ok, either O1, O2 are the same or we could not prove anything based off of

lib/SILOptimizer/Analysis/MemoryBehavior.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ class MemoryBehaviorVisitor
173173

174174
MemBehavior visitLoadInst(LoadInst *LI);
175175
MemBehavior visitStoreInst(StoreInst *SI);
176+
MemBehavior visitCopyAddrInst(CopyAddrInst *CAI);
176177
MemBehavior visitApplyInst(ApplyInst *AI);
177178
MemBehavior visitTryApplyInst(TryApplyInst *AI);
178179
MemBehavior visitBuiltinInst(BuiltinInst *BI);
@@ -243,6 +244,10 @@ MemBehavior MemoryBehaviorVisitor::visitLoadInst(LoadInst *LI) {
243244
if (!mayAlias(LI->getOperand()))
244245
return MemBehavior::None;
245246

247+
// A take is modelled as a write. See MemoryBehavior::MayWrite.
248+
if (LI->getOwnershipQualifier() == LoadOwnershipQualifier::Take)
249+
return MemBehavior::MayReadWrite;
250+
246251
LLVM_DEBUG(llvm::dbgs() << " Could not prove that load inst does not alias "
247252
"pointer. Returning may read.\n");
248253
return MemBehavior::MayRead;
@@ -266,6 +271,34 @@ MemBehavior MemoryBehaviorVisitor::visitStoreInst(StoreInst *SI) {
266271
return MemBehavior::MayWrite;
267272
}
268273

274+
MemBehavior MemoryBehaviorVisitor::visitCopyAddrInst(CopyAddrInst *CAI) {
275+
// If it's an assign to the destination, a destructor might be called on the
276+
// old value. This can have any side effects.
277+
// We could also check if it's a trivial type (which cannot have any side
278+
// effect on destruction), but such copy_addr instructions are optimized to
279+
// load/stores anyway, so it's probably not worth it.
280+
if (!CAI->isInitializationOfDest())
281+
return MemBehavior::MayHaveSideEffects;
282+
283+
bool mayWrite = mayAlias(CAI->getDest());
284+
bool mayRead = mayAlias(CAI->getSrc());
285+
286+
if (mayRead) {
287+
if (mayWrite)
288+
return MemBehavior::MayReadWrite;
289+
290+
// A take is modelled as a write. See MemoryBehavior::MayWrite.
291+
if (CAI->isTakeOfSrc())
292+
return MemBehavior::MayReadWrite;
293+
294+
return MemBehavior::MayRead;
295+
}
296+
if (mayWrite)
297+
return MemBehavior::MayWrite;
298+
299+
return MemBehavior::None;
300+
}
301+
269302
MemBehavior MemoryBehaviorVisitor::visitBuiltinInst(BuiltinInst *BI) {
270303
// If our callee is not a builtin, be conservative and return may have side
271304
// effects.

lib/SILOptimizer/PassManager/PassPipeline.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,9 @@ void addSSAPasses(SILPassPipelinePlan &P, OptimizationLevelKind OpLevel) {
275275
// splits up copy_addr.
276276
P.addCopyForwarding();
277277

278+
// Optimize copies from a temporary (an "l-value") to a destination.
279+
P.addTempLValueOpt();
280+
278281
// Split up opaque operations (copy_addr, retain_value, etc.).
279282
P.addLowerAggregateInstrs();
280283

lib/SILOptimizer/Transforms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ silopt_register_sources(
3535
Sink.cpp
3636
SpeculativeDevirtualizer.cpp
3737
StackPromotion.cpp
38+
TempLValueOpt.cpp
3839
TempRValueElimination.cpp
3940
UnsafeGuaranteedPeephole.cpp
4041
)

0 commit comments

Comments
 (0)