@@ -365,6 +365,44 @@ entry(%addr : $*X, %instance : @owned $X):
365365 return %retval : $()
366366}
367367
368+ // Hoist up to a (transitive) use of an address_to_pointer instruction. In
369+ // particular, do _some_ hoisting despite the fact that such an instruction is
370+ // a use.
371+ //
372+ // CHECK-LABEL: sil [ossa] @hoist_upto_address_to_pointer_use : {{.*}} {
373+ // CHECK: address_to_pointer
374+ // CHECK: pointer_to_address
375+ // CHECK: load [copy]
376+ // CHECK: destroy_addr
377+ // CHECK: tuple
378+ // CHECK-LABEL: } // end sil function 'hoist_upto_address_to_pointer_use'
379+ sil [ossa] @hoist_upto_address_to_pointer_use : $@convention(thin) (@in X) -> (@owned X) {
380+ entry(%instance : $*X):
381+ %pointer = address_to_pointer %instance : $*X to $Builtin.RawPointer
382+ %addr = pointer_to_address %pointer : $Builtin.RawPointer to $*X
383+ %value = load [copy] %addr : $*X
384+ %retval = tuple ()
385+ destroy_addr %instance : $*X
386+ return %value : $X
387+ }
388+
389+ // Hoist even if the pointerified address gets used.
390+ //
391+ // CHECK-LABEL: sil [ossa] @hoist_despite_use_of_pointer : {{.*}} {
392+ // CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] :
393+ // CHECK-NEXT: destroy_addr [[INSTANCE]]
394+ // CHECK-LABEL: } // end sil function 'hoist_despite_use_of_pointer'
395+ sil [ossa] @hoist_despite_use_of_pointer : $@convention(thin) (@inout X) -> () {
396+ entry(%instance : $*X):
397+ %addr_for_pointer = alloc_stack $Builtin.RawPointer
398+ %pointer = address_to_pointer %instance : $*X to $Builtin.RawPointer
399+ store %pointer to [trivial] %addr_for_pointer : $*Builtin.RawPointer
400+ %retval = tuple ()
401+ destroy_addr %instance : $*X
402+ dealloc_stack %addr_for_pointer : $*Builtin.RawPointer
403+ return %retval : $()
404+ }
405+
368406// Fold destroy_addr and a load [copy] into a load [take] even when that
369407// load [take] is guarded by an access scope.
370408//
0 commit comments