Chinaunix

标题: gcc优化编译问题请教 [打印本页]

作者: bacmoz    时间: 2006-08-07 21:49
标题: gcc优化编译问题请教
#include "stdio.h"

typedef unsigned long long u64;
typedef unsigned int u32;

inline u64 mod_mul(u64 a, u64 b, u64 p)
{
u64 ret;
__asm__(
"movq %0, %%rax;\n"
"mulq %1;\n"
"divq %2;\n"
"movq %%rdx, %3;"
:
:"g"(a), "g"(b), "g"(p), "g"(ret)
:"%rax", "rdx"
);
return ret;
}

u64 mod_test(u64 a, u64 n, u64 p)

{
u64 ret = 1;
u64 b = mod_mul(a, a, p);
ret = mod_mul(ret, b, p);
return ret;
}

int main()
{
u64 ret = mod_test(2, 3, 10);
printf("%llu\n", ret);
return 0;
}
gcc版本是4.1.1-1
x86-64版本的fc5
在不加优化的情况下运行正常,输出为4
在加了-O2或-O1优化后,输出为1
加-S查看汇编代码,发现问题在mod_test函数中
主要汇编代码如下:
mod_test:
.LFB13:
movq%rdx, %rcx
#APP
movq %rdi, %rax;
mulq %rdi;
divq %rcx;
movq %rdx, %rax;//内联mod_mul(a, a, p)结束(1)
movq $1, %rax;//此处出现问题 (2)
mulq %rax;//(3)
divq %rcx;
movq %rdx, %rax;
在(1)结束之后,应该对b进行赋值的,而不是将返回值暂存在rax中
暂存在rax中的好处是少一次movq指令,但怎么能保证在b = mod_mul(a, a, p)到(3)之间rax没有变化呢
并且在(2)中,第一个参数(ret)已经使用了rax,第二个参数怎么还能用rax来传进来
作者: bacmoz    时间: 2006-08-07 21:50
把程序改成这样子,汇编代码就正确了(但这样不能够实现功能)
#include "stdio.h"

typedef unsigned long long u64;
typedef unsigned int u32;

inline u64 mod_mul(u64 a, u64 b, u64 p)
{
u64 ret = (a * b)%p;
return ret;
}

u64 mod_test(u64 a, u64 n, u64 p)

{

u64 ret = 0x3344;

u64 b = mod_mul(a, a, p);
ret = mod_mul(ret, b, p);
return ret;

}

int main()
{
u64 ret = mod_test(2, 3, 10);
printf("%llu\n", ret);
return 0;
}
生成的主要汇编代码:
mod_test:
.LFB13:
movq%rdi, %rax
movq%rdx, %rsi
xorl%edx, %edx
imulq%rdi, %rax
divq%rsi //内联mod_mul(a, a, p)结束 (1)
imulq$13124, %rdx, %rax
xorl%edx, %edx
divq%rsi
movq%rdx, %rax
ret
主要的不同在于(1)之后没有把rdx传到rax中,也就是用rdx保存b的值(内联把返回值也给省掉了),这样后面就没有冲突了
不知道第一个程序为什么会生成错误的汇编代码
作者: bacmoz    时间: 2006-08-07 21:51
gcc优化选项对内联汇编有什么要求?




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2