@@ -2589,9 +2589,107 @@ getPartialApplicationFunction(IRGenSILFunction &IGF, SILValue v,
2589
2589
llvm_unreachable (" bad kind" );
2590
2590
}
2591
2591
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
+
2592
2656
void IRGenSILFunction::visitPartialApplyInst (swift::PartialApplyInst *i) {
2593
2657
SILValue v (i);
2594
2658
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
+
2595
2693
// NB: We collect the arguments under the substituted type.
2596
2694
auto args = i->getArguments ();
2597
2695
auto calleeTy = i->getSubstCalleeType ();
0 commit comments