我有一些要优化的代码:
...
else {
if ( A < C )
results[i] = A;
else if ( C < B )
results[i] = B;
else
results[i] = C;
}
...
我要删除一些分支,我需要类似(median.c.004t.gimple
)的东西:
[median.c:80:15] gimple_cond <lt_expr, CD.1436, BD.1435, <D.1472>, <D.1473>>
gimple_label <<D.1472>>
[median.c:81:11] gimple_assign <var_decl, DD.1437, BD.1435, NULL, NULL>
gimple_goto <<D.1474>>
gimple_label <<D.1473>>
[median.c:83:11] gimple_assign <var_decl, DD.1437, CD.1436, NULL, NULL>
gimple_label <<D.1474>>
gimple_label <<D.1471>>
gimple_label <<D.1468>>
[median.c:85:12] gimple_assign <nop_expr, _16, iD.1438, NULL, NULL>
[median.c:85:12] gimple_assign <mult_expr, _17, _16, 4, NULL>
[median.c:85:12] gimple_assign <pointer_plus_expr, _18, resultsD.1431, _17, NULL>
[median.c:85:16] gimple_assign <var_decl, [median.c:85:12] *_18, DD.1437, NULL, NULL>
[median.c:62:28] gimple_assign <plus_expr, iD.1438, iD.1438, 1, NULL>
gimple_label <<D.1440>>
[median.c:62:22] gimple_assign <plus_expr, _19, nD.1429, -1, NULL>
[median.c:62:3] gimple_cond <lt_expr, iD.1438, _19, <D.1439>, <D.1441>>
gimple_label <<D.1441>>
但是GCC会给我这种代码:
[median.c:41:15] gimple_cond <lt_expr, CD.1423, BD.1422, <D.1457>, <D.1458>>
gimple_label <<D.1457>>
[median.c:42:16] gimple_assign <nop_expr, _32, iD.1425, NULL, NULL>
[median.c:42:16] gimple_assign <mult_expr, _33, _32, 8, NULL>
[median.c:42:16] gimple_assign <pointer_plus_expr, _34, resultsD.1418, _33, NULL>
[median.c:42:20] gimple_assign <nop_expr, _35, BD.1422, NULL, NULL>
[median.c:42:20] gimple_assign <ssa_name, [median.c:42:16] *_34, _35, NULL, NULL>
gimple_goto <<D.1459>>
gimple_label <<D.1458>>
[median.c:44:16] gimple_assign <nop_expr, _36, iD.1425, NULL, NULL>
[median.c:44:16] gimple_assign <mult_expr, _37, _36, 8, NULL>
[median.c:44:16] gimple_assign <pointer_plus_expr, _38, resultsD.1418, _37, NULL>
[median.c:44:20] gimple_assign <nop_expr, _39, CD.1423, NULL, NULL>
[median.c:44:20] gimple_assign <ssa_name, [median.c:44:16] *_38, _39, NULL, NULL>
gimple_label <<D.1459>>
gimple_label <<D.1456>>
gimple_label <<D.1453>>
[median.c:23:28] gimple_assign <plus_expr, iD.1425, iD.1425, 1, NULL>
gimple_label <<D.1427>>
[median.c:23:22] gimple_assign <plus_expr, _40, nD.1416, -1, NULL>
[median.c:23:3] gimple_cond <lt_expr, iD.1425, _40, <D.1426>, <D.1428>>
gimple_label <<D.1428>>
>
换句话说,GCC不会分配一些中间变量,如果它“看到”存储了索引存储的内存,他将不会从比较操作lt
或{{1} },最后发出与gt
的比较,而不是直线branch
,这使分支预测变量崩溃。
后一次在asm中发出:
min/max
代替:
.L5:
addi a1,a1,4
addi a2,a2,8
bne a1,a0,.L9
.L1:
ret
.L3:
blt a4,a3,.L12
bgt a5,a3,.L11
.L8:
sd a3,0(a2)
j .L5
.L11:
sd a5,0(a2)
j .L5
添加了.L18:
lw a5,4(a1)
lw a4,0(a1)
lw a3,8(a1)
blt a4,a5,.L21
max a5,a5,a3
sext.w a5,a5
bge a4,a3,.L17
mv a5,a4
sw a5,0(a2)
addi a1,a1,4
addi a2,a2,4
bne a0,a1,.L18
.L14:
ret
并删除了分支。