From 7ab94c5f99cc524ddfbbcedca4304ec7943f74e1 Mon Sep 17 00:00:00 2001 From: Matt Turner Date: Sun, 31 Jul 2011 22:42:24 -0400 Subject: [PATCH] mmx: compile on ARM for iwmmxt optimizations Check in configure for at least gcc-4.6, since gcc-4.7 (and hopefully 4.6) will be the eariest version capable of compiling the _mm_* intrinsics on ARM/iwmmxt. Even for suitable compile versions I use _mm_srli_si64 which is known to cause unpatched compilers to fail. Select iwmmxt at runtime only after NEON, since we expect the NEON optimizations to be more capable and faster than iwmmxt. Signed-off-by: Matt Turner --- configure.ac | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ pixman/Makefile.am | 12 ++++++++++++ pixman/pixman-cpu.c | 24 +++++++++++++++++++++--- pixman/pixman-private.h | 2 +- 4 files changed, 82 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 561cb67..481d0bb 100644 --- a/configure.ac +++ b/configure.ac @@ -540,6 +540,54 @@ if test $enable_arm_neon = yes && test $have_arm_neon = no ; then AC_MSG_ERROR([ARM NEON intrinsics not detected]) fi +dnl =========================================================================== +dnl Check for IWMMXT + +if test "x$IWMMXT_CFLAGS" = "x" ; then + IWMMXT_CFLAGS="-march=iwmmxt -flax-vector-conversions -Winline" +fi + +have_iwmmxt_intrinsics=no +AC_MSG_CHECKING(whether to use ARM IWMMXT intrinsics) +xserver_save_CFLAGS=$CFLAGS +CFLAGS="$IWMMXT_CFLAGS $CFLAGS" +AC_COMPILE_IFELSE([ +#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 3 && __GNUC_MINOR__ < 6)) +#error "Need GCC >= 4.6 for IWMMXT intrinsics" +#endif +#include +int main () { + union { + __m64 v; + [char c[8];] + } a = { .c = {1, 2, 3, 4, 5, 6, 7, 8} }; + int b = 4; + __m64 c = _mm_srli_si64 (a.v, b); +}], have_iwmmxt_intrinsics=yes) +CFLAGS=$xserver_save_CFLAGS + +AC_ARG_ENABLE(arm-iwmmxt, + [AC_HELP_STRING([--disable-arm-iwmmxt], + [disable ARM IWMMXT fast paths])], + [enable_iwmmxt=$enableval], [enable_iwmmxt=auto]) + +if test $enable_iwmmxt = no ; then + have_iwmmxt_intrinsics=disabled +fi + +if test $have_iwmmxt_intrinsics = yes ; then + AC_DEFINE(USE_ARM_IWMMXT, 1, [use ARM IWMMXT compiler intrinsics]) +else + IWMMXT_CFLAGS= +fi + +AC_MSG_RESULT($have_iwmmxt_intrinsics) +if test $enable_iwmmxt = yes && test $have_iwmmxt_intrinsics = no ; then + AC_MSG_ERROR([IWMMXT intrinsics not detected]) +fi + +AM_CONDITIONAL(USE_ARM_IWMMXT, test $have_iwmmxt_intrinsics = yes) + dnl ========================================================================================= dnl Check for GNU-style inline assembly support diff --git a/pixman/Makefile.am b/pixman/Makefile.am index 0932ce7..286b7cf 100644 --- a/pixman/Makefile.am +++ b/pixman/Makefile.am @@ -90,5 +90,17 @@ libpixman_1_la_LIBADD += libpixman-arm-neon.la ASM_CFLAGS_arm_neon= endif +# iwmmxt code +if USE_ARM_IWMMXT +noinst_LTLIBRARIES += libpixman-iwmmxt.la +libpixman_iwmmxt_la_SOURCES = pixman-mmx.c +libpixman_iwmmxt_la_CFLAGS = $(DEP_CFLAGS) $(IWMMXT_CFLAGS) +libpixman_iwmmxt_la_LIBADD = $(DEP_LIBS) +libpixman_1_la_LDFLAGS += $(IWMMXT_LDFLAGS) +libpixman_1_la_LIBADD += libpixman-iwmmxt.la + +ASM_CFLAGS_IWMMXT=$(IWMMXT_CFLAGS) +endif + .c.s : $(libpixmaninclude_HEADERS) $(BUILT_SOURCES) $(CC) $(CFLAGS) $(ASM_CFLAGS_$(@:pixman-%.s=%)) $(ASM_CFLAGS_$(@:pixman-arm-%.s=arm_%)) -DHAVE_CONFIG_H -I$(srcdir) -I$(builddir) -I$(top_builddir) -S -o $@ $< diff --git a/pixman/pixman-cpu.c b/pixman/pixman-cpu.c index 78d3033..dff27d1 100644 --- a/pixman/pixman-cpu.c +++ b/pixman/pixman-cpu.c @@ -187,7 +187,7 @@ pixman_have_vmx (void) #endif /* __APPLE__ */ #endif /* USE_VMX */ -#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) +#if defined(USE_ARM_SIMD) || defined(USE_ARM_NEON) || defined(USE_ARM_IWMMXT) #if defined(_MSC_VER) @@ -328,14 +328,27 @@ pixman_have_arm_neon (void) #endif /* USE_ARM_NEON */ +#if defined(USE_ARM_IWMMXT) +pixman_bool_t +pixman_have_arm_iwmmxt (void) +{ + if (!arm_tests_initialized) + pixman_arm_read_auxv (); + + return arm_has_iwmmxt; +} + +#endif /* USE_ARM_IWMMXT */ + #else /* linux ELF */ #define pixman_have_arm_simd() FALSE #define pixman_have_arm_neon() FALSE +#define pixman_have_arm_iwmmxt() FALSE #endif -#endif /* USE_ARM_SIMD || USE_ARM_NEON */ +#endif /* USE_ARM_SIMD || USE_ARM_NEON || USE_ARM_IWMMXT */ #if defined(USE_X86_MMX) || defined(USE_SSE2) /* The CPU detection code needs to be in a file not compiled with @@ -596,11 +609,16 @@ _pixman_choose_implementation (void) imp = _pixman_implementation_create_arm_simd (imp); #endif +#ifdef USE_ARM_IWMMXT + if (pixman_have_arm_iwmmxt ()) + imp = _pixman_implementation_create_mmx (imp); +#endif + #ifdef USE_ARM_NEON if (pixman_have_arm_neon ()) imp = _pixman_implementation_create_arm_neon (imp); #endif - + #ifdef USE_VMX if (pixman_have_vmx ()) imp = _pixman_implementation_create_vmx (imp); diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 09f88c8..4d645fe 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -545,7 +545,7 @@ _pixman_implementation_create_fast_path (pixman_implementation_t *fallback); pixman_implementation_t * _pixman_implementation_create_noop (pixman_implementation_t *fallback); -#ifdef USE_X86_MMX +#if defined USE_X86_MMX || defined USE_ARM_IWMMXT pixman_implementation_t * _pixman_implementation_create_mmx (pixman_implementation_t *fallback); #endif -- 2.7.4