inline assembly causes ICC to generate invalid instruction

inline assembly causes ICC to generate invalid instruction

Hi,

I am trying to compile a piece of code that uses GCC style inline assembly using Intel C++ compiler (ICC 13.0.0).

It seems that the following inline assembly causes ICC to output invalid assembly:

asm volatile (
"movq %0, %%rax\n\t"
"movq %%rbp, 16(%%rax)\n\t"
"movq %%rsp, 8(%%rax)\n\t"
"leaq 4(%%rip), %%rbx\n\t"
"movq %%rbx, 24(%%rax)\n\t"
: : "g" (frame) : "rax", "rbx" );

which produces the assembly code as expected, but after the sequence, a "lea 0" is generated.

Strangely, if I were to split this sequence into two pieces:

asm volatile (
"movq %0, %%rax\n\t"
"movq %%rbp, 16(%%rax)\n\t"
"movq %%rsp, 8(%%rax)\n\t"
: : "g" (frame) : "rax", "rbx" );
asm volatile (
"leaq 4(%%rip), %%rbx\n\t"
"movq %%rbx, 24(%%rax)\n\t"
: : : "rbx" );

then it compiles just fine, outputting expected code.  

When I used gcc to compile either piece, things compile just fine.
I am wondering if I am doing something invalid in my inline assembly, or is the code triggering a bug in the compiler.
I have attached a small piece of C code that triggers this behavior.  Any help is greatly appreciated.

Thanks,
Angelina 

AttachmentSize
Downloadtext/x-csrc bug.c703 bytes
5 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

If you can support the importance of this usage, and verify a problem in a current compiler release, a problem report would be indicated, when the problem report system comes back on line.

The sequence of assembly essentially captures the stack pointer, base pointer, and program counter value of a function instance, and store those values into a struct.

asm volatile (
"movq %0, %%rax\n\t"
"movq %%rbp, 16(%%rax)\n\t"
"movq %%rsp, 8(%%rax)\n\t"
"leaq 4(%%rip), %%rbx\n\t"
"movq %%rbx, 24(%%rax)\n\t"
: : "g" (frame) : "rax", "rbx" );

The program counter is used by another thread to resume the function instance, at the program point right after the assembly sequence.  (Hence it's storing %rip + 4).  A possible work-around is to write the assembly sequence as the following:

asm volatile (
"movq %0, %%rax\n\t"
"movq %%rbp, 16(%%rax)\n\t"
"movq %%rsp, 8(%%rax)\n\t"
: : "g" (frame) : "rax", "rbx" );

asm volatile ("leaq 4(%%rip), %%rbx\n\t"
"movq %%rbx, %0\n\t" : "=g"(frame->rip) : : "rax", "rbx");

but the problem is, it's no longer clear that %rip+4 is the right value to store in the frame, because I don't know for sure how many instructions this sequence ends up generating.  I can look at the assembly output (right now it's just one instruction), but it's rather fragile.  If the compiler version changes or different set of compiler flags are used, there is no guarantee that the as the last instruction "movq %%rbx, %0" will be generated the same way.

Is there another work-around that you can suggest?

Thanks,
Angelina

Untested code:

asm volatile (
            "movq %0, %%raxnt"
            "movq %%rbp, 16(%%rax)nt"
            "movq %%rsp, 8(%%rax)nt"
            "movq %%rip, %%rbxnt"
            "leaq 8(%%rbx), %%rbxnt"
            "movq %%rbx, 24(%%rax)nt"
            : : "g" (frame) : "rax", "rbx" );

Jim Dempsey

www.quickthreadprogramming.com

Thanks!  That seems to work (compiles correct at least).
I don't know why I had the impression that one can't simply do a movq on %rip, but apparently I was mistaken.

Thanks,
Angelina 

Leave a Comment

Please sign in to add a comment. Not a member? Join today