You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When converting load [copy] -> load_borrow, do not insert end_borrow if the block insert point is a dead end block.
This is important to do since otherwise, we may be implicitly reducing the
lifetime of a value which we can not do yet since we do not require all interior
pointer instructions to be guarded by borrows (yet). Once that constraint is in
place, we will not have this problem.
Consider a situation where one has a @owned switch_enum on an
indirect box case which is post-dominated by an unreachable that we want
to convert to @guaranteed:
enum MyEnum {
indirect case FirstCase(Int)
...
}
bb0(%in_guaranteed_addr : $*MyEnum):
...
%0 = load [copy] %in_guaranteed_addr : $*MyEnum
switch_enum %0 : $MyEnum, case #MyEnum.FirstCase: bb1, ...
bb1(%1 : @owned ${ var Int }):
%2 = project_box %1 : ${ var Int }, 0
%3 = load [trivial] %2 : $*Int
apply %log(%3) : $@convention(thin) (Int) -> ()
unreachable
In this case, we will not have a destroy_value on the box, but we may
have a project_box on the box. This is ok since we are going to leak the
value. But since we are using all consuming uses to determine the
lifetime, we will want to insert an end_borrow at the head of the
switch_enum dest block like follows:
bb0(%in_guaranteed_addr : $*MyEnum):
...
%0 = load_borrow %in_guaranteed_addr : $*MyEnum
switch_enum %0 : $MyEnum, case #MyEnum.FirstCase: bb1, ...
bb1(%1 : @guaranteed ${ var Int }):
end_borrow %1 : ${ var Int }
%2 = project_box %1 : ${ var Int }, 0
%3 = load [trivial] %2 : $*Int
apply %log(%3) : $@convention(thin) (Int) -> ()
unreachable
which would violate ownership invariants. Instead, we need to realize
that %1 is dominated by a dead end block so we may not have a
destroy_value upon it meaning we should just not insert the end_borrow
here. If we have a destroy_value upon it (since we did not get rid of a
destroy_value), then we will still get rid of the destroy_value if we are
going to optimize this, so we are still correct.
rdar://68096662
0 commit comments