diff --git a/bench/profiling.hs b/bench/profiling.hs
--- a/bench/profiling.hs
+++ b/bench/profiling.hs
@@ -12,6 +12,9 @@
 import System.Random (Random(random), RandomGen, getStdGen)
 
 import Options.Applicative
+#if MIN_VERSION_optparse_applicative(0, 13, 0)
+import Data.Monoid ((<>))
+#endif
 
 import System.Clock (Clock(Monotonic), TimeSpec(sec, nsec), getTime, diffTimeSpec)
 
diff --git a/cbits/config.h.in b/cbits/config.h.in
--- a/cbits/config.h.in
+++ b/cbits/config.h.in
@@ -9,6 +9,11 @@
 /* Define to 1 if you have the <cpuid.h> header file. */
 #undef HAVE_CPUID_H
 
+/* Define to 1 if you have the declaration of `__get_cpuid_count(const
+   unsigned int, const unsigned int, unsigned int *, unsigned int *, unsigned
+   int *, unsigned int *)', and to 0 if you don't. */
+#undef HAVE_DECL___GET_CPUID_COUNT
+
 /* Define to 1 if you have the <emmintrin.h> header file. */
 #undef HAVE_EMMINTRIN_H
 
@@ -100,6 +105,9 @@
 
 /* Define to 1 if AVX2 works */
 #undef RS_HAVE_AVX2
+
+/* Define to 1 if C compiller supports __builtin_shuffle */
+#undef RS_HAVE_BUILTIN_SHUFFLE
 
 /* Define to 1 if Clang's `loop unroll` pragma works */
 #undef RS_HAVE_CLANG_LOOP_UNROLL
diff --git a/cbits/configure b/cbits/configure
--- a/cbits/configure
+++ b/cbits/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for reedsolomon 0.0.4.2.
+# Generated by GNU Autoconf 2.69 for reedsolomon 0.0.4.3.
 #
 # Report bugs to <https://github.com/NicolasT/reedsolomon/issues>.
 #
@@ -580,8 +580,8 @@
 # Identity of this package.
 PACKAGE_NAME='reedsolomon'
 PACKAGE_TARNAME='reedsolomon'
-PACKAGE_VERSION='0.0.4.2'
-PACKAGE_STRING='reedsolomon 0.0.4.2'
+PACKAGE_VERSION='0.0.4.3'
+PACKAGE_STRING='reedsolomon 0.0.4.3'
 PACKAGE_BUGREPORT='https://github.com/NicolasT/reedsolomon/issues'
 PACKAGE_URL='https://github.com/NicolasT/reedsolomon'
 
@@ -1297,7 +1297,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures reedsolomon 0.0.4.2 to adapt to many kinds of systems.
+\`configure' configures reedsolomon 0.0.4.3 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1367,7 +1367,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of reedsolomon 0.0.4.2:";;
+     short | recursive ) echo "Configuration of reedsolomon 0.0.4.3:";;
    esac
   cat <<\_ACEOF
 
@@ -1462,7 +1462,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-reedsolomon configure 0.0.4.2
+reedsolomon configure 0.0.4.3
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1868,11 +1868,57 @@
   eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
 
 } # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_c_check_decl ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  as_decl_name=`echo $2|sed 's/ *(.*//'`
+  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+  (void) $as_decl_use;
+#else
+  (void) $as_decl_name;
+#endif
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_decl
 cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by reedsolomon $as_me 0.0.4.2, which was
+It was created by reedsolomon $as_me 0.0.4.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2740,7 +2786,7 @@
 
 # Define the identity of the package.
  PACKAGE='reedsolomon'
- VERSION='0.0.4.2'
+ VERSION='0.0.4.3'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -6268,6 +6314,76 @@
 
 
 ## Checks for compiler-specific features
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C compiler supports __builtin_shuffle" >&5
+$as_echo_n "checking whether C compiler supports __builtin_shuffle... " >&6; }
+if test "$cross_compiling" = yes; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no (assumed, cross-compiling)" >&5
+$as_echo "no (assumed, cross-compiling)" >&6; }
+     rs_have_builtin_shuffle=0
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+            #include <stdint.h>
+
+            typedef uint8_t v16u8v __attribute__((vector_size(16)));
+
+int
+main ()
+{
+
+            v16u8v v1 = { 0, 1,  2,  3,  4,  5,  6,  7
+                        , 8, 9, 10, 11, 12, 13, 14, 15 },
+                   v2 = { 0, 0, 0, 0, 0, 0, 0, 0
+                        , 0, 0, 0, 0, 0, 0, 0, 0 },
+                   mask = {  0, 20,  4, 24,  8, 28, 12, 32
+                          , 18,  2, 22,  6, 26, 10, 30, 16 },
+                   result = __builtin_shuffle(v1, v2, mask),
+                   expected = { 0, 0, 4, 0, 8,  0, 12, 0
+                              , 0, 2, 0, 6, 0, 10,  0, 0 };
+
+            int equal =    result[0] == expected[0]
+                        && result[1] == expected[1]
+                        && result[2] == expected[2]
+                        && result[3] == expected[3]
+                        && result[4] == expected[4]
+                        && result[5] == expected[5]
+                        && result[6] == expected[6]
+                        && result[7] == expected[7]
+                        && result[8] == expected[8]
+                        && result[9] == expected[9]
+                        && result[10] == expected[10]
+                        && result[11] == expected[11]
+                        && result[12] == expected[12]
+                        && result[13] == expected[13]
+                        && result[14] == expected[14]
+                        && result[15] == expected[15];
+
+            return equal ? 0 : 1;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+     rs_have_builtin_shuffle=1
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+     rs_have_builtin_shuffle=0
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+cat >>confdefs.h <<_ACEOF
+#define RS_HAVE_BUILTIN_SHUFFLE $rs_have_builtin_shuffle
+_ACEOF
+
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether Clang's \`loop unroll\` pragma works" >&5
 $as_echo_n "checking whether Clang's \`loop unroll\` pragma works... " >&6; }
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -6572,7 +6688,24 @@
 fi
 
 
+as_ac_Symbol=`$as_echo "ac_cv_have_decl___get_cpuid_count(const unsigned int, const unsigned int, unsigned int *, unsigned int *, unsigned int *, unsigned int *)" | $as_tr_sh`
+ac_fn_c_check_decl "$LINENO" "__get_cpuid_count(const unsigned int, const unsigned int, unsigned int *, unsigned int *, unsigned int *, unsigned int *)" "$as_ac_Symbol" "
+        #if defined(HAVE_CPUID_H) && HAVE_CPUID_H
+        # include <cpuid.h>
+        #endif
 
+"
+if eval test \"x\$"$as_ac_Symbol"\" = x"yes"; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL___GET_CPUID_COUNT $ac_have_decl
+_ACEOF
+
+
 # Definitions based on discovered compiler or ISA characteristics.
 rs_generic=1
 if test x$rs_neon = x1; then
@@ -7249,7 +7382,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by reedsolomon $as_me 0.0.4.2, which was
+This file was extended by reedsolomon $as_me 0.0.4.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -7316,7 +7449,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-reedsolomon config.status 0.0.4.2
+reedsolomon config.status 0.0.4.3
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -8177,10 +8310,18 @@
 
 rs_backends=""
 if test x$rs_generic = x1; then
-    rs_backends="$rs_backends, generic"
+    if test x$rs_have_builtin_shuffle = x1; then
+        rs_backends="$rs_backends, generic (__builtin_shuffle)"
+    else
+        rs_backends="$rs_backends, generic"
+    fi
 fi
 if test x$rs_sse2 = x1; then
-    rs_backends="$rs_backends, sse2"
+    if test x$rs_have_builtin_shuffle = x1; then
+        rs_backends="$rs_backends, sse2 (__builtin_shuffle)"
+    else
+        rs_backends="$rs_backends, sse2"
+    fi
 fi
 if test x$rs_ssse3 = x1; then
     rs_backends="$rs_backends, ssse3"
diff --git a/cbits/configure.ac b/cbits/configure.ac
--- a/cbits/configure.ac
+++ b/cbits/configure.ac
@@ -103,6 +103,55 @@
 AX_CHECK_COMPILE_FLAG([-mavx2], [rs_avx2=1], [rs_avx2=0])
 
 ## Checks for compiler-specific features
+AC_MSG_CHECKING([whether C compiler supports __builtin_shuffle])
+AC_RUN_IFELSE(
+    [AC_LANG_PROGRAM(
+        [
+            #include <stdint.h>
+
+            typedef uint8_t v16u8v __attribute__((vector_size(16)));
+        ],
+        [[
+            v16u8v v1 = { 0, 1,  2,  3,  4,  5,  6,  7
+                        , 8, 9, 10, 11, 12, 13, 14, 15 },
+                   v2 = { 0, 0, 0, 0, 0, 0, 0, 0
+                        , 0, 0, 0, 0, 0, 0, 0, 0 },
+                   mask = {  0, 20,  4, 24,  8, 28, 12, 32
+                          , 18,  2, 22,  6, 26, 10, 30, 16 },
+                   result = __builtin_shuffle(v1, v2, mask),
+                   expected = { 0, 0, 4, 0, 8,  0, 12, 0
+                              , 0, 2, 0, 6, 0, 10,  0, 0 };
+
+            int equal =    result[0] == expected[0]
+                        && result[1] == expected[1]
+                        && result[2] == expected[2]
+                        && result[3] == expected[3]
+                        && result[4] == expected[4]
+                        && result[5] == expected[5]
+                        && result[6] == expected[6]
+                        && result[7] == expected[7]
+                        && result[8] == expected[8]
+                        && result[9] == expected[9]
+                        && result[10] == expected[10]
+                        && result[11] == expected[11]
+                        && result[12] == expected[12]
+                        && result[13] == expected[13]
+                        && result[14] == expected[14]
+                        && result[15] == expected[15];
+
+            return equal ? 0 : 1;
+        ]])],
+    [AC_MSG_RESULT([yes])
+     rs_have_builtin_shuffle=1],
+    [AC_MSG_RESULT([no])
+     rs_have_builtin_shuffle=0],
+    [AC_MSG_RESULT([no (assumed, cross-compiling)])
+     rs_have_builtin_shuffle=0])
+AC_DEFINE_UNQUOTED(
+    [RS_HAVE_BUILTIN_SHUFFLE],
+    [$rs_have_builtin_shuffle],
+    [Define to 1 if C compiller supports __builtin_shuffle])
+
 AC_MSG_CHECKING([whether Clang's `loop unroll` pragma works])
 AC_COMPILE_IFELSE(
     [AC_LANG_PROGRAM(
@@ -200,6 +249,15 @@
 
 # Checks for library functions.
 AC_FUNC_MALLOC
+AC_CHECK_DECLS(
+    [[__get_cpuid_count(const unsigned int, const unsigned int, unsigned int *, unsigned int *, unsigned int *, unsigned int *)]],
+    [],
+    [],
+    [[
+        #if defined(HAVE_CPUID_H) && HAVE_CPUID_H
+        # include <cpuid.h>
+        #endif
+    ]])
 
 # Definitions based on discovered compiler or ISA characteristics.
 rs_generic=1
@@ -259,10 +317,18 @@
 
 rs_backends=""
 if test x$rs_generic = x1; then
-    rs_backends="$rs_backends, generic"
+    if test x$rs_have_builtin_shuffle = x1; then
+        rs_backends="$rs_backends, generic (__builtin_shuffle)"
+    else
+        rs_backends="$rs_backends, generic"
+    fi
 fi
 if test x$rs_sse2 = x1; then
-    rs_backends="$rs_backends, sse2"
+    if test x$rs_have_builtin_shuffle = x1; then
+        rs_backends="$rs_backends, sse2 (__builtin_shuffle)"
+    else
+        rs_backends="$rs_backends, sse2"
+    fi
 fi
 if test x$rs_ssse3 = x1; then
     rs_backends="$rs_backends, ssse3"
diff --git a/cbits/reedsolomon.c b/cbits/reedsolomon.c
--- a/cbits/reedsolomon.c
+++ b/cbits/reedsolomon.c
@@ -306,6 +306,10 @@
 #elif USE_ALTIVEC
         const v128 zeros = set1_epi8_v(0),
                    result = { .uint8x16 = vec_perm(vec.uint8x16, zeros.uint8x16, mask.uint8x16) };
+#elif defined(RS_HAVE_BUILTIN_SHUFFLE) && RS_HAVE_BUILTIN_SHUFFLE
+        const v16u8v zeros = { 0, 0, 0, 0, 0, 0, 0, 0
+                             , 0, 0, 0, 0, 0, 0, 0, 0 };
+        const v128 result = { .v16u8 = __builtin_shuffle(vec.v16u8, zeros, mask.v16u8) };
 #else
         v128 result = { .u64 = { 0, 0 } };
 
diff --git a/cbits/reedsolomon_dispatch.c b/cbits/reedsolomon_dispatch.c
--- a/cbits/reedsolomon_dispatch.c
+++ b/cbits/reedsolomon_dispatch.c
@@ -58,6 +58,22 @@
 # define ALWAYS_INLINE
 #endif
 
+/* The prototype we expect for `__get_cpuid_count`. This is already somewhat
+ * checked by autoconf, but this won't hurt to ensure 'our' version below is
+ * consistent with the 'system' one.
+ */
+static inline int __get_cpuid_count(
+        const unsigned int level,
+        const unsigned int count,
+        unsigned int *eax,
+        unsigned int *ebx,
+        unsigned int *ecx,
+        unsigned int *edx);
+
+/* GCC 6.3.1 includes a predefined version of this function, so we should only
+ * define it on systems which don't have it available from cpuid.h
+ */
+#if !defined(HAVE_DECL___GET_CPUID_COUNT) || !HAVE_DECL___GET_CPUID_COUNT
 static inline ALWAYS_INLINE int __get_cpuid_count(
         const unsigned int level,
         const unsigned int count,
@@ -74,6 +90,7 @@
         __cpuid_count(level, count, *eax, *ebx, *ecx, *edx);
         return 1;
 }
+#endif /* !HAVE_DECL___GET_CPUID_COUNT */
 
 struct cpuid_registers {
         unsigned int eax, ebx, ecx, edx;
diff --git a/examples/simple-decoder.lhs b/examples/simple-decoder.lhs
--- a/examples/simple-decoder.lhs
+++ b/examples/simple-decoder.lhs
@@ -14,6 +14,9 @@
 > import System.IO.Posix.MMap (unsafeMMapFile)
 >
 > import Options.Applicative
+#if MIN_VERSION_optparse_applicative(0, 13, 0)
+> import Data.Monoid ((<>))
+#endif
 >
 > import qualified Data.ByteString as BS
 >
diff --git a/examples/simple-encoder.lhs b/examples/simple-encoder.lhs
--- a/examples/simple-encoder.lhs
+++ b/examples/simple-encoder.lhs
@@ -15,6 +15,9 @@
 > import qualified Data.Vector.Generic as V
 >
 > import Options.Applicative
+#if MIN_VERSION_optparse_applicative(0, 13, 0)
+> import Data.Monoid ((<>))
+#endif
 >
 > import System.IO.Posix.MMap (unsafeMMapFile)
 >
diff --git a/reedsolomon.cabal b/reedsolomon.cabal
--- a/reedsolomon.cabal
+++ b/reedsolomon.cabal
@@ -1,5 +1,5 @@
 Name:                reedsolomon
-Version:             0.0.4.2
+Version:             0.0.4.3
 Synopsis:            Reed-Solomon Erasure Coding in Haskell
 Description:         Please see README.md
 Homepage:            http://github.com/NicolasT/reedsolomon
@@ -114,7 +114,7 @@
     Build-Depends:     base
                      , bytestring
                      , vector
-                     , optparse-applicative >= 0.11 && < 0.13
+                     , optparse-applicative >= 0.11 && < 0.14
                      , filepath >= 1.3 && < 1.5
                      , bytestring-mmap >= 0.2 && < 0.3
                      , reedsolomon
@@ -130,7 +130,7 @@
     Build-Depends:     base
                      , bytestring
                      , vector
-                     , optparse-applicative >= 0.11 && < 0.13
+                     , optparse-applicative >= 0.11 && < 0.14
                      , filepath >= 1.3 && < 1.5
                      , bytestring-mmap >= 0.2 && < 0.3
                      , reedsolomon
@@ -170,7 +170,7 @@
                      , vector
                      , deepseq >= 1.3 && < 1.5
                      , random >= 1.1 && < 1.2
-                     , optparse-applicative >= 0.11 && < 0.13
+                     , optparse-applicative >= 0.11 && < 0.14
                      , clock >= 0.4 && < 0.8
                      , reedsolomon
   else
