Swift中函数的通用专业化
在今天的帖子中,我们将讨论Swift编译器的Generic专业化知识,并对它是什么以及SIL Optimizer为什么执行此操作以获得更高性能的代码进行基本概述。 此外,我们还将简要介绍Swift中间语言(SIL)表示形式以及它在此通用专业优化遍历中的作用。
首先…
编译器
在深入研究泛型专长之前,我们需要至少从高层次上了解有关编译器流程的一些知识。
swift编译器获取您的Swift代码,将其处理为手动编码的Lexer,将其标记化并将其转换为抽象语法树(AST),然后是语义分析(Sema),其中编译器将使用解析器生成的AST并进行类型检查的AST并检查其中的语义问题。 然后,Swift中级语言生成(SILGen)阶段将通过语义分析生成的AST转换为他们所谓的原始SIL,在对SIL进行了一些优化(如通用专业化,ARC优化等)之后……它生成了这种被称为规范SIL的优化SIL。然后将其交给IRGen生成中间表示(IR),该中间表示将传递给LLVM,以使其继续工作并生成目标文件(.o),该文件随后将由链接器粘合在一起并生成最终的二进制文件。
这是对编译器管道的简要概述。 这只是让我们了解编译器的各个阶段,但是在这里,我们将重点介绍发生通用专业化的SILGen和SIL Optimization Pass。 仅供参考,Swift中间语言(SIL)是一种静态单分配形式(SSA形式)中间表示形式,用于实现swift编译器,目的是在源代码与LLVM IR之间架起抽象桥梁,从而提供一种执行高级别的优化,例如通用专业化,保留/发布优化,动态方法去虚拟化等等……以及高级诊断分析。
您可以在快速主存储库的说明文件[1]中找到有关SIL的更多信息。
返回通用专业化
因此,泛型专业化是SIL优化过程,它分析了对泛型函数的所有调用(使用完整模块编译模式时在模块中)或具有@_specialize属性的泛型代码(我们将在后面讨论),然后生成新的特殊化这些函数的版本将泛型的所有专用用法替换为直接调用生成的专用函数。
使用专用函数的性能更高,因为它可以使用特定的具体类型最有效的布局,并且在诸如将参数复制到局部变量之类的操作中,例如,它避免了动态分配泛型类型和保存对运行时类型元数据大小和对齐方式的值见证表。
让我们看一下如何生成专用SIL的实际示例
生成的SIL上还有很多其他内容,但仅突出显示与我们定义的函数相关的内容。
仅查看生成的SIL,我们就可以看到编译器如何发出通用和专用SIL表示形式。
我们可以注意到,主SIL调用了函数@ $ S4main9incrementyxxs13BinaryIntegerRzlFSi_Tg5的引用,正如我们看到的那样,它是增量的专用版本。 这意味着主要功能正在调用优化的专用功能。
另外,我们可以注意到专用版本针对Int进行了完全优化,而在通用SIL上,所有操作都基于基于元类型信息的调用(应用)函数。
告诉SIL优化器不执行专业化
我们可以告诉编译器,由于某种原因,我们不希望使用@_semantics属性对该通用函数进行专用化。 您可以在HighLevelSILOptimizations文档的“优化语义”属性部分中找到有关语义的更多信息。
这就是本文的全部内容\ o /
如果您有任何意见或疑问,请告诉我。 您的反馈意见非常重要,因此我们可以改善此问题以及将来的帖子,很高兴收到它:))
您可以在Twitter上@ LucianoPassos11找到我。
感谢您阅读🙂
参考文献
- Swift中级Languange(SIL)。 https://github.com/apple/swift/blob/master/docs/SIL.rst
- SIL程序员手册。 https://github.com/apple/swift/blob/master/docs/SILProgrammersManual.md
- 泛型。 https://github.com/apple/swift/blob/master/docs/Generics.rst
- SIL中的高级优化。 https://github.com/apple/swift/blob/master/docs/HighLevelSILOptimizations.rst