编译器优化

即时编译器的中间表达形式(IR)

可紊 提交于 2019-12-20 19:45:35
原文链接: https://www.520mwx.com/view/36709 一、中间表达形式(IR) 在编译原理课程中,我们通常将编译器分为前端和后端。其中,前端会对所输入的程序进行词法分析、语法分析、语义分析,然后生成中间表达形式,也就是 IR(Intermediate Representation )。后端会对 IR 进行优化,然后生成目标代码。 如果不考虑解释执行的话,从 Java 源代码到最终的机器码实际上经过了两轮编译:Java 编译器将 Java 源代码编译成 Java 字节码,而即时编译器则将 Java 字节码编译成机器码。 对于即时编译器来说,所输入的 Java 字节码剥离了很多高级的 Java 语法,而且其采用的基于栈的计算模型非常容易建模。因此,即时编译器并不需要重新进行词法分析、语法分析以及语义分析,而是直接将 Java 字节码作为一种 IR。 不过,Java 字节码本身并不适合直接作为可供优化的 IR。这是因为现代编译器一般采用静态单赋值(Static Single Assignment,SSA)IR。这种 IR 的特点是每个变量只能被赋值一次,而且只有当变量被赋值之后才能使用。 y = 1; y = 2; x = y; 举个例子( 来源 ),上面这段代码所对应的 SSA 形式伪代码是下面这段: y1 = 1; y2 = 2; x1 = y2;

描述编译和链接过程

谁都会走 提交于 2019-12-20 18:04:09
原文摘自: http://www.cppblog.com/shifan3/archive/2007/01/05/17325.html [yc]详解link 详解link 有些人写C/C++(以下假定为C++)程序,对unresolved external link或者duplicated external simbol的错误信息不知所措(因为这样的错误信息不能定位到某一行)。或者对语言的一些部分不知道为什么要(或者不要)这样那样设计。了解本文之后,或许会有一些答案。 首先看看我们是如何写一个程序的。如果你在使用某种IDE(Visual Studio,Elicpse,Dev C++等),你可能不会发现程序是如何组织起来的(很多人因此而反对初学者使用IDE)。因为使用IDE,你所做的事情,就是在一个项目里新建一系列的.cpp和.h文件,编写好之后在菜单里点击“编译”,就万事大吉了。但其实以前,程序员写程序不是这样的。他们首先要打开一个编辑器,像编写文本文件一样的写好代码,然后在命令行下敲 cc 1.cpp -o 1.o cc 2.cpp -o 2.o cc 3.cpp -o 3.o 这里cc代表某个C/C++编译器,后面紧跟着要编译的cpp文件,并且以-o指定要输出的文件(请原谅我没有使用任何一个流行编译器作为例子)。这样当前目录下就会出现: 1.o 2.o 3.o 最后

微信团队分享:极致优化,iOS版微信编译速度3倍提升的实践总结

你说的曾经没有我的故事 提交于 2019-12-20 00:57:35
1、引言 岁月真是个养猪场,这几年,人胖了,微信代码也翻了。 记得 14 年转岗来微信时,用自己笔记本编译微信工程才十来分钟。如今用公司配的 17 年款 27-inch iMac 编译要接近半小时;偶然间更新完代码,又莫名其妙需要全新编译。在这么低的编译效率下,开发心情受到严重影响。 于是年初我向上头请示,优化微信编译效率,上头也同意了。 学习交流: - 即时通讯/推送技术开发交流5群: 215477170 [推荐] - 移动端IM开发入门文章:《 新手入门一篇就够:从零开发移动端IM 》 (本文同步发布于: http://www.52im.net/thread-2873-1-1.html ) 2、相关文章 《 微信团队分享:微信移动端的全文检索多音字问题解决方案 》 《 微信团队分享:iOS版微信的高性能通用key-value组件技术实践 》 《 微信团队分享:iOS版微信是如何防止特殊字符导致的炸群、APP崩溃的? 》 《 微信团队原创分享:iOS版微信的内存监控系统技术实践 》 《 iOS后台唤醒实战:微信收款到账语音提醒技术总结 》 《 微信团队分享:微信Android版小视频编码填过的那些坑 》 《 微信手机端的本地数据全文检索优化之路 》 《 微信团队披露:微信界面卡死超级bug“15。。。。”的来龙去脉 》 《 微信客户端团队负责人技术访谈

微信团队分享:极致优化,iOS版微信编译速度3倍提升的实践总结

╄→尐↘猪︶ㄣ 提交于 2019-12-20 00:41:09
1、引言 岁月真是个养猪场,这几年,人胖了,微信代码也翻了。 记得 14 年转岗来微信时,用自己笔记本编译微信工程才十来分钟。如今用公司配的 17 年款 27-inch iMac 编译要接近半小时;偶然间更新完代码,又莫名其妙需要全新编译。在这么低的编译效率下,开发心情受到严重影响。 于是年初我向上头请示,优化微信编译效率,上头也同意了。 学习交流: - 即时通讯/推送技术开发交流5群: 215477170 [推荐] - 移动端IM开发入门文章:《 新手入门一篇就够:从零开发移动端IM 》 (本文同步发布于: http://www.52im.net/thread-2873-1-1.html ) 2、相关文章 《 微信团队分享:微信移动端的全文检索多音字问题解决方案 》 《 微信团队分享:iOS版微信的高性能通用key-value组件技术实践 》 《 微信团队分享:iOS版微信是如何防止特殊字符导致的炸群、APP崩溃的? 》 《 微信团队原创分享:iOS版微信的内存监控系统技术实践 》 《 iOS后台唤醒实战:微信收款到账语音提醒技术总结 》 《 微信团队分享:微信Android版小视频编码填过的那些坑 》 《 微信手机端的本地数据全文检索优化之路 》 《 微信团队披露:微信界面卡死超级bug“15。。。。”的来龙去脉 》 《 微信客户端团队负责人技术访谈

值得推荐的C/C++框架和库

前提是你 提交于 2019-12-19 23:27:36
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> C/C++程序员必须熟练应用的开源项目 作为一个经验丰富的C/C++程序员, 肯定亲手写过各种功能的代码, 比如封装过数据库访问的类, 封装过网络通信的类,封装过日志操作的类, 封装过文件访问的类, 封装过UI界面库等, 也在实际的项目中应用过, 但是回过头仔细想想,其实以前自己写过的这些代码,只能是在特定的项目或者特定的环境中使用, 对于自己来说, 在不同的项目中应用, 只需要复制代码, 改改也就可以了, 因为自己写的代码自己很熟悉。问题是, 你封装的这些库, 在给别人使用的时候, 别人用起来是否很方便, 跨平台方面是不是也很通用, 性能是不是足够的好, 是不是支持多线程, 功能是不是也足够强大,可以适用于各种不同的需求。如果你上面这些都做到了, 证明你在这个库上确实花费了一番功夫, 经过了持续的改进和优化。 在日常的开发中, 作为一个程序员, 很多东西已经没有必要再重新开发了, 可以直接拿过来使用, 毕竟21世纪都已经过了N年了。我们没有必要重新发明轮子(不可否认发明轮子的过程可以学到很多东西,我就是这么走过来的)。 下面结合自己多年的开发经验, 想到哪里写到哪里, 希望对新人有一定的帮助。 一、网络 网络库必须掌握 ACE 和 libevent, 一个是重量级的网络库, 一个是轻量级的网络库。仔细想想

为什么这些构造使用前后递增的未定义行为?

人走茶凉 提交于 2019-12-19 15:48:41
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> #include <stdio.h> int main(void) { int i = 0; i = i++ + ++i; printf("%d\n", i); // 3 i = 1; i = (i++); printf("%d\n", i); // 2 Should be 1, no ? volatile int u = 0; u = u++ + ++u; printf("%d\n", u); // 1 u = 1; u = (u++); printf("%d\n", u); // 2 Should also be one, no ? register int v = 0; v = v++ + ++v; printf("%d\n", v); // 3 (Should be the same as u ?) int w = 0; printf("%d %d\n", ++w, w); // shouldn't this print 1 1 int x[2] = { 5, 8 }, y = 0; x[y] = y ++; printf("%d %d\n", x[0], x[1]); // shouldn't this print 0 8? or 5 0? } #1楼 尽管不太可能有任何编译器和处理器实际执行此操作

volatile的作用

前提是你 提交于 2019-12-17 11:08:41
[转] http://blog.21ic.com/user1/2949/archives/2007/35599.html   一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 1). 并行设备的硬件寄存器(如:状态寄存器) 2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 3). 多线程应用中被几个任务共享的变量 回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。 假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。 1). 一个参数既可以是const还可以是volatile吗?解释为什么。 2). 一个指针可以是volatile 吗?解释为什么。 3). 下面的函数有什么错误: int square(volatile int *ptr) { return *ptr * *ptr; }

Java编译器的优化

妖精的绣舞 提交于 2019-12-15 20:58:34
public class Notice { public static void main(String[] args) { // 右侧20是一个int类型,但没有超过左侧数值范围,就是正确的 // int --> byte 不是自动类型转换 byte num1 = 20; System.out.println(num1); // 20 // 错误:不兼容的类型: 从int转换到byte可能会有损失 // byte num2 = 128; // System.out.println(num2); char zifu = 65; System.out.println(zifu); // A } } 对于byte/short/char三种数据类型,如果右侧没有超过左侧数值范围,则编译器会自动进行优化,在右侧隐含地添加(byte) / (short) / (char) 如果右侧超过左侧数值范围,则编译器直接报错。 public class Notice2{ public static void main(String[] args){ short num1 = 10, num2 = 8; // short + short --> int + int --> int // short = int + int // short num3 = num1 + num2; // 错误写法

Keil C51里关于堆栈指针的处理

假如想象 提交于 2019-12-15 20:44:59
Keil C是非常优秀的C51编译器,可能是最好的C51编译器,提供各种优化模式,对变量的优化和地址安排做得非常好。这是用C语言写代码的好处之一,如果用汇编写,得费一大番功夫给各个变量安排内存物理地址,还得时刻记住哪些地址的内存单元是已经分配了,新增加的变量就不能占用那些已经分配了的单元,以免产生内存交叠冲突和溢出。我一直非常信赖Keil C51的编译结果,在我的印象里,它对内存的分配是完美的,只要代码用它编译时没有报告任何warning和error,代码运行时不可能内存冲突或溢出的现象。 但,今天发生的事情证明我错了。 手头上有个产品的代码,代码量很大。程序跑起来的效果不大好,因此打算把代码优化一下。代码量越大,通常可优化的地方也越多。对8051来说,访问芯片内部的data区(0~7FH)内存速度是最快的,直接访问,一条指令就能读写,而idata区(80H~FFH)虽然还是内存区,但由于地址分配上跟特殊寄存器SFR重合,只能间接地址访问,两条指令才能读写,速度稍慢点,而外存xdata区(0~7FFFH)必须使用DPTR指针才能访问,速度是最慢的。很明显,优化的原则就是尽量把频繁读写的变量优先安排在data区,然后是idata区,最后才是xdata区。 当我做完变量手工优化工作后,把编译模式设为SMALL,这样C51编译器会自动把那些我没手工指定存放区的变量优先安排进data区

单片机中断全局变量保护方法

℡╲_俬逩灬. 提交于 2019-12-15 14:28:40
首先要明白这几个知识点:关键字volatile的使用,原子操作,临界区的使用。明白的直接跳到文中的 4.全局变量的使用及保护 处查看。 1.关键字volatile 关键字volatile用于告诉编译器,说明被修身的变量可能会被意想不到地改变,防止编译器对代码进行优化。 比如如下程序: 1 ucNms=0x65;2 ucNms=0x66;3 ucNms=0x67;4 ucNms=0x68; 上述4条语句,如果变量在声明的时候(unsigned char ucNms;)没有使用volatile,那么编译器有可能对其优化,只编译最后一条语句ucNms=0x68;(即忽略前三条语句,只产生一条机器汇编代码);如果变量在声明的时候(volatile unsigned char ucNms;)使用了volatile,则编译器会逐一地进行编译并产生四条相应的机器代码(产生四条代码)。 精确地说就是,编译器在编译这个变量语句时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。所以下面几个情况在声明的时候需要用volatile关键字对其修饰: 1)并行设备的硬件寄存器(如:状态寄存器) 2)一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 3)多线程应用中被几个任务共享的变量 2.原子操作 原子操作可以理解为不被打断的操作