@@ -146,42 +146,20 @@ SILCombiner::optimizeApplyOfConvertFunctionInst(FullApplySite AI,
146146 if (SubstCalleeTy->hasArchetype () || ConvertCalleeTy->hasArchetype ())
147147 return nullptr ;
148148
149- // Indirect results are not currently handled.
150- if (AI.hasIndirectSILResults ())
151- return nullptr ;
152-
153- // Bail if the result type of the converted callee is different from the callee's
154- // result type of the apply instruction.
155- if (SubstCalleeTy->getAllResultsSubstType (
156- AI.getModule (), AI.getFunction ()->getTypeExpansionContext ()) !=
157- ConvertCalleeTy->getAllResultsSubstType (
158- AI.getModule (), AI.getFunction ()->getTypeExpansionContext ())) {
159- return nullptr ;
160- }
161-
162149 // Ok, we can now perform our transformation. Grab AI's operands and the
163150 // relevant types from the ConvertFunction function type and AI.
164151 Builder.setCurrentDebugScope (AI.getDebugScope ());
165- OperandValueArrayRef Ops = AI.getArgumentsWithoutIndirectResults ();
152+ OperandValueArrayRef Ops = AI.getArguments ();
166153 SILFunctionConventions substConventions (SubstCalleeTy, FRI->getModule ());
167154 SILFunctionConventions convertConventions (ConvertCalleeTy, FRI->getModule ());
168155 auto context = AI.getFunction ()->getTypeExpansionContext ();
169- auto oldOpTypes = substConventions.getParameterSILTypes (context);
170- auto newOpTypes = convertConventions.getParameterSILTypes (context);
171-
172- assert (Ops.size () == SubstCalleeTy->getNumParameters ()
173- && " Ops and op types must have same size." );
174- assert (Ops.size () == ConvertCalleeTy->getNumParameters ()
175- && " Ops and op types must have same size." );
156+ auto oldOpRetTypes = substConventions.getIndirectSILResultTypes (context);
157+ auto newOpRetTypes = convertConventions.getIndirectSILResultTypes (context);
158+ auto oldOpParamTypes = substConventions.getParameterSILTypes (context);
159+ auto newOpParamTypes = convertConventions.getParameterSILTypes (context);
176160
177161 llvm::SmallVector<SILValue, 8 > Args;
178- auto newOpI = newOpTypes.begin ();
179- auto oldOpI = oldOpTypes.begin ();
180- for (unsigned i = 0 , e = Ops.size (); i != e; ++i, ++newOpI, ++oldOpI) {
181- SILValue Op = Ops[i];
182- SILType OldOpType = *oldOpI;
183- SILType NewOpType = *newOpI;
184-
162+ auto convertOp = [&](SILValue Op, SILType OldOpType, SILType NewOpType) {
185163 // Convert function takes refs to refs, address to addresses, and leaves
186164 // other types alone.
187165 if (OldOpType.isAddress ()) {
@@ -190,17 +168,68 @@ SILCombiner::optimizeApplyOfConvertFunctionInst(FullApplySite AI,
190168 Args.push_back (UAC);
191169 } else if (OldOpType.getASTType () != NewOpType.getASTType ()) {
192170 auto URC =
193- Builder.createUncheckedReinterpretCast (AI.getLoc (), Op, NewOpType);
171+ Builder.createUncheckedBitCast (AI.getLoc (), Op, NewOpType);
194172 Args.push_back (URC);
195173 } else {
196174 Args.push_back (Op);
197175 }
176+ };
177+
178+ unsigned OpI = 0 ;
179+
180+ auto newRetI = newOpRetTypes.begin ();
181+ auto oldRetI = oldOpRetTypes.begin ();
182+
183+ for (auto e = newOpRetTypes.end (); newRetI != e;
184+ ++OpI, ++newRetI, ++oldRetI) {
185+ convertOp (Ops[OpI], *oldRetI, *newRetI);
186+ }
187+
188+ auto newParamI = newOpParamTypes.begin ();
189+ auto oldParamI = oldOpParamTypes.begin ();
190+ for (auto e = newOpParamTypes.end (); newParamI != e;
191+ ++OpI, ++newParamI, ++oldParamI) {
192+ convertOp (Ops[OpI], *oldParamI, *newParamI);
198193 }
199194
195+ // Convert the direct results if they changed.
196+ auto oldResultTy = SubstCalleeTy
197+ ->getDirectFormalResultsType (AI.getModule (),
198+ AI.getFunction ()->getTypeExpansionContext ());
199+ auto newResultTy = ConvertCalleeTy
200+ ->getDirectFormalResultsType (AI.getModule (),
201+ AI.getFunction ()->getTypeExpansionContext ());
202+
200203 // Create the new apply inst.
201204 if (auto *TAI = dyn_cast<TryApplyInst>(AI)) {
205+ // If the results need to change, create a new landing block to do that
206+ // conversion.
207+ auto normalBB = TAI->getNormalBB ();
208+ if (oldResultTy != newResultTy) {
209+ normalBB = AI.getFunction ()->createBasicBlockBefore (TAI->getNormalBB ());
210+ Builder.setInsertionPoint (normalBB);
211+ SmallVector<SILValue, 4 > branchArgs;
212+
213+ auto oldOpResultTypes = substConventions.getDirectSILResultTypes (context);
214+ auto newOpResultTypes = convertConventions.getDirectSILResultTypes (context);
215+
216+ auto oldRetI = oldOpResultTypes.begin ();
217+ auto newRetI = newOpResultTypes.begin ();
218+ auto origArgs = TAI->getNormalBB ()->getArguments ();
219+ auto origArgI = origArgs.begin ();
220+ for (auto e = newOpResultTypes.end (); newRetI != e;
221+ ++oldRetI, ++newRetI, ++origArgI) {
222+ auto arg = normalBB->createPhiArgument (*newRetI, (*origArgI)->getOwnershipKind ());
223+ auto converted = Builder.createUncheckedBitCast (AI.getLoc (),
224+ arg, *oldRetI);
225+ branchArgs.push_back (converted);
226+ }
227+
228+ Builder.createBranch (AI.getLoc (), TAI->getNormalBB (), branchArgs);
229+ }
230+
202231 return Builder.createTryApply (AI.getLoc (), FRI, SubstitutionMap (), Args,
203- TAI-> getNormalBB () , TAI->getErrorBB (),
232+ normalBB , TAI->getErrorBB (),
204233 TAI->getApplyOptions ());
205234 }
206235
@@ -213,12 +242,13 @@ SILCombiner::optimizeApplyOfConvertFunctionInst(FullApplySite AI,
213242 Options |= ApplyFlags::DoesNotThrow;
214243 ApplyInst *NAI = Builder.createApply (AI.getLoc (), FRI, SubstitutionMap (),
215244 Args, Options);
216- assert (FullApplySite (NAI).getSubstCalleeType ()->getAllResultsSubstType (
217- AI.getModule (), AI.getFunction ()->getTypeExpansionContext ()) ==
218- AI.getSubstCalleeType ()->getAllResultsSubstType (
219- AI.getModule (), AI.getFunction ()->getTypeExpansionContext ()) &&
220- " Function types should be the same" );
221- return NAI;
245+ SILInstruction *result = NAI;
246+
247+ if (oldResultTy != newResultTy) {
248+ result = Builder.createUncheckedBitCast (AI.getLoc (), NAI, oldResultTy);
249+ }
250+
251+ return result;
222252}
223253
224254// / Try to optimize a keypath application with an apply instruction.
0 commit comments