/xmlbench/trunk

To get this branch, use:
bzr branch http://darksoft.org/webbzr/xmlbench/trunk

« back to all changes in this revision

Viewing changes to parse/parabix.20090922/lib/lib_simd.h

  • Committer: Suren A. Chilingaryan
  • Date: 2009-09-23 17:13:04 UTC
  • Revision ID: csa@dside.dyndns.org-20090923171304-osvtr4zqb29h11kd
Intel, Tango, Phobos, and RapidXML parsers; Memory benchmark scripts

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*  lib_simd_h:  SIMD Library including idealized SIMD operations
 
2
    Copyright (C) 2008, Robert D. Cameron
 
3
    Licensed to the public under the Open Software License 3.0.
 
4
    Licensed to International Characters Inc. 
 
5
       under the Academic Free License version 3.0.
 
6
 
 
7
    This file contains generic architecture-independent definitions,
 
8
    importing architecture-specific implementations from appropriate
 
9
    files.
 
10
*/
 
11
 
 
12
/*------------------------------------------------------------*/
 
13
#ifndef LIB_SIMD_H
 
14
#define LIB_SIMD_H
 
15
#include <sys/types.h>
 
16
#include <limits.h>
 
17
 
 
18
#if (defined(__i386) || defined(__x86_64))
 
19
#ifdef TEMPLATED_SIMD_LIB
 
20
#include "sse_simd_t.h"
 
21
#endif
 
22
#ifndef TEMPLATED_SIMD_LIB
 
23
#include "sse_simd.h"
 
24
#endif
 
25
#endif
 
26
#ifdef _ARCH_PPC
 
27
#include "altivec_simd.h"
 
28
#endif
 
29
 
 
30
/* Useful definitions from Linux kernel*/
 
31
#ifdef __GNUC__
 
32
/*
 
33
#define likely(x) __builtin_expect((x),1)
 
34
#define unlikely(x) __builtin_expect((x),0)
 
35
*/
 
36
static inline long likely(long x) {
 
37
        return __builtin_expect(x, 1);
 
38
}
 
39
static inline long unlikely(long x) {
 
40
        return __builtin_expect(x, 0);
 
41
}
 
42
 
 
43
#endif
 
44
#ifdef _MSC_VER
 
45
#define likely(x) (x)
 
46
#define unlikely(x) (x)
 
47
#endif
 
48
 
 
49
/* Shift forward and back operations, based on endianness */
 
50
#if BYTE_ORDER == BIG_ENDIAN
 
51
#define sisd_sfl(blk, n) sisd_srl(blk, n)
 
52
#define sisd_sbl(blk, n) sisd_sll(blk, n)
 
53
#define sisd_sfli(blk, n) sisd_srli(blk, n)
 
54
#define sisd_sbli(blk, n) sisd_slli(blk, n)
 
55
#define sb_op(x, n) ((x)<<(n))
 
56
#define sf_op(x, n) ((x)>>(n))
 
57
#define cfzl __builtin_clzl
 
58
#endif
 
59
#if BYTE_ORDER == LITTLE_ENDIAN
 
60
#ifdef TEMPLATED_SIMD_LIB
 
61
static inline SIMD_type sisd_sfl(SIMD_type blk, SIMD_type n) {
 
62
        return simd<128>::sll(blk, n);
 
63
}
 
64
 
 
65
static inline SIMD_type sisd_sbl(SIMD_type blk, SIMD_type n) {
 
66
        return simd<128>::srl(blk, n);
 
67
}
 
68
#define sisd_sfli(blk, n) simd<128>::slli<n>(blk)
 
69
#define sisd_sbli(blk, n) simd<128>::srli<n>(blk)
 
70
#endif
 
71
#ifndef TEMPLATED_SIMD_LIB
 
72
static inline SIMD_type sisd_sfl(SIMD_type blk, SIMD_type n) {
 
73
        return sisd_sll(blk, n);
 
74
}
 
75
static inline SIMD_type sisd_sbl(SIMD_type blk, SIMD_type n) {
 
76
        return sisd_srl(blk, n);
 
77
}
 
78
#define sisd_sfli(blk, n) sisd_slli(blk, n)
 
79
#define sisd_sbli(blk, n) sisd_srli(blk, n)
 
80
#endif
 
81
#define sb_op(x, n) ((x)>>(n))
 
82
#define sf_op(x, n) ((x)<<(n))
 
83
#ifdef __GNUC__
 
84
#define cfzl __builtin_ctzl
 
85
#endif
 
86
#ifdef _MSC_VER
 
87
#include <intrin.h>
 
88
#pragma intrinsic(_BitScanForward)
 
89
//  precondition: x > 0
 
90
static inline unsigned long cfzl(unsigned long x) {
 
91
        unsigned long zeroes;
 
92
        _BitScanForward(&zeroes, x);
 
93
        return zeroes;
 
94
}
 
95
#endif
 
96
#endif
 
97
 
 
98
 
 
99
static inline int count_forward_zeroes(SIMD_type bits) {
 
100
  union {SIMD_type vec; unsigned long elems[sizeof(SIMD_type)/sizeof(long)];} v;
 
101
  v.vec = bits;
 
102
  if (v.elems[0] != 0) return cfzl(v.elems[0]);
 
103
  else if (v.elems[1] != 0) return LONG_BIT + cfzl(v.elems[1]);
 
104
#ifdef _MSC_VER
 
105
  else if (v.elems[2] != 0) return 2*LONG_BIT + cfzl(v.elems[2]);
 
106
  else if (v.elems[3] != 0) return 3*LONG_BIT + cfzl(v.elems[3]);
 
107
#endif
 
108
#ifndef _MSC_VER
 
109
#if LONG_BIT < 64
 
110
  else if (v.elems[2] != 0) return 2*LONG_BIT + cfzl(v.elems[2]);
 
111
  else if (v.elems[3] != 0) return 3*LONG_BIT + cfzl(v.elems[3]);
 
112
#endif
 
113
#endif
 
114
  else return 8*sizeof(SIMD_type);
 
115
}
 
116
 
 
117
static inline unsigned long bitstream_segment_from(SIMD_type * stream, int bit_posn) {
 
118
  unsigned long * bitstream_ptr = (unsigned long *) (((intptr_t) stream) + bit_posn/8);
 
119
  return sb_op(*bitstream_ptr, bit_posn % 8);
 
120
}
 
121
 
 
122
/* Scans for a 1 as long as it takes.  Use a sentinel to fence. 
 
123
   Works for either endianness.  */
 
124
static inline int bitstream_scan(SIMD_type * stream, int bit_posn) {
 
125
  unsigned long * bitstream_ptr = (unsigned long *) (((intptr_t) stream) + bit_posn/8);
 
126
  unsigned long bitstream_slice = sb_op(*bitstream_ptr, bit_posn % 8);
 
127
  if (bitstream_slice != 0) return bit_posn + cfzl(bitstream_slice);
 
128
  else {
 
129
    do {
 
130
      bitstream_ptr++;
 
131
      bitstream_slice = *bitstream_ptr;
 
132
    } while (bitstream_slice == 0);
 
133
    int base_posn = 8*((intptr_t) bitstream_ptr - (intptr_t) stream);
 
134
    return base_posn + cfzl(bitstream_slice);
 
135
  }
 
136
}
 
137
 
 
138
static inline int bitstream_scan0(SIMD_type * stream) {
 
139
  unsigned long * bitstream_ptr = (unsigned long *) stream;
 
140
  unsigned long bitstream_slice = *bitstream_ptr;
 
141
  int base_posn = 0;
 
142
  while (bitstream_slice == 0) {
 
143
    bitstream_ptr++;
 
144
    bitstream_slice = *bitstream_ptr;
 
145
  }
 
146
  base_posn = 8*((intptr_t) bitstream_ptr - (intptr_t) stream);
 
147
  return base_posn + cfzl(bitstream_slice);
 
148
}
 
149
 
 
150
 
 
151
/* Allocator for arrays of aligned SIMD data values.
 
152
   Ideally the new operator could be used to allocate arrays
 
153
   of vector data aligned on the required boundaries 
 
154
   (16-byte for SSE or Altivec).  But since this alignment
 
155
   is not guaranteed except on Mac OS X, the following routine
 
156
   is used. */
 
157
 
 
158
static inline SIMD_type * simd_new(size_t SIMD_packs) {
 
159
#ifdef __APPLE__
 
160
        return new SIMD_type [SIMD_packs];
 
161
#endif
 
162
#ifdef _MSC_VER
 
163
        SIMD_type * v = (SIMD_type*)_aligned_malloc(sizeof(SIMD_type) * SIMD_packs, sizeof(SIMD_type));
 
164
        if (v != 0) return v;
 
165
        else {
 
166
                printf("Failed to allocated new array of %i SIMD packs.\n", SIMD_packs);
 
167
                exit(-1);
 
168
        }
 
169
#endif
 
170
#if !defined(__APPLE__) && !defined(_MSC_VER)
 
171
        SIMD_type * v;
 
172
        int rslt = posix_memalign((void **) &v,
 
173
                                  sizeof(SIMD_type),
 
174
                                  sizeof(SIMD_type) * SIMD_packs);
 
175
        if (rslt == 0) return v;
 
176
        else {
 
177
                printf("Failed to allocated new array of %i SIMD packs.\n", SIMD_packs);
 
178
                exit(-1);
 
179
        }
 
180
#endif
 
181
}
 
182
 
 
183
static inline void simd_delete(SIMD_type * blk_ptr) {
 
184
#ifdef __APPLE__
 
185
  delete [] blk_ptr;
 
186
#endif
 
187
#ifndef __APPLE__
 
188
  free((void *) blk_ptr);
 
189
#endif
 
190
}
 
191
 
 
192
#endif
 
193