Skip to content

Instantly share code, notes, and snippets.

@pervognsen
Last active October 23, 2022 10:58
Show Gist options
  • Save pervognsen/12d358c8fdd531d21fbccdca251fc2cd to your computer and use it in GitHub Desktop.
Save pervognsen/12d358c8fdd531d21fbccdca251fc2cd to your computer and use it in GitHub Desktop.
void next(void) {
// Compilers will generate something like CMP r1, ' '; LEA r2, [r3+1]; CMOVEQ r3, r2, which has 2 cycle latency.
input += *input == ' '; // The most common intertoken spacing is 0 or 1 (e.g. look at this file), so use a branchless skip.
start:
switch (*input) {
case '\r':
input++;
if (*input != '\n') goto start;
// Default-predicted fallthrough case for \r\n on Windows.
case '\n': {
input++;
line++;
int len;
// Do a branchless SIMD skip of up to 16 indentation spaces after a newline.
_m128i chars = _mm_loadu_si128((_m_m128i *)input);
BitScanForward(&len, ~_mm_movemask_epi8(_mm_cmpeq_epi8(chars, _mm_set1_epi8(' '))));
input += len;
goto start;
}
case ' ':
case '\t':
case '\v':
// This path should be rare: more than 1 intertoken space, more than 16 spaces after newline, or rare whitespace character.
do input++; while (isspace(*input)); // Probably not libc isspace but you get the idea: just eat the length mispredict.
goto start;
// ...
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment