My current favorites:

void popFront(ref char[] s) @trusted pure nothrow {
  immutable byte c = s[0];
  if (c >= -2) {
    s = s.ptr[1 .. s.length];
  } else {
    import core.bitop;
    size_t i = 7u - bsr(~c);
    import std.algorithm;
    s = s.ptr[min(i, s.length) .. s.length];
  }
}

I also experimented with explicit speculation:

void popFront(ref char[] s) @trusted pure nothrow {
  immutable byte c = s[0];
  s = s.ptr[1 .. s.length];
  if (c < -2) {
    import core.bitop;
    size_t i = 6u - bsr(~c);
    import std.algorithm;
    s = s.ptr[min(i, s.length) .. s.length];
  }
}


LDC and GDC both compile these to 23 instructions.
DMD does worse than with my other code.

You can influence GDC's block layout with __builtin_expect.

I notice that many other snippets posted use uint instead of size_t in the multi-byte branch. This generates extra instructions for me.

Reply via email to