문제

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.data)
    : "%rax","%rdx");

asm("" : : "r"(borrow) : ); // work-around to keep borrow alive ...
.

이상한 코드는 아래 코드가 최적화없이 훌륭하게 작동하지만 -O3 IT SEG-Faults :

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");
.

나는 그것이 많은 레지스터를 사용하고 있다는 사실과 관련이 있다고 생각합니다.여기에 누락 된 것이 있습니까? 아니면 GCC 인라인 어셈블리가있는 레지스터 할당은 정말 버그가 있습니까?

도움이 되었습니까?

해결책

What you're missing is that GCC's optimiser will assume that the only side-effect of an asm block is to change the output operands. If those operands are not subsequently used, it may assume that the asm block in unnecessary and can be deleted.

e.g. in your first example, if borrow is not subsequently used, it is free to assume that there is no point in including the asm block at all, because its only side-effect is to update a variable that is never used again. And in the second example, if hi and carry are not used again after the code you've shown, it will probably infer that it can delete pretty much everything!

You can tell GCC that your inline assembly blocks should not be deleted by writing asm volatile(...) instead of just asm(...).

For more detail about this, see http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html (about half-way down the page).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top