Skip to content

Commit f096787

Browse files
authored
Merge pull request #78384 from eeckstein/enable-code-motion-in-ossa
Optimizer: enable SILCodeMotion in OSSA, but only for trivial values.
2 parents db21128 + 53d78ab commit f096787

File tree

8 files changed

+143
-46
lines changed

8 files changed

+143
-46
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/PhiUpdater.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ private func createBorrowedFrom(for phi: Phi, _ context: some MutatingContext) {
126126
if !phi.value.uses.contains(where: { $0.forwardingBorrowedFromUser != nil }) {
127127
let builder = Builder(atBeginOf: phi.value.parentBlock, context)
128128
let bfi = builder.createBorrowedFrom(borrowedValue: phi.value, enclosingValues: [])
129-
phi.value.uses.ignore(user: bfi).replaceAll(with: bfi, context)
129+
phi.value.uses.ignoreUsers(ofType: BorrowedFromInst.self).replaceAll(with: bfi, context)
130130
}
131131
}
132132

include/swift/SILOptimizer/Utils/OwnershipOptUtils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ void updateGuaranteedPhis(SILPassManager *pm, ArrayRef<SILPhiArgument *> phis);
367367
/// Replaces phis with the unique incoming values if all incoming values are the same.
368368
void replacePhisWithIncomingValues(SILPassManager *pm, ArrayRef<SILPhiArgument *> phis);
369369

370+
bool hasOwnershipOperandsOrResults(SILInstruction *inst);
371+
370372
} // namespace swift
371373

372374
#endif

lib/SILOptimizer/LoopTransforms/LICM.cpp

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "swift/SILOptimizer/PassManager/Transforms.h"
3333
#include "swift/SILOptimizer/Utils/CFGOptUtils.h"
3434
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
35+
#include "swift/SILOptimizer/Utils/OwnershipOptUtils.h"
3536
#include "swift/SILOptimizer/Utils/SILSSAUpdater.h"
3637

3738
#include "llvm/ADT/DepthFirstIterator.h"
@@ -849,21 +850,6 @@ static bool analyzeBeginAccess(BeginAccessInst *BI,
849850
return true;
850851
}
851852

852-
static bool hasOwnershipOperandsOrResults(SILInstruction *inst) {
853-
if (!inst->getFunction()->hasOwnership())
854-
return false;
855-
856-
for (SILValue result : inst->getResults()) {
857-
if (result->getOwnershipKind() != OwnershipKind::None)
858-
return true;
859-
}
860-
for (Operand &op : inst->getAllOperands()) {
861-
if (op.get()->getOwnershipKind() != OwnershipKind::None)
862-
return true;
863-
}
864-
return false;
865-
}
866-
867853
// Analyzes current loop for hosting/sinking potential:
868854
// Computes set of instructions we may be able to move out of the loop
869855
// Important Note:

lib/SILOptimizer/Transforms/SILCodeMotion.cpp

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "swift/SILOptimizer/PassManager/Passes.h"
2828
#include "swift/SILOptimizer/PassManager/Transforms.h"
2929
#include "swift/SILOptimizer/Utils/InstOptUtils.h"
30+
#include "swift/SILOptimizer/Utils/OwnershipOptUtils.h"
3031
#include "llvm/ADT/STLExtras.h"
3132
#include "llvm/ADT/Statistic.h"
3233
#include "llvm/Support/CommandLine.h"
@@ -917,6 +918,8 @@ static const int SinkSearchWindow = 6;
917918

918919
/// Returns True if we can sink this instruction to another basic block.
919920
static bool canSinkInstruction(SILInstruction *Inst) {
921+
if (hasOwnershipOperandsOrResults(Inst))
922+
return false;
920923
return !Inst->hasUsesOfAnyResult() && !isa<TermInst>(Inst);
921924
}
922925

@@ -1178,6 +1181,9 @@ static bool sinkArgument(EnumCaseDataflowContext &Context, SILBasicBlock *BB, un
11781181
if (!FSI || !hasOneNonDebugUse(FSI))
11791182
return false;
11801183

1184+
if (hasOwnershipOperandsOrResults(FSI))
1185+
return false;
1186+
11811187
// The list of identical instructions.
11821188
SmallVector<SingleValueInstruction *, 8> Clones;
11831189
Clones.push_back(FSI);
@@ -1743,38 +1749,43 @@ static bool processFunction(SILFunction *F, AliasAnalysis *AA,
17431749
LLVM_DEBUG(llvm::dbgs() << " Merging predecessors!\n");
17441750
State.mergePredecessorStates();
17451751

1746-
// If our predecessors cover any of our enum values, attempt to hoist
1747-
// releases up the CFG onto enum payloads or sink retains out of switch
1748-
// regions.
1749-
LLVM_DEBUG(llvm::dbgs() << " Attempting to move releases into "
1750-
"predecessors!\n");
1751-
1752-
// Perform a relatively local forms of retain sinking and release hoisting
1753-
// regarding switch regions and SILargument. This are not handled by retain
1754-
// release code motion.
1755-
if (HoistReleases) {
1756-
Changed |= State.hoistDecrementsIntoSwitchRegions(AA);
1757-
}
1752+
if (!F->hasOwnership()) {
1753+
// If our predecessors cover any of our enum values, attempt to hoist
1754+
// releases up the CFG onto enum payloads or sink retains out of switch
1755+
// regions.
1756+
LLVM_DEBUG(llvm::dbgs() << " Attempting to move releases into "
1757+
"predecessors!\n");
1758+
1759+
// Perform a relatively local forms of retain sinking and release hoisting
1760+
// regarding switch regions and SILargument. This are not handled by retain
1761+
// release code motion.
1762+
if (HoistReleases) {
1763+
Changed |= State.hoistDecrementsIntoSwitchRegions(AA);
1764+
}
17581765

1759-
// Sink switch related retains.
1760-
Changed |= sinkIncrementsIntoSwitchRegions(State.getBB(), AA, RCIA);
1761-
Changed |= State.sinkIncrementsOutOfSwitchRegions(AA, RCIA);
1766+
// Sink switch related retains.
1767+
Changed |= sinkIncrementsIntoSwitchRegions(State.getBB(), AA, RCIA);
1768+
Changed |= State.sinkIncrementsOutOfSwitchRegions(AA, RCIA);
17621769

1763-
// Then attempt to sink code from predecessors. This can include retains
1764-
// which is why we always attempt to move releases up the CFG before sinking
1765-
// code from predecessors. We will never sink the hoisted releases from
1766-
// predecessors since the hoisted releases will be on the enum payload
1767-
// instead of the enum itself.
1768-
Changed |= canonicalizeRefCountInstrs(State.getBB());
1770+
// Then attempt to sink code from predecessors. This can include retains
1771+
// which is why we always attempt to move releases up the CFG before sinking
1772+
// code from predecessors. We will never sink the hoisted releases from
1773+
// predecessors since the hoisted releases will be on the enum payload
1774+
// instead of the enum itself.
1775+
Changed |= canonicalizeRefCountInstrs(State.getBB());
1776+
}
17691777
Changed |= sinkCodeFromPredecessors(BBToStateMap, State.getBB());
17701778
Changed |= sinkArgumentsFromPredecessors(BBToStateMap, State.getBB());
17711779
Changed |= sinkLiteralsFromPredecessors(State.getBB());
1772-
// Try to hoist release of a SILArgument to predecessors.
1773-
Changed |= hoistSILArgumentReleaseInst(State.getBB());
17741780

1775-
// Then perform the dataflow.
1776-
LLVM_DEBUG(llvm::dbgs() << " Performing the dataflow!\n");
1777-
Changed |= State.process();
1781+
if (!F->hasOwnership()) {
1782+
// Try to hoist release of a SILArgument to predecessors.
1783+
Changed |= hoistSILArgumentReleaseInst(State.getBB());
1784+
1785+
// Then perform the dataflow.
1786+
LLVM_DEBUG(llvm::dbgs() << " Performing the dataflow!\n");
1787+
Changed |= State.process();
1788+
}
17781789
}
17791790

17801791
return Changed;
@@ -1791,9 +1802,6 @@ class SILCodeMotion : public SILFunctionTransform {
17911802
/// The entry point to the transformation.
17921803
void run() override {
17931804
auto *F = getFunction();
1794-
// Skip functions with ownership for now.
1795-
if (F->hasOwnership())
1796-
return;
17971805

17981806
auto *AA = getAnalysis<AliasAnalysis>(F);
17991807
auto *PO = getAnalysis<PostOrderAnalysis>()->get(F);

lib/SILOptimizer/Utils/OwnershipOptUtils.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1951,3 +1951,18 @@ void swift::replacePhisWithIncomingValues(SILPassManager *pm, ArrayRef<SILPhiArg
19511951
}
19521952
replacePhisWithIncomingValuesFunction({pm->getSwiftPassInvocation()}, ArrayRef(bridgedPhis));
19531953
}
1954+
1955+
bool swift::hasOwnershipOperandsOrResults(SILInstruction *inst) {
1956+
if (!inst->getFunction()->hasOwnership())
1957+
return false;
1958+
1959+
for (SILValue result : inst->getResults()) {
1960+
if (result->getOwnershipKind() != OwnershipKind::None)
1961+
return true;
1962+
}
1963+
for (Operand &op : inst->getAllOperands()) {
1964+
if (op.get()->getOwnershipKind() != OwnershipKind::None)
1965+
return true;
1966+
}
1967+
return false;
1968+
}

test/SILOptimizer/earlycodemotion.sil

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,36 @@ bb3(%12 : $Bool):
522522
return %12 : $Bool
523523
}
524524

525+
// CHECK-LABEL: sil [ossa] @sink_struct_ossa :
526+
// CHECK: bb0({{.*}}):
527+
// CHECK: switch_enum
528+
// CHECK: bb1({{.*}}):
529+
// CHECK: integer_literal $Builtin.Int1, -1
530+
// CHECK: br bb3({{.*}} : $Builtin.Int1)
531+
// CHECK: bb2:
532+
// CHECK: integer_literal $Builtin.Int1, 0
533+
// CHECK: br bb3({{.*}} : $Builtin.Int1)
534+
// CHECK: bb3({{.*}} : $Builtin.Int1):
535+
// CHECK: struct $Bool
536+
// CHECK: } // end sil function 'sink_struct_ossa'
537+
sil [ossa] @sink_struct_ossa : $@convention(thin) (Optional<Builtin.Int32>) -> Bool {
538+
bb0(%0 : $Optional<Builtin.Int32>):
539+
switch_enum %0 : $Optional<Builtin.Int32>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
540+
541+
bb1(%2 : $Builtin.Int32):
542+
%6 = integer_literal $Builtin.Int1, -1
543+
%7 = struct $Bool (%6 : $Builtin.Int1)
544+
br bb3(%7 : $Bool)
545+
546+
bb2:
547+
%9 = integer_literal $Builtin.Int1, 0
548+
%10 = struct $Bool (%9 : $Builtin.Int1)
549+
br bb3(%10 : $Bool)
550+
551+
bb3(%12 : $Bool):
552+
return %12 : $Bool
553+
}
554+
525555
// Sink retain down the successors so we can pair up retain with release on the
526556
// fast path.
527557
class Test {
@@ -1402,6 +1432,26 @@ bb3(%z1 : $Builtin.RawPointer):
14021432
return %z1 : $Builtin.RawPointer
14031433
}
14041434

1435+
// CHECK-LABEL: sil [ossa] @sink_literals_through_arguments_ossa :
1436+
// CHECK: string_literal utf8 "0"
1437+
// CHECK-NEXT: return
1438+
// CHECK: } // end sil function 'sink_literals_through_arguments_ossa'
1439+
sil [ossa] @sink_literals_through_arguments_ossa : $@convention(thin) (Builtin.Int1) -> Builtin.RawPointer {
1440+
bb0(%0 : $Builtin.Int1):
1441+
cond_br %0, bb1, bb2
1442+
1443+
bb1:
1444+
%x1 = string_literal utf8 "0"
1445+
br bb3(%x1 : $Builtin.RawPointer)
1446+
1447+
bb2:
1448+
%y1 = string_literal utf8 "0"
1449+
br bb3(%y1 : $Builtin.RawPointer)
1450+
1451+
bb3(%z1 : $Builtin.RawPointer):
1452+
return %z1 : $Builtin.RawPointer
1453+
}
1454+
14051455
// CHECK-LABEL: sil hidden @sink_allocation_inst
14061456
sil hidden @sink_allocation_inst : $@convention(thin) (Boo, Boo) -> Bool {
14071457
bb0(%0 : $Boo, %1 : $Boo):

test/SILOptimizer/simplify_cfg_dom_jumpthread.sil

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,3 +558,39 @@ bb6:
558558
fix_lifetime %6 : $E2
559559
unreachable
560560
}
561+
562+
// CHECK-LABEL: sil [ossa] @test_update_borrowed_from :
563+
// CHECK: bb3([[A1:%.*]] : @guaranteed $C, [[A2:%.*]] : @reborrow $C):
564+
// CHECK-DAG: = borrowed [[A2]] : $C from ()
565+
// CHECK-DAG: = borrowed [[A1]] : $C from ([[A2]] : $C)
566+
// CHECK: } // end sil function 'test_update_borrowed_from'
567+
sil [ossa] @test_update_borrowed_from : $@convention(thin) (Builtin.Int1, @inout C) -> () {
568+
bb0(%0 : $Builtin.Int1, %1 : $*C):
569+
cond_br %0, bb2, bb1
570+
571+
bb1:
572+
br bb3
573+
574+
bb2:
575+
%4 = load [take] %1
576+
store %4 to [init] %1
577+
br bb3
578+
579+
bb3:
580+
%7 = load_borrow %1
581+
cond_br %0, bb5, bb4
582+
583+
bb4:
584+
br bb6(%7)
585+
586+
bb5:
587+
%10 = unchecked_ref_cast %7 to $C
588+
br bb6(%10)
589+
590+
bb6(%12 : @guaranteed $C):
591+
%13 = borrowed %12 from (%7)
592+
end_borrow %7
593+
%15 = tuple ()
594+
return %15
595+
}
596+

test/Serialization/source-loc.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ let _ = foo(x: 100)
1414
//CHECK: {{.*builtin "cmp_ult_Int64".*}} loc "{{.*}}def_source_loc.swift":3:11
1515
//CHECK: {{.*cond_br.*}} loc "{{.*}}def_source_loc.swift":3:11
1616
//CHECK: {{.*integer_literal.*}} 1, loc "{{.*}}def_source_loc.swift":7:12
17-
//CHECK: {{.*struct \$UInt64.*}} loc "{{.*}}def_source_loc.swift":7:12
1817
//CHECK: {{.*br.*}} loc "{{.*}}def_source_loc.swift":7:5
18+
//CHECK: {{.*struct \$UInt64.*}} loc "{{.*}}def_source_loc.swift":7:12
1919
//CHECK: {{.*return.*}} loc "{{.*}}def_source_loc.swift":8:2

0 commit comments

Comments
 (0)