18
18
19
19
using namespace swift ;
20
20
21
- // / Determine the pattern for global_addr.
21
+ // / Determine InitExistential from global_addr.
22
22
// / %3 = global_addr @$P : $*SomeP
23
23
// / %4 = init_existential_addr %3 : $*SomeP, $SomeC
24
24
// / %5 = alloc_ref $SomeC
25
25
// / store %5 to %4 : $*SomeC
26
26
// / %8 = alloc_stack $SomeP
27
27
// / copy_addr %3 to [initialization] %8 : $*SomeP
28
- // / %9 = open_existential_addr immutable_access %8 : $*SomeP to $*@opened SomeP
29
- SILValue swift::findInitExistentialFromGlobalAddr (GlobalAddrInst * GAI,
30
- CopyAddrInst *CAI) {
31
- assert (CAI-> getSrc () == SILValue (GAI) &&
32
- " Broken Assumption! Global Addr is not the source of the passed in "
33
- " copy_addr?! " );
34
-
28
+ // / %10 = apply %9(%3) : $@convention(thin) (@in_guaranteed SomeP)
29
+ // / Assumptions: Insn is a direct user of GAI (e.g., copy_addr or
30
+ // / apply pattern shown above) and that a valid init_existential_addr
31
+ // / value is returned only if it can prove that the value it
32
+ // / initializes is the same value at the use point.
33
+ static SILValue findInitExistentialFromGlobalAddr (GlobalAddrInst *GAI,
34
+ SILInstruction *Insn) {
35
35
// / Check for a single InitExistential usage for GAI and
36
- // / a simple dominance check: both InitExistential and CAI are in
36
+ // / a simple dominance check: both InitExistential and Insn are in
37
37
// / the same basic block and only one InitExistential
38
- // / occurs between GAI and CAI .
38
+ // / occurs between GAI and Insn .
39
39
llvm::SmallPtrSet<SILInstruction *, 8 > IEUses;
40
40
for (auto *Use : GAI->getUses ()) {
41
41
if (auto *InitExistential =
@@ -48,10 +48,11 @@ SILValue swift::findInitExistentialFromGlobalAddr(GlobalAddrInst *GAI,
48
48
if (IEUses.empty ())
49
49
return SILValue ();
50
50
51
- // / Walk backwards from CAI instruction till the begining of the basic block
52
- // / looking for InitExistential.
51
+ // / Walk backwards from Insn instruction till the begining of the basic block
52
+ // / looking for an InitExistential.
53
53
SILValue SingleIE;
54
- for (auto II = CAI->getIterator ().getReverse (), IE = CAI->getParent ()->rend ();
54
+ for (auto II = Insn->getIterator ().getReverse (),
55
+ IE = Insn->getParent ()->rend ();
55
56
II != IE; ++II) {
56
57
if (!IEUses.count (&*II))
57
58
continue ;
@@ -63,6 +64,56 @@ SILValue swift::findInitExistentialFromGlobalAddr(GlobalAddrInst *GAI,
63
64
return SingleIE;
64
65
}
65
66
67
+ // / Determine InitExistential from global_addr and copy_addr.
68
+ // / %3 = global_addr @$P : $*SomeP
69
+ // / %4 = init_existential_addr %3 : $*SomeP, $SomeC
70
+ // / %5 = alloc_ref $SomeC
71
+ // / store %5 to %4 : $*SomeC
72
+ // / %8 = alloc_stack $SomeP
73
+ // / copy_addr %3 to [initialization] %8 : $*SomeP
74
+ SILValue
75
+ swift::findInitExistentialFromGlobalAddrAndCopyAddr (GlobalAddrInst *GAI,
76
+ CopyAddrInst *CAI) {
77
+ assert (CAI->getSrc () == SILValue (GAI) &&
78
+ " Broken Assumption! Global Addr is not the source of the passed in "
79
+ " copy_addr?!" );
80
+ return findInitExistentialFromGlobalAddr (GAI, cast<SILInstruction>(CAI));
81
+ }
82
+
83
+ // / Determine InitExistential from global_addr and an apply argument.
84
+ // / Pattern 1
85
+ // / %3 = global_addr @$P : $*SomeP
86
+ // / %4 = init_existential_addr %3 : $*SomeP, $SomeC
87
+ // / %5 = alloc_ref $SomeC
88
+ // / store %5 to %4 : $*SomeC
89
+ // / %10 = apply %9(%3) : $@convention(thin) (@in_guaranteed SomeP)
90
+ // / Pattern 2
91
+ // / %3 = global_addr @$P : $*SomeP
92
+ // / %9 = open_existential_addr mutable_access %3 : $*SomeP to $*@opened SomeP
93
+ // / %15 = apply %11(%9) : $@convention(thin) (@in_guaranteed SomeP)
94
+ SILValue swift::findInitExistentialFromGlobalAddrAndApply (GlobalAddrInst *GAI,
95
+ ApplySite Apply,
96
+ int ArgIdx) {
97
+ // / Code to ensure that we are calling only in two pattern matching scenarios.
98
+ bool isArg = false ;
99
+ auto Arg = Apply.getArgument (ArgIdx);
100
+ if (auto *ApplyGAI = dyn_cast<GlobalAddrInst>(Arg)) {
101
+ if (ApplyGAI->isIdenticalTo (GAI)) {
102
+ isArg = true ;
103
+ }
104
+ } else if (auto Open = dyn_cast<OpenExistentialAddrInst>(Arg)) {
105
+ auto Op = Open->getOperand ();
106
+ if (auto *OpGAI = dyn_cast<GlobalAddrInst>(Op)) {
107
+ if (OpGAI->isIdenticalTo (GAI)) {
108
+ isArg = true ;
109
+ }
110
+ }
111
+ }
112
+ assert (isArg && " Broken Assumption! Global Addr is not an argument to "
113
+ " apply?!" );
114
+ return findInitExistentialFromGlobalAddr (GAI, Apply.getInstruction ());
115
+ }
116
+
66
117
// / Returns the address of an object with which the stack location \p ASI is
67
118
// / initialized. This is either a init_existential_addr or the destination of a
68
119
// / copy_addr. Returns a null value if the address does not dominate the
@@ -130,7 +181,7 @@ SILValue swift::getAddressOfStackInit(AllocStackInst *ASI,
130
181
return getAddressOfStackInit (ASI, CAI, isCopied);
131
182
// Check if the CAISrc is a global_addr.
132
183
if (auto *GAI = dyn_cast<GlobalAddrInst>(CAISrc)) {
133
- return findInitExistentialFromGlobalAddr (GAI, CAI);
184
+ return findInitExistentialFromGlobalAddrAndCopyAddr (GAI, CAI);
134
185
}
135
186
return CAISrc;
136
187
}
0 commit comments