摘要:
自从年初手断了以后好久不写文字了, 说好的笔耕不辍也忘了(=.=), 今天正好有同学问AntiDepBreaker, 就花点时间看了下代码(顺便水一篇). 背景概述 1. 什么是Anti Dependency 在数据流分析中一般将数据依赖分为三种: 写后读(RAW, read after write 阅读全文
摘要:
这周定位一个与DenseMap有关的问题, 正好趁机过一下它的实现. DenseMap(稠密映射)是LLVM自定义的关系类的容器, 我们可以像std::map一样使用它, 但要注意两者之间稍稍有些区别. 概述 类似于unorderd_map, DenseMap也是通过哈希实现, 区别在于DenseM 阅读全文
摘要:
再有半个小时就迎来2021年啦, 看着别人对过去一年的总结, 也想要说些什么. 回望2020是充满变数的一年, 不管是大环境从年初的CVOID到美帝经济制裁再到换届选举川普下台, 几十年来的和平发展环境逐渐转向冲突对抗, 还是从自身而言: 团队变动各位伙伴各奔东西, 新的工作新的职责新的团队, 一切 阅读全文
摘要:
上节介绍了IR中底层的数据表达方式(Value)及其组织方式(有向图), 有了这个基础就可以理解LLVM IR中的一些基本构成. 本节将要介绍其中的一个基础概念: 指令(Instruction). LLVM IR指令基础 LLVM使用Instruction来描述一条具体的指令. 与ISA设计类似, 阅读全文
摘要:
ADT(advanced data type)是LLVM针对其业务逻辑自定义的高性能抽象类型, 其定义见include/llvm/ADT目录. ADT目录下既包含了DenseMap/SmallVector这类容器封装, 也包含了APInt等大数运算支持, 还有triple这类从编译器业务抽象出来的类 阅读全文
摘要:
在LLVM中输入程序流以IR的形式呈现, 之前培训过如何打印与阅读文本形式的IR, 这次简要介绍一下在内存中IR的组织形式, 以及处理/转换IR时需要注意点. 本节主要介绍IR组织中最底层的数据结构(Value), 它们是如何组织的(有向图)以及如何修改它们之间的联系. 一切皆Value 当在提及L 阅读全文
摘要:
上周同事讨论ARM内存序问题, 正好是感兴趣的方面于是就研究了一下, 可惜电脑爆炸了拖到今天才恢复正常. 内存序问题的由来 内存序(memory ordering)是指处理器访问内存的顺序, 在传统的in order处理器上对内存的访问顺序由compiler在编译期间决定, 处理器顺序执行指令流, 阅读全文
摘要:
问题 如下所示有两个cxx源文件, 分别定义与使用一个const变量. 将其一起编译时报错: undefined reference of 'meow::miao'. [01:06:44] hansy@hansy:~/testcase$ cat 1.cc namespace meow { const 阅读全文
摘要:
趁着放假把之前记得笔记整理下, 顺带看下是否有新的理解, 首先从ADT与Support目录开始. LLVM扩展了运行时类型识别能力, 提供一组自定义接口用于安全的动态判断与类型转换(isa<>, dyn_cast<>, .etc), 熟悉LLVM代码的开发者应该比较熟悉其使用方法了, 对于不熟悉的开 阅读全文
摘要:
semihosting背景介绍 semihosting是ARM提出的一种新的调试机制, 它允许运行在目标ARM架构上的代码与主机通信并借用主机侧的IO功能, 一般用于仿真环境/调试环境. 更多信息见ARM官方文档. 有意思的是, RISCV在今年也推出了基于自身架构的semihosting标准, 其 阅读全文
摘要:
今天看到一个浮点运算的问题, 觉得很有代表性, 就记录一下. 有同事问下面这段代码运行结果是什么, 还很贴心的给了4个选项: 30500 (0.000061 * 500 * 1000000) 与A同量级的近似值 具体值不知道, 但肯定是小于A量级某个浮点数 1024.0 (精确值) #include 阅读全文
摘要:
今天定位了一个const引入的优化问题, 问题本身挺简单的, 但是自己太菜, 写代码时竟然没注意, 所以记录一下, 引起警戒. 问题背景与定位 测试团队反馈修改newlib系统调用以后跑coremark报错bad alloc, 于是就看了了下sbrk()的修改. 因为之前在修改newlib时需要通过 阅读全文
摘要:
最近在适配newlib代码时遇到一个关于弱声明的问题, 研究了一下才发现自己对weak属性与链接时符号选择理解有误. 问题背景 在一个库(liba.a)中重新定义了一个weak属性的函数(func_a), 在同一库中调用该函数时链接了弱声明的函数版本, 但是当通过另一个库(libb.a)的库函数(f 阅读全文
摘要:
平时工作常常遇到一些有趣的问题, 可惜因为时间原因没能及时总结. 最近下定决心把这些问题收集起来做个记录, 以供以后有空时候回顾自己当时定位问题的思路与盲区, 总结经验与教训, 如果有空还可以补充拓展相关背景, 补齐自己的知识短板. 问题现象 这个问题是两年前刚接触编译器开发时遇到的问题, 回头来看 阅读全文
摘要:
本节主要介绍指令选择的具体步骤(select). select是将基于ISD SDNode的DAG替换成基于机器指令节点的DAG的过程. select基本流程 在完成combine与legalize之后SelectionDAGISel::CodeGenAndEmitDAG()会调用Selection 阅读全文
摘要:
本节介绍指令选择中legalize的概念, 为中端IR精确匹配机器指令需要同时检查操作符与操作数, 在正式指令选择前对不合法的操作符或操作数作出转换的过程即legalize. 通常情况下给定一个后端架构其支持的指令集: 1. 不一定能支持表达所有中端IR的操作. 一个显而易见的例子是在一个不支持浮点 阅读全文
摘要:
本节将要介绍指令选择中combine优化的概念, combine的目的是简化DAG, 合并/消除冗余节点, 为生成更优的指令做准备. 大部分combine是与架构无关的优化, 但LLVM也提供了修改combine的custom接口. 尽管本节介绍的是combine的流程, 但combine与lega 阅读全文
摘要:
本节主要介绍SelectionDAG的构成与lowering的过程. SelectionDAG是LLVM指令选择的基础框架, 不论是O0编译时使用的FastISel还是O2编译时使用的SelectionDAGISel都会使用SelectionDAG来描述输入的程序流. 将输入的IR转换成Select 阅读全文
摘要:
本文最初是基于对新员工培训, 使其快速上手编译器后端代码而写的入门简介. 为方便阅读又根据模块细分为若干章, 内容以分析代码为主, 偶尔也会穿插一些理论扩展. 什么是指令选择 指令选择(instruction selection)是将中间语言转换成汇编或机器代码的过程. 如果仅为单一语言在单一目标上 阅读全文
摘要:
今天打开vimdiff时自动切到后台了, 手动fg还恢复不了, 但是尝试换个帐号登录是正常的, 怀疑是某个配置导致的问题. 于是比较下两者的vimrc, 发现之前为了能使vim识别alias命令开启了interactive shell, 导致vim的diff命令与shell的diff命令冲突了. 在 阅读全文
摘要:
之前写tablegen的介绍写到一半放弃了, 最近培训需要再拉出来看看, 顺便做个笔记. 1. 语法介绍 官方文档见 "这里" , 以下是文档的翻译. 1.1. 类型系统 tablegen是强类型语言, 其类型系统同时包含low level(i.e. bit int)与high level(i.e. 阅读全文
摘要:
mimalloc是微软去年6月开源的(竟然拖了半年才开始写笔记)新的内存分配器, 其最早由Daan Leijen开发, 为Koka与Lean等语言的runtime system提供内存管理. 根据 "官方文档" 描述, mimalloc在各类benchmark上性能均优于其它主流allocator( 阅读全文
摘要:
1. 什么是指令的side effect 在后端优化中常常见到MI.hasUnmodeledSideEffects()这个接口, 其代表该指令具有无法衡量的副作用. 对于这类指令, 编译器在优化时会保守处理, 比如指令调度会以此为边界(在其之后的指令不会调度到之前). 2. 查看指令的side ef 阅读全文
摘要:
好久没更新博客了, 最近调研安全编译选项(各类sanitizer), 抽空做个笔记. 本来想系统的分析一下compiler rt代码, 但是最近实在太懒了, 所以先介绍最简单的安全栈safestack, 之后有空再补上compiler rt框架以及其它sanitizer工具. 1. 什么是safes 阅读全文
摘要:
1. SMS介绍 SMS(Swing Modulo Scheduling, 摇摆模调度)是一个基于循环的与架构无关的SWP(software pipelining)指令调度框架, 其目的是通过将当前迭代的指令与上一迭代同时发射来提升并行度. 考虑以下伪代码: 不考虑跳转指令, 该循环需要独立发射三条 阅读全文
摘要:
1. 什么是RDF RDF(register data flow)是高通在开发Hexagon时实现的一套寄存器分配后dataflow graph. 由于LLVM框架本身推荐在SSA form下实现各类变换, 因此缺少在寄存器分配后的数据流分析工具. 然而在某些情况下(比如copy propagati 阅读全文
摘要:
1. pass的概念 在LLVM中优化以pass形式实现, 每一个pass代表一种优化. pass分为两类, 一类是分析(analysis)pass, 负责收集信息共其它pass使用, 辅助调试或使程序可视化; 另一类是变换(transform)pass, 改变程序的dataflow / contr 阅读全文
摘要:
1. 什么是IR IR(intermediate representation)是LLVM独创的中间表达式. 经典的compiler架构由前端frontend(读入源代码, 通过词法, 语法与语义分析建立AST), 中端optimizer(优化模块)与backend(通过指令选择, 寄存器分配等阶段 阅读全文
摘要:
1. 什么是tablegen tablegen是llvm用于开发和维护编译器中公共特性的条目(e.g. 指令描述, 寄存器描述)的代码, 使之灵活的描述与构造的自动化工具. 其本质是一个parser, 将输入的td文件转化为特定的数据结构后再输出为易于阅读的cpp代码. 更多介绍可见http://l 阅读全文
摘要:
findfile()类似find命令, 可以快速查找文件. 它接受三个参数: (被搜索的)文件名, 搜索路径(与搜索方式)与匹配次数(-1为不限次数). 返回值是一个包含给定匹配次数的文件列表.例如平时工作时需要在头文件与源文件之间快速切换, 而两者又不在统一目录, 那么可以使用以下代码: 使用fi 阅读全文