什么是编译
对于语言,有高级语言,低级语言和机器语言的方式来表示,因为机器是只能做数字计算的,能够让机器去运算的只有机器语言,从高级语言转为机器语言的过程就叫做编译,由编译器来完成
例如:由 C 转换为汇编语言需要 汇编器来执行
C 和汇编语言转换为机器语言都是由编译器来指向的
编译器的架构
传统的编译器架构
前端:词法分析,语法分析,语义分析,生成中间代码
优化器:中间代码优化
后端:生成机器码
编译优化的方法
常量传播
编译优化时,能够将计算出来的变量直接替换为常量
void main()
{
int a=1;
printf("%d",a);
}
优化后
void main()
{
printf("%d",1);
}
公共子表达式消除
如果一个表达式已经计算过,并且表达式中的变量一直没有变化,那么这个这个表达式就是公共子表达式
void main()
{
int a =1,b=2,x=0;
x=(a+c)*12+(c+a);
}
优化后
void main()
{
int a =1,b=2,x=0;
x=E*12+E;
}
方法内联
循环优化
循环嵌套外大内小
循环条件使用<要快于<=
for(int i=0;i<50;i++)
把外层可以计算的尽可能放到外层,减少在内层的运算,有判断条件的语句和与循环不相关的操作语句尽量放在for外面
循环展开
循环交换
https://blog.csdn.net/zhengzhoudaxue2/article/details/6459890
再看这个例子
int main(int argc,char **argv)
{
int i,m,k1,k2,k3,k4,k5,k6,k7,k8;
m=10000000;
for(i=0;i<m;i++){
k1++; k5++;
k2++; k6++;
k3++; k7++;
k4++; k8++;
}
return (0);
}
这个for循环,我们是让这些数每次循环都加1,这个效率也不是达到了最优,是这样的,在每次for循环的时候,编译器会给变量i,变量m每个独占一个寄存器,因为是循环嘛,编译器给i和m也是为了效率考虑,不用再向寄存器加载每次循环的判断变量了,但是,一般基于Intel的处理器都只有8个通用寄存器,这样,我们就剩下了6个寄存器给for循环里的内容中的变量使用,但是,我们的变量有8个,我们这时会在把其他的变量入栈,这样,我们的效率变低了,每次出战或者入栈都会消耗两个CPU时钟周期
优化后:
int main(int argc,char **argv)
{
int i,m,k1,k2,k3,k4,k5,k6,k7,k8;
m=10000000;
for(i=0;i<m;i++){
k1++; k5++;
k2++; k6++;
}
for(i=0;i<m;i++){
k3++; k7++;
k4++; k8++;
}
return (0)
}
LLVM
llvm项目是模块化、可重用的编译器以及工具链技术的集合
LLVM架构
- 不同的前端后端使用统一的中间代码LLVM Intermediate Representation(LLVM IR)
- 如果需要支持一种新的编程语言,那么只需要实现一个新的前端
- 如果需要支持一种新的硬件设备,那么只需要实现一个新的后端
- 优化阶段是一个通用的阶段,它针对的是统一的LLVM IR,不论是支持新的编程语言还是支持新的硬件设备,都不需要对优化阶段做修改
- 相比之下,GCC的前端和后端没分得太开,前端后端耦合在了一起。所以GCC为了支持一门新的语言,或者为了支持一个新的目标平台,就 变得特别困难
- LLVM现在被作为实现各种静态和运行时编译语言的通用基础结构(GCC家族、Java、.NET、Python、Ruby、Scheme、Haskell、D等)
Clang
Clang是LLVM的一个子项目,基于LLVM架构的C/C++/Objective-C编译器的前端
Clang对比GCC的优点
- 编译速度快:在某些平台上,Clang的编译速度显著的快过GCC(Debug模式下编译OC速度比GGC快3倍)
- 占用内存小:Clang生成的AST所占用的内存是GCC的五分之一左右
- 模块化设计:Clang采用基于库的模块化设计,易于 IDE 集成及其他用途的重用
- 诊断信息可读性强:在编译过程中,Clang 创建并保留了大量详细的元数据 (metadata),有利于调试和错误报告
- 设计清晰简单,容易理解,易于扩展增强
LLVM整体架构,前端用的是clang,广义的LLVM是指整个LLVM架构,一般狭义的LLVM指的是LLVM后端(包含代码优化和目标代码生成)。
源代码(c/c++)经过clang–> 中间代码(经过一系列的优化,优化用的是Pass) --> 机器码
参考
深入浅出让你理解什么是LLVM
https://www.jianshu.com/p/1367dad95445
编译器常用优化方法
https://www.jianshu.com/p/0caa9cfd995a
你的for循环真的高效吗
https://blog.csdn.net/zhengzhoudaxue2/article/details/6453366