|
28 | 28 |
|
29 | 29 | using namespace swift;
|
30 | 30 |
|
31 |
| -static llvm::cl::opt<bool> |
32 |
| -EnableExistentialSpecializer("enable-existential-specializer", |
33 |
| - llvm::cl::Hidden, |
34 |
| - llvm::cl::init(true)); |
35 |
| - |
36 | 31 | STATISTIC(NumFunctionsWithExistentialArgsSpecialized,
|
37 | 32 | "Number of functions with existential args specialized");
|
38 | 33 |
|
@@ -71,7 +66,7 @@ class ExistentialSpecializer : public SILFunctionTransform {
|
71 | 66 | auto *F = getFunction();
|
72 | 67 |
|
73 | 68 | /// Don't optimize functions that should not be optimized.
|
74 |
| - if (!F->shouldOptimize() || !EnableExistentialSpecializer) { |
| 69 | + if (!F->shouldOptimize() || !F->getModule().getOptions().ExistentialSpecializer) { |
75 | 70 | return;
|
76 | 71 | }
|
77 | 72 |
|
@@ -115,6 +110,19 @@ bool ExistentialSpecializer::findConcreteTypeFromSoleConformingType(
|
115 | 110 | return true;
|
116 | 111 | }
|
117 | 112 |
|
| 113 | +/// Check if the argument Arg is used in a destroy_use instruction. |
| 114 | +static void |
| 115 | +findIfCalleeUsesArgInDestroyUse(SILValue Arg, |
| 116 | + ExistentialTransformArgumentDescriptor &ETAD) { |
| 117 | + for (Operand *ArgUse : Arg->getUses()) { |
| 118 | + auto *ArgUser = ArgUse->getUser(); |
| 119 | + if (isa<DestroyAddrInst>(ArgUser)) { |
| 120 | + ETAD.DestroyAddrUse = true; |
| 121 | + break; |
| 122 | + } |
| 123 | + } |
| 124 | +} |
| 125 | + |
118 | 126 | /// Helper function to ensure that the argument is not InOut or InOut_Aliasable
|
119 | 127 | static bool isNonInoutIndirectArgument(SILValue Arg,
|
120 | 128 | SILArgumentConvention ArgConvention) {
|
@@ -180,27 +188,24 @@ bool ExistentialSpecializer::canSpecializeExistentialArgsInFunction(
|
180 | 188 | continue;
|
181 | 189 | }
|
182 | 190 |
|
183 |
| - /// Determine attributes of the existential addr argument. |
| 191 | + /// Determine attributes of the existential addr arguments such as |
| 192 | + /// destroy_use, immutable_access. |
184 | 193 | ExistentialTransformArgumentDescriptor ETAD;
|
185 | 194 | auto paramInfo = origCalleeConv.getParamInfoForSILArg(Idx);
|
186 |
| - // The ExistentialSpecializerCloner copies the incoming generic argument |
187 |
| - // into an existential. This won't work if the original argument is |
188 |
| - // mutated. Furthermore, SILCombine would not be able to replace a mutated |
189 |
| - // existential with a concrete value, so the specialization thunk could not |
190 |
| - // be optimized away. |
191 |
| - if (paramInfo.isIndirectMutating()) |
192 |
| - continue; |
193 |
| - |
194 |
| - ETAD.AccessType = paramInfo.isConsumed() |
| 195 | + ETAD.AccessType = (paramInfo.isIndirectMutating() || paramInfo.isConsumed()) |
195 | 196 | ? OpenedExistentialAccess::Mutable
|
196 | 197 | : OpenedExistentialAccess::Immutable;
|
197 |
| - ETAD.isConsumed = paramInfo.isConsumed(); |
| 198 | + ETAD.DestroyAddrUse = false; |
| 199 | + if ((CalleeArgs[Idx]->getType().getPreferredExistentialRepresentation( |
| 200 | + F->getModule())) |
| 201 | + != ExistentialRepresentation::Class) |
| 202 | + findIfCalleeUsesArgInDestroyUse(CalleeArg, ETAD); |
198 | 203 |
|
199 | 204 | /// Save the attributes
|
200 | 205 | ExistentialArgDescriptor[Idx] = ETAD;
|
201 | 206 | LLVM_DEBUG(llvm::dbgs()
|
202 | 207 | << "ExistentialSpecializer Pass:Function: " << F->getName()
|
203 |
| - << " Arg:" << Idx << " has a concrete type.\n"); |
| 208 | + << " Arg:" << Idx << "has a concrete type.\n"); |
204 | 209 | returnFlag |= true;
|
205 | 210 | }
|
206 | 211 | return returnFlag;
|
|
0 commit comments