Skip to content

Commit 1e039cc

Browse files
authored
Merge pull request #35563 from gottesmm/pr-cd7c9e97e46a0141e37f10fbfb74c094e0576ff3-followups
[ownership] cd7c9e9 followups
2 parents 4988127 + 90b23a6 commit 1e039cc

File tree

4 files changed

+114
-29
lines changed

4 files changed

+114
-29
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//===--- SmallPtrSetVector.h ----------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_BASIC_SMALLPTRSETVECTOR_H
14+
#define SWIFT_BASIC_SMALLPTRSETVECTOR_H
15+
16+
#include "swift/Basic/LLVM.h"
17+
#include "llvm/ADT/SetVector.h"
18+
#include "llvm/ADT/SmallPtrSet.h"
19+
#include "llvm/ADT/SmallVector.h"
20+
21+
namespace swift {
22+
23+
/// A SetVector that performs no allocations if smaller than a certain
24+
/// size. Uses a SmallPtrSet/SmallVector internally.
25+
template <typename T, unsigned VectorSize, unsigned SetSize = VectorSize>
26+
class SmallPtrSetVector : public llvm::SetVector<T, SmallVector<T, VectorSize>,
27+
SmallPtrSet<T, SetSize>> {
28+
public:
29+
SmallPtrSetVector() = default;
30+
31+
/// Initialize a SmallPtrSetVector with a range of elements
32+
template <typename It> SmallPtrSetVector(It Start, It End) {
33+
this->insert(Start, End);
34+
}
35+
};
36+
37+
} // namespace swift
38+
39+
namespace std {
40+
41+
/// Implement std::swap in terms of SmallSetVector swap.
42+
///
43+
/// This matches llvm's implementation for SmallSetVector.
44+
template <typename T, unsigned VectorSize, unsigned SetSize = VectorSize>
45+
inline void swap(swift::SmallPtrSetVector<T, VectorSize, SetSize> &LHS,
46+
swift::SmallPtrSetVector<T, VectorSize, SetSize> &RHS) {
47+
LHS.swap(RHS);
48+
}
49+
50+
} // end namespace std
51+
52+
#endif

lib/SIL/IR/SILValue.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ SILInstruction *ValueBase::getDefiningInsertionPoint() {
8383

8484
SILInstruction *ValueBase::getNextInstruction() {
8585
if (auto *inst = getDefiningInstruction())
86-
return std::next(inst);
86+
return &*std::next(inst->getIterator());
8787
if (auto *arg = dyn_cast<SILArgument>(this))
8888
return &*arg->getParentBlock()->begin();
8989
return nullptr;

lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp

Lines changed: 57 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -569,8 +569,14 @@ static bool canBeUsedAsCastDestination(SILValue value, CastInst *castInst,
569569

570570
SILInstruction *SILCombiner::visitUnconditionalCheckedCastAddrInst(
571571
UnconditionalCheckedCastAddrInst *uccai) {
572-
// Optimize the unconditional_checked_cast_addr in this pattern:
572+
573+
// Optimize the unconditional_checked_cast_addr in the following non-ossa/ossa
574+
// pattern:
575+
//
576+
// Non-OSSA Pattern
573577
//
578+
// %value = ...
579+
// ...
574580
// %box = alloc_existential_box $Error, $ConcreteError
575581
// %a = project_existential_box $ConcreteError in %b : $Error
576582
// store %value to %a : $*ConcreteError
@@ -581,33 +587,67 @@ SILInstruction *SILCombiner::visitUnconditionalCheckedCastAddrInst(
581587
// ConcreteError in %dest : $*ConcreteError
582588
//
583589
// to:
584-
// ...
590+
//
585591
// retain_value %value : $ConcreteError
592+
// ...
593+
// %box = alloc_existential_box $Error, $ConcreteError
594+
// %a = project_existential_box $ConcreteError in %b : $Error
595+
// store %value to %a : $*ConcreteError
596+
// %err = alloc_stack $Error
597+
// store %box to %err : $*Error
586598
// destroy_addr %err : $*Error
587599
// store %value to %dest $*ConcreteError
588600
//
589-
// This lets the alloc_existential_box become dead and it can be removed in
590-
// following optimizations.
601+
// OSSA Pattern:
602+
//
603+
// %value = ...
604+
// ...
605+
// %box = alloc_existential_box $Error, $ConcreteError
606+
// %a = project_existential_box $ConcreteError in %b : $Error
607+
// store %value to [init] %a : $*ConcreteError
608+
// %err = alloc_stack $Error
609+
// store %box to [init] %err : $*Error
610+
// %dest = alloc_stack $ConcreteError
611+
// unconditional_checked_cast_addr Error in %err : $*Error to
612+
// ConcreteError in %dest : $*ConcreteError
613+
//
614+
// to:
615+
//
616+
// %value_copy = copy_value %value
617+
// ...
618+
// %box = alloc_existential_box $Error, $ConcreteError
619+
// %a = project_existential_box $ConcreteError in %b : $Error
620+
// store %value to [init] %a : $*ConcreteError
621+
// %err = alloc_stack $Error
622+
// store %box to [init] %err : $*Error
623+
// destroy_addr %err : $*Error
624+
// store %value to %dest $*ConcreteError
625+
//
626+
// In both cases, this lets the alloc_existential_box become dead and it can
627+
// be removed in other subsequent optimizations.
591628
SILValue val = getConcreteValueOfExistentialBoxAddr(uccai->getSrc(), uccai);
592629
while (auto *cvi = dyn_cast_or_null<CopyValueInst>(val))
593630
val = cvi->getOperand();
594631
if (canBeUsedAsCastDestination(val, uccai, DA)) {
595632
// We need to copy the value at its insertion point.
596633
{
597-
auto *valInsertPt = val->getDefiningInsertionPoint();
598-
if (!valInsertPt)
634+
auto *nextInsertPt = val->getNextInstruction();
635+
if (!nextInsertPt)
599636
return nullptr;
600-
auto valInsertPtIter = valInsertPt->getIterator();
601637
// If our value is defined by an instruction (not an argument), we want to
602638
// insert the copy after that. Otherwise, we have an argument and we want
603639
// to insert the copy right at the beginning of the block.
604-
if (val->getDefiningInstruction())
605-
valInsertPtIter = std::next(valInsertPtIter);
606-
SILBuilderWithScope builder(valInsertPtIter, Builder);
607-
val = builder.emitCopyValueOperation(valInsertPtIter->getLoc(), val);
640+
SILBuilderWithScope builder(nextInsertPt, Builder);
641+
// We use an autogenerated location to ensure that if next is a
642+
// terminator, we do not trip an assertion around mismatched debug info.
643+
//
644+
// FIXME: We should find a better way of solving this than losing location
645+
// info!
646+
auto loc = RegularLocation::getAutoGeneratedLocation();
647+
val = builder.emitCopyValueOperation(loc, val);
608648
}
609649

610-
// Then we insert the destroy value/store at the cast location.
650+
// Then we insert the destroy addr/store at the cast location.
611651
SILBuilderWithScope builder(uccai, Builder);
612652
SILLocation loc = uccai->getLoc();
613653
builder.createDestroyAddr(loc, uccai->getSrc());
@@ -816,17 +856,12 @@ visitCheckedCastAddrBranchInst(CheckedCastAddrBranchInst *CCABI) {
816856
// We need to insert the copy after the defining instruction of val or at
817857
// the top of the block if val is an argument.
818858
{
819-
auto *valInsertPt = val->getDefiningInsertionPoint();
820-
if (!valInsertPt)
859+
auto *nextInsertPt = val->getNextInstruction();
860+
if (!nextInsertPt)
821861
return nullptr;
822-
auto valInsertPtIter = valInsertPt->getIterator();
823-
// If our value is defined by an instruction (not an argument), we want to
824-
// insert the copy after that. Otherwise, we have an argument and we want
825-
// to insert the copy right at the beginning of the block.
826-
if (val->getDefiningInstruction())
827-
valInsertPtIter = std::next(valInsertPtIter);
828-
SILBuilderWithScope builder(valInsertPtIter, Builder);
829-
val = builder.emitCopyValueOperation(valInsertPtIter->getLoc(), val);
862+
SILBuilderWithScope builder(nextInsertPt, Builder);
863+
auto loc = RegularLocation::getAutoGeneratedLocation();
864+
val = builder.emitCopyValueOperation(loc, val);
830865
}
831866

832867
SILBuilderWithScope builder(CCABI, Builder);

lib/SILOptimizer/Utils/InstOptUtils.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "swift/AST/GenericSignature.h"
1515
#include "swift/AST/SemanticAttrs.h"
1616
#include "swift/AST/SubstitutionMap.h"
17+
#include "swift/Basic/SmallPtrSetVector.h"
1718
#include "swift/SIL/ApplySite.h"
1819
#include "swift/SIL/BasicBlockUtils.h"
1920
#include "swift/SIL/DebugUtils.h"
@@ -701,11 +702,9 @@ SILValue swift::
701702
getConcreteValueOfExistentialBox(AllocExistentialBoxInst *existentialBox,
702703
SILInstruction *ignoreUser) {
703704
StoreInst *singleStore = nullptr;
704-
SmallVector<Operand *, 32> worklist;
705-
SmallPtrSet<Operand *, 8> addedToWorklistPreviously;
705+
SmallPtrSetVector<Operand *, 32> worklist;
706706
for (auto *use : getNonDebugUses(existentialBox)) {
707-
worklist.push_back(use);
708-
addedToWorklistPreviously.insert(use);
707+
worklist.insert(use);
709708
}
710709

711710
while (!worklist.empty()) {
@@ -722,8 +721,7 @@ getConcreteValueOfExistentialBox(AllocExistentialBoxInst *existentialBox,
722721
// Look through copy_value, begin_borrow
723722
for (SILValue result : user->getResults())
724723
for (auto *transitiveUse : result->getUses())
725-
if (!addedToWorklistPreviously.insert(transitiveUse).second)
726-
worklist.push_back(use);
724+
worklist.insert(transitiveUse);
727725
break;
728726
case SILInstructionKind::ProjectExistentialBoxInst: {
729727
auto *projectedAddr = cast<ProjectExistentialBoxInst>(user);

0 commit comments

Comments
 (0)