[PATCH] libosmocore[master]: core/conv: add x86 SSE support for Viterbi decoder

2017-05-19 Thread Tom Tsou
Hello Vadim Yanitskiy, Harald Welte, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

https://gerrit.osmocom.org/2454

to look at the new patch set (#9).

core/conv: add x86 SSE support for Viterbi decoder

Fast convolutional decoding is provided through x86 intrinsic based
SSE operations. SSE3, found on virtually all modern x86 processors,
is the minimal requirement. SSE4.1 and AVX2 are used if available.

Also, the original code was extended with runtime SIMD detection,
so only supported extensions will be used by target CPU. It makes
the library more partable, what is very important for binary
packages distribution. Runtime SIMD detection is currently
implemented through the __builtin_cpu_supports call.

Change-Id: I1da6d71ed0564f1d684f3a836e998d09de5f0351
---
M src/Makefile.am
M src/viterbi.c
M src/viterbi_gen.c
A src/viterbi_sse.c
4 files changed, 748 insertions(+), 10 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/54/2454/9

diff --git a/src/Makefile.am b/src/Makefile.am
index 6948e1a..e8e67ef 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,12 @@
 macaddr.c stat_item.c stats.c stats_statsd.c prim.c \
 viterbi.c viterbi_gen.c
 
+if HAVE_SSE3
+libosmocore_la_SOURCES += viterbi_sse.c
+# Per-object flags hack
+viterbi_sse.lo : CFLAGS += $(SIMD_FLAGS)
+endif
+
 BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c
 
 if ENABLE_PLUGIN
diff --git a/src/viterbi.c b/src/viterbi.c
index 21c6a57..2097a02 100644
--- a/src/viterbi.c
+++ b/src/viterbi.c
@@ -24,11 +24,34 @@
 #include 
 #include 
 
-#include 
 #include "config.h"
+
+#include 
 
 #define BIT2NRZ(REG,N) (((REG >> N) & 0x01) * 2 - 1) * -1
 #define NUM_STATES(K)  (K == 7 ? 64 : 16)
+
+static int init_complete = 0;
+
+__attribute__ ((visibility("hidden"))) int avx2_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse3_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse41_supported = 0;
+
+/**
+ * This pointers will be initialized by the osmo_conv_init()
+ * depending on supported SIMD extensions.
+ */
+static int16_t *(*vdec_malloc)(size_t n);
+static void (*vdec_free)(int16_t *ptr);
+
+/* Forward malloc wrappers */
+int16_t *osmo_conv_vdec_malloc(size_t n);
+void osmo_conv_vdec_free(int16_t *ptr);
+
+#ifdef HAVE_SSE3
+int16_t *osmo_conv_vdec_malloc_sse3(size_t n);
+void osmo_conv_vdec_free_sse3(int16_t *ptr);
+#endif
 
 /* Forward Metric Units */
 void osmo_conv_gen_metrics_k5_n2(const int8_t *seq, const int16_t *out,
@@ -43,6 +66,21 @@
int16_t *sums, int16_t *paths, int norm);
 void osmo_conv_gen_metrics_k7_n4(const int8_t *seq, const int16_t *out,
int16_t *sums, int16_t *paths, int norm);
+
+#ifdef HAVE_SSE3
+void osmo_conv_gen_metrics_k5_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+#endif
 
 /* Trellis State
  * state - Internal lshift register value
@@ -89,12 +127,6 @@
void (*metric_func)(const int8_t *, const int16_t *,
int16_t *, int16_t *, int);
 };
-
-/* Non-aligned Memory Allocator */
-static int16_t *vdec_malloc(size_t n)
-{
-   return (int16_t *) malloc(sizeof(int16_t) * n);
-}
 
 /* Accessor calls */
 static inline int conv_code_recursive(const struct osmo_conv_code *code)
@@ -294,9 +326,9 @@
if (!trellis)
return;
 
+   vdec_free(trellis->outputs);
+   vdec_free(trellis->sums);
free(trellis->vals);
-   free(trellis->outputs);
-   free(trellis->sums);
free(trellis);
 }
 
@@ -430,7 +462,7 @@
if (!dec)
return;
 
-   free(dec->paths[0]);
+   vdec_free(dec->paths[0]);
free(dec->paths);
free_trellis(dec->trellis);
free(dec);
@@ -456,13 +488,31 @@
if (dec->k == 5) {
switch (dec->n) {
case 2:
+   #ifdef HAVE_SSE3
+   dec->metric_func = !sse3_supported ?
+   osmo_conv_gen_metrics_k5_n2 :
+   osmo_conv_gen_metrics_k5_n2_sse;
+   #else
dec->metric_func = osmo_conv_gen_metrics_k5_n2;
+   #endif
break;
case 3:
+   #ifdef HAVE_SSE3
+   

[PATCH] libosmocore[master]: core/conv: add x86 SSE support for Viterbi decoder

2017-05-19 Thread Tom Tsou
Hello Vadim Yanitskiy, Harald Welte, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

https://gerrit.osmocom.org/2454

to look at the new patch set (#8).

core/conv: add x86 SSE support for Viterbi decoder

Fast convolutional decoding is provided through x86 intrinsic based
SSE operations. SSE3, found on virtually all modern x86 processors,
is the minimal requirement. SSE4.1 and AVX2 are used if available.

Also, the original code was extended with runtime SIMD detection,
so only supported extensions will be used by target CPU. It makes
the library more partable, what is very important for binary
packages distribution. Runtime SIMD detection is currently
implemented through the __builtin_cpu_supports call.

Change-Id: I1da6d71ed0564f1d684f3a836e998d09de5f0351
---
M src/Makefile.am
M src/viterbi.c
M src/viterbi_gen.c
A src/viterbi_sse.c
4 files changed, 748 insertions(+), 10 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/54/2454/8

diff --git a/src/Makefile.am b/src/Makefile.am
index 6948e1a..e8e67ef 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,12 @@
 macaddr.c stat_item.c stats.c stats_statsd.c prim.c \
 viterbi.c viterbi_gen.c
 
+if HAVE_SSE3
+libosmocore_la_SOURCES += viterbi_sse.c
+# Per-object flags hack
+viterbi_sse.lo : CFLAGS += $(SIMD_FLAGS)
+endif
+
 BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c
 
 if ENABLE_PLUGIN
diff --git a/src/viterbi.c b/src/viterbi.c
index 21c6a57..2097a02 100644
--- a/src/viterbi.c
+++ b/src/viterbi.c
@@ -24,11 +24,34 @@
 #include 
 #include 
 
-#include 
 #include "config.h"
+
+#include 
 
 #define BIT2NRZ(REG,N) (((REG >> N) & 0x01) * 2 - 1) * -1
 #define NUM_STATES(K)  (K == 7 ? 64 : 16)
+
+static int init_complete = 0;
+
+__attribute__ ((visibility("hidden"))) int avx2_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse3_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse41_supported = 0;
+
+/**
+ * This pointers will be initialized by the osmo_conv_init()
+ * depending on supported SIMD extensions.
+ */
+static int16_t *(*vdec_malloc)(size_t n);
+static void (*vdec_free)(int16_t *ptr);
+
+/* Forward malloc wrappers */
+int16_t *osmo_conv_vdec_malloc(size_t n);
+void osmo_conv_vdec_free(int16_t *ptr);
+
+#ifdef HAVE_SSE3
+int16_t *osmo_conv_vdec_malloc_sse3(size_t n);
+void osmo_conv_vdec_free_sse3(int16_t *ptr);
+#endif
 
 /* Forward Metric Units */
 void osmo_conv_gen_metrics_k5_n2(const int8_t *seq, const int16_t *out,
@@ -43,6 +66,21 @@
int16_t *sums, int16_t *paths, int norm);
 void osmo_conv_gen_metrics_k7_n4(const int8_t *seq, const int16_t *out,
int16_t *sums, int16_t *paths, int norm);
+
+#ifdef HAVE_SSE3
+void osmo_conv_gen_metrics_k5_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+#endif
 
 /* Trellis State
  * state - Internal lshift register value
@@ -89,12 +127,6 @@
void (*metric_func)(const int8_t *, const int16_t *,
int16_t *, int16_t *, int);
 };
-
-/* Non-aligned Memory Allocator */
-static int16_t *vdec_malloc(size_t n)
-{
-   return (int16_t *) malloc(sizeof(int16_t) * n);
-}
 
 /* Accessor calls */
 static inline int conv_code_recursive(const struct osmo_conv_code *code)
@@ -294,9 +326,9 @@
if (!trellis)
return;
 
+   vdec_free(trellis->outputs);
+   vdec_free(trellis->sums);
free(trellis->vals);
-   free(trellis->outputs);
-   free(trellis->sums);
free(trellis);
 }
 
@@ -430,7 +462,7 @@
if (!dec)
return;
 
-   free(dec->paths[0]);
+   vdec_free(dec->paths[0]);
free(dec->paths);
free_trellis(dec->trellis);
free(dec);
@@ -456,13 +488,31 @@
if (dec->k == 5) {
switch (dec->n) {
case 2:
+   #ifdef HAVE_SSE3
+   dec->metric_func = !sse3_supported ?
+   osmo_conv_gen_metrics_k5_n2 :
+   osmo_conv_gen_metrics_k5_n2_sse;
+   #else
dec->metric_func = osmo_conv_gen_metrics_k5_n2;
+   #endif
break;
case 3:
+   #ifdef HAVE_SSE3
+   

[PATCH] libosmocore[master]: core/conv: add x86 SSE support for Viterbi decoder

2017-05-07 Thread Vadim Yanitskiy
Hello Harald Welte, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

https://gerrit.osmocom.org/2454

to look at the new patch set (#7).

core/conv: add x86 SSE support for Viterbi decoder

Fast convolutional decoding is provided through x86 intrinsic based
SSE operations. SSE3, found on virtually all modern x86 processors,
is the minimal requirement. SSE4.1 and AVX2 are used if available.

Also, the original code was extended with runtime SIMD detection,
so only supported extensions will be used by target CPU. It makes
the library more partable, what is very important for binary
packages distribution. Runtime SIMD detection is currently
implemented through the __builtin_cpu_supports call.

Change-Id: I1da6d71ed0564f1d684f3a836e998d09de5f0351
---
M src/Makefile.am
M src/viterbi.c
M src/viterbi_gen.c
A src/viterbi_sse.c
4 files changed, 748 insertions(+), 10 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/54/2454/7

diff --git a/src/Makefile.am b/src/Makefile.am
index 6948e1a..e8e67ef 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,12 @@
 macaddr.c stat_item.c stats.c stats_statsd.c prim.c \
 viterbi.c viterbi_gen.c
 
+if HAVE_SSE3
+libosmocore_la_SOURCES += viterbi_sse.c
+# Per-object flags hack
+viterbi_sse.lo : CFLAGS += $(SIMD_FLAGS)
+endif
+
 BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c
 
 if ENABLE_PLUGIN
diff --git a/src/viterbi.c b/src/viterbi.c
index 21c6a57..2097a02 100644
--- a/src/viterbi.c
+++ b/src/viterbi.c
@@ -24,11 +24,34 @@
 #include 
 #include 
 
-#include 
 #include "config.h"
+
+#include 
 
 #define BIT2NRZ(REG,N) (((REG >> N) & 0x01) * 2 - 1) * -1
 #define NUM_STATES(K)  (K == 7 ? 64 : 16)
+
+static int init_complete = 0;
+
+__attribute__ ((visibility("hidden"))) int avx2_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse3_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse41_supported = 0;
+
+/**
+ * This pointers will be initialized by the osmo_conv_init()
+ * depending on supported SIMD extensions.
+ */
+static int16_t *(*vdec_malloc)(size_t n);
+static void (*vdec_free)(int16_t *ptr);
+
+/* Forward malloc wrappers */
+int16_t *osmo_conv_vdec_malloc(size_t n);
+void osmo_conv_vdec_free(int16_t *ptr);
+
+#ifdef HAVE_SSE3
+int16_t *osmo_conv_vdec_malloc_sse3(size_t n);
+void osmo_conv_vdec_free_sse3(int16_t *ptr);
+#endif
 
 /* Forward Metric Units */
 void osmo_conv_gen_metrics_k5_n2(const int8_t *seq, const int16_t *out,
@@ -43,6 +66,21 @@
int16_t *sums, int16_t *paths, int norm);
 void osmo_conv_gen_metrics_k7_n4(const int8_t *seq, const int16_t *out,
int16_t *sums, int16_t *paths, int norm);
+
+#ifdef HAVE_SSE3
+void osmo_conv_gen_metrics_k5_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+#endif
 
 /* Trellis State
  * state - Internal lshift register value
@@ -89,12 +127,6 @@
void (*metric_func)(const int8_t *, const int16_t *,
int16_t *, int16_t *, int);
 };
-
-/* Non-aligned Memory Allocator */
-static int16_t *vdec_malloc(size_t n)
-{
-   return (int16_t *) malloc(sizeof(int16_t) * n);
-}
 
 /* Accessor calls */
 static inline int conv_code_recursive(const struct osmo_conv_code *code)
@@ -294,9 +326,9 @@
if (!trellis)
return;
 
+   vdec_free(trellis->outputs);
+   vdec_free(trellis->sums);
free(trellis->vals);
-   free(trellis->outputs);
-   free(trellis->sums);
free(trellis);
 }
 
@@ -430,7 +462,7 @@
if (!dec)
return;
 
-   free(dec->paths[0]);
+   vdec_free(dec->paths[0]);
free(dec->paths);
free_trellis(dec->trellis);
free(dec);
@@ -456,13 +488,31 @@
if (dec->k == 5) {
switch (dec->n) {
case 2:
+   #ifdef HAVE_SSE3
+   dec->metric_func = !sse3_supported ?
+   osmo_conv_gen_metrics_k5_n2 :
+   osmo_conv_gen_metrics_k5_n2_sse;
+   #else
dec->metric_func = osmo_conv_gen_metrics_k5_n2;
+   #endif
break;
case 3:
+   #ifdef HAVE_SSE3
+   dec->metric_func = 

[PATCH] libosmocore[master]: core/conv: add x86 SSE support for Viterbi decoder

2017-05-02 Thread Vadim Yanitskiy
Hello Harald Welte, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

https://gerrit.osmocom.org/2454

to look at the new patch set (#6).

core/conv: add x86 SSE support for Viterbi decoder

Fast convolutional decoding is provided through x86 intrinsic based
SSE operations. SSE3, found on virtually all modern x86 processors,
is the minimal requirement. SSE4.1 and AVX2 are used if available.

Also, the original code was extended with runtime SIMD detection,
so only supported extensions will be used by target CPU. It makes
the library more partable, what is very important for binary
packages distribution. The SIMD detection is currently implemented
through the __builtin_cpu_supports(EXT), which is only supported
by GCC.

Change-Id: I1da6d71ed0564f1d684f3a836e998d09de5f0351
---
M src/Makefile.am
M src/viterbi.c
M src/viterbi_gen.c
A src/viterbi_sse.c
4 files changed, 747 insertions(+), 11 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/54/2454/6

diff --git a/src/Makefile.am b/src/Makefile.am
index 6948e1a..2f19838 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,7 +4,7 @@
 LIBVERSION=8:0:0
 
 AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include
-AM_CFLAGS = -Wall $(TALLOC_CFLAGS)
+AM_CFLAGS = -Wall $(TALLOC_CFLAGS) $(SIMD_FLAGS)
 
 lib_LTLIBRARIES = libosmocore.la
 
@@ -19,6 +19,10 @@
 macaddr.c stat_item.c stats.c stats_statsd.c prim.c \
 viterbi.c viterbi_gen.c
 
+if HAVE_SSE3
+libosmocore_la_SOURCES += viterbi_sse.c
+endif
+
 BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c
 
 if ENABLE_PLUGIN
diff --git a/src/viterbi.c b/src/viterbi.c
index 21c6a57..d68db23 100644
--- a/src/viterbi.c
+++ b/src/viterbi.c
@@ -24,11 +24,34 @@
 #include 
 #include 
 
-#include 
 #include "config.h"
+
+#include 
 
 #define BIT2NRZ(REG,N) (((REG >> N) & 0x01) * 2 - 1) * -1
 #define NUM_STATES(K)  (K == 7 ? 64 : 16)
+
+static int init_complete = 0;
+
+__attribute__ ((visibility("hidden"))) int avx2_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse3_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse41_supported = 0;
+
+/**
+ * This pointers will be initialized by the osmo_conv_init()
+ * depending on supported SIMD extensions.
+ */
+static int16_t *(*vdec_malloc)(size_t n);
+static void (*vdec_free)(int16_t *ptr);
+
+/* Forward malloc wrappers */
+int16_t *osmo_conv_vdec_malloc(size_t n);
+void osmo_conv_vdec_free(int16_t *ptr);
+
+#ifdef HAVE_SSE3
+int16_t *osmo_conv_vdec_malloc_sse3(size_t n);
+void osmo_conv_vdec_free_sse3(int16_t *ptr);
+#endif
 
 /* Forward Metric Units */
 void osmo_conv_gen_metrics_k5_n2(const int8_t *seq, const int16_t *out,
@@ -43,6 +66,21 @@
int16_t *sums, int16_t *paths, int norm);
 void osmo_conv_gen_metrics_k7_n4(const int8_t *seq, const int16_t *out,
int16_t *sums, int16_t *paths, int norm);
+
+#ifdef HAVE_SSE3
+void osmo_conv_gen_metrics_k5_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+#endif
 
 /* Trellis State
  * state - Internal lshift register value
@@ -89,12 +127,6 @@
void (*metric_func)(const int8_t *, const int16_t *,
int16_t *, int16_t *, int);
 };
-
-/* Non-aligned Memory Allocator */
-static int16_t *vdec_malloc(size_t n)
-{
-   return (int16_t *) malloc(sizeof(int16_t) * n);
-}
 
 /* Accessor calls */
 static inline int conv_code_recursive(const struct osmo_conv_code *code)
@@ -294,9 +326,9 @@
if (!trellis)
return;
 
+   vdec_free(trellis->outputs);
+   vdec_free(trellis->sums);
free(trellis->vals);
-   free(trellis->outputs);
-   free(trellis->sums);
free(trellis);
 }
 
@@ -430,7 +462,7 @@
if (!dec)
return;
 
-   free(dec->paths[0]);
+   vdec_free(dec->paths[0]);
free(dec->paths);
free_trellis(dec->trellis);
free(dec);
@@ -456,13 +488,31 @@
if (dec->k == 5) {
switch (dec->n) {
case 2:
+   #ifdef HAVE_SSE3
+   dec->metric_func = !sse3_supported ?
+   osmo_conv_gen_metrics_k5_n2 :
+   osmo_conv_gen_metrics_k5_n2_sse;
+   #else
dec->metric_func 

[PATCH] libosmocore[master]: core/conv: add x86 SSE support for Viterbi decoder

2017-05-01 Thread Vadim Yanitskiy
Hello Harald Welte, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

https://gerrit.osmocom.org/2454

to look at the new patch set (#4).

core/conv: add x86 SSE support for Viterbi decoder

Fast convolutional decoding is provided through x86 intrinsic based
SSE operations. SSE3, found on virtually all modern x86 processors,
is the minimal requirement. SSE4.1 and AVX2 are used if available.

Also, the original code was extended with runtime SIMD detection,
so only supported extensions will be used by target CPU. It makes
the library more partable, what is very important for binary
packages distribution. The SIMD detection is currently implemented
through the __builtin_cpu_supports(EXT), which is only supported
by GCC.

Change-Id: I1da6d71ed0564f1d684f3a836e998d09de5f0351
---
M src/Makefile.am
M src/viterbi.c
M src/viterbi_gen.c
A src/viterbi_sse.c
4 files changed, 746 insertions(+), 10 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/54/2454/4

diff --git a/src/Makefile.am b/src/Makefile.am
index 999436d..2f19838 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,10 @@
 macaddr.c stat_item.c stats.c stats_statsd.c prim.c \
 viterbi.c viterbi_gen.c
 
+if HAVE_SSE3
+libosmocore_la_SOURCES += viterbi_sse.c
+endif
+
 BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c
 
 if ENABLE_PLUGIN
diff --git a/src/viterbi.c b/src/viterbi.c
index 21c6a57..d68db23 100644
--- a/src/viterbi.c
+++ b/src/viterbi.c
@@ -24,11 +24,34 @@
 #include 
 #include 
 
-#include 
 #include "config.h"
+
+#include 
 
 #define BIT2NRZ(REG,N) (((REG >> N) & 0x01) * 2 - 1) * -1
 #define NUM_STATES(K)  (K == 7 ? 64 : 16)
+
+static int init_complete = 0;
+
+__attribute__ ((visibility("hidden"))) int avx2_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse3_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse41_supported = 0;
+
+/**
+ * This pointers will be initialized by the osmo_conv_init()
+ * depending on supported SIMD extensions.
+ */
+static int16_t *(*vdec_malloc)(size_t n);
+static void (*vdec_free)(int16_t *ptr);
+
+/* Forward malloc wrappers */
+int16_t *osmo_conv_vdec_malloc(size_t n);
+void osmo_conv_vdec_free(int16_t *ptr);
+
+#ifdef HAVE_SSE3
+int16_t *osmo_conv_vdec_malloc_sse3(size_t n);
+void osmo_conv_vdec_free_sse3(int16_t *ptr);
+#endif
 
 /* Forward Metric Units */
 void osmo_conv_gen_metrics_k5_n2(const int8_t *seq, const int16_t *out,
@@ -43,6 +66,21 @@
int16_t *sums, int16_t *paths, int norm);
 void osmo_conv_gen_metrics_k7_n4(const int8_t *seq, const int16_t *out,
int16_t *sums, int16_t *paths, int norm);
+
+#ifdef HAVE_SSE3
+void osmo_conv_gen_metrics_k5_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+#endif
 
 /* Trellis State
  * state - Internal lshift register value
@@ -89,12 +127,6 @@
void (*metric_func)(const int8_t *, const int16_t *,
int16_t *, int16_t *, int);
 };
-
-/* Non-aligned Memory Allocator */
-static int16_t *vdec_malloc(size_t n)
-{
-   return (int16_t *) malloc(sizeof(int16_t) * n);
-}
 
 /* Accessor calls */
 static inline int conv_code_recursive(const struct osmo_conv_code *code)
@@ -294,9 +326,9 @@
if (!trellis)
return;
 
+   vdec_free(trellis->outputs);
+   vdec_free(trellis->sums);
free(trellis->vals);
-   free(trellis->outputs);
-   free(trellis->sums);
free(trellis);
 }
 
@@ -430,7 +462,7 @@
if (!dec)
return;
 
-   free(dec->paths[0]);
+   vdec_free(dec->paths[0]);
free(dec->paths);
free_trellis(dec->trellis);
free(dec);
@@ -456,13 +488,31 @@
if (dec->k == 5) {
switch (dec->n) {
case 2:
+   #ifdef HAVE_SSE3
+   dec->metric_func = !sse3_supported ?
+   osmo_conv_gen_metrics_k5_n2 :
+   osmo_conv_gen_metrics_k5_n2_sse;
+   #else
dec->metric_func = osmo_conv_gen_metrics_k5_n2;
+   #endif
break;
case 3:
+   #ifdef HAVE_SSE3
+   dec->metric_func = !sse3_supported ?
+ 

[PATCH] libosmocore[master]: core/conv: add x86 SSE support for Viterbi decoder

2017-05-01 Thread Vadim Yanitskiy
Hello Harald Welte, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

https://gerrit.osmocom.org/2454

to look at the new patch set (#3).

core/conv: add x86 SSE support for Viterbi decoder

Fast convolutional decoding is provided through x86 intrinsic based
SSE operations. SSE3, found on virtually all modern x86 processors,
is the minimal requirement. SSE4.1 and AVX2 are used if available.

Also, the original code was extended with runtime SIMD detection,
so only supported extensions will be used by target CPU. It makes
the library more partable, what is very important for binary
packages distribution. The SIMD detection is currently implemented
through the __builtin_cpu_supports(EXT), which is only supported
by GCC.

Change-Id: I1da6d71ed0564f1d684f3a836e998d09de5f0351
---
M src/Makefile.am
M src/viterbi.c
M src/viterbi_gen.c
A src/viterbi_sse.c
4 files changed, 746 insertions(+), 19 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/54/2454/3

diff --git a/src/Makefile.am b/src/Makefile.am
index 999436d..2f19838 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,10 @@
 macaddr.c stat_item.c stats.c stats_statsd.c prim.c \
 viterbi.c viterbi_gen.c
 
+if HAVE_SSE3
+libosmocore_la_SOURCES += viterbi_sse.c
+endif
+
 BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c
 
 if ENABLE_PLUGIN
diff --git a/src/viterbi.c b/src/viterbi.c
index ea4fb21..d68db23 100644
--- a/src/viterbi.c
+++ b/src/viterbi.c
@@ -24,12 +24,34 @@
 #include 
 #include 
 
-#include 
 #include "config.h"
+
+#include 
 
 #define BIT2NRZ(REG,N) (((REG >> N) & 0x01) * 2 - 1) * -1
 #define NUM_STATES(K)  (K == 7 ? 64 : 16)
-#define SSE_ALIGN  16
+
+static int init_complete = 0;
+
+__attribute__ ((visibility("hidden"))) int avx2_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse3_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse41_supported = 0;
+
+/**
+ * This pointers will be initialized by the osmo_conv_init()
+ * depending on supported SIMD extensions.
+ */
+static int16_t *(*vdec_malloc)(size_t n);
+static void (*vdec_free)(int16_t *ptr);
+
+/* Forward malloc wrappers */
+int16_t *osmo_conv_vdec_malloc(size_t n);
+void osmo_conv_vdec_free(int16_t *ptr);
+
+#ifdef HAVE_SSE3
+int16_t *osmo_conv_vdec_malloc_sse3(size_t n);
+void osmo_conv_vdec_free_sse3(int16_t *ptr);
+#endif
 
 /* Forward Metric Units */
 void osmo_conv_gen_metrics_k5_n2(const int8_t *seq, const int16_t *out,
@@ -44,6 +66,21 @@
int16_t *sums, int16_t *paths, int norm);
 void osmo_conv_gen_metrics_k7_n4(const int8_t *seq, const int16_t *out,
int16_t *sums, int16_t *paths, int norm);
+
+#ifdef HAVE_SSE3
+void osmo_conv_gen_metrics_k5_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+#endif
 
 /* Trellis State
  * state - Internal lshift register value
@@ -90,20 +127,6 @@
void (*metric_func)(const int8_t *, const int16_t *,
int16_t *, int16_t *, int);
 };
-
-/* Aligned Memory Allocator
- * SSE requires 16-byte memory alignment. We store relevant trellis values
- * (accumulated sums, outputs, and path decisions) as 16 bit signed integers
- * so the allocated memory is casted as such.
- */
-static int16_t *vdec_malloc(size_t n)
-{
-#ifdef HAVE_SSE3
-   return (int16_t *) memalign(SSE_ALIGN, sizeof(int16_t) * n);
-#else
-   return (int16_t *) malloc(sizeof(int16_t) * n);
-#endif
-}
 
 /* Accessor calls */
 static inline int conv_code_recursive(const struct osmo_conv_code *code)
@@ -303,9 +326,9 @@
if (!trellis)
return;
 
+   vdec_free(trellis->outputs);
+   vdec_free(trellis->sums);
free(trellis->vals);
-   free(trellis->outputs);
-   free(trellis->sums);
free(trellis);
 }
 
@@ -439,7 +462,7 @@
if (!dec)
return;
 
-   free(dec->paths[0]);
+   vdec_free(dec->paths[0]);
free(dec->paths);
free_trellis(dec->trellis);
free(dec);
@@ -465,13 +488,31 @@
if (dec->k == 5) {
switch (dec->n) {
case 2:
+   #ifdef HAVE_SSE3
+   dec->metric_func = !sse3_supported ?
+   osmo_conv_gen_metrics_k5_n2 :
+

[PATCH] libosmocore[master]: core/conv: add x86 SSE support for Viterbi decoder

2017-04-30 Thread Vadim Yanitskiy
Hello Jenkins Builder,

I'd like you to reexamine a change.  Please visit

https://gerrit.osmocom.org/2454

to look at the new patch set (#2).

core/conv: add x86 SSE support for Viterbi decoder

Fast convolutional decoding is provided through x86 intrinsic based
SSE operations. SSE3, found on virtually all modern x86 processors,
is the minimal requirement. SSE4.1 and AVX2 are used if available.

To enable this feature, the source code should be configured with
SIMD support (see --enable-simd). Otherwise, the viterbi_sse.c
won't be compiled.

Also, the original code was extended with runtime SIMD detection,
so only supported extensions will be used by target CPU. It makes
the library more partable, what is very important for binary
packages distribution. The SIMD detection is currently implemented
through the __builtin_cpu_supports(EXT), which is only supported
by GCC.

Change-Id: I1da6d71ed0564f1d684f3a836e998d09de5f0351
---
M src/Makefile.am
M src/viterbi.c
M src/viterbi_gen.c
A src/viterbi_sse.c
4 files changed, 746 insertions(+), 19 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/54/2454/2

diff --git a/src/Makefile.am b/src/Makefile.am
index 999436d..2f19838 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,10 @@
 macaddr.c stat_item.c stats.c stats_statsd.c prim.c \
 viterbi.c viterbi_gen.c
 
+if HAVE_SSE3
+libosmocore_la_SOURCES += viterbi_sse.c
+endif
+
 BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c
 
 if ENABLE_PLUGIN
diff --git a/src/viterbi.c b/src/viterbi.c
index ea4fb21..d68db23 100644
--- a/src/viterbi.c
+++ b/src/viterbi.c
@@ -24,12 +24,34 @@
 #include 
 #include 
 
-#include 
 #include "config.h"
+
+#include 
 
 #define BIT2NRZ(REG,N) (((REG >> N) & 0x01) * 2 - 1) * -1
 #define NUM_STATES(K)  (K == 7 ? 64 : 16)
-#define SSE_ALIGN  16
+
+static int init_complete = 0;
+
+__attribute__ ((visibility("hidden"))) int avx2_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse3_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse41_supported = 0;
+
+/**
+ * This pointers will be initialized by the osmo_conv_init()
+ * depending on supported SIMD extensions.
+ */
+static int16_t *(*vdec_malloc)(size_t n);
+static void (*vdec_free)(int16_t *ptr);
+
+/* Forward malloc wrappers */
+int16_t *osmo_conv_vdec_malloc(size_t n);
+void osmo_conv_vdec_free(int16_t *ptr);
+
+#ifdef HAVE_SSE3
+int16_t *osmo_conv_vdec_malloc_sse3(size_t n);
+void osmo_conv_vdec_free_sse3(int16_t *ptr);
+#endif
 
 /* Forward Metric Units */
 void osmo_conv_gen_metrics_k5_n2(const int8_t *seq, const int16_t *out,
@@ -44,6 +66,21 @@
int16_t *sums, int16_t *paths, int norm);
 void osmo_conv_gen_metrics_k7_n4(const int8_t *seq, const int16_t *out,
int16_t *sums, int16_t *paths, int norm);
+
+#ifdef HAVE_SSE3
+void osmo_conv_gen_metrics_k5_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+#endif
 
 /* Trellis State
  * state - Internal lshift register value
@@ -90,20 +127,6 @@
void (*metric_func)(const int8_t *, const int16_t *,
int16_t *, int16_t *, int);
 };
-
-/* Aligned Memory Allocator
- * SSE requires 16-byte memory alignment. We store relevant trellis values
- * (accumulated sums, outputs, and path decisions) as 16 bit signed integers
- * so the allocated memory is casted as such.
- */
-static int16_t *vdec_malloc(size_t n)
-{
-#ifdef HAVE_SSE3
-   return (int16_t *) memalign(SSE_ALIGN, sizeof(int16_t) * n);
-#else
-   return (int16_t *) malloc(sizeof(int16_t) * n);
-#endif
-}
 
 /* Accessor calls */
 static inline int conv_code_recursive(const struct osmo_conv_code *code)
@@ -303,9 +326,9 @@
if (!trellis)
return;
 
+   vdec_free(trellis->outputs);
+   vdec_free(trellis->sums);
free(trellis->vals);
-   free(trellis->outputs);
-   free(trellis->sums);
free(trellis);
 }
 
@@ -439,7 +462,7 @@
if (!dec)
return;
 
-   free(dec->paths[0]);
+   vdec_free(dec->paths[0]);
free(dec->paths);
free_trellis(dec->trellis);
free(dec);
@@ -465,13 +488,31 @@
if (dec->k == 5) {
switch (dec->n) {
case 2:
+   #ifdef HAVE_SSE3
+

[PATCH] libosmocore[master]: core/conv: add x86 SSE support for Viterbi decoder

2017-04-30 Thread Vadim Yanitskiy

Review at  https://gerrit.osmocom.org/2454

core/conv: add x86 SSE support for Viterbi decoder

Fast convolutional decoding is provided through x86 intrinsic based
SSE operations. SSE3, found on virtually all modern x86 processors,
is the minimal requirement. SSE4.1 and AVX2 are used if available.

To enable this feature, the source code should be configured with
SIMD support (see --enable-simd). Otherwise, the viterbi_sse.c
won't be compiled.

Also, the original code was extended with runtime SIMD detection,
so only supported extensions will be used by target CPU. It makes
the library more partable, what is very important for binary
packages distribution. The SIMD detection is currently implemented
through the __builtin_cpu_supports(EXT), which is only supported
by GCC.

Change-Id: I1da6d71ed0564f1d684f3a836e998d09de5f0351
---
M src/Makefile.am
M src/viterbi.c
A src/viterbi_sse.c
3 files changed, 699 insertions(+), 6 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/54/2454/1

diff --git a/src/Makefile.am b/src/Makefile.am
index 999436d..2f19838 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -19,6 +19,10 @@
 macaddr.c stat_item.c stats.c stats_statsd.c prim.c \
 viterbi.c viterbi_gen.c
 
+if HAVE_SSE3
+libosmocore_la_SOURCES += viterbi_sse.c
+endif
+
 BUILT_SOURCES = crc8gen.c crc16gen.c crc32gen.c crc64gen.c
 
 if ENABLE_PLUGIN
diff --git a/src/viterbi.c b/src/viterbi.c
index ea4fb21..1484a31 100644
--- a/src/viterbi.c
+++ b/src/viterbi.c
@@ -20,16 +20,30 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#include 
 #include 
 #include 
 #include 
 
-#include 
 #include "config.h"
+
+#include 
 
 #define BIT2NRZ(REG,N) (((REG >> N) & 0x01) * 2 - 1) * -1
 #define NUM_STATES(K)  (K == 7 ? 64 : 16)
 #define SSE_ALIGN  16
+
+static int init_complete = 0;
+
+__attribute__ ((visibility("hidden"))) int avx2_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse3_supported = 0;
+__attribute__ ((visibility("hidden"))) int sse41_supported = 0;
+
+/**
+ * This pointer will be initialized by the osmo_conv_init()
+ * depending on supported SIMD extensions.
+ */
+static int16_t *(*vdec_malloc)(size_t n);
 
 /* Forward Metric Units */
 void osmo_conv_gen_metrics_k5_n2(const int8_t *seq, const int16_t *out,
@@ -44,6 +58,21 @@
int16_t *sums, int16_t *paths, int norm);
 void osmo_conv_gen_metrics_k7_n4(const int8_t *seq, const int16_t *out,
int16_t *sums, int16_t *paths, int norm);
+
+#ifdef HAVE_SSE3
+void osmo_conv_gen_metrics_k5_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k5_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n2_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n3_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+void osmo_conv_gen_metrics_k7_n4_sse(const int8_t *seq, const int16_t *out,
+   int16_t *sums, int16_t *paths, int norm);
+#endif
 
 /* Trellis State
  * state - Internal lshift register value
@@ -96,13 +125,14 @@
  * (accumulated sums, outputs, and path decisions) as 16 bit signed integers
  * so the allocated memory is casted as such.
  */
-static int16_t *vdec_malloc(size_t n)
+static int16_t *vdec_malloc_no_sse3(size_t n)
 {
-#ifdef HAVE_SSE3
-   return (int16_t *) memalign(SSE_ALIGN, sizeof(int16_t) * n);
-#else
return (int16_t *) malloc(sizeof(int16_t) * n);
-#endif
+}
+
+static int16_t *vdec_malloc_sse3(size_t n)
+{
+   return (int16_t *) memalign(SSE_ALIGN, sizeof(int16_t) * n);
 }
 
 /* Accessor calls */
@@ -465,13 +495,31 @@
if (dec->k == 5) {
switch (dec->n) {
case 2:
+   #ifdef HAVE_SSE3
+   dec->metric_func = !sse3_supported ?
+   osmo_conv_gen_metrics_k5_n2 :
+   osmo_conv_gen_metrics_k5_n2_sse;
+   #else
dec->metric_func = osmo_conv_gen_metrics_k5_n2;
+   #endif
break;
case 3:
+   #ifdef HAVE_SSE3
+   dec->metric_func = !sse3_supported ?
+   osmo_conv_gen_metrics_k5_n3 :
+   osmo_conv_gen_metrics_k5_n3_sse;
+   #else
dec->metric_func = osmo_conv_gen_metrics_k5_n3;
+   #endif
break;
case 4:
+   #ifdef HAVE_SSE3
+   dec->metric_func = !sse3_supported ?
+   osmo_conv_gen_metrics_k5_n4 :
+