|
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 | + |
31 | 36 | STATISTIC(NumFunctionsWithExistentialArgsSpecialized,
|
32 | 37 | "Number of functions with existential args specialized");
|
33 | 38 |
|
@@ -66,7 +71,7 @@ class ExistentialSpecializer : public SILFunctionTransform {
|
66 | 71 | auto *F = getFunction();
|
67 | 72 |
|
68 | 73 | /// Don't optimize functions that should not be optimized.
|
69 |
| - if (!F->shouldOptimize() || !F->getModule().getOptions().ExistentialSpecializer) { |
| 74 | + if (!F->shouldOptimize() || !EnableExistentialSpecializer) { |
70 | 75 | return;
|
71 | 76 | }
|
72 | 77 |
|
@@ -110,19 +115,6 @@ bool ExistentialSpecializer::findConcreteTypeFromSoleConformingType(
|
110 | 115 | return true;
|
111 | 116 | }
|
112 | 117 |
|
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 |
| - |
126 | 118 | /// Helper function to ensure that the argument is not InOut or InOut_Aliasable
|
127 | 119 | static bool isNonInoutIndirectArgument(SILValue Arg,
|
128 | 120 | SILArgumentConvention ArgConvention) {
|
@@ -188,24 +180,27 @@ bool ExistentialSpecializer::canSpecializeExistentialArgsInFunction(
|
188 | 180 | continue;
|
189 | 181 | }
|
190 | 182 |
|
191 |
| - /// Determine attributes of the existential addr arguments such as |
192 |
| - /// destroy_use, immutable_access. |
| 183 | + /// Determine attributes of the existential addr argument. |
193 | 184 | ExistentialTransformArgumentDescriptor ETAD;
|
194 | 185 | auto paramInfo = origCalleeConv.getParamInfoForSILArg(Idx);
|
195 |
| - ETAD.AccessType = (paramInfo.isIndirectMutating() || paramInfo.isConsumed()) |
| 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() |
196 | 195 | ? OpenedExistentialAccess::Mutable
|
197 | 196 | : OpenedExistentialAccess::Immutable;
|
198 |
| - ETAD.DestroyAddrUse = false; |
199 |
| - if ((CalleeArgs[Idx]->getType().getPreferredExistentialRepresentation( |
200 |
| - F->getModule())) |
201 |
| - != ExistentialRepresentation::Class) |
202 |
| - findIfCalleeUsesArgInDestroyUse(CalleeArg, ETAD); |
| 197 | + ETAD.isConsumed = paramInfo.isConsumed(); |
203 | 198 |
|
204 | 199 | /// Save the attributes
|
205 | 200 | ExistentialArgDescriptor[Idx] = ETAD;
|
206 | 201 | LLVM_DEBUG(llvm::dbgs()
|
207 | 202 | << "ExistentialSpecializer Pass:Function: " << F->getName()
|
208 |
| - << " Arg:" << Idx << "has a concrete type.\n"); |
| 203 | + << " Arg:" << Idx << " has a concrete type.\n"); |
209 | 204 | returnFlag |= true;
|
210 | 205 | }
|
211 | 206 | return returnFlag;
|
|
0 commit comments