被split if困惑很久了,找了个例子研究下。整个流程在PhaseIdealLoop::do_split_if,可以大概分四步:
- split up instructions which must be in this block up through the merge point
- split if through merge point
- split if projs through merge point
- handle uses of merge point
这两幅图的变换就是split_up做的事情。它会在Region#1523到If#1402之间找符合条件的指令,这个时候找到AddI#1335,然后创建新的Phi#1571,用新Phi替换了之前的AddI,形象点就是把AddI给UP到上面的bb。
在经过一系列split_up之后,B61就没有(必须存在于当前bb的)指令了,全部被清理到了上面的bb。
接下来分两步,对应图片两张。
- 沿着merge点split If#1402
- 沿着merge点split If#1402的true/false projs。
对If#1402做split_thr_region(Region#1523),会得到If#1575和If#1576以及一个new_iff_region,即Region#1574(该region会在后面死掉然后被remove),同样对If#1402的IfTrueProj和IfFalseProj做split_thr_region(Region#1523),得到Region#1577和Region#1580。
// Replace both uses of 'new_iff' with Regions merging True/False
// paths. This makes 'new_iff' go dead.
到这里If#1402它本身以及true/false projs都完全split了,所以它已经死了。清除掉所有死节点之后,IR长这样
一个生动的例子是identical if的merge:
public static void test5(int a, int b){
if (a == b) {
int_field = 0x42;
} else {
int_field = 42;
}
if (a == b) {
int_field = 0x42;
} else {
int_field = 42;
}
}
=>
public static void test5(int a, int b){
if (a == b) {
int_field = 0x42;
int_field = 0x42;
} else {
int_field = 42;
int_field = 42;
}
}
这个变换就用到了split if。IR变换如下:
If#42被“split“成两个,然后支配它的Region#35被移除,和第一个例子如出一辙。代码类似这样:
public static void test5(int a, int b){
if (a == b) {
int_field = 0x42;
if (a == b) {
L1:
int_field = 0x42;
} else {
goto L2;
}
} else {
int_field = 42;
if (a == b) {
goto L1;
} else {
L2:
int_field = 42;
}
}
}
总结一下,split if的作用就是Split If
标签:merge,int,42,field,0x42,Split,C2,split From: https://www.cnblogs.com/kelthuzadx/p/17204508.html