gcc内联程序集的奇怪行为
在gcc中内联程序集时,我发现自己必须定期添加空的asm块,以便在早期的块中保持变量的活动性,例如:gcc内联程序集的奇怪行为,gcc,inline-assembly,register-allocation,Gcc,Inline Assembly,Register Allocation,在gcc中内联程序集时,我发现自己必须定期添加空的asm块,以便在早期的块中保持变量的活动性,例如: asm("rcr $1,%[borrow];" "movq 0(%[b_],%[i],8),%%rax;" "adcq %%rax,0(%[r_top],%[i],8);" "rcl $1,%[borrow];" : [borrow]"+r"(borrow) : [i]"r"(i),[b_]"r"(b_.data),[r_top]"r"(r_top.dat
asm("rcr $1,%[borrow];"
"movq 0(%[b_],%[i],8),%%rax;"
"adcq %%rax,0(%[r_top],%[i],8);"
"rcl $1,%[borrow];"
: [borrow]"+r"(borrow)
: [i]"r"(i),[b_]"r"(b_.data),[r_top]"r"(r_top.data)
: "%rax","%rdx");
asm("" : : "r"(borrow) : ); // work-around to keep borrow alive ...
另一个奇怪的例子是,下面的代码在没有优化的情况下工作得很好,但有-O3 it seg错误:
ulong carry = 0,hi = 0,qh = s.data[1],ql = s.data[0];
asm("movq 0(%[b]),%%rax;"
"mulq %[ql];"
"movq %%rax,0(%[sb]);"
"movq %%rdx,%[hi];"
: [hi]"=r"(hi)
: [ql]"r"(ql),[b]"r"(b.data),[sb]"r"(sb.data)
: "%rax","%rdx","memory");
for (long i = 1; i < b.size; i++)
{
asm("movq 0(%[b],%[i],8),%%rax;"
"mulq %[ql];"
"xorq %%r10,%%r10;"
"addq %%rax,%[hi];"
"adcq %%rdx,%[carry];"
"adcq $0,%%r10;"
"movq -8(%[b],%[i],8),%%rax;"
"mulq %[qh];"
"addq %%rax,%[hi];"
"adcq %%rdx,%[carry];"
"adcq $0,%%r10;"
"movq %[hi],0(%[sb],%[i],8);"
"movq %[carry],%[hi];"
"movq %%r10,%[carry];"
: [carry]"+r"(carry),[hi]"+r"(hi)
: [i]"r"(i),[ql]"r"(ql),[qh]"r"(qh),[b]"r"(b.data),[sb]"r"(sb.data)
: "%rax","%rdx","%r10","memory");
}
asm("movq -8(%[b],%[i],8),%%rax;"
"mulq %[qh];"
"addq %%rax,%[hi];"
"adcq %%rdx,%[carry];"
"movq %[hi],0(%[sb],%[i],8);"
"movq %[carry],8(%[sb],%[i],8);"
: [hi]"+r"(hi),[carry]"+r"(carry)
: [i]"r"(long(b.size)),[qh]"r"(qh),[b]"r"(b.data),[sb]"r"(sb.data)
: "%rax","%rdx","memory");
ulong进位=0,hi=0,qh=s.data[1],ql=s.data[0];
asm(“movq 0(%[b]),%%rax
“mulq%[ql];”
“movq%%rax,0(%[sb])
“movq%%rdx,%[hi];”
:[hi]“=r”(hi)
:[ql]“r”(ql),[b]“r”(b.data),[sb]“r”(sb.data)
:“%rax”、“rdx”、“内存”);
用于(长i=1;i
我认为这与它使用了这么多寄存器这一事实有关。这里是否有我遗漏的东西,或者gcc内联汇编的寄存器分配真的有问题?您遗漏的是gcc的优化程序将假定
asm
块的唯一副作用是更改输出操作数。如果随后未使用这些操作数,则可能会认为asm
块不必要,可以删除
e、 g.在您的第一个示例中,如果随后未使用借用
,则可以自由地假设包含asm
块没有任何意义,因为它唯一的副作用是更新一个从未使用过的变量。在第二个示例中,如果在显示代码后不再使用hi
和carry
,则可能会推断它可以删除几乎所有内容
您可以告诉GCC,不应该通过写入asm volatile(…)
而仅仅asm(…)
来删除内联程序集块
有关这方面的更多详细信息,请参见(本页的一半)