技术文章:编译器的寄存器分配

2022年07月04日18:36:25 科技 1923

因为存储速度成本之间的问题,电脑的整个存储系统按照CPU从近到远可以分为4级:寄存器、cache缓存、主内存、硬盘。

离CPU最近的寄存器,读写速度最快

离CPU最远的硬盘,读写速度最慢。

包括C语言在内的大多数语言,是不需要关注寄存器怎么分配的。这部分的工作被编译器处理了。

当然,汇编语言是需要手动分配寄存器的。

程序员在写汇编时,会按照自己的直觉给出一个寄存器分配方案。

例如 5 / 3 = 1;汇编是这么写的:

mov 5, eax

xor edx, edx

mov 3, ecx

div ecx

这时,在eax里,余数在edx里。英特尔的CPU就是这么设计除法指令的。

除法使用固定的寄存器eax和edx,是CISC架构的缺点,让寄存器的分配变得麻烦。

如果是int a = 5, b = 3, c = a / b;

那么就要尽量给c分配寄存器eax,因为除法的商默认就在eax里,这样可以提高生成的汇编码的效率

如果是c = a % b,那么就要尽量给c分配寄存器edx,因为余数默认就在edx里。

因为寄存器只有16个,在程序规模较大的时候,是没法这么理想的分配寄存器的。

编译器里,寄存器的分配是根据变量之间的活跃度来的:同时活跃变量不能使用同一个寄存器,否则数据就互相覆盖了。

c = a / b这行代码的被除数a和除数b肯定是同时活跃的,在除法指令运行的那一刻它们必须同时有效(而且互相覆盖)。

c与a、b并不是同时活跃的,它是在除法运行之后开始活跃。

如果变量a在这行代码之后不再使用,那么c和a是可以共用eax的。

如果后续还要使用a,那么就不能共用eax。例如:

int a = 5, b = 3;

int c = a / b;

c += a; // a在这里还是活跃的,不能在第二行c = a / b时被覆盖。

这时就只能给c分配eax,同时edx除法指令占用,所以a和b只能使用ecx和ebx

以上代码翻译成汇编:

mov 5, ecx // a使用ecx

mov 3, ebx // b使用ebx

mov ebx, eax // 加载被除数的最低32位到eax

xor edx, edx // 被除数的高32位清零

div ebx // 真正的除法运算只是这一条

add ecx, eax // c += a

技术文章:编译器的寄存器分配 - 天天要闻

上面2行代码c = a / b, c += a的寄存器冲突图,如上。

给这个图的3个顶点a、b、c着色,被冲突线连接两个顶点不能是同一个颜色,即不能分配同一个寄存器

因为CISC的除法使用edx,我们把它也作为一个约束条件添加到这个图里:变量a是不能使用它的,因为它会被除法运算的余数覆盖,而a在c += a这行代码还要使用。

c可以使用它,但c作为除法运算的商应该优先分配eax,否则就还需要多1条mov eax, edx的汇编码。

技术文章:编译器的寄存器分配 - 天天要闻

64位寄存器的字节分配

实际CPU的寄存器是个64位的寄存器组,它的最低8位AL、次低8位AH、最低16位AX、最低32位EAX、整个寄存器RAX的关系如图。

al和rax是冲突的:

char buf[8] = {0};

char c = 'A';

char* p = buf;

*p += c;

如果指针p使用了rax,那么char类型的变量c就不能再使用al,反之也一样。

代码 *p += c里,指针变量p和字符变量c是同时活跃的。

这种情况可以通过掩码来判断,可以用1个二进制表示寄存器的1个字节

1,RAX是8字节的寄存器,掩码就是0xff。

2,al是1字节的寄存器,掩码就是0x1。

3,ah的掩码是0x2,因为它使用的是第2个字节。

4,ax的掩码是0x3,2个字节。

5,eax的掩码是0xf,4个字节。

如果掩码的与运算不为0,就是互相冲突的寄存器,不能用于同一个变量。

当然不是同一个寄存器组的寄存器,肯定是不冲突的。

ah和al是不冲突的,因为0x2 & 0x1 == 0。

ah和ax是冲突的,因为0x2 & 0x3 != 0。

技术文章:编译器的寄存器分配 - 天天要闻

科技分类资讯推荐

从领先到落后:英特尔正经历“寒冬” - 天天要闻

从领先到落后:英特尔正经历“寒冬”

【环球网科技综合报道】7月11日,据外媒报道,英特尔首席执行官陈立武近日在发表内部讲话时直言英特尔已不再是领先芯片制造商,甚至不在前十。其市值如今仅约1000亿美元,与18个月前相比大幅缩水,而英伟达市值却一度突破4万亿美元,形成鲜明对比。“二三十年前,我们确实是行业领导者。可如今的世界已经变了,我们已不在全...
“中国太酷了”!硬核实力圈粉世界 - 天天要闻

“中国太酷了”!硬核实力圈粉世界

日前举行的国新办新闻发布会上,有记者提到,随着大量海外博主分享来华见闻,“中国变酷了”的印象被越来越多全球网友所认同。对此,国家发展改革委主任郑栅洁表示,这背后反映了中国的综合国力。中国变酷了!酷在哪里?
华为Pura 80 Ultra国际版亮相:系统开机是EMUI 15.0,电池容量为5170mAh - 天天要闻

华为Pura 80 Ultra国际版亮相:系统开机是EMUI 15.0,电池容量为5170mAh

当地时间7月10日,华为在迪拜推出全新的Pura 80 Ultra影像旗舰,售价是5099阿联酋迪拉姆,约合人民币9961元。对比国行版,Pura 80 Ultra国际版有两大变化,一是系统调整为EMUI 15.0,国行版系统是鸿蒙5.1,二是电池容量为5170mAh,国行版电池容量是5700mAh。来源 江南都市报、快科技编辑 贾凯 审核 蒋波 陈洁...
AMD下代桌面锐龙处理器:N2工艺、Zen6架构、更多内核、依旧AM5插槽 - 天天要闻

AMD下代桌面锐龙处理器:N2工艺、Zen6架构、更多内核、依旧AM5插槽

有关于AMD下代桌面端锐龙处理器的更多信息浮出水面。AMD下代桌面端锐龙处理器代号“Medusa Ridge”,将采用全新的Zen6架构,该架构将使用TSMC的N2(2nm)工艺节点构建CCD,相比于前代Zen5架构的台积电N4P工艺节点,N2工艺的晶体管密度将显著提升。此前单CCD的最大核心数量为8个,而在Medusa Ridge上AMD可能会将单个CCD
AI终结传统软件业,如同互联网终结传统媒体 - 天天要闻

AI终结传统软件业,如同互联网终结传统媒体

AI编程工具正推动软件行业走向“峰值时刻”。近日,芯片金融分析公司Fabricated Knowledge的创始人Doug O'Laughlin发表文章称,生成式AI正以类似互联网颠覆传统媒体的方式,重塑软件行业的格局。文章指出,AI工具,比如Cursor和Claude Code,正在让编写代码的成本和时间大幅下降,过去需要每token数千美元才能完成的开发
英特尔CEO陈立武坦言:公司已跌出半导体行业前十 - 天天要闻

英特尔CEO陈立武坦言:公司已跌出半导体行业前十

【TechWeb】7月11日消息,据外媒报道,英特尔CEO陈立武在内部讲话中坦言,公司已跌出半导体行业前十。陈立武表示,20到30年前,英特尔确实是领导者,世界已经发生了变化。我们现在已经不是排名前十的半导体公司了。有报道称,英特尔公司发言人后续解释称其所指为 "市值" 而非技术。在过去的 18 个月里,英特尔的市值从 202...
华为海思Cat.1物联芯片Hi2131正式上市 - 天天要闻

华为海思Cat.1物联芯片Hi2131正式上市

7月10日,华为海思正式宣布,Hi2131 Cat.1物联芯片正式上市。据介绍,Hi2131 Cat.1 芯片采用超轻量芯片架构与极简休眠管理,将休眠功耗一举压缩至 150uA。相较于常见的同类型芯片,保活功耗直降 30% 以上,数传功耗亦降低 10%。功耗的显著优化直接转化为设备续航能力的跃升。这意味着共享设备维护周期大幅延长,用户体验与...