spec: 500.perlbench_r
文件: regexec.c:4929
函数: S_regmatch
scan变量
spec 544
文件: eff.c +768
函数:nbond
spec 538
文件: magick/morphology.c
函数:MorphologyPrimitive:3021~3037
(这个地方需要中端先把struct.field Promote成寄存器变量。但是,手改后,仍被spill了)
看起来,循环的权重考虑似乎还不够。
从cpu2017 看,这是个非常普遍的问题,对几个例子都有5+%以上的影响。 主要体现在以下特点的liverange
1)横跨大函数,LR很长;
2)经过某些hot loop body
由于1)我们在计算权重的时候长度是负向因素,导致LR未能被分配到寄存器,而spill/reload 又出现在了hot loop里面。倾向应该在loop内外做区别处理,至少spill 和reload希望放到循环外
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。
场景1里,scan对应的寄存器,存活于1601个bb中, 在循环内的50多个bb有def、ues。
(gdb) p pri
$42 = 2.02294835e+09
(gdb) p log(pri)/bbNum
$45 = 0.013384023650472029
而,跟它有冲突的其中几个权重很大的reg是,仅在一个bb里(同一层循环或更内层的循环),一个或多个def/use点,如,
priority = 14.5086575,
luMap = std::map with 1 element = {
[903] = 0x7ffff13a73b8
},
priority = 15.6072702,
luMap = std::map with 1 element = {
[985] = 0x7ffff0d862b0
},
另一个问题是对同一个vreg的多次reload操作:
R251在这里,不是被spill了,是因为被分配到的是caller save寄存器,但是跨call了,所以插入的是caller save相关处理。
第二个例子 -- 544 的例子,还需要其他优化删掉冗余分支的代码。手动删除后,没有ra问题。暂时忽略
第三例,538的例子,与第一例相似。用最新代码,中端已经将相应的结构体field(result.xx)的访问promote的寄存器。这几个寄存器,live range都拉得很长,然后分配到了一个caller save寄存器,又跨call,导致caller save相关处理.
spec 500 S_regmatch函数:
基于0910的最后一个版本:
scan变量(R6596)没有拿到callee save寄存器,分析了跟它冲突的且权重比它高的vreg,并比对了GCC的分配情况:
登录 后才可以发表评论