自定义LLVM通行证
Julia有许多自定义LLVM通行证。 从广义上讲,它们可以分为运行以维护Julia语义所需的传递和利用Julia语义优化LLVM IR的传递。
语义传递
这些传递用于将LLVM IR转换为可在CPU上运行的合法代码。 它们的主要目的是使codegen能够发出更简单的IR,然后使其他LLVM传递能够优化常见模式。
CPUFeatures
*文件名: llvm-cpufeatures。cpp
*类名: [医][医][医][医][医]
*选择名称: 模块(CPUFeatures)
这张通行证降低了 朱莉娅。cpu。have_fma。(f32/f64) 固有的true或false,具体取决于函数上存在的目标体系结构和目标功能。 这个内在通常用于确定是否使用依赖于快速的算法https://en.wikipedia.org/wiki/Multiply%E2%80%93accumulate_operation#Fused_multiply%E2%80%93add[fused multiply-add]运算优于使用不依赖于此类指令的标准算法。
DemoteFloat16
*文件名: llvm-降级-float16。cpp
*类名: Demotefloat16通
*选择名称 功能(DemoteFloat16)
此通行证取代https://en.wikipedia.org/wiki/Half-precision_floating-point_format[float16]在原生不支持float16操作的体系结构上使用float32操作的操作。 这是通过插入来完成的 n.fpext 和 [医]fptrunc 关于任何float16操作的说明。 在支持本机float16操作的体系结构上,此传递是一个无操作。
[医]迟发性
*文件名: llvm-late-gc-lowering。cpp
*类名: LateLowerGCPass的
*选择名称: 功能(LateLowerGCFrame)
此通道执行跟踪GC安全点之间的指针所需的大部分GC生根工作。 它还降低了几个内在函数对其相应的指令转换,并允许违反以前建立的非积分不变量(pointer_from_objref 被降低到一个 ptrtoint的 这里的指示)。 由于其数据流算法可以最大限度地减少任何安全点上的对象数量,因此此传递通常在所有自定义Julia传递中占用最多的时间。
[医]终结
*文件名: llvm-final-gc-lowering。cpp
*类名: 最后,最后
*选择名称: 模块(FinalLowerGC)
这一过程降低了一些最后的内在函数到它们的最终形式目标函数 [医]利朱利亚 图书馆。 将此与 [医]迟发性 允许其他后端(GPU编译)为这些内部函数提供自己的自定义lower,从而使Julia管道也可以在这些后端使用。
下岗工人
*文件名: llvm-lower-handlers。cpp
*类名: [医]低碳纤维
*选择名称: 功能(LowerExcHandlers)
此过程将异常处理内部函数降低到对处理异常时实际调用的运行时函数的调用中。
诺维尼
*文件名: llvm-remove-ni。cpp
*类名: 清除,清除
*选择名称: 模块(RemoveNI)
此通道从模块的datalayout字符串中删除非整数地址空间。 这使后端能够将Julia的自定义地址空间直接降低到机器代码,而无需将每个指针操作重写到地址空间0。
辛德鲁普
*文件名: llvm-simdloop。cpp
*类名: [医]低音喇叭
*选择名称: 循环(LowerSIMDLoop)
这个通行证是 @simd 注释。 Codegen插入一个 !llvm。环形结构 标记在循环的后分支,此通道用于标识最初标记为 @simd. 然后,此过程查找形成reduce的浮点运算链并添加 合约 和 重新分配 快速数学标志允许重新关联(从而矢量化)。 此传递既不保留循环信息也不保留推理正确性,因此它可能会以令人惊讶的方式违反Julia语义。 如果循环被注释为 ivdep 同样,通过将循环标记为没有循环携带的依赖关系(如果用户注释不正确或应用于错误的循环,则结果行为未定义)。
低点,低点
*文件名: llvm-ptls。cpp
*类名: N.低点,低点
*选择名称: 模块(LowerPTLSPass)
此传递将线程本地Julia内部函数降低为汇编指令。 Julia依赖于线程本地存储进行垃圾回收和多线程任务调度。 在编译系统映像和包映像的代码时,此过程使用在加载时初始化的全局变量的加载替换对内部函数的调用。
如果codegen产生一个函数 迅捷自我 参数和调用约定,此传递假定 迅捷自我 参数是pgcstack,并将用该参数替换内部函数。 这样做可以加快线程本地存储访问速度较慢的体系结构。
移除空间
*文件名: llvm-remove-addrspaces。cpp
*类名: 清除;清除
*选择名称: 模块(RemoveAddrspaces)
此传递将一个地址空间中的指针重命名为另一个地址空间。 这用于从LLVM IR中删除Julia特定的地址空间。
[医]脱去,脱去
*文件名: llvm-remove-addrspaces。cpp
*类名: [医]除菌剂
*选择名称: 模块(RemoveJuliaAddrspaces)
此通道从LLVM IR中删除Julia特定的地址空间。 它主要用于以不那么杂乱的格式显示LLVM IR。 在内部,它是通过RemoveAddrspaces传递实现的。
多版本控制
*文件名: llvm-多版本控制。cpp
*类名: 多版本控制通
*选择名称: 模块(JuliaMultiVersioning)
此过程执行对模块的修改,以创建针对在不同体系结构上运行而优化的函数(请参阅sysimg.md 和pkgimg.md 欲了解更多详情)。 在实现方面,它克隆函数并对其应用不同的目标特定属性,以允许优化器使用该平台的矢量化和指令调度等高级功能。 它还创建了一些基础结构,使Julia映像加载器能够根据加载器运行的体系结构选择要调用的函数的适当版本。 目标特定属性由 朱莉娅.mv.规格 模块标志,它在编译期间从 JULIA_CPU_目标环境变量。 该通行证还必须通过提供一个启用 julia.mv.启用 值为1的模块标志。
|
警告使用 |
Gcinvariant验证器
*文件名: llvm-gc-invariant-verifier。cpp
*类名: [医][医][医][医][医][医][医]
*选择名称: 模块(GCInvariantVerifier)
此传递用于验证Julia关于LLVM IR的不变量。 这包括诸如不存在 ptrtoint的 在朱莉娅的https://llvm.org/docs/LangRef.html#non-integral-pointer-type[非完整地址空间]脚注:nislides[只有有福的存在 [医增效剂 指令(跟踪->派生,0->跟踪等)。 它对IR不执行任何转换。
优化通过
这些传递用于对LLVM IR执行LLVM不会自行执行的转换,例如快速数学标志传播,转义分析以及对Julia特定内部函数的优化。 他们使用有关Julia语义的知识来执行这些优化。
分配,分配
*文件名: llvm-alloc-opt。cpp
*类名: 分配通,分配通
*选择名称: 功能(分配)
Julia没有程序堆栈的概念作为分配可变对象的地方。 但是,在堆栈上分配对象会降低GC压力,并且对于GPU编译至关重要。 因此, 分配,分配 执行堆到堆栈转换的对象,它可以证明不https://en.wikipedia.org/wiki/Escape_analysis[转义]当前函数。 它还对分配执行许多其他优化,例如删除从不使用的分配,优化对新分配对象的typeof调用,以及删除立即复盖的分配的存储。 逃逸分析实现位于 llvm-alloc-helpers。cpp. 目前,此通行证不使用来自 逃逸分析。jl,虽然这可能会在未来改变。
传播,传播
*文件名: llvm-propagate-addrspaces。cpp
*类名: 传播[医]传播[医]传播[医]传播[医]传播[医]传播[医]传播
*选择名称: 函数(PropagateJuliaAddrspaces)
此传递用于通过指针上的操作传播Julia特定的地址空间。 LLVM不允许通过优化引入或删除addrspacecast指令,因此此传递通过在Julia地址空间中用等效操作替换操作来消除冗余的addrspace强制转换。 有关Julia地址空间的更多信息,请参阅(TODO链接到llvm.md)。
[医]朱利亚
*文件名: llvm-julia-licm。cpp
*类名: [医]朱利卡
*选择名称: 环(JuliaLICM)
此通道用于将Julia特定的内部函数从循环中提升出来。 具体来说,它执行以下转换:
-
提升机/提升机
gc_preserve_begin和下沉gc_preserve_end当保存的对象是循环不变的时,循环外。 -
由于在循环中保留的对象可能会在循环的持续时间内保留,因此此转换可以减少
gc_preserve_begin/gc_preserve_end对在IR中。 这使得它更容易为LateLowerGCPass的识别特定对象的保存位置。 -
提升具有不变对象的写入障碍
-
在这里,我们假设只有两代对象可以成为其中的一部分。 鉴于此,写屏障只需要对同一对象的任何一对执行一次。 因此,当被写入的对象是循环不变的时,我们可以将写入障碍从循环中提升出来。
-
当它们没有逃出循环时,将分配从循环中提升出来
-
我们在这里使用了一个非常保守的escape定义,与在
分配通,分配通. 这种转换可以减少IR中的分配数量,即使分配完全逃逸函数也是如此。
|
请注意,此通行证是需要保留LLVM的https://llvm.org/docs/MemorySSA.html[MemorySSA](https://www.youtube.com/watch?v=bdxWmryoHak[短片],https://www.youtube.com/watch?v=1e5y6WDbXCQ[更长的视频])和https://baziotis.cs.illinois.edu/compilers/introduction-to-scalar-evolution.html[标量卷积](较新的幻灯片https://llvm.org/devmtg/2009-10/ScalarEvolutionAndLoopOptimization.pdf[旧幻灯片])分析。 |