tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestSIMD.cpp (28115B)


      1 /* -*- Mode: C++; tab-width: 9; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/Assertions.h"
      8 #include "mozilla/SIMD.h"
      9 
     10 using mozilla::SIMD;
     11 
     12 void TestTinyString() {
     13  const char* test = "012\n";
     14 
     15  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '0', 3) == test + 0x0);
     16  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '0', 3) == test + 0x0);
     17  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '1', 3) == test + 0x1);
     18  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '1', 3) == test + 0x1);
     19  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '2', 3) == test + 0x2);
     20  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '2', 3) == test + 0x2);
     21  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '\n', 3) == nullptr);
     22  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '\n', 3) == nullptr);
     23 }
     24 
     25 void TestShortString() {
     26  const char* test = "0123456789\n";
     27 
     28  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '0', 10) == test + 0x0);
     29  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '0', 10) == test + 0x0);
     30  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '1', 10) == test + 0x1);
     31  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '1', 10) == test + 0x1);
     32  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '2', 10) == test + 0x2);
     33  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '2', 10) == test + 0x2);
     34  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '3', 10) == test + 0x3);
     35  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '3', 10) == test + 0x3);
     36  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '4', 10) == test + 0x4);
     37  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '4', 10) == test + 0x4);
     38  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '5', 10) == test + 0x5);
     39  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '5', 10) == test + 0x5);
     40  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '6', 10) == test + 0x6);
     41  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '6', 10) == test + 0x6);
     42  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '7', 10) == test + 0x7);
     43  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '7', 10) == test + 0x7);
     44  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '8', 10) == test + 0x8);
     45  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '8', 10) == test + 0x8);
     46  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '9', 10) == test + 0x9);
     47  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '9', 10) == test + 0x9);
     48  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '\n', 10) == nullptr);
     49  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '\n', 10) == nullptr);
     50 }
     51 
     52 void TestMediumString() {
     53  const char* test = "0123456789abcdef\n";
     54 
     55  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '0', 16) == test + 0x0);
     56  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '0', 16) == test + 0x0);
     57  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '1', 16) == test + 0x1);
     58  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '1', 16) == test + 0x1);
     59  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '2', 16) == test + 0x2);
     60  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '2', 16) == test + 0x2);
     61  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '3', 16) == test + 0x3);
     62  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '3', 16) == test + 0x3);
     63  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '4', 16) == test + 0x4);
     64  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '4', 16) == test + 0x4);
     65  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '5', 16) == test + 0x5);
     66  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '5', 16) == test + 0x5);
     67  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '6', 16) == test + 0x6);
     68  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '6', 16) == test + 0x6);
     69  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '7', 16) == test + 0x7);
     70  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '7', 16) == test + 0x7);
     71  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '8', 16) == test + 0x8);
     72  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '8', 16) == test + 0x8);
     73  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '9', 16) == test + 0x9);
     74  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '9', 16) == test + 0x9);
     75  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, 'a', 16) == test + 0xa);
     76  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, 'a', 16) == test + 0xa);
     77  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, 'b', 16) == test + 0xb);
     78  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, 'b', 16) == test + 0xb);
     79  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, 'c', 16) == test + 0xc);
     80  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, 'c', 16) == test + 0xc);
     81  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, 'd', 16) == test + 0xd);
     82  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, 'd', 16) == test + 0xd);
     83  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, 'e', 16) == test + 0xe);
     84  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, 'e', 16) == test + 0xe);
     85  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, 'f', 16) == test + 0xf);
     86  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, 'f', 16) == test + 0xf);
     87  MOZ_RELEASE_ASSERT(SIMD::memchr8(test, '\n', 16) == nullptr);
     88  MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test, '\n', 16) == nullptr);
     89 }
     90 
     91 void TestLongString() {
     92  // NOTE: here we make sure we go all the way up to 256 to ensure we're
     93  // handling negative-valued chars appropriately. We don't need to bother
     94  // testing this side of things with char16_t's because they are very
     95  // sensibly guaranteed to be unsigned.
     96  const size_t count = 256;
     97  char test[count];
     98  for (size_t i = 0; i < count; ++i) {
     99    test[i] = static_cast<char>(i);
    100  }
    101 
    102  for (size_t i = 0; i < count - 1; ++i) {
    103    MOZ_RELEASE_ASSERT(SIMD::memchr8(test, static_cast<char>(i), count - 1) ==
    104                       test + i);
    105    MOZ_RELEASE_ASSERT(
    106        SIMD::memchr8SSE2(test, static_cast<char>(i), count - 1) == test + i);
    107  }
    108  MOZ_RELEASE_ASSERT(
    109      SIMD::memchr8(test, static_cast<char>(count - 1), count - 1) == nullptr);
    110 }
    111 
    112 void TestGauntlet() {
    113  const size_t count = 256;
    114  char test[count];
    115  for (size_t i = 0; i < count; ++i) {
    116    test[i] = static_cast<char>(i);
    117  }
    118 
    119  for (size_t i = 0; i < count - 1; ++i) {
    120    for (size_t j = 0; j < count - 1; ++j) {
    121      for (size_t k = 0; k < count - 1; ++k) {
    122        if (i >= k) {
    123          const char* expected = nullptr;
    124          if (j >= k && j < i) {
    125            expected = test + j;
    126          }
    127          MOZ_RELEASE_ASSERT(
    128              SIMD::memchr8(test + k, static_cast<char>(j), i - k) == expected);
    129          MOZ_RELEASE_ASSERT(SIMD::memchr8SSE2(test + k, static_cast<char>(j),
    130                                               i - k) == expected);
    131        }
    132      }
    133    }
    134  }
    135 }
    136 
    137 void TestTinyString16() {
    138  const char16_t* test = u"012\n";
    139 
    140  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'0', 3) == test + 0x0);
    141  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'0', 3) == test + 0x0);
    142  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'1', 3) == test + 0x1);
    143  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'1', 3) == test + 0x1);
    144  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'2', 3) == test + 0x2);
    145  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'2', 3) == test + 0x2);
    146  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'\n', 3) == nullptr);
    147  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'\n', 3) == nullptr);
    148 }
    149 
    150 void TestShortString16() {
    151  const char16_t* test = u"0123456789\n";
    152 
    153  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'0', 10) == test + 0x0);
    154  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'0', 10) == test + 0x0);
    155  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'1', 10) == test + 0x1);
    156  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'1', 10) == test + 0x1);
    157  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'2', 10) == test + 0x2);
    158  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'2', 10) == test + 0x2);
    159  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'3', 10) == test + 0x3);
    160  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'3', 10) == test + 0x3);
    161  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'4', 10) == test + 0x4);
    162  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'4', 10) == test + 0x4);
    163  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'5', 10) == test + 0x5);
    164  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'5', 10) == test + 0x5);
    165  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'6', 10) == test + 0x6);
    166  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'6', 10) == test + 0x6);
    167  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'7', 10) == test + 0x7);
    168  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'7', 10) == test + 0x7);
    169  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'8', 10) == test + 0x8);
    170  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'8', 10) == test + 0x8);
    171  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'9', 10) == test + 0x9);
    172  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'9', 10) == test + 0x9);
    173  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'\n', 10) == nullptr);
    174  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'\n', 10) == nullptr);
    175 }
    176 
    177 void TestMediumString16() {
    178  const char16_t* test = u"0123456789abcdef\n";
    179 
    180  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'0', 16) == test + 0x0);
    181  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'0', 16) == test + 0x0);
    182  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'1', 16) == test + 0x1);
    183  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'1', 16) == test + 0x1);
    184  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'2', 16) == test + 0x2);
    185  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'2', 16) == test + 0x2);
    186  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'3', 16) == test + 0x3);
    187  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'3', 16) == test + 0x3);
    188  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'4', 16) == test + 0x4);
    189  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'4', 16) == test + 0x4);
    190  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'5', 16) == test + 0x5);
    191  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'5', 16) == test + 0x5);
    192  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'6', 16) == test + 0x6);
    193  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'6', 16) == test + 0x6);
    194  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'7', 16) == test + 0x7);
    195  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'7', 16) == test + 0x7);
    196  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'8', 16) == test + 0x8);
    197  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'8', 16) == test + 0x8);
    198  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'9', 16) == test + 0x9);
    199  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'9', 16) == test + 0x9);
    200  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'a', 16) == test + 0xa);
    201  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'a', 16) == test + 0xa);
    202  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'b', 16) == test + 0xb);
    203  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'b', 16) == test + 0xb);
    204  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'c', 16) == test + 0xc);
    205  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'c', 16) == test + 0xc);
    206  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'd', 16) == test + 0xd);
    207  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'd', 16) == test + 0xd);
    208  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'e', 16) == test + 0xe);
    209  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'e', 16) == test + 0xe);
    210  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'f', 16) == test + 0xf);
    211  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'f', 16) == test + 0xf);
    212  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, u'\n', 16) == nullptr);
    213  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, u'\n', 16) == nullptr);
    214 }
    215 
    216 void TestLongString16() {
    217  const size_t count = 256;
    218  char16_t test[count];
    219  for (size_t i = 0; i < count; ++i) {
    220    test[i] = i;
    221  }
    222 
    223  for (size_t i = 0; i < count - 1; ++i) {
    224    MOZ_RELEASE_ASSERT(
    225        SIMD::memchr16(test, static_cast<char16_t>(i), count - 1) == test + i);
    226    MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, static_cast<char16_t>(i),
    227                                          count - 1) == test + i);
    228  }
    229  MOZ_RELEASE_ASSERT(SIMD::memchr16(test, count - 1, count - 1) == nullptr);
    230  MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test, count - 1, count - 1) == nullptr);
    231 }
    232 
    233 void TestGauntlet16() {
    234  const size_t count = 257;
    235  char16_t test[count];
    236  for (size_t i = 0; i < count; ++i) {
    237    test[i] = i;
    238  }
    239 
    240  for (size_t i = 0; i < count - 1; ++i) {
    241    for (size_t j = 0; j < count - 1; ++j) {
    242      for (size_t k = 0; k < count - 1; ++k) {
    243        if (i >= k) {
    244          const char16_t* expected = nullptr;
    245          if (j >= k && j < i) {
    246            expected = test + j;
    247          }
    248          MOZ_RELEASE_ASSERT(SIMD::memchr16(test + k, static_cast<char16_t>(j),
    249                                            i - k) == expected);
    250          MOZ_RELEASE_ASSERT(SIMD::memchr16SSE2(test + k,
    251                                                static_cast<char16_t>(j),
    252                                                i - k) == expected);
    253        }
    254      }
    255    }
    256  }
    257 }
    258 
    259 void TestTinyString64() {
    260  const uint64_t test[4] = {0, 1, 2, 3};
    261 
    262  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 0, 3) == test + 0x0);
    263  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 1, 3) == test + 0x1);
    264  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 2, 3) == test + 0x2);
    265  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 3, 3) == nullptr);
    266 }
    267 
    268 void TestShortString64() {
    269  const uint64_t test[16] = {0, 1, 2,  3,  4,  5,  6,  7,
    270                             8, 9, 10, 11, 12, 13, 14, 15};
    271 
    272  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 0, 15) == test + 0);
    273  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 1, 15) == test + 1);
    274  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 2, 15) == test + 2);
    275  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 3, 15) == test + 3);
    276  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 4, 15) == test + 4);
    277  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 5, 15) == test + 5);
    278  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 6, 15) == test + 6);
    279  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 7, 15) == test + 7);
    280  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 8, 15) == test + 8);
    281  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 9, 15) == test + 9);
    282  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 9, 15) == test + 9);
    283  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 10, 15) == test + 10);
    284  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 11, 15) == test + 11);
    285  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 12, 15) == test + 12);
    286  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 13, 15) == test + 13);
    287  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 14, 15) == test + 14);
    288  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 15, 15) == nullptr);
    289 }
    290 
    291 void TestMediumString64() {
    292  const uint64_t test[32] = {0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10,
    293                             11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
    294                             22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
    295 
    296  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 0, 31) == test + 0);
    297  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 1, 31) == test + 1);
    298  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 2, 31) == test + 2);
    299  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 3, 31) == test + 3);
    300  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 4, 31) == test + 4);
    301  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 5, 31) == test + 5);
    302  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 6, 31) == test + 6);
    303  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 7, 31) == test + 7);
    304  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 8, 31) == test + 8);
    305  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 9, 31) == test + 9);
    306  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 9, 31) == test + 9);
    307  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 10, 31) == test + 10);
    308  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 11, 31) == test + 11);
    309  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 12, 31) == test + 12);
    310  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 13, 31) == test + 13);
    311  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 14, 31) == test + 14);
    312  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 15, 31) == test + 15);
    313  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 16, 31) == test + 16);
    314  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 17, 31) == test + 17);
    315  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 18, 31) == test + 18);
    316  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 19, 31) == test + 19);
    317  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 20, 31) == test + 20);
    318  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 21, 31) == test + 21);
    319  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 22, 31) == test + 22);
    320  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 23, 31) == test + 23);
    321  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 24, 31) == test + 24);
    322  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 25, 31) == test + 25);
    323  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 26, 31) == test + 26);
    324  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 27, 31) == test + 27);
    325  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 28, 31) == test + 28);
    326  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 29, 31) == test + 29);
    327  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 30, 31) == test + 30);
    328  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, 31, 31) == nullptr);
    329 }
    330 
    331 void TestLongString64() {
    332  const size_t count = 256;
    333  uint64_t test[count];
    334  for (size_t i = 0; i < count; ++i) {
    335    test[i] = i;
    336  }
    337 
    338  for (uint64_t i = 0; i < count - 1; ++i) {
    339    MOZ_RELEASE_ASSERT(SIMD::memchr64(test, i, count - 1) == test + i);
    340  }
    341  MOZ_RELEASE_ASSERT(SIMD::memchr64(test, count - 1, count - 1) == nullptr);
    342 }
    343 
    344 void TestGauntlet64() {
    345  const size_t count = 257;
    346  uint64_t test[count];
    347  for (size_t i = 0; i < count; ++i) {
    348    test[i] = i;
    349  }
    350 
    351  for (uint64_t i = 0; i < count - 1; ++i) {
    352    for (uint64_t j = 0; j < count - 1; ++j) {
    353      for (uint64_t k = 0; k < count - 1; ++k) {
    354        if (i >= k) {
    355          const uint64_t* expected = nullptr;
    356          if (j >= k && j < i) {
    357            expected = test + j;
    358          }
    359          MOZ_RELEASE_ASSERT(SIMD::memchr64(test + k, j, i - k) == expected);
    360        }
    361      }
    362    }
    363  }
    364 }
    365 
    366 void TestTinyString2x8() {
    367  const char* test = "012\n";
    368 
    369  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '0', '1', 3) == test + 0x0);
    370  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '1', '2', 3) == test + 0x1);
    371  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '2', '\n', 3) == nullptr);
    372  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '0', '2', 3) == nullptr);
    373  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '1', '\n', 3) == nullptr);
    374 }
    375 
    376 void TestShortString2x8() {
    377  const char* test = "0123456789\n";
    378 
    379  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '0', '1', 10) == test + 0x0);
    380  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '1', '2', 10) == test + 0x1);
    381  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '2', '3', 10) == test + 0x2);
    382  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '3', '4', 10) == test + 0x3);
    383  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '4', '5', 10) == test + 0x4);
    384  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '5', '6', 10) == test + 0x5);
    385  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '6', '7', 10) == test + 0x6);
    386  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '7', '8', 10) == test + 0x7);
    387  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '8', '9', 10) == test + 0x8);
    388  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '9', '\n', 10) == nullptr);
    389 }
    390 
    391 void TestMediumString2x8() {
    392  const char* test = "0123456789abcdef\n";
    393 
    394  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '0', '1', 16) == test + 0x0);
    395  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '1', '2', 16) == test + 0x1);
    396  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '2', '3', 16) == test + 0x2);
    397  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '3', '4', 16) == test + 0x3);
    398  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '4', '5', 16) == test + 0x4);
    399  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '5', '6', 16) == test + 0x5);
    400  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '6', '7', 16) == test + 0x6);
    401  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '7', '8', 16) == test + 0x7);
    402  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '8', '9', 16) == test + 0x8);
    403  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, '9', 'a', 16) == test + 0x9);
    404  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, 'a', 'b', 16) == test + 0xa);
    405  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, 'b', 'c', 16) == test + 0xb);
    406  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, 'c', 'd', 16) == test + 0xc);
    407  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, 'd', 'e', 16) == test + 0xd);
    408  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, 'e', 'f', 16) == test + 0xe);
    409  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, 'f', '\n', 16) == nullptr);
    410 }
    411 
    412 void TestLongString2x8() {
    413  const size_t count = 256;
    414  char test[count];
    415  for (size_t i = 0; i < count; ++i) {
    416    test[i] = static_cast<char>(i);
    417  }
    418 
    419  for (size_t i = 0; i < count - 2; ++i) {
    420    MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, static_cast<char>(i),
    421                                       static_cast<char>(i + 1),
    422                                       count - 1) == test + i);
    423  }
    424  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test, static_cast<char>(count - 2),
    425                                     static_cast<char>(count - 1),
    426                                     count - 1) == nullptr);
    427 }
    428 
    429 void TestTinyString2x16() {
    430  const char16_t* test = u"012\n";
    431 
    432  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'0', u'1', 3) == test + 0x0);
    433  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'1', u'2', 3) == test + 0x1);
    434  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'2', u'\n', 3) == nullptr);
    435  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'0', u'2', 3) == nullptr);
    436  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'1', u'\n', 3) == nullptr);
    437 }
    438 
    439 void TestShortString2x16() {
    440  const char16_t* test = u"0123456789\n";
    441 
    442  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'0', u'1', 10) == test + 0x0);
    443  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'1', u'2', 10) == test + 0x1);
    444  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'2', u'3', 10) == test + 0x2);
    445  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'3', u'4', 10) == test + 0x3);
    446  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'4', u'5', 10) == test + 0x4);
    447  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'5', u'6', 10) == test + 0x5);
    448  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'6', u'7', 10) == test + 0x6);
    449  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'7', u'8', 10) == test + 0x7);
    450  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'8', u'9', 10) == test + 0x8);
    451  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'9', u'\n', 10) == nullptr);
    452  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'0', u'2', 10) == nullptr);
    453 }
    454 
    455 void TestMediumString2x16() {
    456  const char16_t* test = u"0123456789abcdef\n";
    457 
    458  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'0', u'1', 16) == test + 0x0);
    459  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'1', u'2', 16) == test + 0x1);
    460  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'2', u'3', 16) == test + 0x2);
    461  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'3', u'4', 16) == test + 0x3);
    462  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'4', u'5', 16) == test + 0x4);
    463  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'5', u'6', 16) == test + 0x5);
    464  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'6', u'7', 16) == test + 0x6);
    465  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'7', u'8', 16) == test + 0x7);
    466  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'8', u'9', 16) == test + 0x8);
    467  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'9', u'a', 16) == test + 0x9);
    468  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'a', u'b', 16) == test + 0xa);
    469  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'b', u'c', 16) == test + 0xb);
    470  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'c', u'd', 16) == test + 0xc);
    471  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'd', u'e', 16) == test + 0xd);
    472  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'e', u'f', 16) == test + 0xe);
    473  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'f', u'\n', 16) == nullptr);
    474  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, u'0', u'2', 10) == nullptr);
    475 }
    476 
    477 void TestLongString2x16() {
    478  const size_t count = 257;
    479  char16_t test[count];
    480  for (size_t i = 0; i < count; ++i) {
    481    test[i] = static_cast<char16_t>(i);
    482  }
    483 
    484  for (size_t i = 0; i < count - 2; ++i) {
    485    MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, static_cast<char16_t>(i),
    486                                        static_cast<char16_t>(i + 1),
    487                                        count - 1) == test + i);
    488  }
    489  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test, static_cast<char16_t>(count - 2),
    490                                      static_cast<char16_t>(count - 1),
    491                                      count - 1) == nullptr);
    492 }
    493 
    494 void TestGauntlet2x8() {
    495  const size_t count = 256;
    496  char test[count * 2];
    497  // load in the evens
    498  for (size_t i = 0; i < count / 2; ++i) {
    499    test[i] = static_cast<char>(2 * i);
    500  }
    501  // load in the odds
    502  for (size_t i = 0; i < count / 2; ++i) {
    503    test[count / 2 + i] = static_cast<char>(2 * i + 1);
    504  }
    505  // load in evens and odds sequentially
    506  for (size_t i = 0; i < count; ++i) {
    507    test[count + i] = static_cast<char>(i);
    508  }
    509 
    510  for (size_t i = 0; i < count - 1; ++i) {
    511    for (size_t j = 0; j < count - 2; ++j) {
    512      for (size_t k = 0; k < count - 1; ++k) {
    513        if (i > k + 1) {
    514          const char* expected1 = nullptr;
    515          const char* expected2 = nullptr;
    516          if (i > j + 1) {
    517            expected1 = test + j + count;  // Add count to skip over odds/evens
    518            if (j >= k) {
    519              expected2 = test + j + count;
    520            }
    521          }
    522          char a = static_cast<char>(j);
    523          char b = static_cast<char>(j + 1);
    524          // Make sure it doesn't pick up any in the alternating odd/even
    525          MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test + k, a, b, i - k + count) ==
    526                             expected1);
    527          // Make sure we cover smaller inputs
    528          MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test + k + count, a, b, i - k) ==
    529                             expected2);
    530        }
    531      }
    532    }
    533  }
    534 }
    535 
    536 void TestGauntlet2x16() {
    537  const size_t count = 1024;
    538  char16_t test[count * 2];
    539  // load in the evens
    540  for (size_t i = 0; i < count / 2; ++i) {
    541    test[i] = static_cast<char16_t>(2 * i);
    542  }
    543  // load in the odds
    544  for (size_t i = 0; i < count / 2; ++i) {
    545    test[count / 2 + i] = static_cast<char16_t>(2 * i + 1);
    546  }
    547  // load in evens and odds sequentially
    548  for (size_t i = 0; i < count; ++i) {
    549    test[count + i] = static_cast<char16_t>(i);
    550  }
    551 
    552  for (size_t i = 0; i < count - 1; ++i) {
    553    for (size_t j = 0; j < count - 2; ++j) {
    554      for (size_t k = 0; k < count - 1; ++k) {
    555        if (i > k + 1) {
    556          const char16_t* expected1 = nullptr;
    557          const char16_t* expected2 = nullptr;
    558          if (i > j + 1) {
    559            expected1 = test + j + count;  // Add count to skip over odds/evens
    560            if (j >= k) {
    561              expected2 = test + j + count;
    562            }
    563          }
    564          char16_t a = static_cast<char16_t>(j);
    565          char16_t b = static_cast<char16_t>(j + 1);
    566          // Make sure it doesn't pick up any in the alternating odd/even
    567          MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test + k, a, b, i - k + count) ==
    568                             expected1);
    569          // Make sure we cover smaller inputs
    570          MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test + k + count, a, b, i - k) ==
    571                             expected2);
    572        }
    573      }
    574    }
    575  }
    576 }
    577 
    578 void TestSpecialCases() {
    579  // The following 4 asserts test the case where we do two overlapping checks,
    580  // where the first one ends with our first search character, and the second
    581  // one begins with our search character. Since they are overlapping, we want
    582  // to ensure that the search function doesn't carry the match from the
    583  // first check over to the second check.
    584  const char* test1 = "x123456789abcdey";
    585  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test1, 'y', 'x', 16) == nullptr);
    586  const char* test2 = "1000000000000000200000000000000030b000000000000a40";
    587  MOZ_RELEASE_ASSERT(SIMD::memchr2x8(test2, 'a', 'b', 50) == nullptr);
    588  const char16_t* test1wide = u"x123456y";
    589  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test1wide, 'y', 'x', 8) == nullptr);
    590  const char16_t* test2wide = u"100000002000000030b0000a40";
    591  MOZ_RELEASE_ASSERT(SIMD::memchr2x16(test2wide, 'a', 'b', 26) == nullptr);
    592 }
    593 
    594 int main(void) {
    595  TestTinyString();
    596  TestShortString();
    597  TestMediumString();
    598  TestLongString();
    599  TestGauntlet();
    600 
    601  TestTinyString16();
    602  TestShortString16();
    603  TestMediumString16();
    604  TestLongString16();
    605  TestGauntlet16();
    606 
    607  TestTinyString64();
    608  TestShortString64();
    609  TestMediumString64();
    610  TestLongString64();
    611  TestGauntlet64();
    612 
    613  TestTinyString2x8();
    614  TestShortString2x8();
    615  TestMediumString2x8();
    616  TestLongString2x8();
    617 
    618  TestTinyString2x16();
    619  TestShortString2x16();
    620  TestMediumString2x16();
    621  TestLongString2x16();
    622 
    623  TestSpecialCases();
    624 
    625  // These are too slow to run all the time, but they should be run when making
    626  // meaningful changes just to be sure.
    627  // TestGauntlet2x8();
    628  // TestGauntlet2x16();
    629 
    630  return 0;
    631 }