Skip to content

Commit b7b93a1

Browse files
authored
Merge pull request swiftlang#74329 from eeckstein/fix-block-cloning
SIL: update borrowed-from instructions when cloning a basic block
2 parents 3dd4198 + d80813e commit b7b93a1

File tree

3 files changed

+89
-29
lines changed

3 files changed

+89
-29
lines changed

include/swift/SIL/SILCloner.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ class SILCloner : protected SILInstructionVisitor<ImplClass> {
8787
/// blocks.
8888
llvm::DenseMap<SILBasicBlock*, SILBasicBlock*> BBMap;
8989

90+
/// Blocks, where edge-spitting may have "converted" terminator result
91+
/// arguments to phi-arguments.
92+
llvm::SmallVector<SILBasicBlock *> blocksWithNewPhiArgs;
93+
9094
private:
9195
/// MARK: Private state hidden from CRTP extensions.
9296

@@ -872,9 +876,15 @@ void SILCloner<ImplClass>::visitBlocksDepthFirst(SILBasicBlock *startBB) {
872876
&& isa<BranchInst>(BB->getTerminator())) {
873877
continue;
874878
}
879+
TermInst *term = BB->getTerminator();
880+
881+
// After edge-spitting, terminator result arguments become phi arguments.
882+
if (!isa<BranchInst>(term))
883+
blocksWithNewPhiArgs.push_back(BB->getSuccessors()[succIdx]);
884+
875885
// This predecessor has multiple successors, so cloning it without
876886
// cloning its successors would create a critical edge.
877-
splitEdge(BB->getTerminator(), succIdx, DomTree);
887+
splitEdge(term, succIdx, DomTree);
878888
assert(!BBMap.count(BB->getSuccessors()[succIdx]));
879889
}
880890
// Map the successor to a new BB. Layout the cloned blocks in the order

lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -125,41 +125,47 @@ void BasicBlockCloner::updateSSAAfterCloning() {
125125
break;
126126
}
127127
}
128-
if (!needsSSAUpdate)
129-
return;
130-
131-
SILSSAUpdater ssaUpdater(&updateSSAPhis);
132-
for (auto availValPair : availVals) {
133-
auto inst = availValPair.first;
134-
if (inst->use_empty())
135-
continue;
128+
if (needsSSAUpdate) {
129+
SILSSAUpdater ssaUpdater(&updateSSAPhis);
130+
for (auto availValPair : availVals) {
131+
auto inst = availValPair.first;
132+
if (inst->use_empty())
133+
continue;
136134

137-
SILValue newResult(availValPair.second);
135+
SILValue newResult(availValPair.second);
138136

139-
SmallVector<UseWrapper, 16> useList;
140-
// Collect the uses of the value.
141-
for (auto *use : inst->getUses())
142-
useList.push_back(UseWrapper(use));
137+
SmallVector<UseWrapper, 16> useList;
138+
// Collect the uses of the value.
139+
for (auto *use : inst->getUses())
140+
useList.push_back(UseWrapper(use));
143141

144-
ssaUpdater.initialize(inst->getFunction(), inst->getType(),
145-
inst->getOwnershipKind());
146-
ssaUpdater.addAvailableValue(origBB, inst);
147-
ssaUpdater.addAvailableValue(getNewBB(), newResult);
142+
ssaUpdater.initialize(inst->getFunction(), inst->getType(),
143+
inst->getOwnershipKind());
144+
ssaUpdater.addAvailableValue(origBB, inst);
145+
ssaUpdater.addAvailableValue(getNewBB(), newResult);
148146

149-
if (useList.empty())
150-
continue;
147+
if (useList.empty())
148+
continue;
151149

152-
// Update all the uses.
153-
for (auto useWrapper : useList) {
154-
Operand *use = useWrapper; // unwrap
155-
SILInstruction *user = use->getUser();
156-
assert(user && "Missing user");
150+
// Update all the uses.
151+
for (auto useWrapper : useList) {
152+
Operand *use = useWrapper; // unwrap
153+
SILInstruction *user = use->getUser();
154+
assert(user && "Missing user");
157155

158-
// Ignore uses in the same basic block.
159-
if (user->getParent() == origBB)
160-
continue;
156+
// Ignore uses in the same basic block.
157+
if (user->getParent() == origBB)
158+
continue;
161159

162-
ssaUpdater.rewriteUse(*use);
160+
ssaUpdater.rewriteUse(*use);
161+
}
162+
}
163+
}
164+
for (SILBasicBlock *b : blocksWithNewPhiArgs) {
165+
for (SILArgument *arg : b->getArguments()) {
166+
if (arg->getOwnershipKind() == OwnershipKind::Guaranteed) {
167+
updateSSAPhis.push_back(cast<SILPhiArgument>(arg));
168+
}
163169
}
164170
}
165171
updateBorrowedFromPhis(pm, updateSSAPhis);

test/SILOptimizer/simplify_cfg_ossa.sil

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class Klass {
2525
var a: Int
2626
deinit
2727
init()
28+
func foo() -> Int?
2829
}
2930

3031
class B {}
@@ -38,6 +39,10 @@ struct KlassWrapper {
3839
var k: Klass
3940
}
4041

42+
struct OptionalKlassWrapper {
43+
@_hasStorage var k: Optional<Klass>
44+
}
45+
4146
internal enum CompareResult {
4247
case equal
4348
case less
@@ -1843,3 +1848,42 @@ bb10(%7 : $()):
18431848
bb11:
18441849
unreachable
18451850
}
1851+
1852+
// CHECK-LABEL: sil [ossa] @jump_threading_creates_phi :
1853+
// CHECK: = borrowed %{{[0-9]+}} : $Klass from (%1 : $OptionalKlassWrapper)
1854+
// CHECK: } // end sil function 'jump_threading_creates_phi'
1855+
sil [ossa] @jump_threading_creates_phi: $@convention(thin) (Optional<A>, @guaranteed OptionalKlassWrapper) -> () {
1856+
bb0(%0 : $Optional<A>, %1 : @guaranteed $OptionalKlassWrapper):
1857+
%2 = alloc_stack [lexical] $Optional<A>
1858+
store %0 to [trivial] %2 : $*Optional<A>
1859+
switch_enum_addr %2 : $*Optional<A>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
1860+
1861+
bb1:
1862+
%5 = unchecked_take_enum_data_addr %2 : $*Optional<A>, #Optional.some!enumelt
1863+
%6 = load [trivial] %5 : $*A
1864+
br bb3(%6 : $A)
1865+
1866+
bb2:
1867+
%8 = enum $A, #A.B!enumelt
1868+
br bb3(%8 : $A)
1869+
1870+
bb3(%10 : $A):
1871+
dealloc_stack %2 : $*Optional<A>
1872+
%12 = enum $Optional<A>, #Optional.some!enumelt, %10 : $A
1873+
%13 = struct_extract %1 : $OptionalKlassWrapper, #OptionalKlassWrapper.k
1874+
switch_enum %13 : $Optional<Klass>, case #Optional.some!enumelt: bb4, case #Optional.none!enumelt: bb5
1875+
1876+
bb4(%15 : @guaranteed $Klass):
1877+
%16 = class_method %15 : $Klass, #Klass.foo : (Klass) -> () -> Int?, $@convention(method) (@guaranteed Klass) -> Optional<Int>
1878+
%17 = apply %16(%15) : $@convention(method) (@guaranteed Klass) -> Optional<Int>
1879+
br bb6(%17 : $Optional<Int>)
1880+
1881+
bb5:
1882+
%19 = enum $Optional<Int>, #Optional.none!enumelt
1883+
br bb6(%19 : $Optional<Int>)
1884+
1885+
bb6(%21 : $Optional<Int>):
1886+
%22 = tuple ()
1887+
return %22 : $()
1888+
}
1889+

0 commit comments

Comments
 (0)