Skip to content

Commit 2d52058

Browse files
Merge pull request swiftlang#63876 from nate-chandler/lexical-phis
[SIL] Phi with incoming lexical value is lexical.
2 parents 5f93166 + 785834c commit 2d52058

File tree

6 files changed

+351
-9
lines changed

6 files changed

+351
-9
lines changed

include/swift/SIL/SILArgument.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ class SILPhiArgument : public SILArgument {
241241
/// result.
242242
bool isPhi() const;
243243

244+
/// Whether any of the values incoming to this phi are lexical.
245+
bool isLexical() const;
246+
244247
/// Return true if this block argument is a terminator result.
245248
bool isTerminatorResult() const { return !isPhi(); }
246249

@@ -291,7 +294,7 @@ class SILPhiArgument : public SILArgument {
291294
///
292295
/// Returns false when called on a non-phi and when the visitor returns false.
293296
bool visitTransitiveIncomingPhiOperands(
294-
function_ref<bool(SILPhiArgument *, Operand *)> visitor);
297+
function_ref<bool(SILPhiArgument *, Operand *)> visitor) const;
295298

296299
/// Returns true if we were able to find a single terminator operand value for
297300
/// each predecessor of this arguments basic block. The found values are

lib/SIL/IR/SILArgument.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,12 @@ bool SILPhiArgument::getIncomingPhiValues(
227227
}
228228

229229
bool SILPhiArgument::visitTransitiveIncomingPhiOperands(
230-
function_ref<bool(SILPhiArgument *, Operand *)> visitor) {
230+
function_ref<bool(SILPhiArgument *, Operand *)> visitor) const {
231231
if (!isPhi())
232232
return false;
233233

234234
GraphNodeWorklist<SILPhiArgument *, 4> worklist;
235-
worklist.initialize(this);
235+
worklist.insert(const_cast<SILPhiArgument *>(this));
236236

237237
while (auto *argument = worklist.pop()) {
238238
SmallVector<Operand *> operands;

lib/SIL/IR/SILValue.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,38 @@ ValueBase::getDefiningInstructionResult() {
115115
return None;
116116
}
117117

118+
bool SILPhiArgument::isLexical() const {
119+
if (!isPhi())
120+
return false;
121+
122+
// FIXME: Cache this on the node.
123+
124+
// Does there exist an incoming value which is lexical?
125+
//
126+
// Invert the condition to "is every incoming value non-lexical?" in order to
127+
// stop visiting incoming values once one lexical value is
128+
// found--visitTransitiveIncomingPhiOperands stops once false is returned
129+
// from it.
130+
auto isEveryIncomingValueNonLexical =
131+
visitTransitiveIncomingPhiOperands([&](auto *, auto *operand) {
132+
auto value = operand->get();
133+
SILPhiArgument *phi = dyn_cast<SILPhiArgument>(value);
134+
if (phi && phi->isPhi()) {
135+
return true;
136+
}
137+
// If this non-phi incoming value is lexical, then there is one at least
138+
// one lexical value incoming to this phi, to it's lexical.
139+
return !value->isLexical();
140+
});
141+
return !isEveryIncomingValueNonLexical;
142+
}
143+
118144
bool ValueBase::isLexical() const {
119145
if (auto *argument = dyn_cast<SILFunctionArgument>(this))
120146
return argument->getLifetime().isLexical();
147+
auto *phi = dyn_cast<SILPhiArgument>(this);
148+
if (phi && phi->isPhi())
149+
return phi->isLexical();
121150
if (auto *bbi = dyn_cast<BeginBorrowInst>(this))
122151
return bbi->isLexical();
123152
if (auto *mvi = dyn_cast<MoveValueInst>(this))

lib/SILOptimizer/UtilityPasses/UnitTestRunner.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,22 @@ struct IsDeinitBarrierTest : UnitTest {
434434
}
435435
};
436436

437+
// Arguments:
438+
// - value
439+
// Dumps:
440+
// - value
441+
// - whether it's lexical
442+
struct IsLexicalTest : UnitTest {
443+
IsLexicalTest(UnitTestRunner *pass) : UnitTest(pass) {}
444+
void invoke(Arguments &arguments) override {
445+
auto value = arguments.takeValue();
446+
auto isLexical = value->isLexical();
447+
value->dump();
448+
auto *boolString = isLexical ? "true" : "false";
449+
llvm::errs() << boolString << "\n";
450+
}
451+
};
452+
437453
struct ShrinkBorrowScopeTest : UnitTest {
438454
ShrinkBorrowScopeTest(UnitTestRunner *pass) : UnitTest(pass) {}
439455
void invoke(Arguments &arguments) override {
@@ -759,6 +775,7 @@ void UnitTestRunner::withTest(StringRef name, Doit doit) {
759775
ADD_UNIT_TEST_SUBCLASS("function-get-self-argument-index", FunctionGetSelfArgumentIndex)
760776
ADD_UNIT_TEST_SUBCLASS("interior-liveness", InteriorLivenessTest)
761777
ADD_UNIT_TEST_SUBCLASS("is-deinit-barrier", IsDeinitBarrierTest)
778+
ADD_UNIT_TEST_SUBCLASS("is-lexical", IsLexicalTest)
762779
ADD_UNIT_TEST_SUBCLASS("linear-liveness", LinearLivenessTest)
763780
ADD_UNIT_TEST_SUBCLASS("multidef-liveness", MultiDefLivenessTest)
764781
ADD_UNIT_TEST_SUBCLASS("pruned-liveness-boundary-with-list-of-last-users-insertion-points", PrunedLivenessBoundaryWithListOfLastUsersInsertionPointsTest)

test/SILOptimizer/copy_propagation_canonicalize_with_reborrows.sil

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -297,14 +297,15 @@ bb1(%4 : @guaranteed $X, %5 : @owned $X):
297297
// Lifetime analysis is successful; the copy/destroy in bb1 are removed. The
298298
// end_borrow/destroy maintain their position.
299299
//
300-
// CHECK-LABEL: sil [ossa] @reborrow_adjacent_to_consume : $@convention(thin) (@owned X) -> () {
300+
// CHECK-LABEL: sil [ossa] @reborrow_adjacent_to_consume : $@convention(thin) () -> () {
301301
// CHECK: bb1(%{{.*}} : @guaranteed $X, %{{.*}} : @owned $X):
302302
// CHECK-NEXT: br bb2
303303
// CHECK: bb2(%{{.*}} : @guaranteed $X, %{{.*}} : @owned $X):
304304
// CHECK-NEXT: end_borrow
305305
// CHECK-NEXT: destroy_value
306-
sil [ossa] @reborrow_adjacent_to_consume : $@convention(thin) (@owned X) -> () {
307-
bb0(%0 : @owned $X):
306+
sil [ossa] @reborrow_adjacent_to_consume : $@convention(thin) () -> () {
307+
bb0:
308+
%0 = apply undef() : $@convention(thin) () -> (@owned X)
308309
%1 = begin_borrow %0 : $X
309310
br bb1(%1 : $X, %0 : $X)
310311

@@ -328,14 +329,15 @@ bb2(%6 : @guaranteed $X, %7 : @owned $X):
328329
//
329330
// Lifetime analysis is successful; the copy/destroy in bb2 are removed.
330331
//
331-
// CHECK-LABEL: sil [ossa] @reborrow_no_adjacent_consume : $@convention(thin) (@owned X) -> () {
332+
// CHECK-LABEL: sil [ossa] @reborrow_no_adjacent_consume : $@convention(thin) () -> () {
332333
// CHECK: bb1(%{{.*}} : @guaranteed $X, %{{.*}} : @owned $X):
333334
// CHECK-NEXT: br bb2
334335
// CHECK: bb2(%{{.*}} : @guaranteed $X):
335336
// CHECK-NEXT: end_borrow
336337
// CHECK-NEXT: destroy_value
337-
sil [ossa] @reborrow_no_adjacent_consume : $@convention(thin) (@owned X) -> () {
338-
bb0(%0 : @owned $X):
338+
sil [ossa] @reborrow_no_adjacent_consume : $@convention(thin) () -> () {
339+
bb0:
340+
%0 = apply undef() : $@convention(thin) () -> (@owned X)
339341
%1 = begin_borrow %0 : $X
340342
br bb1(%1 : $X, %0 : $X)
341343

0 commit comments

Comments
 (0)