工具/软件:TI C/C++编译器
我尝试用C语言而不是汇编程序编写快速代码,并且在我期望的时候偶然发现编译器没有发出MOV32 Rah,RBH {, CNDF}或MOV32 Rah, mem32 {, CNDF}指令。
给定文件test.c:
#include <mathing.h>
双倍测试双倍(双A,双b){
返回fabs (a)> fabs (b)? a:b;
}
静态内嵌双精度QUICK_two_sum (双精度A,双精度b,双精度*ERR){
双s = a + b;
*错误= b -(s - a);
退货;
}
void c_dd_add_dd_d (const double *a,double b,double * restrictd c){
双s1,s2;
如果(fabs (a[0])> fabs (b)){
S1 = A[0];
S2 = b;
}其他{
S1 = b;
S2 = A[0];
}
S1 = quick_two_sum (s1,s2,&s2);
S2 += A[1];
S1 = quick_two_sum (s1,s2,&s2);
C[0]= s1;
C[1]=s2;
}
和命令:
c:/ti/ccsv6/tools/compiler/ti-CGT-C2000_C2000_STS/bin/cl2000"<xmt-block0>2000 17.32000 17.3 -v28 -ml -mt --CLA_support=cla1 --float_support=fpu32 --tmu_support=tmu0 --vcu_support=vcu2 -o4 -opt_for c2000_support=class1 -compiler -fp_per-fm_guide=-fu/fm_support=fm=t_support-fm=t_sym_tools/cru_cru_cruel_crue_d=-cruel_cruel_cruel_f_d=-cruile.d=-f_cru_f_f_f_f_f_dip-f_f_-f_-fp=-cruilt -cruildip_f_f_f_f_-f_-f_fuilt 17.3
我以以下装配体结束(为简洁而剪裁):
测试双精度:
;***4 --------------------------- 返回(ABS (a)> ABS (b))? a:b;
ADDB SP,#2;[CPU_U]
MOV32 R2H,R1H;[CPU_]|4|
MOV32 R3H,R0H;[CPU_]|4|
SubB SP,#2;[CPU]|4|
ABSF32 R2H,R2H;[CPU_]|4|
ABSF32 R3H,R3H;[CPU_]|4|
CMPF32 R3H,R2H;[CPU_]|4|
MOVST0 ZF,NF;[CPU_]|4|
MOV32 R1H,R0H,GT;[CPU_]|4|
MOV32 R0H,R1H;[CPU_]|4|
LRTR;[CPU_]
_c_dd_add_dd_d:
;***16--------------- 3美元=* a;
;***16--------------- 如果( abs(U3美元)> abs(b))转到G3;
ADDB SP,#2;[CPU_U]
MOVL ACC,*+XAR4[0];[CPU_]|16|
MOV32 R2H,ACC;[CPU_]|16|
NOP;[CPU_]
NOP;[CPU_]
MOV32 R1H,R0H;[CPU_]|16|
ABSF32 R1H,R1H;[CPU_]|16|
ABSF32 R2H,R2H;[CPU_]|16|
CMPF32 R2H,R1H;[CPU_]|16|
MOVST0 ZF,NF;[CPU_]|16|
b $C$L1,GT;[CPU_]|16|
;发生分支;[]|16|
;***20--------------- S1 = b;
;***21 --------------------------- S2 = 3元;
;***21 --------------------------- 转到G4;
MOV32 R1H,R0H;[CPU_]|20|
MOV32 R0H,ACC;[CPU_]|21|
b $C$L2,UNC;[CPU_]|21|
;出现分支;[]|21|
$C$L1:
;***--------------- G3:
;***17--------------- S1 = 3元;
;*** 18--------------- S2 = b;
MOV32 R1H,ACC;[CPU_]|17|
NOP;[CPU_]
NOP;[CPU_]
NOP;[CPU_]
NOP;[CPU_]
$C$L2:
;***--------------- G4:
;***8 --------------------------- S = s1+s2;//[2]
;***9 --------------------------- S2 = s2-(s-1)+a[1];//[2]
;***8 --------------------------- S = s+s2;//[2]
;***9 --------------------------- s2 -= s-s;//[2]
;***28------------------ *c = s;
;***29------------------ C[1]=s2;
;***--------------- 返回;
ADDF32 R2H,R0H,R1H;[CPU_]|8|
NOP;[CPU_]
SUBF32 R1H,R2H,R1H;[CPU_]|9|
NOP;[CPU_]
SUBF32 R0H,R0H,R1H;[CPU_]|9|
MOV32 R3H,*+XAR4[2];[CPU_]|9|
ADDF32 R0H,R0H,R3H;[CPU_]|9|
NOP;[CPU_]
ADDF32 R1H,R0H,R2H;[CPU_]|8|
NOP;[CPU_]
SUBF32 R2H,R1H,R2H;[CPU_]|9|
SubB SP,#2;[CPU_U]
SUBF32 R0H,R0H,R2H;[CPU_]|9|
MOV32 *+XAR5[0],R1H;[CPU_]|28|
MOV32 *+XAR5[2],R0H;[CPU_]|29|
LRTR;[CPU_]
在 _test_double中,将浮点状态标志冗余移动到整数状态标志,因为后续移动使用ZF和NF标志。
在_c_dd_add_dd_d中,使用了一个代价高昂的分支,而不是条件移动。
在_c_dd_add_dd_d中 ,使用ACC避免推入和弹出浮点寄存器的成本很高。
我在这里错过了什么吗? 在这种情况下,是否有理由不使用条件移动?
当ACC产生周期罚分时,为什么要将其用作临时寄存器(我处于优化级别4,优化速度5)。