@@ -2589,9 +2589,107 @@ getPartialApplicationFunction(IRGenSILFunction &IGF, SILValue v,
25892589 llvm_unreachable (" bad kind" );
25902590}
25912591
2592+ // A "simple" partial_apply is one where the argument can be directly
2593+ // adopted as the context of the result closure.
2594+ static bool isSimplePartialApply (IRGenFunction &IGF, PartialApplyInst *i) {
2595+ // The callee type must use the `method` convention.
2596+ auto calleeTy = i->getCallee ()->getType ().castTo <SILFunctionType>();
2597+ auto resultTy = i->getFunctionType ();
2598+
2599+ if (calleeTy->getRepresentation () != SILFunctionTypeRepresentation::Method)
2600+ return false ;
2601+
2602+ // There should be one applied argument.
2603+ // (This is a bit stricter than necessary, because empty arguments could be
2604+ // ignored, and for noescape closures, any amount of data less than a pointer
2605+ // in size can be blobbed into a single context word, but those will be
2606+ // handled by a simplification pass in SIL.)
2607+ if (i->getNumArguments () != 1 )
2608+ return false ;
2609+
2610+ auto appliedParam = calleeTy->getParameters ().back ();
2611+ if (resultTy->isNoEscape ()) {
2612+ // A trivial closure accepts an unowned or guaranteed argument, possibly
2613+ // direct or indirect.
2614+ switch (appliedParam.getConvention ()) {
2615+ case ParameterConvention::Indirect_Inout:
2616+ case ParameterConvention::Indirect_In_Constant:
2617+ case ParameterConvention::Indirect_In_Guaranteed:
2618+ case ParameterConvention::Indirect_InoutAliasable:
2619+ // Indirect arguments are trivially word sized.
2620+ return true ;
2621+
2622+ case ParameterConvention::Direct_Guaranteed:
2623+ case ParameterConvention::Direct_Unowned: {
2624+ // Is the direct argument a single word-sized value?
2625+ auto argSchema = IGF.IGM .getTypeInfo (i->getArgument (0 )->getType ())
2626+ .getSchema ();
2627+ if (argSchema.size () != 1 )
2628+ return false ;
2629+
2630+ if (argSchema[0 ].getScalarType ()->getPrimitiveSizeInBits ()
2631+ != IGF.IGM .getPointerSize ().getValueInBits ())
2632+ return false ;
2633+
2634+ return true ;
2635+ }
2636+ default :
2637+ return false ;
2638+ }
2639+ } else {
2640+ // An escaping closure argument's convention should match the callee
2641+ // convention of the result.
2642+ if (resultTy->getCalleeConvention () != appliedParam.getConvention ()) {
2643+ return false ;
2644+ }
2645+ assert (!isIndirectFormalParameter (resultTy->getCalleeConvention ()));
2646+
2647+ auto &argInfo = IGF.IGM .getTypeInfo (i->getArgument (0 )->getType ());
2648+
2649+ if (!argInfo.isSingleSwiftRetainablePointer (ResilienceExpansion::Maximal))
2650+ return false ;
2651+
2652+ return true ;
2653+ }
2654+ }
2655+
25922656void IRGenSILFunction::visitPartialApplyInst (swift::PartialApplyInst *i) {
25932657 SILValue v (i);
25942658
2659+ if (isSimplePartialApply (*this , i)) {
2660+ Explosion function;
2661+
2662+ auto schema = IGM.getTypeInfo (v->getType ()).getSchema ();
2663+ assert (schema.size () == 2 );
2664+ auto calleeTy = schema[0 ].getScalarType ();
2665+ auto contextTy = schema[1 ].getScalarType ();
2666+
2667+ auto callee = getLoweredExplosion (i->getCallee ());
2668+ auto calleeValue = callee.claimNext ();
2669+ assert (callee.empty ());
2670+ calleeValue = Builder.CreateBitOrPointerCast (calleeValue, calleeTy);
2671+ function.add (calleeValue);
2672+
2673+ Explosion context;
2674+ for (auto arg : i->getArguments ()) {
2675+ auto &value = getLoweredValue (arg);
2676+
2677+ if (value.isAddress ()) {
2678+ context.add (value.getAnyAddress ().getAddress ());
2679+ } else {
2680+ getLoweredExplosion (arg, context);
2681+ }
2682+ }
2683+ auto contextValue = context.claimNext ();
2684+ assert (context.empty ());
2685+ contextValue = Builder.CreateBitOrPointerCast (contextValue, contextTy);
2686+ function.add (contextValue);
2687+
2688+ setLoweredExplosion (v, function);
2689+ return ;
2690+ }
2691+
2692+
25952693 // NB: We collect the arguments under the substituted type.
25962694 auto args = i->getArguments ();
25972695 auto calleeTy = i->getSubstCalleeType ();
0 commit comments