Browse Source

SIMD fast path for skipping preprocessing chunks

master
Алексей Олохтонов 2 years ago
parent
commit
c72eecac85
  1. 35
      main.c

35
main.c

@ -8,6 +8,8 @@
#include <time.h> #include <time.h>
#include <fcntl.h> #include <fcntl.h>
#include <immintrin.h>
enum token_kind { enum token_kind {
TOKEN_KEYWORD, TOKEN_KEYWORD,
@ -58,7 +60,7 @@ nondigit(struct str s)
{ {
if (s.size) { if (s.size) {
char c = s.text[0]; char c = s.text[0];
return((c == '_') || ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')); return(('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || (c == '_'));
} }
return(0); return(0);
} }
@ -1035,7 +1037,9 @@ comment(struct str s)
advance(&s, 1); advance(&s, 1);
} }
return(start - s.size); if (s.size) {
return(start - s.size);
}
} }
} }
@ -1087,14 +1091,15 @@ lex(char *text, int size)
} }
static void static void
preprocess(char *data, int size) preprocess_scalar(char *data, int chunk_size, int full_size)
{ {
for (int i = 0; i < size; ++i) { for (int i = 0; i < chunk_size; ++i) {
if (data[i] == '\\') { if (data[i] == '\\') {
for (int j = i + 1; j < size; ++j) { for (int j = i + 1; j < full_size; ++j) {
if (data[j] == '\n') { if (data[j] == '\n') {
data[j] = ' '; data[j] = ' ';
data[i] = ' '; data[i] = ' ';
break;
} else if (data[j] != ' ' && data[j] != '\t') { } else if (data[j] != ' ' && data[j] != '\t') {
break; break;
} }
@ -1103,6 +1108,26 @@ preprocess(char *data, int size)
} }
} }
static void
preprocess(char *data, int size)
{
int chunk_size = 16;
int whole = size & (~(chunk_size - 1));
__m128i mask = _mm_set1_epi8('\\');
for (int i = 0; i < whole; i += chunk_size) {
__m128i chunk = _mm_loadu_si128((__m128i *) (data + i));
__m128i match = _mm_cmpeq_epi8(chunk, mask);
if (!_mm_testz_si128(match, match)) {
preprocess_scalar(data + i, chunk_size, size - i);
}
}
preprocess_scalar(data + whole, size - whole, size - whole);
}
static void static void
run(char *data, int size) run(char *data, int size)
{ {

Loading…
Cancel
Save