Skip to content

Commit b7ecf2a

Browse files
Merge pull request swiftlang#41050 from nate-chandler/sil/move_value_lexical_restricts_motion
[SILOpt] Made lexical flag obstruct some motion.
2 parents 67e3e86 + 689c6ac commit b7ecf2a

File tree

6 files changed

+68
-0
lines changed

6 files changed

+68
-0
lines changed

include/swift/SIL/SILValue.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,8 @@ class ValueBase : public SILNode, public SILAllocated<ValueBase> {
540540
/// NOTE: This is implemented in ValueOwnership.cpp not SILValue.cpp.
541541
ValueOwnershipKind getOwnershipKind() const;
542542

543+
bool isLexical() const;
544+
543545
static bool classof(SILNodePointer node) {
544546
return node->getKind() >= SILNodeKind::First_ValueBase &&
545547
node->getKind() <= SILNodeKind::Last_ValueBase;

lib/SIL/IR/SILValue.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,18 @@ ValueBase::getDefiningInstructionResult() {
9898
return None;
9999
}
100100

101+
bool ValueBase::isLexical() const {
102+
// TODO: Eventually, rather than SILGen'ing a borrow scope for owned
103+
// arguments, we will just have this check here.
104+
// if (auto *argument = dyn_cast<SILArgument>(this))
105+
// return argument->getOwnershipKind() == OwnershipKind::Owned;
106+
if (auto *bbi = dyn_cast<BeginBorrowInst>(this))
107+
return bbi->isLexical();
108+
if (auto *mvi = dyn_cast<MoveValueInst>(this))
109+
return mvi->isLexical();
110+
return false;
111+
}
112+
101113
SILBasicBlock *SILNode::getParentBlock() const {
102114
if (auto *Inst = dyn_cast<SILInstruction>(this))
103115
return Inst->getParent();

lib/SILOptimizer/Utils/CanonicalOSSALifetime.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,9 @@ bool CanonicalizeOSSALifetime::canonicalizeValueLifetime(SILValue def) {
772772
if (def.getOwnershipKind() != OwnershipKind::Owned)
773773
return false;
774774

775+
if (def->isLexical())
776+
return false;
777+
775778
if (poisonRefsMode && !shouldCanonicalizeWithPoison(def))
776779
return false;
777780

lib/SILOptimizer/Utils/OwnershipOptUtils.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,12 @@ bool OwnershipRAUWHelper::hasValidRAUWOwnership(SILValue oldValue,
300300
SILValue newValue) {
301301
auto newOwnershipKind = newValue.getOwnershipKind();
302302

303+
// If the either value is lexical, replacing its uses may result in
304+
// shortening or lengthening its lifetime in ways that don't respect lexical
305+
// scope and deinit barriers.
306+
if (oldValue->isLexical() || newValue->isLexical())
307+
return false;
308+
303309
// If our new kind is ValueOwnershipKind::None, then we are fine. We
304310
// trivially support that. This check also ensures that we can always
305311
// replace any value with a ValueOwnershipKind::None value.

test/SILOptimizer/copy_propagation.sil

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class C {
2828
}
2929

3030
sil [ossa] @dummy : $@convention(thin) () -> ()
31+
sil [ossa] @barrier : $@convention(thin) () -> ()
3132
sil [ossa] @getOwnedC : $@convention(thin) () -> (@owned C)
3233
sil [ossa] @takeOwnedC : $@convention(thin) (@owned C) -> ()
3334
sil [ossa] @takeOwnedCTwice : $@convention(thin) (@owned C, @owned C) -> ()
@@ -836,3 +837,26 @@ bb0(%0 : @owned $C):
836837
%7 = begin_borrow %6 : $C
837838
unreachable
838839
}
840+
841+
// Test that copy propagation doesn't hoist a destroy_value corresponding to
842+
// a move value [lexical] over a barrier.
843+
// CHECK-ONONE-LABEL: sil [ossa] @dont_hoist_move_value_lexical_destroy_over_barrier_apply : {{.*}} {
844+
// CHECK-ONONE: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] : @owned $C):
845+
// CHECK-ONONE: [[LIFETIME:%[^,]+]] = move_value [lexical] [[INSTANCE]]
846+
// CHECK-ONONE: [[BARRIER:%[^,]+]] = function_ref @barrier
847+
// CHECK-ONONE: [[TAKE_GUARANTEED_C:%[^,]+]] = function_ref @takeGuaranteedC
848+
// CHECK-ONONE: apply [[TAKE_GUARANTEED_C]]([[LIFETIME]])
849+
// CHECK-ONONE: apply [[BARRIER]]()
850+
// CHECK-ONONE: destroy_value [[LIFETIME]]
851+
// CHECK-ONONE-LABEL: } // end sil function 'dont_hoist_move_value_lexical_destroy_over_barrier_apply'
852+
sil [ossa] @dont_hoist_move_value_lexical_destroy_over_barrier_apply : $@convention(thin) (@owned C) -> () {
853+
entry(%instance : @owned $C):
854+
%lifetime = move_value [lexical] %instance : $C
855+
%barrier = function_ref @barrier : $@convention(thin) () -> ()
856+
%takeGuaranteedC = function_ref @takeGuaranteedC : $@convention(thin) (@guaranteed C) -> ()
857+
apply %takeGuaranteedC(%lifetime) : $@convention(thin) (@guaranteed C) -> ()
858+
apply %barrier() : $@convention(thin) () -> ()
859+
destroy_value %lifetime : $C
860+
%retval = tuple ()
861+
return %retval : $()
862+
}

test/SILOptimizer/sil_combine_ossa.sil

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4218,6 +4218,27 @@ bb0(%0 : @guaranteed $B):
42184218
return %2 : $B
42194219
}
42204220

4221+
// Check that a mark_dependence on an enum on a lexical value doesn't result in
4222+
// RAUWing the enum with the lexical value and extending the latter's lifetime.
4223+
//
4224+
// CHECK-LABEL: sil [ossa] @mark_dependence_base1_lexical1 : {{.*}} {
4225+
// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] : $*Builtin.Int64, [[INSTANCE:%[^,]+]] : @owned $B):
4226+
// CHECK: [[LIFETIME:%[^,]+]] = move_value [lexical] [[INSTANCE]]
4227+
// CHECK: [[OPTIONAL:%[^,]+]] = enum $FakeOptional<B>, #FakeOptional.some!enumelt, [[LIFETIME]]
4228+
// CHECK: [[DEPENDENT_ADDR:%[^,]+]] = mark_dependence [[ADDR]]
4229+
// CHECK: [[VALUE:%[^,]+]] = load [trivial] [[DEPENDENT_ADDR]]
4230+
// CHECK: return [[VALUE]]
4231+
// CHECK-LABEL: } // end sil function 'mark_dependence_base1_lexical1'
4232+
sil [ossa] @mark_dependence_base1_lexical1 : $@convention(thin) (@inout Builtin.Int64, @owned B) -> Builtin.Int64 {
4233+
bb0(%addr : $*Builtin.Int64, %instance : @owned $B):
4234+
%lifetime = move_value [lexical] %instance : $B
4235+
%optional = enum $FakeOptional<B>, #FakeOptional.some!enumelt, %lifetime : $B
4236+
%dependent_addr = mark_dependence %addr : $*Builtin.Int64 on %optional : $FakeOptional<B>
4237+
%value = load [trivial] %dependent_addr : $*Builtin.Int64
4238+
destroy_value %optional : $FakeOptional<B>
4239+
return %value : $Builtin.Int64
4240+
}
4241+
42214242
protocol _NSArrayCore {}
42224243

42234244
// CHECK-LABEL: sil [ossa] @mark_dependence_base2 :

0 commit comments

Comments
 (0)