Use ADD/SUB instructions on x86 and x86-64 atomics instead of INC/DEC
authorThiago Macieira <thiago.macieira@intel.com>
Sun, 25 Dec 2011 21:30:15 +0000 (19:30 -0200)
committerQt by Nokia <qt-info@nokia.com>
Mon, 26 Mar 2012 12:54:29 +0000 (14:54 +0200)
According to the Intel Optimization Manual section 3.5.1.1 Use of INC
and DEC Instructions, those instructions modify only part of the flags
register, so they mey introduce unnecessary data dependencies on
previous flag-setting operations so that the resulting flags are
computed. Preferring ADD and SUB (rule 33) is recommended.

However, we don't do it for 16-bit integers. The reason is that the
presence of the 0x66 prefix may trigger a slower decoding codepath in
the processor (up to 6 cycles, as opposed to 1). The same Intel manual
talks about Length-Changing Prefix, which applies in particular to
instructions with 16-bit immediates. The assembler generally produces
uses the 8-bit immediate variant of the ADD and SUB instructions, but
to be on the safe side, we prefer to use INC and DEC here.

Change-Id: Ic03236ac600a5b4e087614d21df5d3c666ae064e
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
src/corelib/arch/qatomic_i386.h
src/corelib/arch/qatomic_x86_64.h

index 61d835a..a813761 100644 (file)
@@ -137,7 +137,7 @@ bool QBasicAtomicOps<1>::ref(T &_q_value)
 {
     unsigned char ret;
     asm volatile("lock\n"
-                 "incb %0\n"
+                 "addb $1, %0\n"
                  "setne %1"
                  : "+m" (_q_value), "=qm" (ret)
                  :
@@ -163,7 +163,7 @@ bool QBasicAtomicOps<4>::ref(T &_q_value)
 {
     unsigned char ret;
     asm volatile("lock\n"
-                 "incl %0\n"
+                 "addl $1, %0\n"
                  "setne %1"
                  : "+m" (_q_value), "=qm" (ret)
                  :
@@ -176,7 +176,7 @@ bool QBasicAtomicOps<1>::deref(T &_q_value)
 {
     unsigned char ret;
     asm volatile("lock\n"
-                 "decb %0\n"
+                 "subb $1, %0\n"
                  "setne %1"
                  : "+m" (_q_value), "=qm" (ret)
                  :
@@ -202,7 +202,7 @@ bool QBasicAtomicOps<4>::deref(T &_q_value)
 {
     unsigned char ret;
     asm volatile("lock\n"
-                 "decl %0\n"
+                 "subl $1, %0\n"
                  "setne %1"
                  : "+m" (_q_value), "=qm" (ret)
                  :
index 33427eb..58505e2 100644 (file)
@@ -138,7 +138,7 @@ bool QBasicAtomicOps<1>::ref(T &_q_value)
 {
     unsigned char ret;
     asm volatile("lock\n"
-                 "incb %0\n"
+                 "addb  $1, %0\n"
                  "setne %1"
                  : "=m" (_q_value), "=qm" (ret)
                  : "m" (_q_value)
@@ -164,7 +164,7 @@ bool QBasicAtomicOps<4>::ref(T &_q_value)
 {
     unsigned char ret;
     asm volatile("lock\n"
-                 "incl %0\n"
+                 "addl $1, %0\n"
                  "setne %1"
                  : "=m" (_q_value), "=qm" (ret)
                  : "m" (_q_value)
@@ -177,7 +177,7 @@ bool QBasicAtomicOps<8>::ref(T &_q_value)
 {
     unsigned char ret;
     asm volatile("lock\n"
-                 "incq %0\n"
+                 "addq $1, %0\n"
                  "setne %1"
                  : "=m" (_q_value), "=qm" (ret)
                  : "m" (_q_value)
@@ -190,7 +190,7 @@ bool QBasicAtomicOps<1>::deref(T &_q_value)
 {
     unsigned char ret;
     asm volatile("lock\n"
-                 "decb %0\n"
+                 "subb $1, %0\n"
                  "setne %1"
                  : "=m" (_q_value), "=qm" (ret)
                  : "m" (_q_value)
@@ -215,7 +215,7 @@ bool QBasicAtomicOps<4>::deref(T &_q_value)
 {
     unsigned char ret;
     asm volatile("lock\n"
-                 "decl %0\n"
+                 "subl $1, %0\n"
                  "setne %1"
                  : "=m" (_q_value), "=qm" (ret)
                  : "m" (_q_value)
@@ -228,7 +228,7 @@ bool QBasicAtomicOps<8>::deref(T &_q_value)
 {
     unsigned char ret;
     asm volatile("lock\n"
-                 "decq %0\n"
+                 "subq $1, %0\n"
                  "setne %1"
                  : "=m" (_q_value), "=qm" (ret)
                  : "m" (_q_value)