Skip to content

Fix OwnershipLiveRange for @owned values getting transformed to none values via switch_enum #60101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 18, 2022

Conversation

meg-gupta
Copy link
Contributor

@meg-gupta meg-gupta commented Jul 18, 2022

rdar://95039799

We are currently not computing OwnershipLiveRange correctly in the presence of switch_enum transforming the owned value to a none value.

We can end up with illegal SIL with LoadCopyToLoadBorrowOptimization, due to this.

Example:

sil [ossa] @switch_enum_test : $@convention(thin) (@inout StructWithEnum) -> () {
 bb0(%0 : $*StructWithEnum):
   %1 = struct_element_addr %0 : $*StructWithEnum, #StructWithEnum.val
   %2 = struct_element_addr %0 : $*StructWithEnum, #StructWithEnum.val
   %3 = load [copy] %2 : $*EnumA
   destroy_addr %1 : $*EnumA
   switch_enum %3 : $EnumA, case #EnumA.sometrivial!enumelt: bb1, case #EnumA.somenontrivial!enumelt:bb2, case #EnumA.none!enumelt: bb3

 bb1(%6 : $TrivialStruct):
   %f = function_ref @get_enum : $@convention(thin) () -> @owned EnumA
   %r = apply %f() : $@convention(thin) () -> @owned EnumA
   %ele = struct_element_addr %0 : $*StructWithEnum, #StructWithEnum.val
   store %r to [init] %ele :$*EnumA
   %9999 = tuple()
   return %9999 : $()

 bb2(%7 : @owned $NonTrivialStruct):
  unreachable

 bb3:
  unreachable
 }

can get transformed to:

sil [ossa] @switch_enum_test : $@convention(thin) (@inout StructWithEnum) -> () {

bb0(%0 : $*StructWithEnum):
  %1 = struct_element_addr %0 : $*StructWithEnum, #StructWithEnum.val 
  %2 = struct_element_addr %0 : $*StructWithEnum, #StructWithEnum.val 
  %3 = load_borrow %2 : $*EnumA                   
  destroy_addr %1 : $*EnumA                       
  switch_enum %3 : $EnumA, case #EnumA.sometrivial!enumelt: bb1, case #EnumA.somenontrivial!enumelt: bb2, case #EnumA.none!enumelt: bb3 

bb1(%6 : $TrivialStruct):                         
  end_borrow %3 : $EnumA                          
  
  %8 = function_ref @get_enum : $@convention(thin) () -> @owned EnumA 
  %9 = apply %8() : $@convention(thin) () -> @owned EnumA 
  %10 = struct_element_addr %0 : $*StructWithEnum, #StructWithEnum.val 
  store %9 to [init] %10 : $*EnumA                
  %12 = tuple ()                                  
  return %12 : $()                                

bb2(%14 : @guaranteed $NonTrivialStruct):         
  unreachable                                     

bb3:                                              
  unreachable                                     
} 

which is incorrect:
Write:   destroy_addr %1 : $*EnumA                       
SIL verification failed: Found load borrow that is invalidated by a local write?!: loadBorrowImmutabilityAnalysis.isImmutable(LBI)
Verifying instruction:
     %2 = struct_element_addr %0 : $*StructWithEnum, #StructWithEnum.val 
->   %3 = load_borrow %2 : $*EnumA                
     switch_enum %3 : $EnumA, case #EnumA.sometrivial!enumelt: bb1, case #EnumA.somenontrivial!enumelt: bb2, case #EnumA.none!enumelt: bb3 
     end_borrow %3 : $EnumA                       

@meg-gupta meg-gupta requested review from gottesmm and atrick July 18, 2022 18:40
@meg-gupta
Copy link
Contributor Author

@swift-ci test

@gottesmm
Copy link
Contributor

I am fine with this for 5.6 to fix this bug. That being said, lets get on main the real fix for this as we discussed: getting @atrick's patch that stops OSSA from using dead end blocks committed. That will solve this problem while allowing us to turn back on this optimization. It will also eliminate a bunch of subtle bugs that we have seen due to dead end blocks in OSSA.

@meg-gupta
Copy link
Contributor Author

Fixed a code comment.

@meg-gupta
Copy link
Contributor Author

@swift-ci test

@atrick
Copy link
Contributor

atrick commented Jul 18, 2022

@swift-ci benchmark

Copy link
Contributor

@atrick atrick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@meg-gupta
Copy link
Contributor Author

Pasting benchmark results from the bot :

------- Performance (x86_64): -O -------

REGRESSION OLD NEW DELTA RATIO
FlattenListFlatMap 3006 3768 +25.3% 0.80x (?)

------- Code size: -O -------
------- Performance (x86_64): -Osize -------

IMPROVEMENT OLD NEW DELTA RATIO
FlattenListFlatMap 4206 2640 -37.2% 1.59x (?)
FlattenListLoop 1400 1029 -26.5% 1.36x (?)
PrefixAnySeqCntRange 15 13 -13.3% 1.15x (?)
StringWalk 1360 1240 -8.8% 1.10x (?)
StrComplexWalk 3020 2810 -7.0% 1.07x (?)

------- Code size: -Osize -------
------- Performance (x86_64): -Onone -------

REGRESSION OLD NEW DELTA RATIO
SIMDReduce.Int8 6303 7186 +14.0% 0.88x (?)

IMPROVEMENT OLD NEW DELTA RATIO
ObjectiveCBridgeFromNSDictionaryAnyObjectForced 6850 6400 -6.6% 1.07x (?)

------- Code size: -swiftlibs -------

@meg-gupta meg-gupta merged commit 1f9ffc0 into swiftlang:main Jul 18, 2022
meg-gupta added a commit to meg-gupta/swift that referenced this pull request Jul 19, 2022
Catfish-Man pushed a commit to Catfish-Man/swift that referenced this pull request Jul 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants