x86 addl vs subl
assembly, c, clang, compiler-construction, x86
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
Problem
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 ```