Properly detect vector_size attribute and use fallback otherwise

This commit is contained in:
Behdad Esfahbod 2017-10-15 16:21:03 -04:00
parent f8a0ec50e2
commit 7737e87ac4
2 changed files with 69 additions and 60 deletions

View File

@ -1058,6 +1058,73 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o
} }
/* Vectorization */
struct HbOpOr
{
static const bool passthru_left = true;
static const bool passthru_right = true;
template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
};
struct HbOpAnd
{
static const bool passthru_left = false;
static const bool passthru_right = false;
template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
};
struct HbOpMinus
{
static const bool passthru_left = true;
static const bool passthru_right = false;
template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
};
struct HbOpXor
{
static const bool passthru_left = true;
static const bool passthru_right = true;
template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
};
/* Type behaving similar to vectorized vars defined using __attribute__((vector_size(...))). */
template <typename elt_t, unsigned int byte_size>
struct hb_vector_size_t
{
elt_t& operator [] (unsigned int i) { return v[i]; }
const elt_t& operator [] (unsigned int i) const { return v[i]; }
template <class Op>
inline hb_vector_size_t process (const hb_vector_size_t &o) const
{
hb_vector_size_t r;
for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
Op::process (r.v[i], v[i], o.v[i]);
return r;
}
inline hb_vector_size_t operator | (const hb_vector_size_t &o) const
{ return process<HbOpOr> (o); }
inline hb_vector_size_t operator & (const hb_vector_size_t &o) const
{ return process<HbOpAnd> (o); }
inline hb_vector_size_t operator ^ (const hb_vector_size_t &o) const
{ return process<HbOpXor> (o); }
inline hb_vector_size_t operator ~ () const
{
hb_vector_size_t r;
for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
r.v[i] = ~v[i];
return r;
}
private:
static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size);
elt_t v[byte_size / sizeof (elt_t)];
};
/* The `vector_size' attribute was introduced in gcc 3.1. */
#if defined( __GNUC__ ) && ( __GNUC__ >= 4 )
#define HAVE_VECTOR_SIZE 1
#endif
/* Global runtime options. */ /* Global runtime options. */
struct hb_options_t struct hb_options_t

View File

@ -35,64 +35,6 @@
* hb_set_t * hb_set_t
*/ */
struct HbOpOr
{
static const bool passthru_left = true;
static const bool passthru_right = true;
template <typename T> static void process (T &o, const T &a, const T &b) { o = a | b; }
};
struct HbOpAnd
{
static const bool passthru_left = false;
static const bool passthru_right = false;
template <typename T> static void process (T &o, const T &a, const T &b) { o = a & b; }
};
struct HbOpMinus
{
static const bool passthru_left = true;
static const bool passthru_right = false;
template <typename T> static void process (T &o, const T &a, const T &b) { o = a & ~b; }
};
struct HbOpXor
{
static const bool passthru_left = true;
static const bool passthru_right = true;
template <typename T> static void process (T &o, const T &a, const T &b) { o = a ^ b; }
};
template <typename elt_t, unsigned int byte_size>
struct vector_like_t
{
elt_t& operator [] (unsigned int i) { return v[i]; }
const elt_t& operator [] (unsigned int i) const { return v[i]; }
template <class Op>
inline vector_like_t process (const vector_like_t &o) const
{
vector_like_t r;
for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
Op::process (r.v[i], v[i], o.v[i]);
return r;
}
inline vector_like_t operator | (const vector_like_t &o) const
{ return process<HbOpOr> (o); }
inline vector_like_t operator & (const vector_like_t &o) const
{ return process<HbOpAnd> (o); }
inline vector_like_t operator ^ (const vector_like_t &o) const
{ return process<HbOpXor> (o); }
inline vector_like_t operator ~ () const
{
vector_like_t r;
for (unsigned int i = 0; i < ARRAY_LENGTH (v); i++)
r.v[i] = ~v[i];
return r;
}
private:
static_assert (byte_size / sizeof (elt_t) * sizeof (elt_t) == byte_size);
elt_t v[byte_size / sizeof (elt_t)];
};
struct hb_set_t struct hb_set_t
{ {
struct page_map_t struct page_map_t
@ -194,10 +136,10 @@ struct hb_set_t
typedef uint64_t elt_t; typedef uint64_t elt_t;
#if 0 #if HAVE_VECTOR_SIZE
typedef elt_t vector_t __attribute__((vector_size (PAGE_BITS / 8))); typedef elt_t vector_t __attribute__((vector_size (PAGE_BITS / 8)));
#else #else
typedef vector_like_t<elt_t, PAGE_BITS / 8> vector_t; typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
#endif #endif
vector_t v; vector_t v;