@@ -610,6 +610,78 @@ static SILValue getLoadedCalleeValue(LoadInst *li) {
610
610
return si->getSrc ();
611
611
}
612
612
613
+ // PartialApply/ThinToThick -> ConvertFunction patterns are generated
614
+ // by @noescape closures.
615
+ //
616
+ // FIXME: We don't currently handle mismatched return types, however, this
617
+ // would be a good optimization to handle and would be as simple as inserting
618
+ // a cast.
619
+ static SILValue stripFunctionConversions (SILValue CalleeValue) {
620
+ // Skip any copies that we see.
621
+ CalleeValue = stripCopiesAndBorrows (CalleeValue);
622
+
623
+ // We can also allow a thin @escape to noescape conversion as such:
624
+ // %1 = function_ref @thin_closure_impl : $@convention(thin) () -> ()
625
+ // %2 = convert_function %1 :
626
+ // $@convention(thin) () -> () to $@convention(thin) @noescape () -> ()
627
+ // %3 = thin_to_thick_function %2 :
628
+ // $@convention(thin) @noescape () -> () to
629
+ // $@noescape @callee_guaranteed () -> ()
630
+ // %4 = apply %3() : $@noescape @callee_guaranteed () -> ()
631
+ if (auto *ConvertFn = dyn_cast<ConvertFunctionInst>(CalleeValue)) {
632
+ // If the conversion only changes the substitution level of the function,
633
+ // we can also look through it.
634
+ if (ConvertFn->onlyConvertsSubstitutions ())
635
+ return stripFunctionConversions (ConvertFn->getOperand ());
636
+
637
+ auto FromCalleeTy =
638
+ ConvertFn->getOperand ()->getType ().castTo <SILFunctionType>();
639
+ if (FromCalleeTy->getExtInfo ().hasContext ())
640
+ return CalleeValue;
641
+
642
+ auto ToCalleeTy = ConvertFn->getType ().castTo <SILFunctionType>();
643
+ auto EscapingCalleeTy = ToCalleeTy->getWithExtInfo (
644
+ ToCalleeTy->getExtInfo ().withNoEscape (false ));
645
+ if (FromCalleeTy != EscapingCalleeTy)
646
+ return CalleeValue;
647
+
648
+ return stripCopiesAndBorrows (ConvertFn->getOperand ());
649
+ }
650
+
651
+ // Ignore mark_dependence users. A partial_apply [stack] uses them to mark
652
+ // the dependence of the trivial closure context value on the captured
653
+ // arguments.
654
+ if (auto *MD = dyn_cast<MarkDependenceInst>(CalleeValue)) {
655
+ while (MD) {
656
+ CalleeValue = MD->getValue ();
657
+ MD = dyn_cast<MarkDependenceInst>(CalleeValue);
658
+ }
659
+ return CalleeValue;
660
+ }
661
+
662
+ auto *CFI = dyn_cast<ConvertEscapeToNoEscapeInst>(CalleeValue);
663
+ if (!CFI)
664
+ return stripCopiesAndBorrows (CalleeValue);
665
+
666
+ // TODO: Handle argument conversion. All the code in this file needs to be
667
+ // cleaned up and generalized. The argument conversion handling in
668
+ // optimizeApplyOfConvertFunctionInst should apply to any combine
669
+ // involving an apply, not just a specific pattern.
670
+ //
671
+ // For now, just handle conversion that doesn't affect argument types,
672
+ // return types, or throws. We could trivially handle any other
673
+ // representation change, but the only one that doesn't affect the ABI and
674
+ // matters here is @noescape, so just check for that.
675
+ auto FromCalleeTy = CFI->getOperand ()->getType ().castTo <SILFunctionType>();
676
+ auto ToCalleeTy = CFI->getType ().castTo <SILFunctionType>();
677
+ auto EscapingCalleeTy =
678
+ ToCalleeTy->getWithExtInfo (ToCalleeTy->getExtInfo ().withNoEscape (false ));
679
+ if (FromCalleeTy != EscapingCalleeTy)
680
+ return stripCopiesAndBorrows (CalleeValue);
681
+
682
+ return stripCopiesAndBorrows (CFI->getOperand ());
683
+ }
684
+
613
685
// / Returns the callee SILFunction called at a call site, in the case
614
686
// / that the call is transparent (as in, both that the call is marked
615
687
// / with the transparent flag and that callee function is actually transparently
@@ -646,79 +718,8 @@ getCalleeFunction(SILFunction *F, FullApplySite AI, bool &IsThick,
646
718
CalleeValue = stripCopiesAndBorrows (CalleeValue);
647
719
}
648
720
649
- // PartialApply/ThinToThick -> ConvertFunction patterns are generated
650
- // by @noescape closures.
651
- //
652
- // FIXME: We don't currently handle mismatched return types, however, this
653
- // would be a good optimization to handle and would be as simple as inserting
654
- // a cast.
655
- auto skipFuncConvert = [](SILValue CalleeValue) {
656
- // Skip any copies that we see.
657
- CalleeValue = stripCopiesAndBorrows (CalleeValue);
658
-
659
- // We can also allow a thin @escape to noescape conversion as such:
660
- // %1 = function_ref @thin_closure_impl : $@convention(thin) () -> ()
661
- // %2 = convert_function %1 :
662
- // $@convention(thin) () -> () to $@convention(thin) @noescape () -> ()
663
- // %3 = thin_to_thick_function %2 :
664
- // $@convention(thin) @noescape () -> () to
665
- // $@noescape @callee_guaranteed () -> ()
666
- // %4 = apply %3() : $@noescape @callee_guaranteed () -> ()
667
- if (auto *ConvertFn = dyn_cast<ConvertFunctionInst>(CalleeValue)) {
668
- // If the conversion only changes the substitution level of the function,
669
- // we can also look through it.
670
- if (ConvertFn->onlyConvertsSubstitutions ()) {
671
- return stripCopiesAndBorrows (ConvertFn->getOperand ());
672
- }
673
-
674
- auto FromCalleeTy =
675
- ConvertFn->getOperand ()->getType ().castTo <SILFunctionType>();
676
- if (FromCalleeTy->getExtInfo ().hasContext ())
677
- return CalleeValue;
678
- auto ToCalleeTy = ConvertFn->getType ().castTo <SILFunctionType>();
679
- auto EscapingCalleeTy = ToCalleeTy->getWithExtInfo (
680
- ToCalleeTy->getExtInfo ().withNoEscape (false ));
681
- if (FromCalleeTy != EscapingCalleeTy)
682
- return CalleeValue;
683
- return stripCopiesAndBorrows (ConvertFn->getOperand ());
684
- }
685
-
686
- // Ignore mark_dependence users. A partial_apply [stack] uses them to mark
687
- // the dependence of the trivial closure context value on the captured
688
- // arguments.
689
- if (auto *MD = dyn_cast<MarkDependenceInst>(CalleeValue)) {
690
- while (MD) {
691
- CalleeValue = MD->getValue ();
692
- MD = dyn_cast<MarkDependenceInst>(CalleeValue);
693
- }
694
- return CalleeValue;
695
- }
696
-
697
- auto *CFI = dyn_cast<ConvertEscapeToNoEscapeInst>(CalleeValue);
698
- if (!CFI)
699
- return stripCopiesAndBorrows (CalleeValue);
700
-
701
- // TODO: Handle argument conversion. All the code in this file needs to be
702
- // cleaned up and generalized. The argument conversion handling in
703
- // optimizeApplyOfConvertFunctionInst should apply to any combine
704
- // involving an apply, not just a specific pattern.
705
- //
706
- // For now, just handle conversion that doesn't affect argument types,
707
- // return types, or throws. We could trivially handle any other
708
- // representation change, but the only one that doesn't affect the ABI and
709
- // matters here is @noescape, so just check for that.
710
- auto FromCalleeTy = CFI->getOperand ()->getType ().castTo <SILFunctionType>();
711
- auto ToCalleeTy = CFI->getType ().castTo <SILFunctionType>();
712
- auto EscapingCalleeTy =
713
- ToCalleeTy->getWithExtInfo (ToCalleeTy->getExtInfo ().withNoEscape (false ));
714
- if (FromCalleeTy != EscapingCalleeTy)
715
- return stripCopiesAndBorrows (CalleeValue);
716
-
717
- return stripCopiesAndBorrows (CFI->getOperand ());
718
- };
719
-
720
721
// Look through a escape to @noescape conversion.
721
- CalleeValue = skipFuncConvert (CalleeValue);
722
+ CalleeValue = stripFunctionConversions (CalleeValue);
722
723
723
724
// We are allowed to see through exactly one "partial apply" instruction or
724
725
// one "thin to thick function" instructions, since those are the patterns
@@ -735,7 +736,7 @@ getCalleeFunction(SILFunction *F, FullApplySite AI, bool &IsThick,
735
736
IsThick = true ;
736
737
}
737
738
738
- CalleeValue = skipFuncConvert (CalleeValue);
739
+ CalleeValue = stripFunctionConversions (CalleeValue);
739
740
740
741
auto *FRI = dyn_cast<FunctionRefInst>(CalleeValue);
741
742
if (!FRI)
0 commit comments