@@ -63,7 +63,8 @@ class LargeSILTypeMapper {
6363
6464public:
6565 SILType getNewSILType (GenericEnvironment *GenericEnv, SILType storageType,
66- irgen::IRGenModule &Mod);
66+ irgen::IRGenModule &Mod,
67+ bool useResultConvention = false );
6768 bool shouldTransformResults (GenericEnvironment *env,
6869 CanSILFunctionType fnType,
6970 irgen::IRGenModule &IGM);
@@ -72,9 +73,11 @@ class LargeSILTypeMapper {
7273 irgen::IRGenModule &IGM);
7374 SILParameterInfo getNewParameter (GenericEnvironment *env,
7475 SILParameterInfo param,
75- irgen::IRGenModule &IGM);
76+ irgen::IRGenModule &IGM,
77+ bool useResultConvention);
7678 bool shouldTransformParameter (GenericEnvironment *env, SILParameterInfo param,
77- irgen::IRGenModule &IGM);
79+ irgen::IRGenModule &IGM,
80+ bool useResultConvention);
7881 SmallVector<SILParameterInfo, 4 > getNewParameters (GenericEnvironment *env,
7982 CanSILFunctionType fnType,
8083 irgen::IRGenModule &IGM);
@@ -95,25 +98,59 @@ class LargeSILTypeMapper {
9598 SILType getNewTupleType (GenericEnvironment *GenericEnv,
9699 irgen::IRGenModule &Mod,
97100 const SILType &nonOptionalType,
98- const SILType &storageType);
101+ const SILType &storageType, bool useResultConvention );
99102 bool newResultsDiffer (GenericEnvironment *GenericEnv,
100103 ArrayRef<SILResultInfo> origResults,
101104 irgen::IRGenModule &Mod);
102105 bool shouldConvertBBArg (SILArgument *arg, irgen::IRGenModule &Mod);
103106 bool containsDifferentFunctionSignature (GenericEnvironment *genEnv,
104107 irgen::IRGenModule &Mod,
105108 SILType storageType,
106- SILType newSILType);
109+ SILType newSILType,
110+ bool useResultConvention = false );
111+
112+ struct NewTypeCacheKey {
113+ GenericEnvironment *GenericEnv;
114+ SILType storageType;
115+ bool useResultConvention;
116+ };
107117
108118private:
109119 // Cache of already computed type transforms
110- llvm::MapVector<std::pair<GenericEnvironment *, SILType>, SILType>
111- oldToNewTypeMap;
120+ llvm::MapVector<NewTypeCacheKey, SILType> oldToNewTypeMap;
121+ };
122+
123+ namespace llvm {
124+
125+ template <>
126+ struct DenseMapInfo <LargeSILTypeMapper::NewTypeCacheKey> {
127+ static bool isEqual (const LargeSILTypeMapper::NewTypeCacheKey &lhs,
128+ const LargeSILTypeMapper::NewTypeCacheKey &rhs) {
129+ return lhs.GenericEnv == rhs.GenericEnv &&
130+ lhs.storageType == rhs.storageType &&
131+ lhs.useResultConvention == rhs.useResultConvention ;
132+ }
133+ static inline LargeSILTypeMapper::NewTypeCacheKey getEmptyKey () {
134+ return {nullptr , SILType (), false };
135+ }
136+ static inline LargeSILTypeMapper::NewTypeCacheKey getTombstoneKey () {
137+ return {DenseMapInfo<GenericEnvironment *>::getTombstoneKey (),
138+ DenseMapInfo<SILType>::getTombstoneKey (), false };
139+ }
140+ static unsigned getHashValue (const LargeSILTypeMapper::NewTypeCacheKey &Val) {
141+ return hash_combine (
142+ DenseMapInfo<GenericEnvironment *>::getHashValue (Val.GenericEnv ),
143+ DenseMapInfo<SILType>::getHashValue (Val.storageType ),
144+ Val.useResultConvention ? 1 : 0 );
145+ }
112146};
113147
148+ } // end namespace llvm
149+
114150// / Utility to determine if this is a large loadable type
115151static bool isLargeLoadableType (GenericEnvironment *GenericEnv, SILType t,
116- irgen::IRGenModule &Mod) {
152+ irgen::IRGenModule &Mod,
153+ bool useResultConvention = false ) {
117154 if (t.isAddress () || t.isClassOrClassMetatype ()) {
118155 return false ;
119156 }
@@ -128,7 +165,9 @@ static bool isLargeLoadableType(GenericEnvironment *GenericEnv, SILType t,
128165 assert (t.isObject () && " Expected only two categories: address and object" );
129166 assert (!canType->hasTypeParameter ());
130167 const TypeInfo &TI = Mod.getTypeInfoForLowered (canType);
131- auto &nativeSchemaOrigParam = TI.nativeParameterValueSchema (Mod);
168+ auto &nativeSchemaOrigParam = useResultConvention
169+ ? TI.nativeReturnValueSchema (Mod)
170+ : TI.nativeParameterValueSchema (Mod);
132171 return nativeSchemaOrigParam.requiresIndirect ();
133172 }
134173 return false ;
@@ -144,8 +183,9 @@ static bool modifiableFunction(CanSILFunctionType funcType) {
144183
145184bool LargeSILTypeMapper::shouldTransformParameter (GenericEnvironment *env,
146185 SILParameterInfo param,
147- irgen::IRGenModule &IGM) {
148- auto newParam = getNewParameter (env, param, IGM);
186+ irgen::IRGenModule &IGM,
187+ bool useResultConvention) {
188+ auto newParam = getNewParameter (env, param, IGM, useResultConvention);
149189 return (param != newParam);
150190}
151191
@@ -170,12 +210,13 @@ bool LargeSILTypeMapper::shouldTransformFunctionType(GenericEnvironment *env,
170210 return true ;
171211
172212 for (auto param : fnType->getParameters ()) {
173- if (shouldTransformParameter (env, param, IGM))
213+ if (shouldTransformParameter (env, param, IGM,
214+ /* useResultConvention*/ false ))
174215 return true ;
175216 }
176217
177218 for (auto yield : fnType->getYields ()) {
178- if (shouldTransformParameter (env, yield, IGM))
219+ if (shouldTransformParameter (env, yield, IGM, /* useResultConvention */ true ))
179220 return true ;
180221 }
181222
@@ -205,7 +246,7 @@ static SILType getNonOptionalType(SILType t) {
205246
206247bool LargeSILTypeMapper::containsDifferentFunctionSignature (
207248 GenericEnvironment *genEnv, irgen::IRGenModule &Mod, SILType storageType,
208- SILType newSILType) {
249+ SILType newSILType, bool useResultConvention ) {
209250 if (storageType == newSILType) {
210251 return false ;
211252 }
@@ -218,8 +259,9 @@ bool LargeSILTypeMapper::containsDifferentFunctionSignature(
218259 for (TupleTypeElt canElem : origType->getElements ()) {
219260 auto origCanType = CanType (canElem.getType ());
220261 auto elem = SILType::getPrimitiveObjectType (origCanType);
221- auto newElem = getNewSILType (genEnv, elem, Mod);
222- if (containsDifferentFunctionSignature (genEnv, Mod, elem, newElem)) {
262+ auto newElem = getNewSILType (genEnv, elem, Mod, useResultConvention);
263+ if (containsDifferentFunctionSignature (genEnv, Mod, elem, newElem,
264+ useResultConvention)) {
223265 return true ;
224266 }
225267 }
@@ -384,8 +426,8 @@ static bool shouldTransformYields(GenericEnvironment *genEnv,
384426 for (auto &yield : loweredTy->getYields ()) {
385427 auto yieldStorageType = yield.getSILStorageType (Mod.getSILModule (),
386428 loweredTy, expansion);
387- auto newYieldStorageType =
388- Mapper. getNewSILType ( genEnv, yieldStorageType, Mod);
429+ auto newYieldStorageType = Mapper. getNewSILType (
430+ genEnv, yieldStorageType, Mod, /* useResultConvention */ true );
389431 if (yieldStorageType != newYieldStorageType)
390432 return true ;
391433 }
@@ -403,7 +445,8 @@ static bool modYieldType(SILFunction *F, irgen::IRGenModule &Mod,
403445
404446SILParameterInfo LargeSILTypeMapper::getNewParameter (GenericEnvironment *env,
405447 SILParameterInfo param,
406- irgen::IRGenModule &IGM) {
448+ irgen::IRGenModule &IGM,
449+ bool useResultConvention) {
407450 SILType storageType = param.getSILStorageInterfaceType ();
408451 SILType newOptFuncType =
409452 getNewOptionalFunctionType (env, storageType, IGM);
@@ -418,7 +461,7 @@ SILParameterInfo LargeSILTypeMapper::getNewParameter(GenericEnvironment *env,
418461 } else {
419462 return param;
420463 }
421- } else if (isLargeLoadableType (env, storageType, IGM)) {
464+ } else if (isLargeLoadableType (env, storageType, IGM, useResultConvention )) {
422465 if (param.getConvention () == ParameterConvention::Direct_Owned) {
423466 return SILParameterInfo (storageType.getASTType (),
424467 ParameterConvention::Indirect_In,
@@ -430,7 +473,7 @@ SILParameterInfo LargeSILTypeMapper::getNewParameter(GenericEnvironment *env,
430473 ParameterConvention::Indirect_In_Guaranteed,
431474 param.getOptions ());
432475 } else {
433- auto newType = getNewSILType (env, storageType, IGM);
476+ auto newType = getNewSILType (env, storageType, IGM, useResultConvention );
434477 return SILParameterInfo (newType.getASTType (), param.getConvention (),
435478 param.getOptions ());
436479 }
@@ -442,7 +485,8 @@ LargeSILTypeMapper::getNewParameters(GenericEnvironment *env,
442485 irgen::IRGenModule &IGM) {
443486 SmallVector<SILParameterInfo, 4 > newParams;
444487 for (SILParameterInfo param : fnType->getParameters ()) {
445- auto newParam = getNewParameter (env, param, IGM);
488+ auto newParam =
489+ getNewParameter (env, param, IGM, /* useResultConvention*/ false );
446490 newParams.push_back (newParam);
447491 }
448492 return newParams;
@@ -454,7 +498,8 @@ LargeSILTypeMapper::getNewYields(GenericEnvironment *env,
454498 irgen::IRGenModule &IGM) {
455499 SmallVector<SILYieldInfo, 2 > newYields;
456500 for (auto oldYield : fnType->getYields ()) {
457- auto newYieldAsParam = getNewParameter (env, oldYield, IGM);
501+ auto newYieldAsParam =
502+ getNewParameter (env, oldYield, IGM, /* useResultConvention*/ true );
458503 newYields.push_back (SILYieldInfo (newYieldAsParam.getInterfaceType (),
459504 newYieldAsParam.getConvention ()));
460505 }
@@ -464,14 +509,15 @@ LargeSILTypeMapper::getNewYields(GenericEnvironment *env,
464509SILType LargeSILTypeMapper::getNewTupleType (GenericEnvironment *GenericEnv,
465510 irgen::IRGenModule &Mod,
466511 const SILType &nonOptionalType,
467- const SILType &storageType) {
512+ const SILType &storageType,
513+ bool useResultConvention) {
468514 auto origType = nonOptionalType.getAs <TupleType>();
469515 assert (origType && " Expected a tuple type" );
470516 SmallVector<TupleTypeElt, 2 > newElems;
471517 for (TupleTypeElt canElem : origType->getElements ()) {
472518 auto origCanType = CanType (canElem.getType ());
473519 auto elem = SILType::getPrimitiveObjectType (origCanType);
474- auto newElem = getNewSILType (GenericEnv, elem, Mod);
520+ auto newElem = getNewSILType (GenericEnv, elem, Mod, useResultConvention );
475521 newElems.emplace_back (newElem.getASTType (), canElem.getName ());
476522 }
477523 auto type = TupleType::get (newElems, nonOptionalType.getASTContext ());
@@ -491,9 +537,10 @@ SILType LargeSILTypeMapper::getNewTupleType(GenericEnvironment *GenericEnv,
491537
492538SILType LargeSILTypeMapper::getNewSILType (GenericEnvironment *GenericEnv,
493539 SILType storageType,
494- irgen::IRGenModule &Mod) {
540+ irgen::IRGenModule &Mod,
541+ bool useResultConvention) {
495542 // See if the type is already in the cache:
496- auto typePair = std::make_pair ( GenericEnv, storageType) ;
543+ NewTypeCacheKey typePair = { GenericEnv, storageType, useResultConvention} ;
497544 if (oldToNewTypeMap.find (typePair) != oldToNewTypeMap.end ()) {
498545 return oldToNewTypeMap[typePair];
499546 }
@@ -503,11 +550,12 @@ SILType LargeSILTypeMapper::getNewSILType(GenericEnvironment *GenericEnv,
503550 nonOptionalType = optType;
504551 }
505552 if (nonOptionalType.getAs <TupleType>()) {
506- SILType newSILType =
507- getNewTupleType (GenericEnv, Mod, nonOptionalType, storageType);
508- auto typeToRet = isLargeLoadableType (GenericEnv, newSILType, Mod)
509- ? newSILType.getAddressType ()
510- : newSILType;
553+ SILType newSILType = getNewTupleType (GenericEnv, Mod, nonOptionalType,
554+ storageType, useResultConvention);
555+ auto typeToRet =
556+ isLargeLoadableType (GenericEnv, newSILType, Mod, useResultConvention)
557+ ? newSILType.getAddressType ()
558+ : newSILType;
511559 oldToNewTypeMap[typePair] = typeToRet;
512560 return typeToRet;
513561 }
@@ -522,7 +570,8 @@ SILType LargeSILTypeMapper::getNewSILType(GenericEnvironment *GenericEnv,
522570 newSILType = SILType::getPrimitiveType (newFnType,
523571 storageType.getCategory ());
524572 }
525- } else if (isLargeLoadableType (GenericEnv, storageType, Mod)) {
573+ } else if (isLargeLoadableType (GenericEnv, storageType, Mod,
574+ useResultConvention)) {
526575 newSILType = storageType.getAddressType ();
527576 }
528577 oldToNewTypeMap[typePair] = newSILType;
@@ -589,18 +638,23 @@ struct StructLoweringState {
589638 LargeSILTypeMapper &Mapper)
590639 : F(F), Mod(Mod), Mapper(Mapper) {}
591640
592- bool isLargeLoadableType (CanSILFunctionType fnTy, SILType type) {
593- return ::isLargeLoadableType (getSubstGenericEnvironment (fnTy), type, Mod);
641+ bool isLargeLoadableType (CanSILFunctionType fnTy, SILType type,
642+ bool useResultConvention = false ) {
643+ return ::isLargeLoadableType (getSubstGenericEnvironment (fnTy), type, Mod,
644+ useResultConvention);
594645 }
595646
596- SILType getNewSILType (CanSILFunctionType fnTy, SILType type) {
597- return Mapper.getNewSILType (getSubstGenericEnvironment (fnTy), type, Mod);
647+ SILType getNewSILType (CanSILFunctionType fnTy, SILType type,
648+ bool useResultConvention = false ) {
649+ return Mapper.getNewSILType (getSubstGenericEnvironment (fnTy), type, Mod,
650+ useResultConvention);
598651 }
599652
600- bool containsDifferentFunctionSignature (CanSILFunctionType fnTy,
601- SILType type ) {
653+ bool containsDifferentFunctionSignature (CanSILFunctionType fnTy, SILType type,
654+ bool useResultConvention = false ) {
602655 return Mapper.containsDifferentFunctionSignature (
603- getSubstGenericEnvironment (fnTy), Mod, type, getNewSILType (fnTy, type));
656+ getSubstGenericEnvironment (fnTy), Mod, type,
657+ getNewSILType (fnTy, type, useResultConvention), useResultConvention);
604658 }
605659
606660 bool hasLargeLoadableYields () {
@@ -609,7 +663,8 @@ struct StructLoweringState {
609663
610664 auto env = getSubstGenericEnvironment (fnType);
611665 for (auto yield : fnType->getYields ()) {
612- if (Mapper.shouldTransformParameter (env, yield, Mod))
666+ if (Mapper.shouldTransformParameter (env, yield, Mod,
667+ /* useResultConvention*/ true ))
613668 return true ;
614669 }
615670 return false ;
@@ -1227,7 +1282,8 @@ static bool isYieldUseRewritable(StructLoweringState &pass,
12271282 YieldInst *inst, Operand *operand) {
12281283 assert (inst == operand->getUser ());
12291284 return pass.isLargeLoadableType (pass.F ->getLoweredFunctionType (),
1230- operand->get ()->getType ());
1285+ operand->get ()->getType (),
1286+ /* useResultConvention*/ true );
12311287}
12321288
12331289// / Does the value's uses contain instructions that *must* be rewrites?
@@ -1914,14 +1970,15 @@ static void allocateAndSet(StructLoweringState &pass,
19141970static void allocateAndSetAll (StructLoweringState &pass,
19151971 LoadableStorageAllocation &allocator,
19161972 SILInstruction *user,
1917- MutableArrayRef<Operand> operands) {
1973+ MutableArrayRef<Operand> operands,
1974+ bool useResultConvention) {
19181975 PrettyStackTraceSILNode backtrace (" Running allocateAndSetAll on " , user);
19191976
19201977 for (Operand &operand : operands) {
19211978 SILValue value = operand.get ();
19221979 SILType silType = value->getType ();
1923- if (pass.isLargeLoadableType (pass.F ->getLoweredFunctionType (),
1924- silType )) {
1980+ if (pass.isLargeLoadableType (pass.F ->getLoweredFunctionType (), silType,
1981+ useResultConvention )) {
19251982 allocateAndSet (pass, allocator, value, user, operand);
19261983 }
19271984 }
@@ -2100,12 +2157,14 @@ static void rewriteFunction(StructLoweringState &pass,
21002157 }
21012158 ApplySite applySite = ApplySite (applyInst);
21022159 allocateAndSetAll (pass, allocator, applyInst,
2103- applySite.getArgumentOperands ());
2160+ applySite.getArgumentOperands (),
2161+ /* useResultConvention*/ false );
21042162 }
21052163
21062164 while (!pass.modYieldInsts .empty ()) {
21072165 YieldInst *inst = pass.modYieldInsts .pop_back_val ();
2108- allocateAndSetAll (pass, allocator, inst, inst->getAllOperands ());
2166+ allocateAndSetAll (pass, allocator, inst, inst->getAllOperands (),
2167+ /* useResultConvention*/ true );
21092168 }
21102169
21112170 repeat = !pass.switchEnumInstsToMod .empty () ||
0 commit comments