Skip to content

Commit 4c1dbd7

Browse files
Merge pull request #82784 from nate-chandler/rdar153693915
[Mem2Reg] Don't promote proj(unchecked_addr_cast).
2 parents 57d056e + 41877ae commit 4c1dbd7

File tree

3 files changed

+155
-0
lines changed

3 files changed

+155
-0
lines changed

lib/SILOptimizer/Transforms/SILMem2Reg.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,16 @@ static bool isAddressForLoad(SILInstruction *load, SILBasicBlock *&singleBlock,
438438
!isa<TupleElementAddrInst>(load))
439439
return false;
440440

441+
// In OSSA, the result of an unchecked_bitwise_cast must immediately be
442+
// copied or unchecked_bitwise_cast'd again. In particular, it is not
443+
// permitted to borrow it and perform additional projections (struct_extract,
444+
// tuple_extract) on the borrowed value. Consequently, we cannot promote an
445+
// address if such a promotion would result in such a pattern.
446+
if (load->getFunction()->hasOwnership() &&
447+
isa<UncheckedAddrCastInst>(load->getOperand(0)) &&
448+
!isa<UncheckedAddrCastInst>(load))
449+
return false;
450+
441451
// None of the projections are lowered to owned values:
442452
//
443453
// struct_element_addr and tuple_element_addr instructions are lowered to

test/SILOptimizer/mem2reg.sil

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,24 @@ struct Pair<T, U> {
2929
var u: U
3030
}
3131

32+
class C {}
33+
34+
struct J {
35+
var c: C
36+
}
37+
38+
struct I {
39+
var j: J
40+
}
41+
42+
struct S1 {
43+
var i: I
44+
}
45+
46+
struct S2 {
47+
var t: (J, J)
48+
}
49+
3250
///////////
3351
// Tests //
3452
///////////
@@ -578,3 +596,60 @@ bb0:
578596
dealloc_stack %11 : $*Pair<T, ()>
579597
return undef : $()
580598
}
599+
600+
// CHECK-LABEL: sil @promo_proj_uac_1 : {{.*}} {
601+
// CHECK-NOT: alloc_stack
602+
// CHECK-LABEL: } // end sil function 'promo_proj_uac_1'
603+
sil @promo_proj_uac_1 : $@convention(thin) () -> () {
604+
bb0:
605+
%s = apply undef() : $@convention(thin) () -> (@owned S1)
606+
%addr = alloc_stack $S1
607+
store %s to %addr
608+
%i_addr = unchecked_addr_cast %addr to $*I
609+
%j_addr = struct_element_addr %i_addr, #I.j
610+
%j = load %j_addr
611+
retain_value %j
612+
destroy_addr %addr
613+
dealloc_stack %addr
614+
apply undef(%j) : $@convention(thin) (@owned J) -> ()
615+
%retval = tuple ()
616+
return %retval
617+
}
618+
619+
// CHECK-LABEL: sil @promo_proj_uac_2 : {{.*}} {
620+
// CHECK-NOT: alloc_stack
621+
// CHECK-LABEL: } // end sil function 'promo_proj_uac_2'
622+
sil @promo_proj_uac_2 : $@convention(thin) () -> () {
623+
bb0:
624+
%s = apply undef() : $@convention(thin) () -> (@owned S2)
625+
%addr = alloc_stack $S2
626+
store %s to %addr
627+
%t_addr = unchecked_addr_cast %addr to $*(J, J)
628+
%j_addr = tuple_element_addr %t_addr, 0
629+
%j = load %j_addr
630+
retain_value %j
631+
destroy_addr %addr
632+
dealloc_stack %addr
633+
apply undef(%j) : $@convention(thin) (@owned J) -> ()
634+
%retval = tuple ()
635+
return %retval
636+
}
637+
638+
// CHECK-LABEL: sil @promo_proj_uac_3 : {{.*}} {
639+
// CHECK-NOT: alloc_stack
640+
// CHECK-LABEL: } // end sil function 'promo_proj_uac_3'
641+
sil @promo_proj_uac_3 : $@convention(thin) () -> () {
642+
bb0:
643+
%s = apply undef() : $@convention(thin) () -> (@owned S1)
644+
%addr = alloc_stack $S1
645+
store %s to %addr
646+
%i_addr = unchecked_addr_cast %addr to $*I
647+
%j_addr = unchecked_addr_cast %i_addr to $*J
648+
%j = load %j_addr
649+
retain_value %j
650+
destroy_addr %addr
651+
dealloc_stack %addr
652+
apply undef(%j) : $@convention(thin) (@owned J) -> ()
653+
%retval = tuple ()
654+
return %retval
655+
}

test/SILOptimizer/mem2reg_ossa.sil

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,22 @@ struct S {
4646
var field: C
4747
}
4848

49+
struct J {
50+
var c: C
51+
}
52+
53+
struct I {
54+
var j: J
55+
}
56+
57+
struct S1 {
58+
var i: I
59+
}
60+
61+
struct S2 {
62+
var t: (J, J)
63+
}
64+
4965
///////////
5066
// Tests //
5167
///////////
@@ -761,3 +777,57 @@ entry(%instance : @owned $C):
761777
%retval = tuple ()
762778
return %retval : $()
763779
}
780+
781+
// CHECK-LABEL: sil [ossa] @no_promo_proj_uac_1 : {{.*}} {
782+
// CHECK: alloc_stack
783+
// CHECK-LABEL: } // end sil function 'no_promo_proj_uac_1'
784+
sil [ossa] @no_promo_proj_uac_1 : $@convention(thin) () -> () {
785+
bb0:
786+
%s = apply undef() : $@convention(thin) () -> (@owned S1)
787+
%addr = alloc_stack $S1
788+
store %s to [init] %addr
789+
%i_addr = unchecked_addr_cast %addr to $*I
790+
%j_addr = struct_element_addr %i_addr, #I.j
791+
%j = load [copy] %j_addr
792+
destroy_addr %addr
793+
dealloc_stack %addr
794+
apply undef(%j) : $@convention(thin) (@owned J) -> ()
795+
%retval = tuple ()
796+
return %retval
797+
}
798+
799+
// CHECK-LABEL: sil [ossa] @no_promo_proj_uac_2 : {{.*}} {
800+
// CHECK: alloc_stack
801+
// CHECK-LABEL: } // end sil function 'no_promo_proj_uac_2'
802+
sil [ossa] @no_promo_proj_uac_2 : $@convention(thin) () -> () {
803+
bb0:
804+
%s = apply undef() : $@convention(thin) () -> (@owned S2)
805+
%addr = alloc_stack $S2
806+
store %s to [init] %addr
807+
%t_addr = unchecked_addr_cast %addr to $*(J, J)
808+
%j_addr = tuple_element_addr %t_addr, 0
809+
%j = load [copy] %j_addr
810+
destroy_addr %addr
811+
dealloc_stack %addr
812+
apply undef(%j) : $@convention(thin) (@owned J) -> ()
813+
%retval = tuple ()
814+
return %retval
815+
}
816+
817+
// CHECK-LABEL: sil [ossa] @promo_uac_uac : {{.*}} {
818+
// CHECK-NOT: alloc_stack
819+
// CHECK-LABEL: } // end sil function 'promo_uac_uac'
820+
sil [ossa] @promo_uac_uac : $@convention(thin) () -> () {
821+
bb0:
822+
%s = apply undef() : $@convention(thin) () -> (@owned S1)
823+
%addr = alloc_stack $S1
824+
store %s to [init] %addr
825+
%i_addr = unchecked_addr_cast %addr to $*I
826+
%j_addr = unchecked_addr_cast %i_addr to $*J
827+
%j = load [copy] %j_addr
828+
destroy_addr %addr
829+
dealloc_stack %addr
830+
apply undef(%j) : $@convention(thin) (@owned J) -> ()
831+
%retval = tuple ()
832+
return %retval
833+
}

0 commit comments

Comments
 (0)