Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Help: Inline assembly (SSE) slowdown

  1. Aug 24, 2005 #1
    I'm writing a program in C++ in MS Visual Studio.NET, and I am using inline assembly to do some SSE instructions.

    The trouble is that I am having a hard time getting the assembly to accep the addresses from my C++ from anyting other than explicitly-declared pointers (not even arrays work!). I end up putting extra variables on the stack so I can get pointers to my data, and I believe that this is causing a performance penalty (CPU time).

    My code is this:
    Code (Text):

        inline Vector3 operator +(Vector3 &v) const {
            float result[4];
            Vector3 *vout = (Vector3 *)result;
            Vector3 *vin = &v;
            _asm {
                mov esi, vin;
                mov edi, vout;
                mov eax, this;
                movups xmm0, [eax];
                movups xmm1, [esi];
                addps xmm0, xmm1;
                movups [edi], xmm0;
            return *(Vector3 *)result;
    Is there any way that I can get the inline assembly to use the needed addresses without the extra Vector3 pointer variables? (And if you have any other optimization suggestions, I'll be glad to hear them. :biggrin: )
  2. jcsd
  3. Aug 25, 2005 #2


    User Avatar
    Staff Emeritus

    GCC has a compiler option for optimizing for SSE. Perhaps VS.NET has the same thing.

    The base address of the floating point array should be loaded into a 32 bit register like eax. Move array[0] to sse memory:

    movups xmm0, [eax];

    To move array[1] into sse memory you would do something like this:

    movups xmm1,[eax+0x10];

    The 0x10 is the byte offset in hex. This value depends on how many bytes an array value takes up. You can find out by using the sizeof function.

    If you don't want the temp variable you need to do something like this:

    mov eax, v->array;

    You need the base address of the floating point array, not the base address of the Vector3 structure variable.
  4. Aug 25, 2005 #3


    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    Are you actually looking at the compiled output? Or just guessing there's a performance penalty? Honestly, I strongly doubt that pushing one address on the stack is a big deal compared to the SSE instructions themselves. You don't really need to move the addresses into registers, either, I don't think. Turn on optimizations and check the compiler's output.

    - Warren
  5. Aug 25, 2005 #4


    User Avatar
    Staff Emeritus

    I would definitely turn on sse optimizations and check the asm produced by the compiler to see if it is actually using sse instructions.

    I do believe you need to put the address in a cpu register. You can't just do:

    movups xmm0,[v];

    And you couldn't do the following because the compiler doesn't know the value of v at compile time.

    movups xmm0, *v;
    Last edited: Aug 25, 2005
  6. Aug 26, 2005 #5

    jim mcnamara

    User Avatar

    Staff: Mentor

    Normally, to check performance, you get it working totally correctly. First.
    Then worry about optimizations.

    Next. If and only if it's running too slowly: To validate/ignore your optimization fears try using a profiler. I dunno if MS provides one for the NET environment or not.

    There is nothing worse than misguided optimization to obfuscate and break code.
  7. Aug 27, 2005 #6
    That is correct, I got errors when I tried it without putting it in a register first.

    I read something somewhere that you could use the address of your C/C++ variable in the assembly by putting an underscore before the C/C++ variable name, but this doesn't work in VS.NET (It tells me that it's an undeclared symbol). Is there any way you know of to tell the assembly to use the address of the variable without making a pointer to the variable in the C/C++ code?
  8. Aug 27, 2005 #7


    User Avatar

    I think the main problem is the compiler doesn't (can't) know where 'result' is at compile time as it is in stack memory therefore where it actually lands is calculated by the two moves using fancy addressing mode tricks (like addition). Try declaring 'result' as a static (assuming you don't need multithreading blah blah blah). The additional benefit is you won't have to return result by copy either. As for vin, I'll bet that the first move is only for typing and if you check the optimized assembly output of the compiler it will be gone.

    "Premature optimization is the root of all evil" - Donald Knuth
    but playing with optimized assembly is fun...
Share this great discussion with others via Reddit, Google+, Twitter, or Facebook