Skip to content

Instantly share code, notes, and snippets.

@AngelicosPhosphoros
Created June 27, 2025 22:47
Show Gist options
  • Select an option

  • Save AngelicosPhosphoros/9e10f123f572780e28e320dc81ef9177 to your computer and use it in GitHub Desktop.

Select an option

Save AngelicosPhosphoros/9e10f123f572780e28e320dc81ef9177 to your computer and use it in GitHub Desktop.
strcmp implementation with AVX (works due to paging of virtual memory)
#include <stddef.h>
#include <stdint.h>
#include <immintrin.h>
#include <xmmintrin.h>
static constexpr size_t cPageSize = 4096;
typedef __m256i u256;
typedef __m128i u128;
static inline size_t DistToPageBound(const void* p)
{
const size_t rem = ((size_t)p) & (cPageSize-1);
return cPageSize - rem;
}
__attribute__((target("avx2")))
int MyStrcmp(const char* const arg_sa, const char* const arg_sb)
{
const unsigned char* sa = (const unsigned char*)arg_sa;
const unsigned char* sb = (const unsigned char*)arg_sb;
while (((size_t)sa) & (sizeof(u256)-1))
{
const int a = (int)*sa;
const int b = (int)*sb;
if ((a - b) | (a == 0)) return a - b;
++sa;
++sb;
}
while(true)
{
// No need to check sa because it is vector aligned
while (DistToPageBound(sb) >= sizeof(u256))
{
// We can load next bytes even if they are outside
// of string range because we are inside memory page.
const u256 a = _mm256_load_si256((u256*)sa);
const u256 b = _mm256_loadu_si256((u256*)sb);
// Compare every byte then negate result.
const u256 isne = _mm256_xor_si256(
_mm256_cmpeq_epi8(a, b),
_mm256_set1_epi8(0xFF)
);
// Has zero a
const u256 hza = _mm256_cmpeq_epi8(a, _mm256_setzero_si256());
const u256 hzb = _mm256_cmpeq_epi8(b, _mm256_setzero_si256());
const u256 should_break = _mm256_or_si256(
isne, _mm256_or_si256(hza, hzb)
);
if (!_mm256_testz_si256(should_break, should_break)) break;
sa += sizeof(u256);
sb += sizeof(u256);
}
for (unsigned i = 0; i < sizeof(u256); ++i)
{
const int a = (int)*sa;
const int b = (int)*sb;
if ((a - b) | (a == 0)) return a - b;
++sa;
++sb;
}
}
}
int StrCmpNaive(const char* const arg_sa, const char* const arg_sb)
{
const unsigned char* sa = (const unsigned char*)arg_sa;
const unsigned char* sb = (const unsigned char*)arg_sb;
while (true)
{
const int a = (int)*sa;
const int b = (int)*sb;
if ((a - b) | (a == 0)) return a - b;
++sa;
++sb;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment