��������DZ�ڵĽ����һ������
���찢骷�������Ŀ�е�һ�� bug ������Ϊ���������ǰ��һ�µ��µġ���������ȫ��ͬ�� C ���룬����Ҳ�ϸ�һ�£����Ǽ�����˲���ͬ�Ľ�����Ҷ��������dz�����Ȥ����ϸ�о���һ�³���
ԭʼ����ȽϷ��ӡ���Ū���ԭ�����Ҽ��˳�����Ĵ��룬������������⣺
static void foo(float x) { float xx = x * 0.01f; printf("%d\n", (int)(x * 0.01f)); printf("%d\n", (int)xx); } int main() { foo(2000.0f); return 0; }
ʹ�� gcc 4.9.2 ��ǿ��ʹ�� x87 ��������������У���ᷢ�����˲���Ľ����
gcc a.c -mfpmath=387 19 20
ǰһ�ε������ 19 ����һ���� 20 ��
����Ϊʲô�أ������������� gcc ���ɵĴ��룬�ҽ�ȡ����صĶ��䣺
flds 16(%rbp) flds .LC0(%rip) fmulp %st, %st(1) fstps -4(%rbp) ; 1. x * 0.01f ������浽�ڴ��е� float ������ flds 16(%rbp) flds .LC0(%rip) fmulp %st, %st(1) fisttpl -20(%rbp) ; 2. x * 0.01f ���ֱ��ת��Ϊ���� movl -20(%rbp), %eax movl %eax, %edx leaq .LC1(%rip), %rcx call printf flds -4(%rbp) ; 3. ���� 1. ����ij˷���� fisttpl -20(%rbp) movl -20(%rbp), %eax movl %eax, %edx leaq .LC1(%rip), %rcx call printf
��������������ע�͡�
���ȣ�0.01 ������ȷ��ʾ�� 2 ���Ƶģ����� * 0.01 �������һ���������
�������㶼�� x * 0.01f ����Ȼ�� C ���Ե�ת��������ʽ�ж��� float ʱ���� float �������㡣������ gcc ���ɵĴ��벢û���ϸ����� FPU �ľ��ȿ��ƣ���ע�� 2 ����ط����˷������ֱ�ӴӸ���Ĵ���ת��Ϊ�����ġ�����ע�� 1 ����ط����ѳ˷����ͨ�� fstps �Ե;�����ʽ���浽�ڴ棬����ע�� 3 �ĵط� flds ���ء�
������ע�� 2 ��ע�� 3 �ĵط�������Ĵ��� st �ڵ�ֵ��ʵ���в��ģ������ fisttpl ת��Ϊ����������ͬ��
2018 �� 6 �� 14 �ղ��䣺
�� DDJ 1997 ���һƪ��̸��������̸�������Ƶ����⡣
�������£�
Let me give an example, which arose yesterday. A student was doing a computation involving a simulation of a plasma. It turns out that as you go through this computation there will be certain barriers. This may be a reflecting barrier. That means if a particle moves through this barrier, it should not really go through, it should be reflected. Others may be absorbing, others may be periodic. He has a piece of code that is roughly
float x, y, z; int j; ... x = y + z; if (x >= j) replace (x); y = x; ...
As far as we can tell, when he turns on optimization, the value of x is computed in a register with extra width. This happens on the Intel machine because the registers have extra width. It also happens on some others. The value of x that he computes is not, in fact, a float. It's in a register that's wider. The machine stores x somewhere, and in the course of doing that, converts it to a float. But the value used in the comparison is the value in the register. That x is wider. The condition that the register x be greater than or equal to j doesn't guarantee that x, when stored in y, will be less than j. Sometimes y=j, and that should never be. My student counted on what compiler writers call "referential transparency" and was disappointed because the compiler writer saved some time in optimization by not reloading the register from the stored value.