summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Turner <mattst88@gmail.com>2011-07-31 22:42:24 -0400
committerMatt Turner <mattst88@gmail.com>2011-09-27 13:13:15 -0400
commit7ab94c5f99cc524ddfbbcedca4304ec7943f74e1 (patch)
treebb1d15ed7ef07493351afabc7161fb90f4915a5b
parentf66887d9eae9646c838d518020168b1403705b1e (diff)
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 <mattst88@gmail.com>
-rw-r--r--configure.ac48
-rw-r--r--pixman/Makefile.am12
-rw-r--r--pixman/pixman-cpu.c24
-rw-r--r--pixman/pixman-private.h2
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 <mmintrin.h>
+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