cassemblyx86clang

x86 addl vs subl


I just notice that Clang compiles this statement (without any optimization, of course):

--x; /* int x; */

into:

addl    $4294967295, %ecx       ## imm = 0xFFFFFFFF

Why? Is there any advantage of using addl instead of the "obvious" subl? Or is it just an implementation fact?

What tricks me is that this one:

x -= 1;

becomes:

subl    $1, %eax

Clang info:

Apple clang version 3.0 (tags/Apple/clang-211.12) (based on LLVM 3.0svn)
Target: x86_64-apple-darwin11.2.0
Thread model: posix

Solution

  • This behavior has to do with the way clang handles pre-decrement as opposed to binary operators like sub-and-assign. Note that I will just try to explain, at the clang level, why you see this behavior. I don't know why it was chosen to implement it this way but I guess it was just for ease of implementation.

    All functions I reference here can be found in class ScalarExprEmitter inside lib/CodeGen/CGExprScalar.cpp.

    Pre/post decrement/increment are all handled the same way by the function EmitScalarPrePostIncDec: an LLVM add instruction is emitted with either 1 or -1 as second argument, depending on the expression being an increment or a decrement respectively.

    Therefore,

    --x
    

    will end up, in the LLVM IR, as something like

    add i32 %x, -1
    

    which, quite naturally, translates to x86 as something like

    add $0xffffffff, %ecx
    

    Binary operators, on the other hand, are all handled differently. In your case,

    x -= 1
    

    will be handled by EmitCompoundAssign which in turn calls EmitSub. Something like the following LLVM IR will be emitted:

    sub i32 %x, 1