[LLVMbugs] [Bug 6137] New: unnecessary moves between XMM and general registers by x86 back end

bugzilla-daemon at cs.uiuc.edu bugzilla-daemon at cs.uiuc.edu
Mon Jan 25 08:37:31 PST 2010


http://llvm.org/bugs/show_bug.cgi?id=6137

           Summary: unnecessary moves between XMM and general registers by
                    x86 back end
           Product: new-bugs
           Version: trunk
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: new bugs
        AssignedTo: unassignedbugs at nondot.org
        ReportedBy: brian.sumner at amd.com
                CC: llvmbugs at cs.uiuc.edu


For the following C code:

---- example.c ----------------------
typedef unsigned int uint;
static inline float as_float(uint u) { union { float f; uint u; } v; v.u = u;
return v.f; }
static inline uint as_uint(float f) { union { float f; uint u; } v; v.f = f;
return v.u; }

static float
r(float x)
{
    uint u = as_uint(x);
    uint a = u & 0x7fffffffU;
    float v = (as_float(a) + 0x1.0p+23F) - 0x1.0p+23F;
    return a > 0x4affffffU ? x : as_float(as_uint(v) | (u ^ a));
}
---------------------------------------
The x86 back end is generating several unnecessary MOVD instructions to move
data between XMM and general purpose registers.  These moves are unnecessary
because the argument arrives in an XMM register, the result returns in an XMM
register, and all the operations performed can be done with XMM register
operations.

I would like the x86 back end to generate the same code for the function above
as it does for the following function which performs the same operation
entirely in XMM registers:
---- recoded-example.c -------------------------
#include <xmmintrin.h>
static inline __m128i as_m128i(__m128 f) { union { __m128i i; __m128 f; } v;
v.f=f; return v.i; }
static inline __m128 as_m128(__m128i i) { union { __m128i i; __m128 f; } v;
v.i=i; return v.f; }

static float
r(float xx)
{
    __m128 t = _mm_set_ss(0x1.0p+23F);
    __m128 x = _mm_set_ss(xx);
    __m128i a = _mm_and_si128(as_m128i(x), _mm_set1_epi32(0x7fffffff));
    __m128 v = _mm_sub_ss(_mm_add_ss(as_m128(a), t), t);
    a = _mm_xor_si128(as_m128i(x), a);
    v = as_m128(_mm_or_si128(as_m128i(v), a));
    __m128i m = _mm_cmpgt_epi32(a, _mm_set1_epi32(0x4affffff));
    v = as_m128(_mm_andnot_si128(m, as_m128i(v)));
    x = as_m128(_mm_and_si128(m, as_m128i(x)));
    x = as_m128(_mm_or_si128(as_m128i(x), as_m128i(v)));
    return _mm_cvtss_f32(x);
}
--------------------------------------------------------

Calling one of these functions in a loop (where it is probably inlined) of 1G
iterations with various compilers on an Phenom II processor, I get:

gcc 4.4.1:   orig:  7.99  new:  7.32
icc 11.0:    orig:  5.32  new: 20.50
clang trunk: orig: 11.53  new:  6.82


-- 
Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



More information about the llvm-bugs mailing list