Search code examples
c++visual-c++x86micro-optimizationvisual-c++-2012

fastest way to negate a number


I was thinking this morning here, what would be the fastest way to reverse a number of positive to negative and from negative to positive, of course, the simplest way might be:

int a = 10;
a = a*(-1);

or

int a = 10;
a = -a;

But then, I thought, I take that to do this, using commands shift and pointers ... That really would be possible to change the sign of a value, using commands shift operators and memory?


Solution

  • With optimization disabled, gcc for x86 compiles the first to this asm:

        .file   "optimum.c"
        .def    ___main;    .scl    2;  .type   32; .endef
        .text
    .globl _main
        .def    _main;  .scl    2;  .type   32; .endef
    _main:
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        subl    $16, %esp
        call    ___main               # MinGW library init function
        movl    $10, 12(%esp) ;i = 10
        negl    12(%esp)      ;i = -i
        movl    $0, %eax
        leave
        ret
    

    With optimization disabled, the second one produces:

        .file   "optimum.c"
        .def    ___main;    .scl    2;  .type   32; .endef
        .text
    .globl _main
        .def    _main;  .scl    2;  .type   32; .endef
    _main:
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        subl    $16, %esp
        call    ___main
        movl    $10, 12(%esp)   ;i = 10
        negl    12(%esp)        ;i = -i
        movl    $0, %eax
        leave
        ret
    

    Same output! No difference in the assembly code produced.

    --------------------------EDIT, OP ANSWERS HE USES VC++2012, INTEL ARCH-------------------

    Compiled using cl optimum.c /Fa optimum.asm (optimization disabled)

    ; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01 
    
        TITLE   C:\Users\Dell\Downloads\TTH\TTH\TTH\optimum.c
        .686P
        .XMM
        include listing.inc
        .model  flat
    
    INCLUDELIB LIBCMT
    INCLUDELIB OLDNAMES
    
    PUBLIC  _main
    ; Function compile flags: /Odtp
    _TEXT   SEGMENT
    _a$ = -4                        ; size = 4
    _argc$ = 8                      ; size = 4
    _argv$ = 12                     ; size = 4
    _main   PROC
    ; File c:\users\dell\downloads\tth\tth\tth\optimum.c
    ; Line 4
        push    ebp
        mov ebp, esp
        push    ecx
    ; Line 5
        mov DWORD PTR _a$[ebp], 10          ; 0000000aH
    ; Line 6
        mov eax, DWORD PTR _a$[ebp]
        neg eax ;1 machine cycle!
        mov DWORD PTR _a$[ebp], eax
    ; Line 7
        xor eax, eax
    ; Line 8
        mov esp, ebp
        pop ebp
        ret 0
    _main   ENDP
    _TEXT   ENDS
    END
    

    and with second approach (a = a * -1), optimization disabled MSVC:

    ; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01 
    
        TITLE   C:\Users\Dell\Downloads\TTH\TTH\TTH\optimum.c
        .686P
        .XMM
        include listing.inc
        .model  flat
    
    INCLUDELIB LIBCMT
    INCLUDELIB OLDNAMES
    
    PUBLIC  _main
    ; Function compile flags: /Odtp
    _TEXT   SEGMENT
    _a$ = -4                        ; size = 4
    _argc$ = 8                      ; size = 4
    _argv$ = 12                     ; size = 4
    _main   PROC
    ; File c:\users\dell\downloads\tth\tth\tth\optimum.c
    ; Line 4
        push    ebp
        mov ebp, esp
        push    ecx
    ; Line 5
        mov DWORD PTR _a$[ebp], 10          ; 0000000aH
    ; Line 6
        mov eax, DWORD PTR _a$[ebp]
        imul    eax, -1 ;1 instruction, 3 machine/cycles :|
        mov DWORD PTR _a$[ebp], eax
    ; Line 7
        xor eax, eax
    ; Line 8
        mov esp, ebp
        pop ebp
        ret 0
    _main   ENDP
    _TEXT   ENDS
    END
    

    So if you care about the performance of your debug-mode asm under MSVC, you could optimize your source accordingly. Normally you only care about performance in optimized builds.