
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Neil Henning</title>
    <link>https://www.neilhenning.dev/</link>
    <description>Recent content on Neil Henning</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 05 Jun 2026 00:00:00 +0000</lastBuildDate>
    
      <atom:link href="https://www.neilhenning.dev/index.xml" rel="self" type="application/rss+xml" />
    
    
    <item>
      <title>I&#39;m Allowing AI Use in my Libraries</title>
      <link>https://www.neilhenning.dev/posts/using-ai-in-my-libraries/</link>
      <pubDate>Fri, 05 Jun 2026 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/using-ai-in-my-libraries/</guid>
      <description><![CDATA[<p>I&rsquo;ve taken the decision to allow AI use for PRs to my libraries.</p>
<p>I <em>personally</em>
believe these tools can be a net add (with lots of straight jackets and caveats),
but I also think we&rsquo;ve reached a point where I can&rsquo;t really be sure whether the
incoming PR requests are from people using AI tooling to help them, or just free
roaming OpenClaw instances that are masking their AI nature very well, and so it
feels like I&rsquo;d be firmly swimming against the current as a very part-time open
source contributor to try and police this.</p>
<p>To be an open and clear about my use of AI I&rsquo;ve cut <code>pre-ai</code> releases for all
my libraries so you can get access to the code from the point before I
personally started to use AI tooling (I 100% <strong>cannot</strong> confirm whether any of
the contributions from others to the libraries used AI or not, but I can say
with certainty that I did not use AI before these points).</p>
<p>The <code>pre-ai</code> tags are:</p>
<ul>
<li><a href="https://github.com/sheredom/utest.h/releases/tag/pre-ai">utest.h</a></li>
<li><a href="https://github.com/sheredom/ubench.h/releases/tag/pre-ai">ubench.h</a></li>
<li><a href="https://github.com/sheredom/utf8.h/releases/tag/pre-ai">utf8.h</a></li>
<li><a href="https://github.com/sheredom/json.h/releases/tag/pre-ai">json.h</a></li>
<li><a href="https://github.com/sheredom/subprocess.h/releases/tag/pre-ai">subprocess.h</a></li>
<li><a href="https://github.com/sheredom/hashmap.h/releases/tag/pre-ai">hashmap.h</a></li>
</ul>
<p>I&rsquo;ve also added a disclaimer to the README.md of each of the repositories that
states:</p>
<blockquote>
<p>AI Usage</p>
<p>AI tool use is explicitly permitted in commits to this repository. There is a
tagged release pre-ai that denotes the last release where AI tooling was not used.</p>
</blockquote>
<p>And each of the PRs authored by my <a href="https://pi.dev/">pi.dev</a> agent has the footer:</p>
<blockquote>
<p>🧙 Conjured by AI via pi.dev using gpt-5.5</p>
</blockquote>
<p>As does each commit the AI authored too.</p>
]]></description>
    </item>
    
    <item>
      <title>Five Stages of Grief With the Rise of AI</title>
      <link>https://www.neilhenning.dev/posts/five-stages-grief/</link>
      <pubDate>Wed, 18 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/five-stages-grief/</guid>
      <description><![CDATA[<p>I tried copilot in VS Code sometime in 2025 and was thoroughly disappointed with
its ability. It felt like a really bad auto-complete at best, making plenty of
mistakes and generally being utterly irritating to actually use with its need to
constantly pop in as I was typing with long form coding suggestions that were
often wrong. I was already predisposed to being negative about AI due to the usual
mix of reasons and wrote off all the AI coding tools as useless. All the
AI-pilled people shouting about how good the AIs were were clearly just <em>novice</em>
programmers who didn&rsquo;t understand enough about programming to know they were
generating rubbish.</p>
<p>Over December I noticed an uptick in people that I highly respect using Claude
Code 4.5 in particular, and this got me curious. I <em>knew</em> the AI was rubbish.
These are people I have a huge respect for (I worked with a fair few of them and
knew first hand how good at programming they were). <em>What the heck were they
seeing in the AI that I wasn&rsquo;t?</em>. So I got the cheapest Claude Code plan and
started messing around.</p>
<p>I wanted to evaluate it against something that wasn&rsquo;t on the internet already
that it could find or have seen, and something that I wrote and knew intimately.
That way I could judge its ability and compare what it produced against what I
had. I have a little Rust project that scrapes a bunch of financial data on the
various stocks I&rsquo;m invested in, and gives me fundamentals so that I know at a
glance that the companies are still in as good as a shape as I expected.</p>
<p>I explained to Claude Code what I wanted at a high level (write it in Rust, get
the data from here, calculate these metrics). I was pleasantly surprised when it
came back to me asking me follow-up questions to check it understood what I
wanted (remember - I hadn&rsquo;t used Claude Code before nor seen it in use, so I was
discovering how it worked as I went!). It went off and burned a bunch of tokens
from my plan and then it was done. I ran the program, compared its output to my
own. It matched. <em>Huh</em> I thought. I looked at the code. Well commented, laid out
nicely, it had even optimized a few of the async http request queries in a way I
hadn&rsquo;t thought to do. <em>Huh</em>.</p>
<p>Then Claude Code 4.6 came out with the new models. And <em>oh boy</em> they are better.
I pointed it at my previous blog post
<a href="https://www.neilhenning.dev/posts/musttail_you_about_a_tokenizer/">I [[musttail]] You About a Tokenizer</a> and asked it to flesh that out into a fully
fledged programming language with a few tips here and there of how I wanted it
to look. And it just smashed through it, writing lots of unit tests on its way.
<em>Huh</em>. I upgraded to the Max plan.</p>
<p>I&rsquo;ve since recommended to many people, who were of varying degrees AI-sceptical,
that they try Claude Code. The conversation has roughly went like this:</p>
<ul>
<li>Me: <em>&ldquo;You should try Claude Code.&rdquo;</em></li>
<li>Them: <em>&ldquo;Nah AI is rubbish.&rdquo;</em></li>
<li>Me: <em>&ldquo;No seriously give it a go and tell me what you think.&rdquo;</em></li>
<li>Them: <strong>tries Claude Code</strong> <em>&ldquo;Ok its pretty good.&rdquo;</em></li>
<li>Me: <em>&ldquo;Isn&rsquo;t it?&rdquo;</em></li>
<li>Them: <em>&ldquo;I&rsquo;ve just upgraded to the Max plan.&rdquo;</em></li>
</ul>
<p>This has happened multiple times now, with a similar flow.</p>
<p>My best description of what is happening to our industry now is that we&rsquo;re
collectively going through the
<a href="https://en.wikipedia.org/wiki/Five_stages_of_grief">Five Stages of Grief</a>
for the craft we all love:</p>
<ul>
<li><strong>Denial</strong>: I was telling everyone how crap the AI tooling was.</li>
<li><strong>Anger</strong>: I was getting angry at all the AI lovers telling me how good the models were.</li>
<li><strong>Bargaining</strong>: I was realising the AIs could do something but not <em>my</em> job.</li>
<li><strong>Depression</strong>: I got really down that the thing I&rsquo;ve made a huge part of my identity, coding, was being affected.</li>
<li><strong>Acceptance</strong>: I&rsquo;m now realising that I can use these tools to magnify what I want my code to do by using all the knowledge and taste I&rsquo;ve accumulated to craft more software of the ilk I desire.</li>
</ul>
<p>That&rsquo;s <em>my journey</em> with this, but I&rsquo;ve seen many many people across the
industry who seem to me to be in the various stages. It sucks to be a craft
furniture maker when IKEA just showed up in town.</p>
<p>Now don&rsquo;t get me wrong - there are problems with the models. They are not
perfect. They are like a super eager beaver intern and need a good set of rules
to follow to make software you like. But once you start using them you realise
how you can craft these rules so that the models produce quality code that meets
your quality bar.</p>
<p>But it&rsquo;s starting to feel <em>essential</em> to my future employment, perhaps <em>all</em>
future employment in our industry, that I learn how to do this scaffolding.</p>
]]></description>
    </item>
    
    <item>
      <title>I [[musttail]] You About a Tokenizer</title>
      <link>https://www.neilhenning.dev/posts/musttail_you_about_a_tokenizer/</link>
      <pubDate>Thu, 13 Feb 2025 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/musttail_you_about_a_tokenizer/</guid>
      <description><![CDATA[<p>One thing I&rsquo;ve never really messed with before is the <code>[[clang::musttail]]</code>
compiler attribute. Tail calls are when you exit a function by calling another
function as the final thing within the function. For example:</p>
<pre tabindex="0"><code>int foo(float x);

int bar(float x) {
  x += 42.0f;
  return foo(x);
}
</code></pre><p>In the above example, <code>foo</code> is a tail call within the function <code>bar</code>. Compilers
can take advantage of this by doing something called tail-call optimization,
which allows the compiler to not push a new stack frame, and also to change the
call into a jump. This means you can have infinitely deep callstacks that won&rsquo;t
cause stack overflows for instance.</p>
<p>Clang has a cool compiler attribute <code>[[clang::musttail]]</code> that you can place on
a return statement to <strong>force</strong> a tail call. EG. it becomes a compiler error if
the compiler could not perform a tail call. For example functions with
different arguments would not work.</p>
<pre tabindex="0"><code>int foo(float x);

int bar(float x) {
  x += 42.0f;
  [[clang::musttail]] return foo(x);
}
</code></pre><p>Another fun little thing I&rsquo;ve been toying with is using lookup tables - in
particular jump tables. Jump tables are arrays of function pointers such that
the index into the array will result in you jumping to some other function to
execute.</p>
<p>So an idea came to me - could I use tail calls in combination with jump tables
to create a tokenizer for a toy language? A tokenizer where there were <strong>zero</strong>
branches?</p>
<p>Turns out - yes you can! I&rsquo;ve put up a <a href="https://gist.github.com/sheredom/cc44e5f1f9c1c4d807d49819b01685f7">gist of it here</a>.</p>
<p>An example program in the toy language would be:</p>
<pre tabindex="0"><code># Some cool comment!
some_func := (a : i32, b : f32) : f64 {
  x := a + 42;
  x += 13;
  r := 0;
  for i in range(0, x) {
    if b &gt; 0.0e0 {
      r *= b;
    }
  }
  return r;
}
</code></pre><p>The tokenizer is basically a number of different jump tables all 256 sized (the
number of unique values in an 8-bit ASCII value), and works by passing each
8-bit value as the index to the jump table and then doing a tail call on that
function pointer - thus not creating a call frame. So the code goes into the
main jump table, and from there will filter into sub jump tables whether the
ASCII character is a digit, a symbol, a comment, etc. Lets look at parsing the
comment from the example program above:</p>
<pre tabindex="0"><code># Some cool comment!
</code></pre><p>Firstly - the <code>main_jump_table_s</code> class contains, well, the main jump table. And
the <code>#</code> index into that jump table takes you to a function:</p>
<pre tabindex="0"><code>static int comment(tokenizer_s *const tokenizer, token_t *out_token) {
  *out_token = {token_type_comment, tokenizer-&gt;current, 1, tokenizer-&gt;line,
                tokenizer-&gt;column};
  tokenizer-&gt;skip_current();
  [[clang::musttail]] return comment_jump_table_s::singleton()
      .jt[tokenizer-&gt;data[tokenizer-&gt;current]](tokenizer, out_token);
}
</code></pre><p>This function:</p>
<ul>
<li>Sets the token type to be a comment.</li>
<li>Stores the locations of the start of the token.</li>
<li>Bumps the tokenizer beyond the <code>#</code> character.</li>
<li>And then does a tail call into the <code>comment_jump_table_s</code>, using the next
character in the input <code>data</code> stream for the index.</li>
</ul>
<pre tabindex="0"><code>struct comment_jump_table_s final
    : public tokenizer_jump_table_s&lt;comment_jump_table_s&gt; {
  static int newline(tokenizer_s *const tokenizer, token_t *out_token) {
    tokenizer-&gt;current += 1;
    tokenizer-&gt;line += 1;
    tokenizer-&gt;column = 0;
    return 0;
  }

  static int keep_going(tokenizer_s *const tokenizer, token_t *out_token) {
    tokenizer-&gt;skip_current();
    out_token-&gt;length += 1;
    [[clang::musttail]] return comment_jump_table_s::singleton()
        .jt[tokenizer-&gt;data[tokenizer-&gt;current]](tokenizer, out_token);
  }

  constexpr comment_jump_table_s() : Super(&amp;keep_going) {
    jt[&#39;\n&#39;] = &amp;newline;
    jt[&#39;\0&#39;] = &amp;return_zero;
  }
};
</code></pre><p>Then in the <code>comment_jump_table_s</code> we initialize the jump table by default to
<code>keep_going</code> (see the <code>Super</code> constructor), and specify that for the two exit
conditions we should call their respective functions (either newline, or end
of string).</p>
<p>Through these various jump tables we can build up complex tokenization patterns
without having a complex soup of branching, switches, loops. I&rsquo;m actually quite
impressed at how elegant this tokenizer turned out to be just 742 lines of code.</p>
<p>And what does the codegen look like too?</p>
<pre tabindex="0"><code>&lt;_ZN17main_jump_table_s7commentEP11tokenizer_sP7token_s&gt;:
;     *out_token = {token_type_comment, tokenizer-&gt;current, 1, tokenizer-&gt;line,
mov eax, dword ptr [rdi + 0x8]
mov dword ptr [rsi], 0x1
mov rcx, qword ptr [rdi + 0xc]
mov dword ptr [rsi + 0x4], eax
mov dword ptr [rsi + 0x8], 0x1
mov qword ptr [rsi + 0xc], rcx
;     current += 1;
mov eax, dword ptr [rdi + 0x8]
inc eax
mov dword ptr [rdi + 0x8], eax
;     column += 1;
inc dword ptr [rdi + 0x10]
;         .jt[tokenizer-&gt;data[tokenizer-&gt;current]](tokenizer, out_token);
mov rcx, qword ptr [rdi]
movzx eax, byte ptr [rcx + rax]
;     [[clang::musttail]] return comment_jump_table_s::singleton()
lea rcx, [rip]              # 0x34 &lt;_ZN17main_jump_table_s7commentEP11tokenizer_sP7token_s+0x34&gt;
jmp qword ptr [rcx + 8*rax]
</code></pre><p>And that&rsquo;s overall not too shabby. I could probably change the function
signature to pass bits of the tokenizer and the output token down individually
rather than as pointer arguments, thus avoiding having to do indirect loads and
stores through their pointers. But overall I&rsquo;m quite happy that the whole thing
worked out as nice as it did.</p>
]]></description>
    </item>
    
    <item>
      <title>Custom asserts in LLVM</title>
      <link>https://www.neilhenning.dev/posts/custom-asserts-in-llvm/</link>
      <pubDate>Sat, 16 Nov 2024 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/custom-asserts-in-llvm/</guid>
      <description><![CDATA[<p>I tried (and failed) to <a href="https://discourse.llvm.org/t/rfc-make-asserts-runtime-togglable/81446">convince the LLVM folks to allow for runtime togglable asserts</a>. No biggie - the people much more involved with maintaining upstream didn&rsquo;t want to have yet another codepath to maintain. They said that it&rsquo;d cost 20% runtime performance to have asserts enabled, and that this cost would likely still be paid even if I did have asserts compiled off at runtime. Why you might ask - the answer to which is that LLVM guards a bunch of assert-checking code behind <code>NDEBUG</code> preprocessor checks, and will store extra sideband information if you are running with asserts enabled so as to do some deeper checks.</p>
<p>My motivation in allowing asserts to be runtime togglable is that we tried with the <a href="https://www.neilhenning.dev/posts/verse-transactional-memory/">custom clang compiler we are working on for Verse here at Epic Games</a> to just always enable asserts in clang, and kept running into upstream clang bugs with asserts enabled. We decided to compile asserts off (like mostly everyone does), but it always annoys me that clang could benefit from these found bugs being reported and fixed and that we are now flying blind (like mostly everyone does!) in the face of the upstream bugs.</p>
<p>I deferred to their wisdom - but wondered if there was an easy way to check that their assertions (<em>ba-dum-tish</em>) were correct?</p>
<p>So I hacked the LLVM CMake to add:</p>
<pre tabindex="0"><code>add_definitions(-include AssertInjectoroo.h)
</code></pre><p>To let me include a header upfront in every source file. Then in <code>AssertInjectoroo.h</code> I did:</p>
<pre tabindex="0"><code>#undef NDEBUG
</code></pre><p>To make sure the extra LLVM checks were always compiled in.</p>
<pre tabindex="0"><code>#include &lt;assert.h&gt;
</code></pre><p>Included <code>assert.h</code> so that if any LLVM file included it, it wouldn&rsquo;t be included again.</p>
<pre tabindex="0"><code>#undef assert
</code></pre><p>I undefined the original C <code>assert</code> because I was going to provide my own.</p>
<pre tabindex="0"><code>#if defined(__cplusplus)
extern &#34;C&#34;
#endif
int ExposeAssertsEnabledToC(void) __attribute__((weak));

#define assert(x) if (__builtin_expect(ExposeAssertsEnabledToC(), false)) { if (!(x)) { llvm_unreachable(#x); } }

#if defined(__cplusplus) &amp;&amp; __cplusplus &gt;= 201703L
#include &#34;llvm/Support/CommandLine.h&#34;

#pragma clang diagnostic push
#pragma clang diagnostic ignored &#34;-Wglobal-constructors&#34;

__attribute__ ((weak)) llvm::cl::opt&lt;bool&gt; AssertsEnabled(&#34;enable-asserts&#34;, llvm::cl::desc(&#34;enable asserts&#34;), llvm::cl::init(false));

#pragma clang diagnostic pop

extern &#34;C&#34; int ExposeAssertsEnabledToC(void)
{
  return AssertsEnabled;
}

#endif
</code></pre><p>Then I used this hack to provide my own <code>assert</code> definition. Because I wanted to control whether the assert triggered with an LLVM option (so that the built clang would automagically be able to read my command line option and set this flag), and the LLVM option stuff is C++ metasoup code, I had to provide a hack to get at the definition from C files with the weak symbol.</p>
<p>The new <code>assert</code> itself just checks whether the flag has been set, before doing the underlying asserting check and calling <code>llvm_unreachable</code> if the assert fails.</p>
<p>So first off - executable size differences. My injected assert made the binary <strong>1.85x bigger</strong> on a release build with clang. Ouch! If I compare my build to just compiling with <code>LLVM_ENABLE_ASSERTIONS</code> on in the stock LLVM build my injected assert only made the binary <strong>1.005x</strong> bigger though - so its just that asserts in LLVM are costly for binary size.</p>
<p>Next up - runtime cost. I used a bootstrap build of clang to test the runtime performance (thanks to Chandler Carruth <a href="https://hachyderm.io/@chandlerc/113336331414955301">for this suggestion</a>), building my compiler and stock LLVM and then using these built compilers to rebuild clang. My injected assert that was toggled <em>off</em> at runtime made compilation time <strong>14.00% slower</strong> than stock LLVM. If I had the injected asserts toggled <em>on</em> compilation time was <strong>20.61% slower</strong> than stock LLVM.</p>
<p>So what did we learn? Doing the calls to <code>assert</code> themselves results in a <strong>6% performance hit</strong>. Processing all the other data structures that are hidden behind <code>NDEBUG</code> checks is the main cost with a <strong>14% performance hit</strong> attributed to that. This matches with what Renato Golin and Reid Kleckner said on the thread - that LLVM is just not setup to have runtime togglable asserts the way it is, and it&rsquo;d be a monumental effort to make that work.</p>
]]></description>
    </item>
    
    <item>
      <title>Your Own Constant Folder in C/C&#43;&#43;</title>
      <link>https://www.neilhenning.dev/posts/yourownconstantfolder/</link>
      <pubDate>Thu, 21 Mar 2024 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/yourownconstantfolder/</guid>
      <description><![CDATA[<p>I was talking with someone today that really really wanted the <code>sqrtps</code> to be used in some code they were writing. And because of a quirk with clang (still there as of clang 18.1.0), if you happened to use <code>-ffast-math</code> clang would butcher the use of the intrinsic. So for the code:</p>
<pre tabindex="0"><code>__m128 test(const __m128 vec)
{
    return _mm_sqrt_ps(vec);
}
</code></pre><p>Clang would compile it correctly without fast-math:</p>
<pre tabindex="0"><code>test:                                   # @test
        sqrtps  xmm0, xmm0
        ret
</code></pre><p>And create this monstrosity with <code>-ffast-math</code>:</p>
<pre tabindex="0"><code>.LCPI0_0:
        .long   0xbf000000                      # float -0.5
        .long   0xbf000000                      # float -0.5
        .long   0xbf000000                      # float -0.5
        .long   0xbf000000                      # float -0.5
.LCPI0_1:
        .long   0xc0400000                      # float -3
        .long   0xc0400000                      # float -3
        .long   0xc0400000                      # float -3
        .long   0xc0400000                      # float -3
test:
        rsqrtps xmm1, xmm0
        movaps  xmm2, xmm0
        mulps   xmm2, xmm1
        movaps  xmm3, xmmword ptr [rip + .LCPI0_0] # xmm3 = [-5.0E-1,-5.0E-1,-5.0E-1,-5.0E-1]
        mulps   xmm3, xmm2
        mulps   xmm2, xmm1
        addps   xmm2, xmmword ptr [rip + .LCPI0_1]
        mulps   xmm2, xmm3
        xorps   xmm1, xmm1
        cmpneqps        xmm0, xmm1
        andps   xmm0, xmm2
        ret
</code></pre><p>The optimization flow here in LLVM is:</p>
<ul>
<li>That under fast-math conditions, <code>sqrt(x)</code> == <code>x * rsqrt(x)</code>, so it uses <code>rsqrtps</code> instead.</li>
<li>But that has precision issues between Intel and AMD due to a high ULP tolerance for the <code>rsqrtps</code> instruction.</li>
<li>So LLVM does two newton-raphson iterations anytime it calls <code>rsqrtps</code> to correct the precision between the CPU implementations.</li>
</ul>
<p>The &lsquo;fix&rsquo; here is just to use inline assembly to guarantee you&rsquo;ll get the instruction selection you want always:</p>
<pre tabindex="0"><code>__m128 test(__m128 vec)
{
    __asm__ (&#34;sqrtps %1, %0&#34; : &#34;=x&#34;(vec) : &#34;x&#34;(vec));
    return vec;
}
</code></pre><p>But there is one additional thing I&rsquo;d advocate you do if you need to use inline assembly - write your own constant folding.</p>
<p>See the one downside to the inline assembly above is that if <code>test</code> is inlined and <code>vec</code> was a constant, it wouldn&rsquo;t constant fold it. For example:</p>
<pre tabindex="0"><code>__attribute__((always_inline)) __m128 test(__m128 vec)
{
    __asm__ (&#34;sqrtps %1, %0&#34; : &#34;=x&#34;(vec) : &#34;x&#34;(vec));
    return vec;
}

__m128 call_test()
{
    return test(_mm_setr_ps(1.f, 2.f, 3.f, 4.f));
}
</code></pre><p>Will produce:</p>
<pre tabindex="0"><code>test:
        sqrtps  xmm0, xmm0
        ret
.LCPI1_0:
        .long   0x3f800000                      # float 1
        .long   0x40000000                      # float 2
        .long   0x40400000                      # float 3
        .long   0x40800000                      # float 4
call_test:
        movaps  xmm0, xmmword ptr [rip + .LCPI1_0] # xmm0 = [1.0E+0,2.0E+0,3.0E+0,4.0E+0]
        sqrtps  xmm0, xmm0
        ret
</code></pre><p>So that even under inlining, when we could have constant folded it away entirely, we are still calling <code>sqrtps</code> when we don&rsquo;t have to. So what is the fix?</p>
<p>LLVM has an intrinsic <code>is_constant</code> which can be got at via the Clang-supported GCC extension <code>__builtin_constant_p</code>. If we extend our <code>test</code> above to check when <code>vec</code> is constant, we can call <code>_mm_sqrt_ps</code> when it is constant, and benefit from the constant folder doing its thing and removing the call entirely. So our code becomes:</p>
<pre tabindex="0"><code>__attribute__((always_inline)) __m128 test(__m128 vec)
{
    if (__builtin_constant_p(vec))
    {
        return _mm_sqrt_ps(vec);
    }

    __asm__ (&#34;sqrtps %1, %0&#34; : &#34;=x&#34;(vec) : &#34;x&#34;(vec));
    return vec;
}

__m128 call_test()
{
    return test(_mm_setr_ps(1.f, 2.f, 3.f, 4.f));
}
</code></pre><p>And we get:</p>
<pre tabindex="0"><code>call_test:
        movaps  xmm0, xmmword ptr [rip + .LCPI11_0] # xmm0 = [1.0E+0,2.0E+0,3.0E+0,4.0E+0]
        sqrtps  xmm0, xmm0
        ret
</code></pre><p>What the heck?! It hasn&rsquo;t constant folded! Turns out GCC is a bit picky with this builtin, and it looks like LLVM has inherited that funky behaviour. You cannot use it with a vector - even though LLVM happily has the support in the IR for it. But there is a workaround, an ugly one:</p>
<pre tabindex="0"><code>__attribute__((always_inline)) __m128 test(__m128 vec)
{
    if (__builtin_constant_p(vec[0]) &amp;&amp;
      __builtin_constant_p(vec[1]) &amp;&amp;
      __builtin_constant_p(vec[2]) &amp;&amp;
      __builtin_constant_p(vec[3]))
    {
        return _mm_sqrt_ps(vec);
    }

    __asm__ (&#34;sqrtps %1, %0&#34; : &#34;=x&#34;(vec) : &#34;x&#34;(vec));
    return vec;
}

__m128 call_test()
{
    return test(_mm_setr_ps(1.f, 2.f, 3.f, 4.f));
}
</code></pre><p>Will produce:</p>
<pre tabindex="0"><code>.LCPI15_0:
        .long   0x3f800000                      # float 1
        .long   0x3fb504f3                      # float 1.41421354
        .long   0x3fddb3d7                      # float 1.73205078
        .long   0x40000000                      # float 2
call_test:
        movaps  xmm0, xmmword ptr [rip + .LCPI15_0] # xmm0 = [1.0E+0,1.41421354E+0,1.73205078E+0,2.0E+0]
        ret
</code></pre><p>Nice! We&rsquo;ve got the constant folding we want. And also nicely, if we mark <code>test</code> as <code>noinline</code> instead, the code for <code>test</code> is:</p>
<pre tabindex="0"><code>test:
        sqrtps  xmm0, xmm0
        ret
</code></pre><p>Meaning the branch is folded away. In both cases we now get the behaviour we want. We&rsquo;ve wrote our own constant folder. Nice! You can see the full example on <a href="https://godbolt.org/#z:OYLghAFBqd5QCxAYwPYBMCmBRdBLAF1QCcAaPECAMzwBtMA7AQwFtMQByARg9KtQYEAysib0QXACx8BBAKoBnTAAUAHpwAMvAFYTStJg1AB9U8lJL6yAngGVG6AMKpaAVxYMQkgMykHAGTwGTAA5dwAjTGIQAE4NUgAHVAVCWwZnNw8vXySUmwFA4LCWSOi4i0wrfIYhAiZiAgz3Tx8KqrTa%2BoJC0Iio2PiFOoamrNahrp7i0oGASgtUV2Jkdg4AUgAmbyDkNywAajXvR1UWFiCCYiCAOgQj7DWNAEFHp4B6N/2AFQRMfZI8MAgmJ9mgsNdXqYmARLnhwq4CJhTFAGKggrQgphZrN9qYWFwNgAOfbhJjoYyo9GYiB4gnEgBumGQs1eawA7AAhV77Hn7YiYAhLBi4s7GBQARwaxgSCggjOZRy5z3ZABFWc9aUTQWJaMZSeTKQwMcEICzlZzubz%2BYLiML9RS0UbqcZRUpLtLZVxrlRSPsNt7fd4A/tJN7sYrWWy1cqNcZobD4YjkRAxAB3JgATwUxipwWxuJddJJZLjtHTWZzTpNmoZTLNLwtz15fIFQpFLDFkoIHrldYj5ujL1j%2BK1olouvtacz2dzmFNkaVT2b1rbk7L08rxrnLo7buIPa9Pr9waDR9DVHD3kXqvV70%2BPz%2BNFUmHQoIwmAhsfjV0TSOMKMdLd8xrfYnwdWcaULLV5XrdlF2bKEFA7Yx9ggTYNglBoZUODYAFYuF9TZcI0dD9hAHCNiOFVVHQ3tmTIiiaI2DY6MveCrVbW19nlfsG0HSEoOJMddTAw0t3nc12J5FcuNEwDnVdAV9xlCBD19f0j1PX1zzYyN%2BK/GEfwRP8oCnCtZ2AwTQLwVRS3LGcq23KyYIXS0eUQ5DUPQzCCGwoiCJw4jSPI9CqKYliYIY9DwtYlkrzclsbWFHj4oHW8QOE4wwLMhzxNgxslw4pLrNsnLNwU3clIPYMNMDYMdLi68o1vV4Pm%2BX4SWIVAAGtGDfcEBO/OFjOTMTMUskdiXCLreoYcDHMgybuL7SSErwKhUNMeE6BsOa0AYCZBGlWKErghLl044Ud07KUVJc1LCp5G8Y0egsmCQ0wvOYny/LwgKiJI5iouYsLaMikLmJimDGoSmTkqZXjnqHJ4Mp1PUZsYea8tcpsitXDG5rG6tFPdFS1OPTT6rDGG0peqFDOGpN/xTddzMciai2mnrMbKiCQJc1bcZ5dbNr1VwdqCYx9sO7sEhOoXDgK5sLuK66fJ7e6pMV/TXo8z60O%2Brtfvwwi8MBjZgco7xqLButLahusadeuHluQRHmrpqzMq52a7I3CD8q1l2fZ51ncoqsUqrJmqTypi8naR282ofElMCGfqP0Ghnf1G%2BS8xxEDIiGLHnWclaGy1kXIO22hdqlgQZeOnjcI5EjcJVHFNgANm7gsa7r6W6iOuXm45Lg1nbzuNh76e%2B/F2vJcHwxZboieOUoyecJnru54lvaG6HlfR%2B8CeO/rZszoVlW2zVrsNb7B6L495GELjD6UINjCjYUQL/rN4KKKg2Yqxe2ttmRO2vlxFKTUdao3HHqNO3YiZzkDrDS6qdi7IJpCTZSnoY6UzPNTd2sC4zZxGszXm7MC5WSLt2Sh4l%2Bbl0vq9KuW154DwPsvJuCMW5tw7lvXubC971wOofbhbsW7j03t3QRYthFL2HqvFuG9%2BEyNnkIhe%2B9RFcJHjwjkJ9J7n15Mw5WeMuK31urKTWp1n4JT1h/by39f6myCkDCGVsbbAPBoxMBukFYu2gXpdKXs0a0L9mzbGgtnboLCfQiOe5qpHlqvsLSIYiEPSRhweYtBOC4V4J4DgWhSCoE4I4fYChFjLD%2BJsbwPBSAEE0Fk%2BY3UQDEX0JwSQ%2BTGnFM4LwBQIB4gNMKVk0gcBYAwEQCgVALAEh0CiOQSgaAZlzOiMgXYhhgBcEJFweINBa5RH6RAcI3TwjAmIBmTgdTTnMHOQAeXCNoJkQy6lLLYIIW5RoLnDNIFgeEwBHA6n6dwXgWAWAbPEN8/A/JrB4EZECopmBnzIGMpc3gFxKjdIxNNeoGZnBYG6bCFgqL5hUAMMABQAA1PAmBUy3ISIwVFMhBAiDEOwKQTL5BKDUN03QBEDBGBAKYKW%2Bg4T9MgPMVACRqhAoALS3O8LwVAjJiBXCwGK00bQnlpHsAwJwLhmgSA2H4XVUw%2BhlHiLkVIAhRieAJIkZIVqGCmpKP0colgtUCE6CMfVWQ7XuphZ64Y3RMTTFdYMINNrDUWCDc6mYcR5gVKWCsCQ2TcldO%2BSUjg%2BxVCEi7jKrukhQT8uAPsLZ1wvQaFQrgQgJAcK1NmLwIZWhsSkBad4IM7bO1du7V3dpHBOmkCJW0gpRTM19IGfUxp8wxmTKWbM%2BgZAKAQDnSslA6yjBbJ2XwHaBzKDHO%2BdcnFjLD13IeU8xlrzGAEA%2BbQL5RTfmuH%2BYCxloLwWrHvXgaFNg4XdMRUyFFwLyCCAxd8rFxAcV4vfY2q4RLgUkrJZS6ltL6UFLqfwZlY42XSHQ5ylQ6hvm6F8MWwVZgRXhHVRKqVaRZVUCoO9AgMqwUEAQPsOVCrinKtVWneACbKges8BABwka7UBBDWaiQXACKWuqMJ%2B1eQ0ixv6DsmImqA01AjT621Rr/XVC9cGoo4nJMEQmN6zItro2TDEy66IymE2VOTVwVNHA8mkBHYqzg2bc35sLeuktZaK1VvwEQYgdbHONqnfMX4ZJ%2Bgapyf23gQ74huZ6RwcdgyIuttafEOL7HktjsncMltcWNjptHb0grzb5jKpSHYSQQA">godbolt</a>.</p>
<p>It&rsquo;d be nice if we could just use the vector in <code>__builtin_constant_p</code>, but I think the LLVM folks have purposefully tried to match what GCC would do. I&rsquo;d personally advocate for a loosening of the builtin, and I might file a GitHub issue about just that.</p>
]]></description>
    </item>
    
    <item>
      <title>Verse Transactional Memory</title>
      <link>https://www.neilhenning.dev/posts/verse-transactional-memory/</link>
      <pubDate>Fri, 15 Mar 2024 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/verse-transactional-memory/</guid>
      <description><![CDATA[<p>When I interviewed for Epic Games it was for a graphics post - I wanted back to working on shader compilers. But even though most of my interviews were from the fantastic graphics side of the company, I had a few interviews about something I knew very little about - the <em>Verse</em> language. And on one of those interviews I was asked about something I hadn&rsquo;t thought about for 15 years - Transactional Memory.</p>
<p>When I was an undergrad my honours project was writing a Software Transactional Memory (STM) system for the PlayStation 3. I loved the PlayStation 3&rsquo;s architecture and I knew <em>nothing</em> about STMs before I started. This project ended up being awarded the honours project of the year and I had found STMs so interesting a concept. I even toyed with going to EPFL in Switzerland to do a PhD in STMs.</p>
<p>Cut back to 15 years later. Verse needed an STM, it needed C++ and Verse to behave correctly while sharing the same STM, and it would need to be fast.</p>
<p>Well that&rsquo;s what I, and a great team here at Epic, have been working on - <a href="https://www.unrealengine.com/en-US/tech-blog/bringing-verse-transactional-memory-semantics-to-c">bringing an STM to C++</a>.</p>
<p>I&rsquo;m not going to revisit the contents of the post (please read it!), but suffice to say the last 18 months working on this has been a <em>blast</em>. We&rsquo;ve got a ways to go, and I&rsquo;m looking forward to the challenge.</p>
]]></description>
    </item>
    
    <item>
      <title>Updating GitHub repos to Apple Silicon</title>
      <link>https://www.neilhenning.dev/posts/github-apple-silicon/</link>
      <pubDate>Sun, 04 Feb 2024 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/github-apple-silicon/</guid>
      <description><![CDATA[<p>I&rsquo;ve updated my C/C++ open sources libraries <a href="https://github.com/sheredom/utest.h/commit/31bf761de4d20c9b4f11d48ce4cc60f17d710b9c">utest.h</a>, <a href="https://github.com/sheredom/utf8.h/commit/2aa5709fe39c66d2868c0d52d42788899b90dc92">utf8.h</a>, <a href="https://github.com/sheredom/ubench.h/commit/70b8c05f835c3dfbbb4678b867390e9b5153b4b8">ubench.h</a>, <a href="https://github.com/sheredom/hashmap.h/commit/7846c1d30f3c98a33a4d98651a96bd5afa86a310">hashmap.h</a>, <a href="https://github.com/sheredom/subprocess.h/commit/7e59b6924aa0e1a595be86fdeb1d4c28835aa0b9">subprocess.h</a>, and <a href="https://github.com/sheredom/json.h/commit/cfdee7c025081ce722644f3ac286e1e27ad16f82">json.h</a> to use the new Apple Silicon GitHub CI runners.</p>
<p>So how hard is it? Simple! You just add <code>macos-14</code> to the build -&gt; strategy -&gt; matrix. I took the opportunity to drop <code>macos-latest</code> (which is still set to <code>macos-13</code>, the last x86 runner) and explicity use the oldest supported <code>macos-11</code> instead.</p>
<p>The new Apple Silicon runner is roughly 2x faster than the x86 one too - nice!</p>
]]></description>
    </item>
    
    <item>
      <title>How long does it take to compile LLVM 17 on a Raspberry PI 5</title>
      <link>https://www.neilhenning.dev/posts/how-long-to-compile-llvm-17-on-rpi5/</link>
      <pubDate>Sat, 25 Nov 2023 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/how-long-to-compile-llvm-17-on-rpi5/</guid>
      <description><![CDATA[<p>So I got my Raspberry PI 5. And <a href="https://www.neilhenning.dev/posts/how-long-to-compile-llvm-17-on-rpi/">like in my previous post</a>, I compiled LLVM 17 on the Raspberry PI 5, and have compared the compile speed versus the Raspberry PI 4.</p>
<p>I&rsquo;m going to do the same steps:</p>
<ul>
<li>Compile LLVM using the default clang got via apt-get.</li>
<li>Compile LLVM again using the clang we just built.</li>
<li>And compile it a <em>third time</em> with the clang we built with our own clang (this step should be the most accurate picture of the difference in performance
between the 4 and 5, because it should be the same binary compiling the same
project).</li>
</ul>
<p>I&rsquo;ve used the same LLVM version as before just to make the comparisons accurate. There are a also few discrepencies on the image that I should call out - the Raspberry PI 4 image had Clang 11 as the default, whereas the Raspberry PI 5 has Clang 14. So I expect there to be a performance difference for the initial compile, but by the third go through we should be able to derive a good idea of the actual raw performance between the two boards. I&rsquo;ve used the exact same MicroSD card, have the boards in the same location, and both are using ethernet (not that that will matter as I&rsquo;m not timing the LLVM download from the interwebs, but consistency is key!).</p>

<img src="/images/rpi4vsrpi5/chart.png"  class="center"  style="border-radius: 8px;"    />


<p>I&rsquo;m blown away by this. It is <strong>2.82x</strong> faster to compile on the Raspberry PI 5 than the Raspberry PI 4. That&rsquo;s amazing! I was expecting maybe a 50% improvement at 1.5x, but not nearly three times faster.</p>
<p>So if you have any performance sensitive workloads I highly recommend you upgrade to the new board. I&rsquo;m glad I did!</p>
]]></description>
    </item>
    
    <item>
      <title>How long does it take to compile LLVM 17 on a Raspberry PI 4</title>
      <link>https://www.neilhenning.dev/posts/how-long-to-compile-llvm-17-on-rpi/</link>
      <pubDate>Tue, 03 Oct 2023 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/how-long-to-compile-llvm-17-on-rpi/</guid>
      <description><![CDATA[<p>With the
<a href="https://www.raspberrypi.com/products/raspberry-pi-5/">imminent launch of the Raspberry Pi 5</a> I wondered - how long does it take to compile the latest LLVM
release (17 at the time of writing this blog) on the Raspberry Pi 4. This will
give me a baseline that I can test the Raspberry Pi 5 against once I get ahold
of it.</p>
<p>For my initial exploration I decided to test just three things:</p>
<ol>
<li>Using the stock Clang compiler I could get at via <code>apt get</code> to compile LLVM.
This is Clang 11 at the time of writing this post.</li>
<li>Use the Clang 17 compiler built above to compile LLVM itself again. This
stage will mean that the LLVM code itself is being built with the latest
compiler.</li>
<li>Then use the stage 2 compiler to compile LLVM a <em>third time</em>. This will test
whether the Clang 17 compiler built by the Clang 17 compiler is more optimal.</li>
</ol>
<p>I decided to just build with <code>CMAKE_BUILD_TYPE=RELEASE</code>, and I decided to build
the Bolt, Clang, LLD, and compiler-rt subprojects. Just to keep it simple but
interesting!</p>
<p>So what are the results?</p>
<p>First lets look at the time taken:</p>

<img src="/images/llvm17size/timetaken.png"  class="center"  style="border-radius: 8px;"    />


<p>As can be seen in the chart it takes a cool <strong>9.52 hours</strong> to build with the
stock Clang 11 compiler. First observation - wow that&rsquo;s a long time! But the
Clang 17 compiler we built with Clang 11 goes a cool <strong>12.9% faster</strong>, coming in
at <strong>8.42 hours</strong>. The Clang 17 compiler built with Clang 17 would reliably run
a smidge faster at <strong>13.3% faster</strong> than Clang 11, coming in at <strong>8.40 hours</strong>.</p>
<p>And now the binary size of Clang too:</p>

<img src="/images/llvm17size/clangbinarysize.png"  class="center"  style="border-radius: 8px;"    />


<p>The binary size of the compiler built with Clang 17 was identical in both cases,
which is as expected (it&rsquo;d only differ if there was a compiler bug or some sort
of non-deterministic behaviour in the compiler). The binary built with Clang 17
is <strong>15.3% larger</strong> than the binary built with Clang 11.</p>
<p>Overall this result shows that Clang 17 is faster than Clang 11, but it is
achieving this in part with a sizable increase in binary size.</p>
<p>It&rsquo;ll be interesting to see how the Raspberry Pi 5 compares in comparison once
I can test it!</p>
]]></description>
    </item>
    
    <item>
      <title>My Take On Return To Office and Remote Work</title>
      <link>https://www.neilhenning.dev/posts/my-take-on-return-to-office-and-remote-work/</link>
      <pubDate>Tue, 12 Sep 2023 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/my-take-on-return-to-office-and-remote-work/</guid>
      <description><![CDATA[<p>The <a href="https://x.com/ditheringfm/status/1696476472821826043?s=46&amp;t=DZAx6P36XOqKWP6tSN9-kw">Return to Office</a>
episode of one of my favourite podcasts <a href="https://dithering.fm">Dithering</a> made
me finally decide to post about Remote Work. I&rsquo;ll be back to my irregular coding
posts soon, but I wanted to get this off my chest.</p>
<p>Let me get all the caveats out the way - I worked in an office full time for the
first five years of my career, and have now been working remotely for nine
years. You could argue that there will be a bias in my viewpoint because remote
work is so intrinsic to my ability to live and work on the Isle of
Skye where I&rsquo;ve made my home. But I think I&rsquo;ve managed to have a nuanced take on
this subject. Feel free to judge though.</p>
<p>Remote work is here to stay. Infact I&rsquo;d go as far to argue that <strong>most people in
my industry are already working remotely</strong>, but with a caveat I will cover
later. The pandemic years were obviously a great accelerator for remote work, but
I think the direction of travel was already clear long before the pandemic - it&rsquo;s
just that the pandemic exposed more people to the opportunities that remote work
can provide for them and their families.</p>
<p>But I acknowledge that <strong>in-person teams are more effective</strong>. That ability to
collaborate in a really unstructured way is something you just can&rsquo;t fully
replicate in a remote setting. You can&rsquo;t bond with your colleagues and truly
understand how they work, and how to socialise with them without being
in-person. It is also harder for young people to enter the workforce remotely as
they don&rsquo;t generally have the money to have a good home working environment - at
least as they start their careers. Junior hires also benefit the most from being
in an environment where they can absorb all the knowledge floating about a well
oiled office.</p>
<p>The problem with the return-to-office hawks is that I fear they don&rsquo;t really
understand what modern office work is like. While there are a few companies that
will geographically gate teams to a specific location, nearly <em>all</em> of the big
companies I know will have teams spread across multiple locations.
When I worked for Unity, most people would work in an office, but the teams
would be split across say five offices. This meant that to collaborate with
your team you were using Zoom, and fighting for shared meeting rooms or even
annoying your open-office colleagues because you were taking a call at your
desk.</p>
<p><strong>Long gone are the days where a team is in a single office</strong>.</p>
<p>The reason companies do this is because hiring people with the skills you need
for a specific team is incredibly hard if you restrict them to a single
location. It used to be everyone would relocate to Silicon Valley in search of
their fortune. But nowadays no-one I know wants to move there. You have the
inflated house prices, the polarised political situation in the USA, the visa
pain, the guns - the list goes on. There is also powerful tax benefits available
to companies if they set up offices in other states or countries, and so
companies have taken advantage of this.</p>
<p>If I was to give an ordering from best-to-worst for the various working
arrangements for teams, it&rsquo;d be:</p>
<ol>
<li>A geographically-locked team where everyone on the team commutes into the same office.</li>
<li>A remote team of remote workers.</li>
<li>A remote team where everyone commutes into the different offices.</li>
</ol>
<p>But with the caveat that for 1. you are going to suffer from a much much smaller
potential hiring pool of candidates that are even vaguely suitable for the job.
This can be mitigated if you have local universities and a team that prioritises
hiring junior talent and training them up (a good thing!), but you will have
some amount of attrition of people coming through that end up being poached by
other companies.</p>
<p>So if you work for a company where your team is only accessible via Zoom anyway, mandating a return to office means you have all of the negatives of remote work and all of the negatives of office work. The worst of all worlds.</p>
]]></description>
    </item>
    
    <item>
      <title>How costly is changing the hardware rounding mode?</title>
      <link>https://www.neilhenning.dev/posts/howcostlyischangingroundingmode/</link>
      <pubDate>Sun, 23 Apr 2023 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/howcostlyischangingroundingmode/</guid>
      <description><![CDATA[<p>I was looking at hardware rounding modes the other day, and one thing that I
realised I had no concept of was how costly is it to change the hardware
rounding mode for floating-point operations.</p>
<p>For those that don&rsquo;t know - modern hardware often includes a way to set the
rounding mode that floating-point operations use when there is an imprecision in
the result of a floating-point operation that cannot be encoded in the format.
There are four alternatives that I am aware of:</p>
<ul>
<li>Round to nearest - behaves like how math works, will round up or down to the
nearest number that can fit in the representation. Often the default rounding
mode on CPUs.</li>
<li>Round to zero - all ties go towards 0. Is often the default rounding mode on
GPUs.</li>
<li>Round to positive infinity.</li>
<li>Round to negative infinity.</li>
</ul>
<p>On GPUs, in Vulkan for instance you can use
<a href="https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VK_KHR_shader_float_controls.html">VK_KHR_shader_float_controls</a>
to specify the floating point mode for an entire shader execution.</p>
<p>But on CPUs there is often a hardware register that controls the floating-point
rounding - on x86 it is the <code>mxcsr</code> register and on 64-bit Arm it is the <code>fpcr</code>
register.</p>
<p>C lets you get and set the current rounding mode by using the <code>fenv.h</code> functions
<code>fesetround</code> and <code>fegetround</code>. So how costly is it to use these operations?</p>
<p>I did a few tests on an Arm-based Macbook Air M1:</p>

  <figure class="left" >
    <img src="/images/arm-fpcontrol.svg"   />
    
  </figure>


<p>And an x86-based Threadripper Pro:</p>

  <figure class="left" >
    <img src="/images/x64-fpcontrol.svg"   />
    
  </figure>


<p>The tests were as follows:</p>
<ul>
<li>Set the rounding mode to round-to-nearest.</li>
<li>Run 1024 floating-point adds in a benchmark.</li>
<li>Then run with each call changing the rounding mode to round-to-zero before the
add and then resetting it after to the default.</li>
<li>Then I ran with doing 4, 8, and 16 operations and amortizing any cost when
changing the rounding mode.</li>
<li>And lastly I wanted to know if checking whether the rounding mode matched
before changing it could save any cycles - so I tested getting the rounding
mode, if it matches I don&rsquo;t set it, otherwise if it doesn&rsquo;t I have to set it,
and I tested this when it does match and doesn&rsquo;t.</li>
<li>And did the whole thing above with calls to <code>tanf</code> too.</li>
</ul>
<p>So what did we find?</p>
<p>On Arm it is <strong>30x slower</strong> when you set the rounding mode.
On x86 it is <strong>69x slower</strong>. I&rsquo;d guess that setting these registers does a full
pipeline stall in the hardware (the CPU won&rsquo;t predict ahead), but I don&rsquo;t know
for sure.</p>
<p>On Arm it is only <strong>1.9x slower</strong> if the rounding mode you want is actually
already being used on the CPU (and so you don&rsquo;t have to reset it). On x86 it is
<strong>8.7x slower</strong>. Here&rsquo;s the code to do this check:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> old_mode <span style="color:#f92672">=</span> <span style="color:#a6e22e">fegetround</span>();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (old_mode <span style="color:#f92672">!=</span> FE_TOWARDZERO) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">fesetround</span>(FE_TOWARDZERO);
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// Do your operation here!
</span></span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">fesetround</span>(old_mode);        
</span></span><span style="display:flex;"><span>} <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// Do your operation here!
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>I&rsquo;m not sure if the difference in performance between Arm and x86 is some cost
in querying the register, or just the different hardware costs for doing a
branch like this.</p>
<p>The tan data didn&rsquo;t show anything hugely interesting beyond the add - but it at
least matched the performance characteristics of the floating-point add.</p>
<p>So perhaps unsurprisingly - its slow! Probably about as slow as I would have
expected if you were flipping the rounding mode regularly. This is obviously not
how these APIs are meant to be used, but you could see a situation where you
call some foreign code and you want to ensure it hasn&rsquo;t messed with the control
registers and would want to guard against that - and this gives you some idea of
the cost of doing just that.</p>
]]></description>
    </item>
    
    <item>
      <title>New Web Domain &amp; Mastodon Handle</title>
      <link>https://www.neilhenning.dev/posts/new-domain-new-mastodon-handle/</link>
      <pubDate>Sun, 26 Mar 2023 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/new-domain-new-mastodon-handle/</guid>
      <description><![CDATA[<p>This all started when I wondered what the Mastodon migration process between
accounts was like, and ended with me moving my mastodon over to a new handle
<a href="https://mastodon.gamedev.place/@neilhenning">@neilhenning@mastodon.gamedev.place</a>,
and my website over to a new domain
<a href="https://www.neilhenning.dev/">https://www.neilhenning.dev/</a>.</p>
<p>I remember maybe two or three years into Twitter trying to change my handle over
to be my name, and it was already taken. It always irked me that I couldn&rsquo;t just use my
name, but it wasn&rsquo;t to be. Now with the <em>birdshite</em> being a husk of what it was,
and Mastodon being my primary means to engage with people in the industry, I
thought this might be the opportunity to just use my actual unique ID (my name)
everywhere, including for my website. Anyone who was following me on the old
domain&rsquo;s RSS - sorry! I didn&rsquo;t realise when I made the migration that the RSS
would ping every article like it was new again. Good thing I follow myself on
RSS (just to check the feed works - I promise!) and at least noticed that that
wasn&rsquo;t the best.</p>
<p>So anyway - you&rsquo;ll find new content on these two new links, but with the wonder
of Mastodon all my followers have automagically been pulled over to my new
handle.</p>
]]></description>
    </item>
    
    <item>
      <title>Using Fibonacci Hashing in hashmap.h</title>
      <link>https://www.neilhenning.dev/posts/fibonacci-hashing/</link>
      <pubDate>Wed, 15 Mar 2023 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/fibonacci-hashing/</guid>
      <description><![CDATA[<p>I&rsquo;ve been noodling a lot with my single header C/C++ hashmap recently -
<a href="https://github.com/sheredom/hashmap.h">hashmap.h</a>. I knew from reading around
that the power-of-two size requirement I had meant that it made getting a
bucket location in the range was easy, but that it could result in suboptimal
bucket selection. Various places on the interwebs said that using a prime number
hash was better as doing the modulus by a prime would give a much better
avalanche effect, but this would come at the cost of having to do an actual
integer modulus operation for every hash - which is
<a href="https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/">quite a bit slower</a>.</p>
<p>Then friend of the blog <a href="https://mastodon.gamedev.place/@reedbeta">Nathan Reed</a>
made me aware of
<a href="https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/">Fibonacci Hashing</a>,
which is utterly wonderful.</p>
<p>Before my hasher looked like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">unsigned</span> <span style="color:#a6e22e">get_bucket</span>(<span style="color:#66d9ef">const</span> <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> data, <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">unsigned</span> length) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">unsigned</span> hash <span style="color:#f92672">=</span> <span style="color:#a6e22e">crc32_hasher</span>(data, length);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> hash <span style="color:#f92672">&amp;</span> (capacity <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And now with the fibonacci hash:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">unsigned</span> <span style="color:#a6e22e">get_bucket</span>(<span style="color:#66d9ef">const</span> <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> data, <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">unsigned</span> length) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">unsigned</span> hash <span style="color:#f92672">=</span> <span style="color:#a6e22e">crc32_hasher</span>(data, length);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> (hash <span style="color:#f92672">*</span> <span style="color:#ae81ff">2654435769u</span>) <span style="color:#f92672">&gt;&gt;</span> (<span style="color:#ae81ff">32</span> <span style="color:#f92672">-</span> <span style="color:#a6e22e">integer_log2</span>(capacity));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p><code>2654435769</code> is chosen by doing <code>pow(2, 32) / fibonaccis_golden_ratio</code> and
rounding towards the nearest odd integer (so that the bottom bit is set).</p>
<p>One of the claims of fibonacci hashing is that consecutive inputs will produce
a good spread of outputs, meaning you don&rsquo;t hit problems when multiple things
with similar hashes get inserted next to each other. So how does it perform?</p>
<p><img src="/images/fibonacci.svg" alt="A graph of the avalanche properties of the fibonacci hash"></p>
<p>The four lines on the chart as as follows:</p>
<ul>
<li>avalanche - the percentage of locations that have at least half of their
active bits flipped between consecutive inputs. The closer to 100% this is the
better a hashing approach is regarded to be.</li>
<li>average difference - how different two consecutive inputs are to each other by
using a delta between them, as a percentage of the range. So an average
difference of 50% with a bucket size 8 means that for any two consecutive
inputs we&rsquo;d expect them to have a difference of 4.</li>
<li>min difference - for two consecutive inputs in the integer range that pass
through the fibonacci hash, what is the <em>minimum</em> delta difference between
them. So a bucket size of 16 with a minimum difference of 25% would mean that
<em>every consecutive input</em> has a difference of at least 4.</li>
<li>max difference - the opposite of the min difference!</li>
</ul>
<p>Notice:</p>
<ul>
<li>From a bucket size of 8 and up (highly likely with most hashmaps in my
experience!) the min, average, and max differences are all stable. I&rsquo;m
especially happy with the min difference - as this means that we can rely on
the fibonacci hash putting a <strong>38%</strong> delta difference between consecutive
inputs.</li>
<li>We average about a <strong>47%</strong> difference between any two consecutive inputs.</li>
<li>The avalanche percentage is quite lumpy - this is because any
<code>log2(bucket_size)</code> that is odd will result in us under or over rounding when
we check if at least half the bits flipped. I&rsquo;ve leaned on under rounding any
ties.</li>
<li>Overall we&rsquo;re seeing about a 50% probability for avalanching to have happened
between consecutive inputs. But remember - this fibonacci hash <strong>isn&rsquo;t our
actual hash</strong>! It&rsquo;s what we apply after we&rsquo;ve already hashed the key. So this
will compound with the hash I actually use on the input keys, meaning this
just helps us avalanche <em>better</em> than before. Nice!</li>
</ul>
<p>I&rsquo;m pretty happy overall with this - the hashing performance has no effective
regressions in my benchmarks, but the hashing is much better as a result. I&rsquo;ve
landed this code
<a href="https://github.com/sheredom/hashmap.h/pull/29">in GitHub already</a> so anyone who
uses my hashmap.h library will already benefit from this.</p>
]]></description>
    </item>
    
    <item>
      <title>Making Hashing Faster in hashmap.h</title>
      <link>https://www.neilhenning.dev/posts/making-hashing-faster/</link>
      <pubDate>Tue, 07 Mar 2023 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/making-hashing-faster/</guid>
      <description><![CDATA[<p>One of the C/C++ single header libraries I maintain is <a href="https://github.com/sheredom/hashmap.h">hashmap.h</a>.
This library is a super light weight and easily integrated hashmap - I&rsquo;m not
focused on the performance necessarily here, it&rsquo;s really there primarily as a
nice-to-use hashmap for when you just want to throw something in there. But that
doesn&rsquo;t mean I want the performance to suck either. If I can make it faster
<em>without compromising the API</em>, I&rsquo;m totally gonna do that!</p>
<p>One thing I used previously was adding a special case when people were using
the library with SSE4.2 enabled:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (; i <span style="color:#f92672">&lt;</span> len; i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>  crc32val <span style="color:#f92672">=</span> <span style="color:#a6e22e">_mm_crc32_u8</span>(crc32val, <span style="color:#a6e22e">HASHMAP_CAST</span>(<span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">char</span>, s[i]));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This SSE4.2 path was 2.5x faster than the fallback (a lookup table).</p>
<p>I use a M1 Macbook Air, which as everyone knows uses the Arm architecture. There
is no SSE4.2 on Arm, so can I make this faster on Arm too?</p>
<p>Well turns out I can! There is an extension for CRC32 on Arm too, that I can
use.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (; i <span style="color:#f92672">&lt;</span> len; i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>  crc32val <span style="color:#f92672">=</span> <span style="color:#a6e22e">__crc32b</span>(crc32val, <span style="color:#a6e22e">HASHMAP_CAST</span>(<span style="color:#66d9ef">unsigned</span> <span style="color:#66d9ef">char</span>, s[i]));
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And running this on my M1 Macbook Air this goes <strong>2.5x</strong> too! I patted myself on
the back and went to do a PR on GitHub. Then I realised - why am I only doing my
CRC calculations on a byte-by-byte basis?</p>
<p>Turns out I just didn&rsquo;t know how the CRC intrinsics actually worked. And there
are CRC intrinsics that let us process multiple bytes at a time:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (; (i <span style="color:#f92672">+</span> <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">uint64_t</span>)) <span style="color:#f92672">&lt;</span> len; i <span style="color:#f92672">+=</span> <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">uint64_t</span>)) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">uint64_t</span> next;
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">memcpy</span>(<span style="color:#f92672">&amp;</span>next, <span style="color:#f92672">&amp;</span>s[i], <span style="color:#66d9ef">sizeof</span>(next));
</span></span><span style="display:flex;"><span>  crc32val <span style="color:#f92672">=</span> <span style="color:#a6e22e">__crc32d</span>(crc32val, next);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This will process eight bytes at a time instead of one, so how much faster does
it go? <strong>5.2x</strong> faster than the single-byte CRC intrinsic, and a whopping
<strong>13.3x</strong> faster than the original fallback code.</p>
<p>And the SSE4.2 code can process four bytes at a time with the intrinsics there
too:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (; (i <span style="color:#f92672">+</span> <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">unsigned</span>)) <span style="color:#f92672">&lt;</span> len; i <span style="color:#f92672">+=</span> <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">unsigned</span>)) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">unsigned</span> next;
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">memcpy</span>(<span style="color:#f92672">&amp;</span>next, <span style="color:#f92672">&amp;</span>s[i], <span style="color:#66d9ef">sizeof</span>(next));
</span></span><span style="display:flex;"><span>  crc32val <span style="color:#f92672">=</span> <span style="color:#a6e22e">_mm_crc32_u32</span>(crc32val, next);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Adding this makes the X86 code go <strong>3.1x</strong> faster than the single-byte CRC
intrinsic, and a nice <strong>7.7x</strong> than the original fallback code.</p>
<p>I also noticed that I only have power of 2 size for my hashmap, but I wasn&rsquo;t
relying on this when doing the hashmap calculations (I was doing an integer
modulus, where I could just use an and-mask instead!). Doing this made the
hashing calculations <strong>1.01x</strong> faster, but every little helps.</p>
<p>All the code has now <a href="https://github.com/sheredom/hashmap.h/pull/28">landed in the library</a>
and any users will be able to make use of it already!</p>
]]></description>
    </item>
    
    <item>
      <title>New Year Cleanup</title>
      <link>https://www.neilhenning.dev/posts/2023-new-year-cleanup/</link>
      <pubDate>Sun, 22 Jan 2023 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/2023-new-year-cleanup/</guid>
      <description><![CDATA[<p>As a new year starts I generally have some long awaited cleanup to do on
my C/C++ single header libraries. Maybe I need to update the CI scripts because
they are out of date, maybe I have some features I want to add, or maybe I want
to test more things.</p>
<p>For those that do not know I have <strong>six</strong> main libraries that I maintain that
are single header and work across C/C++:</p>
<ul>
<li>🧪 <a href="https://github.com/sheredom/utest.h">utest.h</a> - a single header unit
testing framework that supports C and C++.</li>
<li>⏱️ <a href="https://github.com/sheredom/ubench.h">ubench.h</a> - a single header unit
benchmarking framework that supports C and C++.</li>
<li>📚 <a href="https://github.com/sheredom/utf8.h">utf8.h</a> - a single header UTF-8 string
implementation supporting header for C and C++.</li>
<li>🗄️ <a href="https://github.com/sheredom/json.h">json.h</a> - a single header JSON parsing
and writing header that supports JSON5 and simplified-JSON, and works with C
and C++.</li>
<li>🐜 <a href="https://github.com/sheredom/subprocess.h">subprocess.h</a> - a single header
process spawning, joining, and interacting with library for C and C++.</li>
<li>#️⃣ <a href="https://github.com/sheredom/hashmap.h">hashmap.h</a> - a single header
hashmap implementation for C and C++.</li>
</ul>
<p>So what have I done in this new year cleanup?</p>
<h2 id="utesth">utest.h</h2>
<p>In my unit testing framework <em>utest.h</em> I&rsquo;ve:</p>
<ul>
<li><a href="https://github.com/sheredom/utest.h/commit/cead5308630996a6b17401e37e7debdd27bddfec">Added support for building with MinGW</a>.
A user of my other library <em>subprocess.h</em> <a href="https://github.com/sheredom/subprocess.h/commit/cf95c9615953c90177498aed43621cb1cbc8f3e1">submitted a PR that adds MinGW support</a>,
and in that PR they had modified <em>utest.h</em> to also support MinGW. But with
that code not merged into the main <em>utest.h</em> repository, any updates to the
library would override the changes. So I added testing and support for MinGW
in utest.h.</li>
<li><a href="https://github.com/sheredom/utest.h/commit/ca895d4f4c715788639540d02e01f693011349eb">Added Clang sanitizer support</a>
for <em>utest.h</em> to ensure I&rsquo;m being as safe as I can be.</li>
<li>A user had <a href="">previously added support for exception handling in tests</a>
and I suddenly realised that this support assumed all users would be compiling
with exceptions enabled in their code. So I made sure my library would work if
the user had <a href="https://github.com/sheredom/utest.h/commit/9617185b5d482c4de437dd778f8d07faf6e155a1">disabled exceptions explicitly</a>.</li>
<li>I also added support for <a href="https://github.com/sheredom/utest.h/commit/24e8f4711926907a90c1a82ea3f5985aa67fd96d">comparing enum classes</a>
for C++11 and onwards. I used this as an opportunity to add explicit testing
for C++14 and C++17 too.</li>
</ul>
<h2 id="ubenchh">ubench.h</h2>
<p>In my benchmarking framework <em>ubench.h</em> I&rsquo;ve <a href="https://github.com/sheredom/ubench.h/commit/ae8e51b25cd217af26946816f95b1ec6de19d744">added sanitizers</a>.
No bugs in the code were found, but its nice to have extra checks for future
changes.</p>
<h2 id="utf8h">utf8.h</h2>
<p>In my UTF-8 string header <em>utf8.h</em> I&rsquo;ve <a href="https://github.com/sheredom/utf8.h/commit/a35aefddd730e87f8c88a6aecf4da2dac6c04604">added sanitizers</a>.
I found one wee bug in my unit tests where a <code>constexpr</code> test was going out of
bounds.</p>
<h2 id="hashmaph">hashmap.h</h2>
<p>In my single header hashmap library <em>hashmap.h</em> I&rsquo;ve <a href="https://github.com/sheredom/hashmap.h/commit/0853417598c4079bd2d75576ac51095a8c9cff96">also added sanitizers</a>.
No bugs in the code were found.</p>
]]></description>
    </item>
    
    <item>
      <title>I&#39;m Pretty Much Done With Twitter</title>
      <link>https://www.neilhenning.dev/posts/pretty-much-done-with-twitter/</link>
      <pubDate>Sat, 21 Jan 2023 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/pretty-much-done-with-twitter/</guid>
      <description><![CDATA[<p>TL;DR - I&rsquo;m pretty much <strong>done</strong> with Twitter (here-in named the <em>&ldquo;birdshite&rdquo;</em>
🦤💩).</p>
<p>Let&rsquo;s be honest - Twitter wasn&rsquo;t exactly ideal for a pretty long time. The sheer
amount of ads that were pushed into the feed even long before Space Karen bought
the birdshite wasn&rsquo;t great. I had already blocked thousands of accounts that
were pushing promoted tweets into my feed, and had to fight the UI that would
constantly try and move me back to the never-ending algorithmic feed that all
these advert-centric businesses so love as it eeks out some percentage more time
where you eyeballs are glued to <em>their</em> content.</p>
<p><img src="/images/coyote.gif" alt="Wile E Coyote realising that he’s about to fall off a cliff"></p>
<p>Third-party clients always had an air of Wile E Coyote about them - they were
off a cliff but hadn&rsquo;t realised that gravity was going to kick in any second
now. This is no slight against all the awesome developers of third-party
birdshite clients - but it always <em>felt</em> like the birdshite were two steps away
from yanking the ground from under the developers feet. The Talk Show podcast
had a <a href="https://daringfireball.net/thetalkshow/2023/01/19/ep-367">great dive into this</a>
that I recommend about Twitterific&rsquo;s journey in this regard, worth a listen.</p>
<p>But the real kicker is just the fragmentation and loss of community on there.
The birdshite was for a long time <em>my view</em> into the games industry. Hell I can
probably say with all honesty that my career so far is a <em>direct</em> result of my
ability to reach a community of fellow bit-twiddlers, mathooligans, and compiler
tinkerers. Who would know a wee plonker like myself who lives as remote as I do
in the Isle of Skye without <em>some</em> sort of social place that people like me
could coinhabit and share ideas.</p>
<p>With the fragmentation of the community on the birdshite something has been
<strong>broken</strong> there. Even with all the will in the world I do not think there is a
way to <em>kintsugi</em> the birdshite back into what it was. Space Karen made a bunch
of people jump ship. Third-party clients being banned has made the ship sink. I
logged into the birdshite and within five clicks around I got asked to join the
subscription service twice. They &lsquo;forgot&rsquo; that I didn&rsquo;t want the algorithmic
feed once already. At most every five tweets there is an ad. It&rsquo;s hellish.</p>
<p>Like a lot of people from my community I&rsquo;ve landed on Mastodon. It&rsquo;s quieter,
more peaceful, and more pleasant. Not everyone has made it over there, and that
obviously makes me sad for the loss of insight and interaction with my friends
lives. But Mastodon gives me what I got from the birdshite all those years ago
without all the garbage fires that now pollute the place.</p>
<p>So you can find me at <a href="https://mastodon.gamedev.place/@neilhenning">https://mastodon.gamedev.place/@neilhenning</a>, where I&rsquo;ll be posting the usual mix of dog
photos, coding funtimes, and the occassional link out to my blog.</p>
<p>I won&rsquo;t be <strong>deleting</strong> my birdshite account - not for any loyalty or desire to
return, but the advice from people leaving is that if you leave someone or some
bot will hoover up your account handle and likely impersonate you. So I&rsquo;ll just
let the account lie in limbo.</p>
]]></description>
    </item>
    
    <item>
      <title>I&#39;ve Joined Epic to Work on Verse</title>
      <link>https://www.neilhenning.dev/posts/joined-epic/</link>
      <pubDate>Mon, 21 Nov 2022 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/joined-epic/</guid>
      <description><![CDATA[<p>After four relaxing weeks off since <a href="https://www.neilhenning.dev/posts/leaving-unity/">I left Unity</a>,
I&rsquo;m pleased to announce I&rsquo;ve joined the Verse team over at Epic.</p>
<p>Today was my first day, so <em>obviously</em> this is the day that I feel the most like
an impostor! I&rsquo;ve done this a few times now (jumping contract to contract when
I worked at Codeplay, and then moving to AMD, Unity, and now Epic), and the
feeling always passes once you become familiar with the way things are done at
the new gig. The team have all been amazingly nice at answering my dumb
questions so far, and I&rsquo;m excited to get my teeth into solving some problems soon.</p>
]]></description>
    </item>
    
    <item>
      <title>Floating Point Compression Revisited</title>
      <link>https://www.neilhenning.dev/posts/floating-point-compression-revisited/</link>
      <pubDate>Mon, 24 Oct 2022 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/floating-point-compression-revisited/</guid>
      <description><![CDATA[<p>In a <a href="/posts/2022-09-17-floatingpointcompression/">previous post</a> I looked at floating-point compression, and it generated quite a lot of interest on Twitter, with lots of people suggesting things. So I haven&rsquo;t tried them all (only the first few that people suggested), but I thought I&rsquo;d present the results I did try. First, the chart!</p>
<p><img src="/images/floating-point-compression/floatcompressionchart.png" alt="A chart of different floating-point compression methods. I’ll talk in detail further on, so the chart isn’t a necessity (more a pretty picture to make the post nicer!)"></p>
<p>There was three different approaches that I looked at with this chart.</p>
<h2 id="zfp">zfp</h2>
<p>One thing that was suggested was <a href="https://computing.llnl.gov/projects/zfp">zfp</a> which claims to compress floating-points really well. I really disliked the API to get this to work - really hard to use. Also it doesn&rsquo;t have a streaming API, so you need to declare up front how many floats are in it. Given that I&rsquo;m compressing 16GB worth of floating point numbers, I didn&rsquo;t want to load up all 16GB of them at one go! So the approach I used was to batch them into 128MB regions, and compress these. Overall zfp achieves a <strong>1.8x</strong> compression ratio against the raw data - which is <strong>4x</strong> worse than the best compression we&rsquo;ve achieved.</p>
<p>If we look at the compression ratio of each individual chunk in the chart below, we can see where we are losing out:</p>
<p><img src="/images/floating-point-compression/zfp.png" alt="A chart of the compression ratio for each zfp chunk)"></p>
<p>As we can see in the chart, the compression ratio of zfp is really good for the densely populated [0..1] range of floating-point numbers - getting a <strong>6x</strong> compression ratio. It&rsquo;s pretty terrible for the higher numbers though, hovering around <strong>1.03x</strong> on average. Meaning basically no compression here at all. The higher inputs to cos will result in vastly different outputs, so its no suprising that the compression is worse up there.</p>
<h2 id="fpzip">fpzip</h2>
<p>Another was <a href="https://computing.llnl.gov/projects/fpzip">fpzip</a>. Similarly to zfp above, there is no streaming API and I thus need to batch the input data. I choose the same chunk size of 128MB.</p>
<p><img src="/images/floating-point-compression/fpzip.png" alt="A chart of the compression ratio for each fpzip chunk in log scale)"></p>
<p>Firstly - note the log scale for the chart. That&rsquo;s because fpzip achieves a much much higher compression ratio for the numbers in the [0..1] range of floating point (almost a <strong>14000x</strong> compression ratio, nice!). But it still suffers badly when the outputs from cos get wildly different - hovering around <strong>1.09x</strong> on average. The compression ratio is better than zfp, with a <strong>2.43x</strong> compression ratio overall compared to the raw data size, but it is still <strong>2.98x</strong> worse than the best compression we have achieved.</p>
<h2 id="per-bit-compression">Per-Bit Compression</h2>
<p>The best approach suggested was what if instead of doing a single zstd for the entire data stream, what if we do 32 zstd compressions, one for each bit of each float in the input stream? The general idea from people who proposed this approach was that <em>so many</em> of the bits would be consistent across subsequent output numbers, zstd would be much better at considering each bit separately.</p>
<p>This turned out to be the <strong>best approach</strong> I tested - zstd at compression level 10 was <strong>2.9x</strong> more compressed doing per-bit compressed streams, and at compression level 21 it is <strong>1.33x</strong> more compressed. Pretty cool!</p>
<p>Strangely xor&rsquo;ing the previous with the current and then doing the per-bit calculation resulted in a worse zstd compression, but delta-encoding the previous with the current gave us a slightly higher compression ratio.</p>
<p>Also of note - doing delta-encoding with the per-bit zfp compression at zstd level 10 was <strong>1.06x</strong> more compressed than doing the next best full-stream compression of xor&rsquo;ing and zstd at compression level 21. This is interesting because compressing at level 10 was many many times faster to compute than using level 21.</p>
<h2 id="other-approaches">Other Approaches</h2>
<p>There are for sure other approaches we could use here. Using the cos identity <code>cos(x) = cos(-x)</code> would cut the encoding range in half (as long as we correctly sign any NaNs produced). We could use a bit precise Payne-Hanek reduction so that we store only the [0..2π]range in the table. Food for thought (but I think I&rsquo;ve scratched my itch with this problem for now!).</p>
]]></description>
    </item>
    
    <item>
      <title>I&#39;m Leaving Unity</title>
      <link>https://www.neilhenning.dev/posts/leaving-unity/</link>
      <pubDate>Fri, 21 Oct 2022 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/leaving-unity/</guid>
      <description><![CDATA[<p>After three years of work at Unity I&rsquo;m leaving the company, today being my last day. I&rsquo;m immensely proud of the work I did to make Burst and HPC# so powerful for our users both within and outwith Unity, and to have worked with some really great people along the way.</p>
<p>I fulfilled a lifelong ambition to work closely with some heroes of mine like <a href="https://twitter.com/deplinenoise">Andreas Fredriksson</a>, <a href="https://twitter.com/daniel_collin">Daniel Collin</a>, <a href="https://twitter.com/postgoodism">Cort Stratton</a>, and many others, and I met some truly amazing people at Unity who I didn&rsquo;t previously know (<a href="https://twitter.com/SavourySnaX">Lee Hammerton</a>, <a href="https://twitter.com/s4schoener/">Sebastian Schöner</a>, <a href="https://twitter.com/AlexThib2">Alex Thibodeau</a>, <a href="https://twitter.com/_tim_jones_">Tim Jones</a>, <a href="https://twitter.com/xoofx">Alexandre Mutel</a>, among many others).</p>
<h2 id="achievements-of-my-time-at-unity">Achievements of my Time at Unity</h2>
<p>It&rsquo;s quite hard to realise how much of a game changer Burst and HPC# has been for Unity and it&rsquo;s users. <strong>8x</strong> performance wins were considered <em>low</em> when using Burst - I frequently remember people being amazed when they refactored for the constraints of HPC# that they would see <strong>40x</strong> performance gains.</p>
<p>When I was interviewing for Unity the pitch for Burst was that maybe a hundred jobs would be written in HPC# and compiled with Burst - the absolute core logic of the game that needed to run as fast as possible. Burst was so successful and provided so much performance that I&rsquo;ve seen shipping titles with over <strong>six thousand</strong> Bursted methods - games that <em>could never</em> ship without Burst.</p>
<p>After shipping six versions of Burst during my tenure here, I can really break down my achievements at Unity into three parts: performance, compile time, and startup time.</p>
<h3 id="performance">Performance</h3>
<p>My main job at Unity was to extract every iota of performance out of our LLVM codepath with Burst. I have eleven years of experience with LLVM as a technology, so I brought all that knowledge to Burst.</p>
<ul>
<li>I added a custom alias-analysis that utilized all the knowledge from Unity&rsquo;s job system to make code run fast</li>
<li>I completely reworked our LLVM pass pipeline to make it 2x faster</li>
<li>I reworked how we vectorize to ensure that vectorization succeeded in many many more cases than with stock LLVM</li>
<li>I added over 15 custom LLVM passes for missing optimizations specific to Burst</li>
<li>I reduced the final game executable size by <strong>43%</strong> on average</li>
</ul>
<p>I also added lots of ways users could tell the compiler about performance sensitive things:</p>
<ul>
<li><code>[NoAlias]</code> / <code>[AssumeRange]</code> attributes</li>
<li><code>Assume</code> / <code>Likely</code> / <code>Unlikely</code> / <code>Pause</code> / <code>Prefetch</code> / <code>umul128</code> / <code>InterlockedAnd</code> / <code>InterlockedOr</code> intrinsics</li>
<li>helper intrinsics to query if the compiler performed optimizations like <code>IsConstantExpression</code> / <code>ExpectAliased</code> / <code>ExpectNotAliased</code></li>
<li><code>DisableSafetyChecks = true</code> to let users bless certain Burst jobs as being safe, with a global option to <code>ForceOn</code> safety checks even for these jobs</li>
<li><code>OptimizeFor</code> for jobs to say what the optimization target was for the code (size, performance, just compile it fast)</li>
<li>per assembly <code>[BurstCompile]</code> attributes that lets you specify the default options for an entire assembly</li>
<li><code>F16C</code> and <code>FMA</code> x86 intrinsics</li>
</ul>
<h3 id="compile-time">Compile Time</h3>
<p>When I started we thought 100 jobs might be Bursted, and as I said before I&rsquo;ve seen titles with 6000 jobs today. That&rsquo;s a <strong>60x</strong> increase in content Burst has to compile, and so compile time became a real focus during my time here.</p>
<ul>
<li>cummulatively I improved the compile time with Burst by <strong>26x</strong> in my time here - so while the amount of content we are dealing with has grown significantly, the compile time hasn&rsquo;t grown linearly with it</li>
<li>I spent a lot of time with big users of Burst ensuring that code compiled fast and was highly optimized. For instance with NetCode I added Burst compiler optimizations that made compile time faster by <strong>39x</strong></li>
</ul>
<h3 id="startup-time">Startup Time</h3>
<p>One often overlooked thing with optimizations is that the <em>feel</em> of the product is oftentimes more important than the raw power. Burst has required over the years a lot of domain-reload time hooks to compile things, setup shared-statics, make direct call work - all these things would result in a cost when the editor starts, and when code changes are made by the user.</p>
<ul>
<li>I made direct call <strong>33x</strong> faster to process during domain reload and startup</li>
<li>I made shared statics <strong>13.3x</strong> faster when entering playmode</li>
<li>I made Burst load <strong>60x</strong> faster during initial startup</li>
<li>And code changes <strong>2x</strong> faster during domain reload</li>
</ul>
<p>Overall these changes didn&rsquo;t make the core work of Burst any faster (compilers still gotta compile), but the <em>feeling</em> of the editor being usable while Burst is background compiling is so important for the productivity of Unity&rsquo;s users.</p>
<h2 id="highlights-of-my-time-at-unity">Highlights of my Time at Unity</h2>
<p>Working with the Burst team, and a bunch of the people across DOTS more broadly was a highlight here. I learned a lot from a lot of people, and I hope I helped others too.</p>
<p>Being able to give people <em>what they need</em> from the compiler was so powerful. Hashing is slow? Here have a <code>umul128</code> intrinsic to make that fast. You don&rsquo;t understand what the compiler is doing? Here have an <code>ExpectAliased</code> intrinsic so you can compile-time enforce things that <em>you</em> - the user - <em>knows</em> , but want to be sure the compiler knows too.</p>
<p>But my biggest highlight is how closely we got to work with Unity&rsquo;s customers, and help them succeed. I was routinely told that Burst was amazing to deal with from a customer perspective because we were super responsive on the forums and on bugs, and we fixed our user issues in a fast and timely manner.</p>
<h2 id="why-am-i-moving-on">Why Am I Moving On?</h2>
<p>It was time for a change, for a new challenge.</p>
<p>This <a href="https://www.youtube.com/watch?v=NRnj_lnpORU">great talk</a> by <a href="https://twitter.com/BrianKaris">Brian Karis</a> had a line from Brian which I&rsquo;ll badly paraphrase to:</p>
<blockquote>
<p>What are the biggest challenges in your field, and why are you not working on them?</p>
</blockquote>
<p>This really hit home for me. I made Burst significantly better during my tenure at Unity, but I no longer felt that what I was doing day-in day-out was really working on the big compiler-focused challenges for the next ten years.</p>
<h2 id="what-now">What Now?</h2>
<p>I&rsquo;ve got some time off before my next gig begins and so I have the time to breathe out and relax for a bit.</p>
<p>I&rsquo;m super excited with what comes next - stay tuned for the details!</p>
]]></description>
    </item>
    
    <item>
      <title>Floating Point Compression - How Small Can We Get?</title>
      <link>https://www.neilhenning.dev/posts/2022-09-17-floatingpointcompression/</link>
      <pubDate>Mon, 17 Oct 2022 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/2022-09-17-floatingpointcompression/</guid>
      <description><![CDATA[<p><em>Editors prefix: I originally penned this in September, but got cold feet that I had somehow <strong>missed something crucial</strong> in my investigations, impostor syndrome reared its head, and I binned the post. But after being involved in a <a href="https://twitter.com/fatlimey/status/1581306707749539841?s=20&amp;t=EiyQMj7cGD1-YjUz8e8DcA">tweet thread</a> about the compressibility of these tables, I&rsquo;m gonna just publish my potentially flawed work incase someone notices something obvious!</em></p>
<p>Having implemented my fair share of drivers, and worked on a few languages too, one thing that has always interested me is how can we check that math functions are correct. OpenCL C has an <a href="https://github.com/KhronosGroup/OpenCL-CTS/blob/a87e686757f9fda5377baf73a32bb3c791eae70c/test_conformance/math_brute_force/reference_math.cpp#L3973">entire reference implementation of the math functions</a>, but if I recall on platforms without 80-bit floats, testing that double precision results matched meant <a href="https://github.com/KhronosGroup/OpenCL-CTS/blob/2d93b122c3078cd67a0528ad9e791dbcadaf03d6/test_common/harness/errorHelpers.cpp#L539">adding 0.5 ULP</a> to ensure your result matched. Not ideal!</p>
<p>But taking all that aside, if you have reference floating-point functions that you want to compare against that <em>do use</em> the floating point units on your machine, there are some fun things that can cause discrepencies. Like if you happen to have any library that uses fast-math, it can <a href="https://simonbyrne.github.io/notes/fastmath/">set the floating point control registers</a>.</p>
<p>The way I&rsquo;ve seen math function checking done correctly is by comparing the results against a soft-float library that has predictable results on all platforms. But how can we be sure that two platforms with the same reference code produce the same results? Ideally we&rsquo;d have to test two different platforms and compare each result matches. To do this without having to have two machines running concurrently, I wondered if it was possible to use <a href="https://www.mpfr.org/">MPFR</a> to generate every possible result of a math function where we can test the entire range before the heat death of the universe? A 32-bit single input function like <code>cos</code> would be possible to test, but every input to a 64-bit <code>cos</code> would not, or a two input 32-bit function like <code>pow</code> would also not be fully testable.</p>
<h2 id="the-raw-data">The Raw Data</h2>
<p>So each result value from <code>cos</code> for a 32-bit input is 32-bits and there are 4,294,967,296 resulting values - meaning the raw uncompressed data would be <strong>16GB</strong>. Not ideal for sending between machines! This data is the output from every representable floating-point number, starting at <code>0x00000000</code> (positive zero), all the way to <code>0xffffffff</code> (a negative NaN).</p>
<h2 id="zstd-to-the-rescue">ZSTD To the Rescue?</h2>
<p>My first thought was to use <a href="https://github.com/facebook/zstd">ZSTD</a> on a high compression level to compress the results, which resulted in a <strong>2.9GB</strong> result file, which is <strong>5.5x</strong> smaller. So obviously better, but still a lot of data to ship around.</p>
<p>Ok, so compression alone is not enough to fix this, can we use some knowledge of the resulting data to help the compression achieve a better result?</p>
<h2 id="some-data-gathering">Some Data Gathering</h2>
<p>So lets look at the graph of <code>cos</code>:</p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/0/06/Cosine.svg/512px-Cosine.svg.png" alt="A plot of the cosine function from Wikimedia"></p>
<p>We can see that in the range <code>[-1..1]</code> each next value should be close to the previous one. And if you didn&rsquo;t know, <a href="https://lemire.me/blog/2017/02/28/how-many-floating-point-numbers-are-in-the-interval-01/">over half the entire range of floating-point numbers lie in that range</a>. So for half the input data the resulting values should be close, and my guess was these would be 1 or 2 bits out on average. So the next thing I did was gather some stats on the entire range of <code>cos</code>:</p>
<ul>
<li>The sign of the output flips between positive and negative in <strong>20.36%</strong> of the consecutive outputs. Given that the high exponent inputs will result in wildly irregular outputs, my guess is these are primarily in these high exponent cases.</li>
<li>The average exponent difference between outputs is <strong>28.01</strong>. Again, I would expect this to be the high outputs that causes this.</li>
<li>If we delta encode the mantissa (by subtracting the previous mantissa from the current one), we need <strong>2.25 bytes</strong> on average to encode it (versus <strong>3 bytes</strong> required in the floating-point standard).</li>
<li>And if we xor the mantissa with the previous one, we need <strong>2.30 bytes</strong> on average.</li>
</ul>
<h2 id="xoring">Xoring</h2>
<p>So my first attempt was to just store the previous output from cos, and xor the current one with the previous:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>let next <span style="color:#f92672">=</span> current <span style="color:#f92672">^</span> previous;
</span></span></code></pre></div><p>The result? <strong>2.6GB</strong> when I xor then ZSTD the result, a <strong>0.3GB</strong> saving against raw ZSTDing. Better but not good enough.</p>
<h2 id="delta-encoding">Delta Encoding</h2>
<p>Next attempt was to just delta encode the entire number. Delta encoding just means we subtract the previous from the current, and store the &lsquo;delta&rsquo; between them instead of the original.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>let next <span style="color:#f92672">=</span> current <span style="color:#f92672">-</span> previous;
</span></span></code></pre></div><p>This took <strong>3.8GB</strong> - ouch! My guess is that with the sign flipping 20% of the time, in those cases the delta will be huge between the two numbers and we&rsquo;ll lose any benefit from the runs being close.</p>
<h2 id="varint-encoding-the-mantissa">Varint Encoding the Mantissa</h2>
<p>At this point - I was running out of ideas. But I remembered that <a href="https://aras-p.info/blog/2016/09/01/SPIR-V-Compression/">varint encoding could be used</a> to reduce the storage space for integers if the number is small enough. And given that for most of our range we should have relatively small differences in the mantissa between each encoded result and that we could encode <strong>3 bytes</strong> down to on average <strong>2.2 bytes</strong> based on the stats I collected earlier, would that help? I used the <a href="https://crates.io/crates/integer-encoding">integer-encoding</a> crate which automatically does zig-zag encoding for signed integers, and used that on the difference of the mantissas only (xor&rsquo;ing everything else).</p>
<p><strong>3.6GB</strong> of space taken. Damn!</p>
<h2 id="conclusion">Conclusion</h2>
<p>I&rsquo;m no compression expert, so there is <strong>probably</strong> some way to compress this better that I don&rsquo;t know about. But even so - my original idea of just shipping these across platforms was a bad one it turns out. It&rsquo;d have to get to below 500MB or thereabouts to make it feasible to ship this to multiple platforms (and you&rsquo;d have to do it for <em>every</em> math function you wanted to test too!).</p>
<p><em>Editors suffix: The next thing I would try is based on <a href="https://twitter.com/fatlimey/status/1581327091064532994?s=20&amp;t=EiyQMj7cGD1-YjUz8e8DcA">this tweet</a>, and use <a href="https://computing.llnl.gov/projects/fpzip">fpzip</a> to try compress the numbers, thanks to <a href="https://twitter.com/fatlimey">Robin Green</a>&rsquo;s suggestion!</em></p>
]]></description>
    </item>
    
    <item>
      <title>LLVM 15 Compile Time With Burst</title>
      <link>https://www.neilhenning.dev/posts/llvm-15-speed/</link>
      <pubDate>Wed, 21 Sep 2022 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/llvm-15-speed/</guid>
      <description><![CDATA[<p>With the <a href="https://docs.unity3d.com/Manual/com.unity.burst.html">Burst</a> compiler
that I work on here at Unity, we use LLVM to produce highly performant codegen
from the High Performance C# (HPC#) subset that we compile. We keep Burst
actively supported all the way back to LLVM 10, so it means that I can always
get an idea of the performance improvements (or regressions) that occur between
LLVM versions.</p>
<p>I&rsquo;ve used a big internal project that amounts to about 2.5 million lines of LLVM
IR after optimizations as the input for this test, and forced all LLVM versions
from LLVM 10 (the oldest supported) to LLVM 15 (the latest supported).</p>

<img src="/images/burst-llvm-15-performance.png"  alt="A chart showing the performance of LLVM across various LLVM versions"  class="center"  style="border-radius: 8px;"    />


<p>As you can see from the chart - performance improvements in LLVM were going
great until LLVM 13, and then LLVM 14 and now LLVM 15 have taken a pretty bad
leap back towards the performance of LLVM 10. We use the new pass manager on
LLVM versions 12 and above, so that is not the cause of this regression. We also
do not use opaque pointers (our codebase relies on typed pointers for now, won&rsquo;t
be easy to unpick that!).</p>
<p>I&rsquo;ve also heard people say that using <code>clang-cl.exe</code> will result in up to 30%
better performance as compared to using the <code>cl.exe</code> shipped with Visual Studio.</p>

<img src="/images/burst-llvm-15-performance-clang-cl.png"  alt="A chart showing the performance of LLVM using cl.exe and clang-cl.exe"  class="center"  style="border-radius: 8px;"    />


<p>And yup - its true. <strong>13%</strong> improved performance just for using the clang-based
compiler. I&rsquo;ll have to do a full performance rundown and check that
debuggability is still just as good with <code>clang-cl.exe</code>, but for that level of
performance improvement it looks like it is worth moving to.</p>
<p><strong>EDIT: I really should have provided the runtime performance across versions
too:</strong></p>

<img src="/images/burst-llvm-15-runtime-perf.png"  alt="A chart showing the runtime performance of LLVM across various LLVM versions"  class="center"  style="border-radius: 8px;"    />


<p><strong>As can be seen - its mostly in the noise, things got a little bit faster on LLVM 14, regressed slightly on LLVM 15, but overall not much between the versions for the significant differences in compile time.</strong></p>
]]></description>
    </item>
    
    <item>
      <title>Adding UTEST_SKIP to utest.h</title>
      <link>https://www.neilhenning.dev/posts/utest_skip/</link>
      <pubDate>Sun, 03 Jul 2022 12:18:05 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/utest_skip/</guid>
      <description><![CDATA[<p>A nice little feature I&rsquo;ve just added to my single header C/C++ unit testing
library <a href="https://github.com/sheredom/utest.h">utest.h</a> is the ability to skip a
test case. The motivation for this feature is from a
<a href="https://github.com/sheredom/utest.h/issues/100">user request</a>, and it
makes sense in the context that sometimes you might be refactoring some code, or
designing a new feature, and the tests aren&rsquo;t <em>quite</em> ready yet. You don&rsquo;t want
to comment out or delete the code, so what do you do?</p>
<p>To support this I&rsquo;ve
<a href="https://github.com/sheredom/utest.h/pull/103">submitted a PR</a> that adds a
<code>UTEST_SKIP</code>, which can be used like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#a6e22e">UTEST</span>(foo, bar) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">UTEST_SKIP</span>(<span style="color:#e6db74">&#34;Need to implement this test!&#34;</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>To let you skip the remainder of the test. Then when executing the test will
output:</p>
<pre tabindex="0"><code>[ RUN      ] foo.bar
   Skipped : &#39;Need to implement this test!&#39;
[  SKIPPED ] foo.bar (39ns)
</code></pre><p>And also reports at the end of execution before any failing tests:</p>
<pre tabindex="0"><code>[==========] 860 test cases ran.
[  PASSED  ] 859 tests.
[  SKIPPED ] 1 tests, listed below:
[  SKIPPED ] foo.bar
</code></pre><p>As a reminder you can get my library at
<a href="https://github.com/sheredom/utest.h">https://github.com/sheredom/utest.h</a>,
it works with mixed C/C++ content, and is
<a href="https://www.neilhenning.dev/posts/utest-h-performance/">blazingly fast</a>.</p>
]]></description>
    </item>
    
    <item>
      <title>Making the LLVM Legacy Pass Manager 1.65x Faster</title>
      <link>https://www.neilhenning.dev/posts/making-legacy-pass-manager-1_65x-faster/</link>
      <pubDate>Thu, 12 May 2022 15:18:05 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/making-legacy-pass-manager-1_65x-faster/</guid>
      <description><![CDATA[<p>One of the things I was going to talk about in my COVID cancelled EuroLLVM 2020
talk was about a neat little trick we used to get the LLVM legacy pass manager
to be significantly faster. So just in time for the legacy pass manager to
finally sail off into the coding afterlife I thought I&rsquo;d share the trick.</p>
<p>TL;DR running less passes makes things compile faster.</p>
<p>The longer version requires a bit more nuance though.</p>
<h2 id="llvms-passmanagerbuilder">LLVM&rsquo;s PassManagerBuilder</h2>
<p>LLVM has a default pass optimization pipeline that you create with the
<code>PassManagerBuilder</code> class:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>llvm<span style="color:#f92672">::</span>legacy<span style="color:#f92672">::</span>PassManager passManager;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>llvm<span style="color:#f92672">::</span>PassManagerBuilder passManagerBuilder;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// We can set the optimization level (-O0 .. -O3)
</span></span></span><span style="display:flex;"><span>passManagerBuilder.OptLevel <span style="color:#f92672">=</span> <span style="color:#ae81ff">3</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Or the size level (-Os -Oz)
</span></span></span><span style="display:flex;"><span>passManagerBuilder.SizeLevel <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// We can add passes at certain extension points.
</span></span></span><span style="display:flex;"><span>passManagerBuilder.<span style="color:#a6e22e">addExtension</span>(
</span></span><span style="display:flex;"><span>  llvm<span style="color:#f92672">::</span>PassManagerBuilder<span style="color:#f92672">::</span>EP_Peephole,
</span></span><span style="display:flex;"><span>  [](<span style="color:#66d9ef">const</span> llvm<span style="color:#f92672">::</span>PassManagerBuilder<span style="color:#f92672">&amp;</span> passManagerBuilder,
</span></span><span style="display:flex;"><span>     llvm<span style="color:#f92672">::</span>legacy<span style="color:#f92672">::</span>PassManagerBase<span style="color:#f92672">&amp;</span> passManager)
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    passManager.<span style="color:#a6e22e">add</span>(<span style="color:#a6e22e">burst_CreatePeepholePass</span>());
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>passManagerBuilder.<span style="color:#a6e22e">populateModulePassManager</span>(passManager);
</span></span><span style="display:flex;"><span>passManager.<span style="color:#a6e22e">run</span>(<span style="color:#f92672">*</span>module);
</span></span></code></pre></div><p>The pros for using the <code>PassManagerBuilder</code>:</p>
<ul>
<li>The best way to start running optimizations on your code</li>
<li>Can specify opt/size levels</li>
<li>Allows you to inject your own passes via extensions</li>
<li>Any LLVM update will have new passes ran at the correct times</li>
</ul>
<p>And the cons:</p>
<ul>
<li>Pass pipeline optimized for C/C++ content (it&rsquo;s used by Clang)</li>
<li>Some passes will probably do nothing as a result for your language</li>
<li>TBAA was unconditionally added to the pass pipeline - even though HPC# doesn&rsquo;t
have typed-based aliasiing guarantees</li>
</ul>
<p>Overall I&rsquo;d argue that using the default pass pipeline is what you should do,
unless you are willing to sink a decent chunk of time with every major LLVM
version bump to check all the new passes and work out if/where they should fit
in your custom pass pipeline.</p>
<h2 id="reducing-the-number-of-passes">Reducing The Number of Passes</h2>
<p>We wanted to be able to use <em>most of</em> what the <code>PassManagerBuilder</code>
provided, but cut out the passes that did nothing on Burst.</p>
<p>To do this we extended the <code>PassManager</code> class and added our own custom <code>add</code>
function that would let us do something before actually adding the pass into the
pass pipeline.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> MyPassManager final : public llvm<span style="color:#f92672">::</span>legacy<span style="color:#f92672">::</span>PassManager {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">add</span>(llvm<span style="color:#f92672">::</span>Pass<span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> pass) override {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span><span style="color:#f92672">*</span> name <span style="color:#f92672">=</span> pass<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">getPassName</span>();
</span></span><span style="display:flex;"><span>    llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">errs</span>() <span style="color:#f92672">&lt;&lt;</span> count <span style="color:#f92672">&lt;&lt;</span> <span style="color:#960050;background-color:#1e0010">“</span> <span style="color:#960050;background-color:#1e0010">”</span> <span style="color:#f92672">&lt;&lt;</span> name <span style="color:#f92672">&lt;&lt;</span> <span style="color:#960050;background-color:#1e0010">“\</span>n<span style="color:#960050;background-color:#1e0010">”</span>;
</span></span><span style="display:flex;"><span>    count<span style="color:#f92672">++</span>;
</span></span><span style="display:flex;"><span>    llvm<span style="color:#f92672">::</span>legacy<span style="color:#f92672">::</span>PassManager<span style="color:#f92672">::</span><span style="color:#a6e22e">add</span>(pass);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">unsigned</span> count <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>} passManager;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>llvm<span style="color:#f92672">::</span>PassManagerBuilder passManagerBuilder;
</span></span><span style="display:flex;"><span>passManagerBuilder.<span style="color:#a6e22e">populateModulePassManager</span>(passManager);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">printf</span>(<span style="color:#960050;background-color:#1e0010">“</span>Total <span style="color:#f92672">%</span>u<span style="color:#960050;background-color:#1e0010">\</span>n<span style="color:#960050;background-color:#1e0010">”</span>, passManager.count);
</span></span></code></pre></div><p>Which at the time I last ran this (in 2020, whatever LLVM version was active
then!) would produce:</p>
<pre tabindex="0"><code>0 Target Transform Information
1 Target Pass Configuration
2 Simplify the CFG
...
Total: 84
</code></pre><p>So we had <strong>84</strong> passes being run in the pass pipeline.</p>
<p>Now with Burst we use golden file generation to ensure we do not regress on the
optimizations that the compiler performs. This means that for every test in our
test suite, we generate the assembly for it and compare it against the last
known good assembly. We then verify any changes to this on each commit, to
ensure we maintain good code quality always. There are over 100,000 tests that
produce assembly into these gold files, which raised an interesting idea - I
could selectively disable each pass, run all the tests, and if there are no gold
file changes then the pass did nothing and could safely be removed.</p>
<p>To do this I used an environment variable <code>DISABLE_PASS_N</code> and skipped the
passes by:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> MyPassManager final : public llvm<span style="color:#f92672">::</span>legacy<span style="color:#f92672">::</span>PassManager {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">add</span>(llvm<span style="color:#f92672">::</span>Pass<span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> pass) override {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (count <span style="color:#f92672">==</span> skip) {
</span></span><span style="display:flex;"><span>      count<span style="color:#f92672">++</span>;
</span></span><span style="display:flex;"><span>      delete pass;
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    count<span style="color:#f92672">++</span>;
</span></span><span style="display:flex;"><span>    llvm<span style="color:#f92672">::</span>legacy<span style="color:#f92672">::</span>PassManager<span style="color:#f92672">::</span><span style="color:#a6e22e">add</span>(pass);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">MyPassManager</span>() {
</span></span><span style="display:flex;"><span>    skip <span style="color:#f92672">=</span> <span style="color:#a6e22e">atoi</span>(<span style="color:#a6e22e">getenv</span>(<span style="color:#960050;background-color:#1e0010">“</span>DISABLE_PASS_N<span style="color:#960050;background-color:#1e0010">”</span>));
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">unsigned</span> count <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>, skip <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>} passManager;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>llvm<span style="color:#f92672">::</span>PassManagerBuilder passManagerBuilder;
</span></span><span style="display:flex;"><span>passManagerBuilder.<span style="color:#a6e22e">populateModulePassManager</span>(passManager);
</span></span></code></pre></div><p>I could then re-run the test suite in a loop, running
<code>DISABLE_PASS_N=0 ./run_tests</code> for each of the 84 passes, and if the test suite
passed then the gold files weren&rsquo;t changed.</p>
<h2 id="how-many-could-we-disable">How Many Could We Disable?</h2>
<p>Turns out that <strong>13</strong> passes did nothing on Burst. And so to disable them we
used this lovely hackeroo:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> MyPassManager final : public llvm<span style="color:#f92672">::</span>legacy<span style="color:#f92672">::</span>PassManager {
</span></span><span style="display:flex;"><span>  llvm<span style="color:#f92672">::</span>SmallDenseSet<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>AnalysisID, <span style="color:#ae81ff">16</span><span style="color:#f92672">&gt;</span> skipSet;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">add</span>(llvm<span style="color:#f92672">::</span>Pass<span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> pass) override {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (skipSet.<span style="color:#a6e22e">count</span>(pass<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">getPassID</span>()) <span style="color:#f92672">!=</span> <span style="color:#ae81ff">0</span>) {
</span></span><span style="display:flex;"><span>      delete pass;
</span></span><span style="display:flex;"><span>      <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    llvm<span style="color:#f92672">::</span>legacy<span style="color:#f92672">::</span>PassManager<span style="color:#f92672">::</span><span style="color:#a6e22e">add</span>(pass);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">MyPassManager</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// We have to create all the passes so we can get their IDs
</span></span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> llvm<span style="color:#f92672">::</span>Pass<span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> passes[] <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>      llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createTypeBasedAAWrapperPass</span>(),
</span></span><span style="display:flex;"><span>      llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createForceFunctionAttrsLegacyPass</span>(),
</span></span><span style="display:flex;"><span>      llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createInferFunctionAttrsLegacyPass</span>(),
</span></span><span style="display:flex;"><span>      llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createCallSiteSplittingPass</span>(),
</span></span><span style="display:flex;"><span>      llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createCalledValuePropagationPass</span>(),
</span></span><span style="display:flex;"><span>      llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createPruneEHPass</span>(),
</span></span><span style="display:flex;"><span>      llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createSpeculativeExecutionPass</span>(),
</span></span><span style="display:flex;"><span>      llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createLibCallsShrinkWrapPass</span>(),
</span></span><span style="display:flex;"><span>      llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createPGOMemOPSizeOptLegacyPass</span>(),
</span></span><span style="display:flex;"><span>      llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createEliminateAvailableExternallyPass</span>(),
</span></span><span style="display:flex;"><span>      llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createGlobalDCEPass</span>(),
</span></span><span style="display:flex;"><span>      llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createAlignmentFromAssumptionsPass</span>(),
</span></span><span style="display:flex;"><span>      llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createStripDeadPrototypesPass</span>(),
</span></span><span style="display:flex;"><span>    };
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">const</span> llvm<span style="color:#f92672">::</span>Pass<span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> pass : passes) {
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// Insert the ID into the skip set, then delete the pass!
</span></span></span><span style="display:flex;"><span>      skipSet.<span style="color:#a6e22e">insert</span>(pass<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">getPassID</span>());
</span></span><span style="display:flex;"><span>      delete pass;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>} passManager;
</span></span></code></pre></div><p>Note: Burst doesn&rsquo;t have global variable support - you have to use
<code>SharedStatic</code>&rsquo;s to get access to global data that is shared between managed C#
code and HPC# with Burst. So a bunch of the global optimization passes are
expensive and useless for us.</p>
<h2 id="how-much-faster-was-compilation">How Much Faster Was Compilation</h2>
<p>In the end this change made our test suite <strong>1.64x faster</strong>, from 391s to 237s.
This translates into happier Burst developers (we&rsquo;re waiting on testing less),
happier CI (it takes less time to run the tests on PRs), and happier Unity users
(Burst compiled their code faster).</p>
<h2 id="the-future">The Future</h2>
<p>Since the fun filled days pre pandemic when I wrote this into the talk we&rsquo;ve
moved away from the above approach in Burst. This was because:</p>
<ul>
<li>We&rsquo;ve moved to the new pass manager for nearly all of our compilations now,
and the new pass manager doesn&rsquo;t have the same fudgeability as the old one</li>
<li>Even with the above reduction in passes, we decided that the cost to the team
to maintain a custom pass pipeline was worth it to improve compile time even
more. Our test suite has grown in size by 2.5x and we&rsquo;ve reduced the run time
of the test suite down to 150s - overall the compiler is about 4x faster than
what I was going to present about in 2020</li>
</ul>
<p>Even though this is soon to be dead tech with the death of the legacy LLVM pass
manager, I quite liked that this tiny code change could result in such a big win
for us and our users.</p>
]]></description>
    </item>
    
    <item>
      <title>Switching subprocess.h to posix_spawn</title>
      <link>https://www.neilhenning.dev/posts/posix_spawn/</link>
      <pubDate>Sun, 01 May 2022 13:18:05 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/posix_spawn/</guid>
      <description><![CDATA[<p>My single header C/C++ cross platform sub-process interaction library
<a href="https://github.com/sheredom/subprocess.h">subprocess.h</a> was designed using
<code>fork()</code> on Linux/macOS. But a little birdie told me that I should be looking
into using <code>posix_spawn()</code> instead as it was faster.</p>
<p>TL;DR - I&rsquo;ve <a href="https://github.com/sheredom/subprocess.h/commit/de3cbecd06d5a631e74ec6e77d03ec466d861726">switched the library to use POSIX spawn</a>.</p>
<p>There are <a href="https://blog.famzah.net/2009/11/20/fork-gets-slower-as-parent-process-use-more-memory/">various reasons fork can be slow</a>, so how does my library
fare? This is running on my MacBook Air (M1, 2020):</p>
<table>
	<thead>
			<tr>
					<th>process created</th>
					<th>fork()</th>
					<th>posix_spawn()</th>
					<th>% faster</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td>clang &ndash;version</td>
					<td>322.304us</td>
					<td>315.700us</td>
					<td>2%</td>
			</tr>
	</tbody>
</table>
<p>So it <strong>is faster</strong>, albeit not by a huge amount. Note this is a really synthetic
example where my parent process doesn&rsquo;t have a huge amount of state, but since
using POSIX spawn is already faster I pulled the trigger and merged it.</p>
]]></description>
    </item>
    
    <item>
      <title>Updated Website Theming</title>
      <link>https://www.neilhenning.dev/posts/new-website-theming/</link>
      <pubDate>Wed, 16 Mar 2022 11:16:05 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/new-website-theming/</guid>
      <description><![CDATA[<p>One ongoing complaint since I
<a href="https://www.neilhenning.dev/posts/switching-to-hugo/">moved from wordpress to hugo</a>
around three years ago was that the theming I decided on wasn&rsquo;t the best. It was
dark mode only, I used a non-serif font for the blog post contents making it
harder to read, and the reader mode didn&rsquo;t work right either.</p>
<p>So I&rsquo;ve attempted (and most likely failed) to switch over to a light mode theme,
used the lovely <a href="https://fonts.google.com/specimen/Alegreya">Alegreya</a> font as
the post font, and moved from the purplish theming to a more neutral bronzy/gold
look. Reader mode should now also work.</p>
<p>Hopefully a bit better overall for my readers!</p>
]]></description>
    </item>
    
    <item>
      <title>A Review of the Zig Programming Language (using Advent of Code 2021)</title>
      <link>https://www.neilhenning.dev/posts/2021-aoc-zig/</link>
      <pubDate>Mon, 27 Dec 2021 12:18:05 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/2021-aoc-zig/</guid>
      <description><![CDATA[<p>I&rsquo;ve long thought that <a href="https://ziglang.org/">Zig</a> was an interesting programming language, potentially
<em>more</em> interesting than Rust in many respects given that Zig seems to be
targetting a more modern C-like language replacement whereas Rust firmly looks
like it is trying to take C++ out back like ol&rsquo; yeller. Rust is powerful, but
the language is <em>complicated</em>, and no I&rsquo;m not talking about the borrow-checker
(a completely genius idea) but the language itself is vast and complex. Try and
read a moderately complex Rust crate and it can be mind boggling to work out
what is going on.</p>
<p>On the other hand Zig, with a strong ethos guided by
<a href="https://twitter.com/andy_kelley">Andrew Kelley</a>, has this guiding light that
there should be one way to do something in the language, and that is something
that I really appreciate in language design.</p>
<p>Last year I attempted to do Advent of Code 2020 in Zig, but the language was
just a little too fresh for me to get into. The documentation was basically
non-existent, and even getting the tools and working how to use them was too
confusing for me. On day one I gave up and switched to Rust instead. This year
though I was determined to try the whole challenge in Zig, and what a difference
a year has made to the language! The community is now massive, there are GitHub
templates for Advent of Code to just get you coding, and the
<a href="https://ziglang.org/documentation">Zig documentation</a> is so rich and detailed
that I could pick up some of the basic concepts quite quickly.</p>
<p>So now that I&rsquo;ve completed Advent of Code 2021, I thought I&rsquo;d share the good and
the bad about Zig, and some summary thoughts on the language.</p>
<blockquote>
<p>Note: I&rsquo;m assuming a base level of understanding about what Zig is here, there
are plenty of guides on the language available elsewhere!</p>
</blockquote>
<h3 id="the-good">The Good</h3>
<p>The best thing about Zig is that the language is small. There isn&rsquo;t even a
<del>foreach</del> <strong>for</strong> like structure and Andrew has stated <em>&lsquo;While loops work, why add another
way?&rsquo;</em> and I really appreciate this approach. It means I am not wondering about
what tool to reach for when I want to do something, there is a single tool with
a single use. Especially when learning a language (for myself and for anyone
else that would want to pick it up) - brevity is key. I think Rust got lost in
trying to nicely provide so much of what C++ badly provides that random users of
the language looking at any arbitrary code written in Rust suffer for the sheer
breadth of the language. Zig&rsquo;s approach here meant I could read the standard
library code and understand what it was doing (even with all the <code>comptime</code> type
fun!).</p>
<p>Nullability is fun in Zig - the fact that optionality is built into the language
with the <code>?</code> prefix on types (so <code>?i32</code> is maybe-a-32-bit-integer) and that they
have combined this with pointers so that you can assume that any pointer (<code>*i32</code>
for instance) <strong>isn&rsquo;t null</strong>. This is great for the compiler, great for the
optimizer, and I think also great for the user.</p>
<p>How things are brought in from the standard library or general foreign code is
interesting:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> std <span style="color:#f92672">=</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">import</span>(<span style="color:#e6db74">&#34;std&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> print <span style="color:#f92672">=</span> std.debug.print;
</span></span></code></pre></div><p>There is a builtin compiler marco <code>@import</code> that does the heavy lifting of
pulling in the code, and then you assign this into a <code>const some_var</code> variable.
This is really neat because you could call that whatever you wanted (to avoid
naming conflicts). Also when you want to pull in definitions from within an
imported package you just use the same mechanism of assigning the
<code>package.with.a.thing.in-it</code> into a constant variable. Most other languages have
a <code>using foo::bar::haz::baz;</code> type mechanism for this, but having it use the
same mechanism for a bunch of different things means that you don&rsquo;t have to
switch in your head to another tool. I hadn&rsquo;t considered this language concept
before using Zig, and its a very good idea!</p>
<p>The fact all containers take an allocator on intialization, and you can only
get a heap pointer via an allocator is <strong>genius</strong> in Zig. Memory isn&rsquo;t free, and
allocations are not cheap, and so making getting at heap allocations harder by
explicitly getting them through an allocator is a great thing.</p>
<p>Also the error mechanism in Zig is wonderful. Zig has this special prefix for a
type (for example <code>!u32</code> means <em>&lsquo;an error or a <code>u32</code>&rsquo;</em>) and you can cascade
errors from deep in Zig code with the <code>try</code> statement. So <code>var x = try foo();</code>
means <code>x</code> is equal to the result of <code>foo()</code> unless there was an error in the
result. If there was an error, return from the function with the error now. This
meant that you don&rsquo;t have the messy littering of if conditionals after every
function that you typically get in C, but you also don&rsquo;t have the complete
disaster that is exceptions in C++/C#. Rust has a similar mechanism to this, but
they use the clunkier <code>Result&lt;T, E&gt;</code>. While Zig has effectively added another
thing for the frontend to handle by adding in a <code>!</code> prefix on the types, the
language is certainly nicer for it.</p>
<h3 id="the-bad">The Bad</h3>
<p>There are a collection of things in Zig that I didn&rsquo;t like. All languages have
things that any random subset of users won&rsquo;t like, so I am not saying Zig should
change any of these or anything like that.</p>
<p>Initializing arrays is <em>weird</em> in Zig. Lets say you want to have a 0 initialized
array, you declare it like <code>[_]u8{0} ** 4</code> which means I want an array, of type
<code>u8</code>, that is initialized to <code>0</code> and is <code>4</code> elements long. You get used to the
syntax, but it&rsquo;s not intuitive.</p>
<p>For loops are a bit strange too - you write <code>for (items) |item| {}</code>, which means
you specify the container before the per-element variable. Mentally I think of
for as <code>for something in many_things {}</code> and so in Zig I constantly had to write
it wrong and then rewrite. Also you use the <code>|</code> character in Zig quite a lot,
and while this may just be a problem with Apple UK keyboards, actually getting
to the <code>|</code> character on my laptop was uncomfortable. When doing C/C++ or Rust,
you use the <code>|</code> character <em>much less</em> and so the pain of writing the character
was something I never noticed before.
<a href="https://twitter.com/Jonathan_Blow">Jonathan Blow</a> has gone on the record to say
that with his language, Jai, he spent a lot of time working out how easy it
would be to type common things, such that the more common an operation in the
language, the easier it would be to type. That seems to be missing here (well at
least for Apple UK keyboard layouts, I&rsquo;d need to write Zig extensively on
another layout to know whether this was a universal thing!).</p>
<p>Switch statements where you want to have multiple arguments resolve to the same
code I wrote as <code>a | b</code>, whereas in Zig it is <code>a, b</code>. Nothing major with this,
but I constantly tripped up on this.</p>
<p>Zig test was a bit clunky - you have to specify the file you want to test. So to
test <code>src/foo.zig</code>, you&rsquo;d do <code>zig test src/foo.zig</code>. I wanted something more
like Rust&rsquo;s <code>cargo test</code> that&rsquo;d find all tests and run them. Maybe Zig does have
this but I just didn&rsquo;t find it?</p>
<p>And how you declare functions is a little strange. Like a function in a struct
would be:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> foo <span style="color:#f92672">=</span> <span style="color:#66d9ef">struct</span> {
</span></span><span style="display:flex;"><span>  pub fn <span style="color:#a6e22e">bar</span>() {}
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p><strong>Everything</strong> in Zig is <code>const x = blah;</code>, so why are functions not
<code>const bar = function() {};</code>?</p>
<h3 id="the-ugly">The Ugly</h3>
<p>Zig is still a little raw in a few areas. Some compile errors are less than
useful. For instance if you forgot to put <code>!T</code> on a return type, but were using
<code>try</code> in the body of the function, the compiler error was very confusing. This
is only really an issue for new Zig users (like I was when I first hit this),
because you quickly learn that when the compiler spits out something less than
useful and you are using <code>try</code>, check the return type first. Occassionally Zig
would spit out 100&rsquo;s of lines of notes after an error, giving me flashbacks to
the C++ template mess errors you&rsquo;d get.</p>
<p>The builtin compiler macros (that start with <code>@</code>) are a bit confusing. Some of
them have a leading uppercase, others a lowercase, and I never did work out any
pattern to them. Is it <code>@as</code> or <code>@As</code>? I still couldn&rsquo;t tell you without looking
at the manual.</p>
<p>The type system in Zig is loose in some ways and tight in others. If Zig can
detect the type of the right hand side of a variable declaration, you don&rsquo;t need
an explicit type. But if you had something like <code>var x = 0;</code> you have to specify
a type. It&rsquo;d be nice for users (but obviously harder for the compiler team!) if
the compiler would be able to deduce these types too.</p>
<p>But the worst bit about Zig at present is the standard library documentation is
broken and non-existent. This is probably the one reason I <em>wouldn&rsquo;t</em> recommend
Zig more generally at present, because I resorted to looking at the source files
of the standard library on GitHub to work out what I could do with what provided
stuff in the standard library. I know there is a plan that with the new compiler
frontend (written in Zig!) to fix this, so its just a time problem.</p>
<h3 id="conclusion">Conclusion</h3>
<p>Overall my gut feeling is that Zig is about ready for developing with for people
like myself (coders that don&rsquo;t mind a bit of pain to a lot of benefit), but it
is not <em>quite</em> ready for more general usage. Fixing the standard library
documentation would be my biggest priority if I worked on Zig, because I think
that is the only thing holding back general usage of the toolchain.</p>
<p>One nugget of knowledge I&rsquo;ve worked out though - Zig <strong>is not</strong> a replacement
for C. It is another replacement for C++. <code>comptime</code> which while amazingly
powerful, already has echoes of the hard to reason about C++ template code or
Rust generic mess, and there are still quite a few bits of syntatic sugar hiding
the real cost of certain operations (like the <code>try</code> error handling, there is
implicit branches everywhere when you use that).</p>
<p>This isn&rsquo;t to say Zig is any lesser by being a <strong>much better</strong> C++ replacement
rather than a C replacement in my estimation, infact I&rsquo;d argue that aslong as
Zig doesn&rsquo;t fall into Rust&rsquo;s trap of constantly adding yet more ways to do the
same damn thing and making the language that little bit harder for new people to
onboard with, then Zig once it hits a stable language around 1.0 will be my
recommended tool going forward.</p>
<p>I really enjoyed doing Advent of Code in Zig, and I think I&rsquo;ll be writing more
software in Zig going forward. I&rsquo;d highly recommend you check out the language
and the community around the language are a great group of people that have been
super helpful with my dumb onboarding questions.</p>
]]></description>
    </item>
    
    <item>
      <title>Porting Burst to the New LLVM Pass Manager</title>
      <link>https://www.neilhenning.dev/posts/llvm-new-pass-manager/</link>
      <pubDate>Thu, 27 May 2021 14:59:05 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/llvm-new-pass-manager/</guid>
      <description><![CDATA[<p>Last week the Burst team shook up our day-to-day schedules with the opposite of a Unity classic - the hackweek. Unity has a strong culture around taking a week or two a year (once with the whole company, maybe once with your team), to hack on something that you think might be an interesting avenue for the future of Unity. These projects have often been spun out into products or parts of products in their own right.</p>
<p>But what about the opposite of hacking - what about spending some time consolidating what is currently there and working on the things that you really think will benefit the product over all, but haven&rsquo;t had the time to work on. We did exactly that last week.</p>
<p>One thing that has been bugging me since LLVM 12 landed was that we were still using the <em>legacy pass manager</em>, which was the default optimization pipeline for LLVM for every release prior to LLVM 12. But in LLVM 12 they finally, after about 7 years since I first heard about the new pass manager, pulled the trigger and switched the default pipeline over. Since the legacy pass manager is still in the codebase (it is still actually being used at present to power the backend infrastructure), we didn&rsquo;t have to use the new one with Burst. But the writing is clearly on the wall for the legacy pass manager, and I&rsquo;ve heard and read claims that the new pass manager does some things better than the legacy one, maybe meaning faster compilation or better codegen.</p>
<p>So TL;DR I&rsquo;ve added the new pass manager support to Burst, and here is a brain dump of how I went about it incase there is anyone else wanting to attempt the feat - hopefully you can avoid a few of the landmines I trod on!</p>
<h2 id="porting-over-a-pass">Porting Over a Pass</h2>
<p>The first thing is - how do you port a pass over from the legacy pass manager to the new one. Keep in mind that our code with Burst has to support LLVM 8..12 at present (for various platform reasons), so all my passes <strong>must</strong> work with the legacy pass manager and the new one concurrently, in the same codebase. I&rsquo;d argue that you should do this approach anyway even if you want to abandon the legacy pass manager because:</p>
<ul>
<li>While porting both the legacy and the new pass manager code should work in the same codebase, letting you A/B test the changes for any regressions.</li>
<li>Also lets you do performance profiling between the pass managers too.</li>
<li>Even after landing you might yet find some corner case in the new pass manager that is broken and need to switch back to the old approach.</li>
</ul>
<p>So let&rsquo;s take one of our custom passes in Burst - a pass that does a much more extensive job of removing dead loops from the code. We need this pass because we found a bunch of cases where vectorization was blocked by a dead inner loop. The pass structure looked like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> DeadLoopRemovalPass final : public llvm<span style="color:#f92672">::</span>FunctionPass
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">DeadLoopRemovalPass</span>() <span style="color:#f92672">:</span> llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">FunctionPass</span>(ID) {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">bool</span> <span style="color:#a6e22e">runOnFunction</span>(llvm<span style="color:#f92672">::</span>Function<span style="color:#f92672">&amp;</span> function) override;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">getAnalysisUsage</span>(llvm<span style="color:#f92672">::</span>AnalysisUsage<span style="color:#f92672">&amp;</span> analysisUsage) <span style="color:#66d9ef">const</span> override;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    llvm<span style="color:#f92672">::</span>StringRef <span style="color:#a6e22e">getPassName</span>() <span style="color:#66d9ef">const</span> override { <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Burst Dead Loop Removal&#34;</span>; }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">char</span> ID;
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">char</span> DeadLoopRemovalPass<span style="color:#f92672">::</span>ID;
</span></span></code></pre></div><p>So I first looked at how LLVM did the dual support for legacy/new pass managers. Their general overall approach is one of two ways:</p>
<ul>
<li>Either they have a wrapper around the new pass manager structure, providing the same code to the legacy pass manager.</li>
<li>Or they have a shared class that both the legacy/new pass managers will use.</li>
</ul>
<p>I decided to use the latter approach, for no reason other than it seemed easier to port over to.</p>
<h3 id="the-implementation-struct">The Implementation Struct</h3>
<p>To do this I first removed the dependency of the struct above on the legacy <code>llvm::FunctionPass</code>, and made it a standalone struct:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> DeadLoopRemoval final
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    explicit <span style="color:#a6e22e">DeadLoopRemoval</span>() {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">bool</span> <span style="color:#a6e22e">run</span>(
</span></span><span style="display:flex;"><span>        llvm<span style="color:#f92672">::</span>Function<span style="color:#f92672">&amp;</span> function,
</span></span><span style="display:flex;"><span>        std<span style="color:#f92672">::</span>function<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>LoopInfo<span style="color:#f92672">&amp;</span> ()<span style="color:#f92672">&gt;</span>,
</span></span><span style="display:flex;"><span>        std<span style="color:#f92672">::</span>function<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>DominatorTree<span style="color:#f92672">*</span> ()<span style="color:#f92672">&gt;</span>,
</span></span><span style="display:flex;"><span>        std<span style="color:#f92672">::</span>function<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>PostDominatorTree<span style="color:#f92672">*</span> ()<span style="color:#f92672">&gt;</span>) <span style="color:#66d9ef">const</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">static</span> llvm<span style="color:#f92672">::</span>StringRef <span style="color:#a6e22e">getPassName</span>() { <span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Burst Dead Loop Removal&#34;</span>; }
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p>Which entailed:</p>
<ul>
<li>Removing the inherit from <code>llvm::FunctionPass</code>.</li>
<li>Removing the <code>static char ID</code>.</li>
<li>Morphing <code>runOnFunction</code> -&gt; <code>run</code>, and passing in callbacks to retrieve the analysis information I required to implement the pass. I changed the name from <code>runOnFunction</code> -&gt; <code>run</code> just so that it gave me compile errors at the callsite as I was porting so I could find everything. Also note the <code>override</code> disappears from the function because we have no abstract virtual function to overload.</li>
<li>Changed <code>getPassName()</code> to be a static function and removed the <code>override</code>. The new pass manager uses a static pass name retriever whereas the old used a virtual member function - so this allows us to support both.</li>
</ul>
<h3 id="the-legacy-wrapping-pass">The Legacy Wrapping Pass</h3>
<p>Then before I even touched the new pass manager, I implemented the original pass for the legacy pass manager again, but making it just wrap the logic of the pass from the new <code>DeadLoopRemoval</code> struct:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> DeadLoopRemovalLegacyPass final : public llvm<span style="color:#f92672">::</span>FunctionPass
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">DeadLoopRemovalLegacyPass</span>() <span style="color:#f92672">:</span> llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">FunctionPass</span>(ID) {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">bool</span> <span style="color:#a6e22e">runOnFunction</span>(llvm<span style="color:#f92672">::</span>Function<span style="color:#f92672">&amp;</span> function) override
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (<span style="color:#a6e22e">skipFunction</span>(function))
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> false;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">auto</span> getLI <span style="color:#f92672">=</span> [<span style="color:#f92672">&amp;</span>]() <span style="color:#f92672">-&gt;</span> llvm<span style="color:#f92672">::</span>LoopInfo<span style="color:#f92672">&amp;</span>
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> getAnalysis<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>LoopInfoWrapperPass<span style="color:#f92672">&gt;</span>().<span style="color:#a6e22e">getLoopInfo</span>();
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">auto</span> getDT <span style="color:#f92672">=</span> [<span style="color:#f92672">&amp;</span>]() <span style="color:#f92672">-&gt;</span> llvm<span style="color:#f92672">::</span>DominatorTree<span style="color:#f92672">*</span>
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            llvm<span style="color:#f92672">::</span>DominatorTreeWrapperPass<span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> dominatorTreeWrapperPass <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>                getAnalysisIfAvailable<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>DominatorTreeWrapperPass<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> dominatorTreeWrapperPass <span style="color:#f92672">?</span>
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">&amp;</span>dominatorTreeWrapperPass<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">getDomTree</span>() <span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>                nullptr;
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">auto</span> getPDT <span style="color:#f92672">=</span> [<span style="color:#f92672">&amp;</span>]() <span style="color:#f92672">-&gt;</span> llvm<span style="color:#f92672">::</span>PostDominatorTree<span style="color:#f92672">*</span>
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            llvm<span style="color:#f92672">::</span>PostDominatorTreeWrapperPass<span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> postDominatorTreeWrapperPass <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>                getAnalysisIfAvailable<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>PostDominatorTreeWrapperPass<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> postDominatorTreeWrapperPass <span style="color:#f92672">?</span>
</span></span><span style="display:flex;"><span>                <span style="color:#f92672">&amp;</span>postDominatorTreeWrapperPass<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">getPostDomTree</span>() <span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>                nullptr;
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> pass.<span style="color:#a6e22e">run</span>(function, getLI, getDT, getPDT);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">getAnalysisUsage</span>(llvm<span style="color:#f92672">::</span>AnalysisUsage<span style="color:#f92672">&amp;</span> analysisUsage) <span style="color:#66d9ef">const</span> override
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// We need loop analysis to replace our intrinsics.
</span></span></span><span style="display:flex;"><span>        analysisUsage.addRequired<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>LoopInfoWrapperPass<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>        analysisUsage.addPreserved<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>LoopInfoWrapperPass<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// We will use the dominator tree, and preserve it during this pass. We
</span></span></span><span style="display:flex;"><span>        <span style="color:#75715e">// do this because recalculating the dominator tree after this pass was
</span></span></span><span style="display:flex;"><span>        <span style="color:#75715e">// much more expensive than just preserving it.
</span></span></span><span style="display:flex;"><span>        analysisUsage.addPreserved<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>DominatorTreeWrapperPass<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>        analysisUsage.addPreserved<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>PostDominatorTreeWrapperPass<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    llvm<span style="color:#f92672">::</span>StringRef <span style="color:#a6e22e">getPassName</span>() <span style="color:#66d9ef">const</span> override { <span style="color:#66d9ef">return</span> DeadLoopRemoval<span style="color:#f92672">::</span><span style="color:#a6e22e">getPassName</span>(); }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">char</span> ID;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>private:
</span></span><span style="display:flex;"><span>    DeadLoopRemoval pass;
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">char</span> DeadLoopRemovalLegacyPass<span style="color:#f92672">::</span>ID;
</span></span></code></pre></div><p>So this code is pretty straight-forward, I started with a copy-paste of the original pass and then started hacking it to use the new struct underneath:</p>
<ul>
<li>I first added the <code>DeadLoopRemoval pass</code> member to the struct.</li>
<li>Then I forwarded the <code>getPassName()</code> member virtual function to the static method in the implementing struct.</li>
<li>For the <code>runOnFunction</code> body I had to query the analysis passes I required in the lambdas, and pass these to the <code>pass.run</code> method.</li>
</ul>
<p>At this point I can test the ported pass with our existing test suite and the legacy pass manager, to ensure that worked before doing anything else. And it did! So next up, lets port it to the new pass manager.</p>
<h3 id="the-new-wrapping-pass">The New Wrapping Pass</h3>
<p>The new pass manager uses a mixin approach with the Curiously Recurring Template Pattern (CRTP, we&rsquo;ll come back to this) to implement the structure. This means no virtuals, no overrides, but there is still a specific function you are expected to provide. For a function pass you implement <code>llvm::PreservedAnalyses run(llvm::Function&amp;, llvm::FunctionAnalysisManager&amp;)</code> for instance. Our new pass manager wrapping pass thus looks like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> DeadLoopRemovalPass final : public llvm<span style="color:#f92672">::</span>PassInfoMixin<span style="color:#f92672">&lt;</span>DeadLoopRemovalPass<span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    explicit <span style="color:#a6e22e">DeadLoopRemovalPass</span>() <span style="color:#f92672">:</span> <span style="color:#a6e22e">pass</span>() {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    llvm<span style="color:#f92672">::</span>PreservedAnalyses <span style="color:#a6e22e">run</span>(llvm<span style="color:#f92672">::</span>Function<span style="color:#f92672">&amp;</span> function, llvm<span style="color:#f92672">::</span>FunctionAnalysisManager<span style="color:#f92672">&amp;</span> analysisManager)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">auto</span> getLI <span style="color:#f92672">=</span> [<span style="color:#f92672">&amp;</span>]() <span style="color:#f92672">-&gt;</span> llvm<span style="color:#f92672">::</span>LoopInfo<span style="color:#f92672">&amp;</span>
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> analysisManager.getResult<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>LoopAnalysis<span style="color:#f92672">&gt;</span>(function);
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">auto</span> getDT <span style="color:#f92672">=</span> [<span style="color:#f92672">&amp;</span>]() <span style="color:#f92672">-&gt;</span> llvm<span style="color:#f92672">::</span>DominatorTree<span style="color:#f92672">*</span>
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> analysisManager.getCachedResult<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>DominatorTreeAnalysis<span style="color:#f92672">&gt;</span>(function);
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">auto</span> getPDT <span style="color:#f92672">=</span> [<span style="color:#f92672">&amp;</span>]() <span style="color:#f92672">-&gt;</span> llvm<span style="color:#f92672">::</span>PostDominatorTree<span style="color:#f92672">*</span>
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> analysisManager.getCachedResult<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>PostDominatorTreeAnalysis<span style="color:#f92672">&gt;</span>(function);
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> (pass.<span style="color:#a6e22e">run</span>(function, getLI, getDT, getPDT))
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            llvm<span style="color:#f92672">::</span>PreservedAnalyses preserved;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            preserved.preserve<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>LoopAnalysis<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>            preserved.preserve<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>DominatorTreeAnalysis<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>            preserved.preserve<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>PostDominatorTreeAnalysis<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> preserved;
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>        {
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span> llvm<span style="color:#f92672">::</span>PreservedAnalyses<span style="color:#f92672">::</span><span style="color:#a6e22e">all</span>();
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">static</span> llvm<span style="color:#f92672">::</span>StringRef <span style="color:#a6e22e">name</span>() { <span style="color:#66d9ef">return</span> DeadLoopRemoval<span style="color:#f92672">::</span><span style="color:#a6e22e">getPassName</span>(); }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>private:
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> DeadLoopRemoval pass;
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p>Digging into this:</p>
<ul>
<li>Our pass derives from <code>llvm::PassInfoMixin&lt;DeadLoopRemovalPass&gt;</code>, taking itself as the template argument (the CRTP paradigm).</li>
<li>We have an implementation of the <code>run</code> method like I stated above.</li>
<li>We use the explicit <code>analysisManager</code> to get the analysis passes we require, rather than using the <code>getAnalysis</code> that the old pass manager used to get at these.</li>
<li>We do not return a true/false value from our <code>run</code> method like the legacy pass manager <code>runOnFunction</code>. True meant <em>&lsquo;something changed, analysis passes might be invalid!&rsquo;</em>. For the new pass manager we explicitly return an <code>llvm::PreservedAnalyses</code> which we add what passes we preserved into.</li>
<li>Also note the <code>static llvm::StringRef name()</code> method - this is how you set the pass name of the pass.</li>
</ul>
<p>And that&rsquo;s it! We now have our pass working both with the new and legacy pass managers. I had to do this same approach with all 20 of our custom LLVM passes, quite a lot of typing, but meant I could be sure at each step it was doing the right thing.</p>
<h2 id="porting-our-custom-pass-pipeline">Porting Our Custom Pass Pipeline</h2>
<p>We long since abandoned the default LLVM pass pipeline for a custom one.</p>
<blockquote>
<p>As an aside my COVID cancelled LLVM talk was going to explain how we cut the cost of using <code>llvm::PassManagerBuilder</code>&rsquo;s default optimization pass structure by 40% by cutting out the cruft from it while still using the builder, but even that wasn&rsquo;t enough control for us to get the abosolute best compile time possible.</p>
</blockquote>
<p>So our legacy pass manager usage involved us calling each of the LLVM passes (a mix of the standard ones and our custom ones, hand crafted for best codegen and compile time):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>mpm.<span style="color:#a6e22e">add</span>(<span style="color:#a6e22e">burst_CreateEarlyMemOptsLegacyPass</span>());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (optLevel <span style="color:#f92672">&gt;=</span> <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    mpm.<span style="color:#a6e22e">add</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createCFGSimplificationPass</span>());
</span></span><span style="display:flex;"><span>    mpm.<span style="color:#a6e22e">add</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createSROAPass</span>());
</span></span><span style="display:flex;"><span>    mpm.<span style="color:#a6e22e">add</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createEarlyCSEPass</span>());
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (optLevel <span style="color:#f92672">&gt;=</span> <span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    mpm.<span style="color:#a6e22e">add</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createIPSCCPPass</span>());
</span></span><span style="display:flex;"><span>    mpm.<span style="color:#a6e22e">add</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createGlobalOptimizerPass</span>());
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This is just a sample from the pass pipeline, but it gives you an idea I hope.</p>
<p>For the new pass pipeline I did the obvious (<strong>and wrong</strong>) thing of copying that and changing it to the new pass manager:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">burst_AddEarlyMemOptsPass</span>(mpm);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (optLevel <span style="color:#f92672">&gt;=</span> <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    mpm.<span style="color:#a6e22e">addPass</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">SimplifyCFGPass</span>());
</span></span><span style="display:flex;"><span>    mpm.<span style="color:#a6e22e">addPass</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">SROA</span>());
</span></span><span style="display:flex;"><span>    mpm.<span style="color:#a6e22e">addPass</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">EarlyCSEPass</span>());
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (optLevel <span style="color:#f92672">==</span> <span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    mpm.<span style="color:#a6e22e">addPass</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">IPSCCPPass</span>());
</span></span><span style="display:flex;"><span>    mpm.<span style="color:#a6e22e">addPass</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">GlobalOptPass</span>());
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>I did this for our entire pass pipeline, Visual Studio showed no errors! I hit compile, and explosions. It took me longer than I&rsquo;d care to admit to work out what the issue was - the new pass manager requires you to add a pass to the <strong>correct</strong> pass manager type.</p>
<p>With the legacy pass manager everything derived from <code>llvm::Pass</code>, including <code>llvm::ModulePass</code> and <code>llvm::FunctionPass</code>. Behind the scenes the pass manager would work out that you were using a function or module pass, and behind your back create a manager of the correct type (so if you used a function pass, it&rsquo;d make a function pass manager for you). This is a bad design, and so with the new pass managers they changed it.</p>
<p>Remember the CRTP thing I mentioned above? This is where it really hurts developers - Visual Studio didn&rsquo;t provide me with compile errors until I actually did a full compile, because the CRTP is basically an interface that requires all the templates to be instantiated with their implementing types, before it can work out you&rsquo;ve done the wrong thing. This shows up two bad bits of C++ - no interfaces (C# interfaces are so very nice for exactly this kind of issue), and templates nearly always result in horrific error messages. Very user hostile!</p>
<p>Because its been an easy 6 years since I last looked at the new pass manager (I honestly figured it would just die after such a long stint in the codebase but not being used by Clang), I took a look at the <code>llvm::PassBuilder</code> which helped me work out my mistake:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    llvm<span style="color:#f92672">::</span>FunctionPassManager fpm;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">burst_AddEarlyMemOptsPass</span>(fpm);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (optLevel <span style="color:#f92672">&gt;=</span> <span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>    {
</span></span><span style="display:flex;"><span>        fpm.<span style="color:#a6e22e">addPass</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">SimplifyCFGPass</span>());
</span></span><span style="display:flex;"><span>        fpm.<span style="color:#a6e22e">addPass</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">SROA</span>());
</span></span><span style="display:flex;"><span>        fpm.<span style="color:#a6e22e">addPass</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">EarlyCSEPass</span>());
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    mpm.<span style="color:#a6e22e">addPass</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">createModuleToFunctionPassAdaptor</span>(std<span style="color:#f92672">::</span><span style="color:#a6e22e">move</span>(fpm)));
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (optLevel <span style="color:#f92672">==</span> <span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    mpm.<span style="color:#a6e22e">addPass</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">IPSCCPPass</span>());
</span></span><span style="display:flex;"><span>    mpm.<span style="color:#a6e22e">addPass</span>(llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">GlobalOptPass</span>());
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>So you can see I had to explicitly make an <code>llvm::FunctionPassManager</code>, add the function passes to that, and then call <code>llvm::createModuleToFunctionPassAdaptor</code> to provide this function pass to the surrounding module pass manager. A bit verbose, and horrific template mess aside, a <strong>much much better</strong> design overall. This makes it really obvious now when you are mixing function pass managers with module passes in a poor way, because you have to re-create the function pass manager each time.</p>
<p>More explicit is always a win in my book.</p>
<p>Another thing that got me was that you have to manually register all the analysis passes you need with the analysis managers explicitly:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>llvm<span style="color:#f92672">::</span>PassBuilder<span style="color:#f92672">&amp;</span> pb; <span style="color:#75715e">// an already created pass builder
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>llvm<span style="color:#f92672">::</span>LoopAnalysisManager lam;
</span></span><span style="display:flex;"><span>pb.<span style="color:#a6e22e">registerLoopAnalyses</span>(lam);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>llvm<span style="color:#f92672">::</span>FunctionAnalysisManager fam;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>fam.<span style="color:#a6e22e">registerPass</span>([<span style="color:#f92672">&amp;</span>] { <span style="color:#66d9ef">return</span> llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">TargetIRAnalysis</span>(targetMachine<span style="color:#f92672">-&gt;</span>LLVM<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">getTargetIRAnalysis</span>()); });
</span></span><span style="display:flex;"><span>fam.<span style="color:#a6e22e">registerPass</span>([<span style="color:#f92672">&amp;</span>] { <span style="color:#66d9ef">return</span> llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">TargetLibraryAnalysis</span>(targetLibraryInfo); });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>llvm<span style="color:#f92672">::</span>AAManager aam;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>aam.registerFunctionAnalysis<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>BasicAA<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (optLevel <span style="color:#f92672">==</span> <span style="color:#ae81ff">3</span>)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    aam.registerFunctionAnalysis<span style="color:#f92672">&lt;</span>llvm<span style="color:#f92672">::</span>ScopedNoAliasAA<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (optLevel <span style="color:#f92672">&gt;=</span> <span style="color:#ae81ff">2</span>)
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">burst_AddExtraAliasAnalysisPass</span>(fam, aam);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>fam.<span style="color:#a6e22e">registerPass</span>([aam] { <span style="color:#66d9ef">return</span> std<span style="color:#f92672">::</span><span style="color:#a6e22e">move</span>(aam); });
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>pb.<span style="color:#a6e22e">registerFunctionAnalyses</span>(fam);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>llvm<span style="color:#f92672">::</span>CGSCCAnalysisManager cgam;
</span></span><span style="display:flex;"><span>pb.<span style="color:#a6e22e">registerCGSCCAnalyses</span>(cgam);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>llvm<span style="color:#f92672">::</span>ModuleAnalysisManager mam;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>pb.<span style="color:#a6e22e">registerModuleAnalyses</span>(mam);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>pb.<span style="color:#a6e22e">crossRegisterProxies</span>(lam, fam, cgam, mam);
</span></span></code></pre></div><p>Here I created an <code>llvm::PassBuilder</code> not to actually build the passes, but to build the analysis managers so that the analysis passes I required are available in the managers. There are some quirks:</p>
<ul>
<li>To provide an analysis to the analysis manager you pass in a callback that creates the pass. Note sure why this is needed (maybe have to delay the initialization?), but it confused me at the beginning!</li>
<li>To register our custom alias analysis we had to add that to a <code>llvm::AAManager</code>, and then register that with our function analysis manager.</li>
<li>You need to call <code>crossRegisterProxies</code> on the pass builder to make sure all the analysis managers know about each each (in the case that, say, a function requires a module-level analysis).</li>
</ul>
<h2 id="the-curious-case-of-the-optimized-optnone-functions">The Curious Case of the Optimized optnone Functions</h2>
<p>LLVM IR has a function level attribute <code>optnone</code> that disables optimization for a specific function. This is really useful for developers when they suspect there is a bug in a specific function, so they can just disable the optimizations there and work out what is going wrong more easily. When I ran our tests with the new pass manager, I noticed that our optimize none tests were&hellip; being optimized?! The functions have <code>optnone</code> on them, how could the pass manager be allowing them to be optimized?</p>
<p>In the legacy pass manager each pass has a <code>skipFunction</code> call on it that tells you if you should skip running on that function. If <code>optnone</code> was set, you&rsquo;d skip that function. The new pass manager of course doesn&rsquo;t use this mechanism and does something entirely different. Obviously.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>llvm<span style="color:#f92672">::</span>PassInstrumentationCallbacks passInstrumentationCallbacks;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>llvm<span style="color:#f92672">::</span>OptNoneInstrumentation <span style="color:#a6e22e">optNoneInstrumentation</span>(false);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>optNoneInstrumentation.<span style="color:#a6e22e">registerCallbacks</span>(passInstrumentationCallbacks);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>llvm<span style="color:#f92672">::</span>PassBuilder <span style="color:#a6e22e">pb</span>(targetMachine<span style="color:#f92672">-&gt;</span>LLVM, llvm<span style="color:#f92672">::</span><span style="color:#a6e22e">PipelineTuningOptions</span>(), llvm<span style="color:#f92672">::</span>None, <span style="color:#f92672">&amp;</span>passInstrumentationCallbacks);
</span></span></code></pre></div><p>You have to register an <code>llvm::OptNoneInstrumentation</code> with a <code>llvm::PassInstrumentationCallbacks</code>, which is then registered in the <code>llvm::PassBuilder</code> constructor. I need to lie down. This then ensures that any function with <code>optnone</code> won&rsquo;t be optimized through some arcane process I don&rsquo;t really understand.</p>
<h2 id="the-performance">The Performance</h2>
<p>I&rsquo;ve long been told that the new pass manager will result in better performance because of how analysis passes are preserved better. So I was excited to run our tests for the first time.</p>
<p>First up the compile time performance:</p>

<img src="/images/new-pass-manager/CompileTimePerformance.png"  class="center"  style="border-radius: 8px;"    />


<p>I&rsquo;ve got to admit - after first running this I was a <em>little</em> disappointed - the new pass manager was meant to magically make everything faster! Then after I calmed down a bit I realised - <em>this is fine</em>. Since we&rsquo;ve already got our own custom curated set of passes that are ordered specifically to not trash analysis passes unnecessarily, it stands to reason that we wouldn&rsquo;t see any magical uplift with the new pass manager. The fact we are seeing numbers that are effectively within the signal-to-noise of each other means that when we do switch to the new pass manager by default, things won&rsquo;t instantly go slower as a result. That&rsquo;s a win.</p>
<p>Now for the binary size:</p>

<img src="/images/new-pass-manager/BinarySize.png"  class="center"  style="border-radius: 8px;"    />


<p>Nothing really to write home about here - slightly higher with -O0 and -O1, and slightly lower with -O2 and -O3. I did a diff of the assembly and its just the usual slight reordering of passes - mostly the same instructions just sometimes in a different order. Again, this is good though - no regressions means we can safely make the switch.</p>
<h2 id="one-last-pain-point">One Last Pain Point</h2>
<p>One thing I generally like to do on Windows is use a <code>RelWithDebInfo</code> compiled LLVM with a <code>Debug</code> or <code>Release</code> compiled our code. This gets me the best of both worlds in terms of some debuggability while not running dreadfully slow. For some reason while this has always worked with the legacy pass manager, someone in the LLVM community has added a bunch of:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#ifndef NDEBUG
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// Some extra struct state!
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#endif
</span></span></span></code></pre></div><p>To some of the new pass manager structs.</p>
<p>They are doing this so that on debug builds they can carry around some extra state in the structs to aid debuggability, but this means that the struct layout is now <strong>different</strong> between <code>Debug</code> and <code>Release</code> builds. This is absolutely awful, and means my <code>RelWithDebInfo</code> compiled approach no longer works. This took me 4 hours to narrow down - I just assumed some of the template mess in the new pass manager was somehow going wrong, it was only when I started printing the size of structs that my head hit the desk. I hope someone can remove these - I&rsquo;d rather carry around the extra state always and not use it, than have structs change size depending on the optimization level.</p>
<h2 id="conclusion">Conclusion</h2>
<p>This work took me a week to do for our reasonably customized LLVM pass pipeline and custom passes. It is a <strong>lot</strong> of boiler plate for something that effectively does the same as before, but it does set us up more cleanly for the day that LLVM actually removes the legacy pass manager from the codebase entirely, meaning that when that day comes we aren&rsquo;t floundering. The new pass manager has some nice features, it is just a shame that C++ is so broken as a language that it takes walking through a wall of template errors to work out what went wrong.</p>
<p>And before anyone @&rsquo;s me - I know concepts will in theory fix this, just colour me highly skeptical on that count.</p>
<p>Until next time!</p>
]]></description>
    </item>
    
    <item>
      <title>Introducing envcache</title>
      <link>https://www.neilhenning.dev/posts/introducing-envcache/</link>
      <pubDate>Sat, 27 Mar 2021 07:59:05 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/introducing-envcache/</guid>
      <description><![CDATA[<p>One thing that has always bugged me with Rust is when you are interacting with
complex non-Rust software. Yes LLVM, I&rsquo;m looking at you! LLVM nearly always
requires you to either a) have <code>llvm-config</code> on the path already, or b) find an
LLVM install in some random place on the filesystem. I generally like to have a
version of LLVM built myself (using <code>RelWithDebInfo</code> and forcing asserts on)
that will naturally live at some arbitrary point in the filesystem - and then I
want to <em>somehow</em> point my Rust code that is using LLVM at that folder.</p>
<p>The general way to do this in Rust is to use an environment variable, and then
in a <code>build.rs</code> you can grab all the paths to the LLVM libraries for linking in.</p>
<p>For instance the <a href="https://crates.io/crates/llvm-sys">llvm-sys</a> crate has an
optional feature <code>no-llvm-linking</code> that lets you control where LLVM is sourced
from. I use this in a project I&rsquo;m cooking up to control how LLVM is brought into
my project. At present my workflow is something like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>LLVM_INSTALL_DIR<span style="color:#f92672">=</span>llvm-install cargo test
</span></span><span style="display:flex;"><span>cargo clippy
</span></span></code></pre></div><p>If you can see the problem already - when I run <em>other</em> commands on auto-pilot
like running <code>cargo clippy</code>, and I <strong>do not</strong> specify the <code>LLVM_INSTALL_DIR</code>,
the command fails to run because it requires <code>LLVM_INSTALL_DIR</code> to be specified.</p>
<p>Coming from a primarily CMake based workflow with my day-to-day job working with
LLVM, this completely does my head in. CMake has a way to cache variables and
then subsequent commands re-use the cached value. So I got thinking - why can&rsquo;t
I do something similar in Rust?</p>
<p>I&rsquo;d like to introduce a simple, dumb, but useful little crate -
<a href="https://crates.io/crates/envcache">envcache</a>. This crate lets you cache any
environment variables you want so they can be used across cargo commands. For
example, in a <code>build.rs</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">extern</span> crate envcache;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>use envcache<span style="color:#f92672">::</span>EnvCache;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>fn <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>    let mut envcache <span style="color:#f92672">=</span> EnvCache<span style="color:#f92672">::</span><span style="color:#a6e22e">new</span>();
</span></span><span style="display:flex;"><span>    envcache.<span style="color:#a6e22e">cache</span>(<span style="color:#e6db74">&#34;LLVM_INSTALL_DIR&#34;</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>By doing this simple thing above, it&rsquo;ll let me specify <code>LLVM_INSTALL_DIR</code> once,
and then have this cached value used thereafter for subsequent commands.</p>
<p>This works by saving a file in the <code>OUT_DIR</code> that you can write to with
<code>build.rs</code> - <code>envcache.config</code>. Crucially this means that if you run
<code>cargo clean</code> it&rsquo;ll wipe out the cache, and you&rsquo;ll need to re-specify the
environment variable. But it does mean you have to specify the environment
variable much less in general development which I find to be much nicer.</p>
<p>The source code is available <a href="https://github.com/sheredom/envcache">here</a>, and
I hope this is useful to some of you.</p>
]]></description>
    </item>
    
    <item>
      <title>Early 2021 Mega Update</title>
      <link>https://www.neilhenning.dev/posts/early-2021-mega-update/</link>
      <pubDate>Mon, 08 Feb 2021 20:30:39 +0100</pubDate>
      <guid>https://www.neilhenning.dev/posts/early-2021-mega-update/</guid>
      <description><![CDATA[<p>The last four years of my coding life have been incredibly stressful. In this
time I&rsquo;ve:</p>
<ul>
<li>Started a job at AMD in the GPU compiler team.</li>
<li>Left a job at AMD for Unity in the Burst compiler team.</li>
<li>Wrapped up my involvement as a creator of Vulkan and SPIR-V.</li>
<li>Learnt the C# and Rust programming languages.</li>
</ul>
<p>You couple this with the absolute trainwreck that was 2020 (COVID yay) and now
it looks like 2021 might be mostly a write-off too, and the fact that my dog
Benji has progressively worsening epilepsy that is horrific to witness - it is
safe to say that I&rsquo;m probably at the <strong>highest level</strong> of stress I&rsquo;ve ever been
under.</p>
<p>I do realise that I&rsquo;m in a very fortunate position nonetheless though - I have a
good and stable job at Unity, I live on a remote island with a big garden and
lots of places I can run while maintaining an easy social distancing. I know a
lot of people have it much worse - very much a first-world-problem level of
stress.</p>
<p>But one thing that has been nagging me for, and I admit with a good dose of
shame, this entire time was that the bug count on my open source C libraries had
creeped up to a level of real annoyance.</p>
<p>These issues could be broke up into a few categories:</p>
<ul>
<li>Later Clang/GCC would add new warnings that my libraries would fail on (I like
to ensure that all the libraries can compile with the full shebang of
<code>-Werror -Wall -Wextra</code>).</li>
<li>I didn&rsquo;t support clang-cl.exe on Windows at all (my libraries assumed that you
were using any of the Visual Studio compilers from 2008 to 2019).</li>
<li>There were a raft of general bugs people had found.</li>
<li>And a few quality of life feature requests thrown in there too.</li>
</ul>
<p>So in this early part of 2021 I&rsquo;ve went on a pretty severe gutting of my
libraries to fix the bugs, implement the features, test the compilers that I
didn&rsquo;t previously test, and generally just get my issue list as close to zero as
possible.</p>
<p>The libraries that I put all the effort into are the following six:</p>
<ul>
<li>🧪 <a href="https://github.com/sheredom/utest.h">utest.h</a> - a single header unit
testing framework that supports C and C++.</li>
<li>⏱️ <a href="https://github.com/sheredom/ubench.h">ubench.h</a> - a single header unit
benchmarking framework that supports C and C++.</li>
<li>📚 <a href="https://github.com/sheredom/utf8.h">utf8.h</a> - a single header UTF-8 string
supporting header for C and C++.</li>
<li>🗄️ <a href="https://github.com/sheredom/json.h">json.h</a> - a single header JSON parsing
and writing header that supports JSON5 and simplified-JSON, and works with C and C++.</li>
<li>🐜 <a href="https://github.com/sheredom/subprocess.h">subprocess.h</a> - a single header
process spawning, joining, and interacting with library for C and C++.</li>
<li>#️⃣ <a href="https://github.com/sheredom/hashmap.h">hashmap.h</a> - a single header
hashmap implementation for C and C++.</li>
</ul>
<h2 id="github-actions">GitHub Actions</h2>
<p>To fix that I wasn&rsquo;t testing the latest Clang and GCC I decided to finally pull
the trigger on using GitHub Actions instead of my old Travis pipelines. Travis
was starting to have some integration issues (I don&rsquo;t know the details, they
just suddenly stopped appearing on the PRs when I pushed changes), and since I
knew I wanted to end up on GitHub Actions anyway I used this as the reason to
just do it.</p>
<p>GitHub Actions was a little daunting at first, but once you get into it the yml
format is very powerful. For example here is the
<a href="https://github.com/sheredom/subprocess.h/blob/master/.github/workflows/cmake.yml">workflow of my subprocess.h library</a>.</p>
<p>The most interesting parts are how I upgraded to the latest clang/gcc:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>- name: Setup dependencies
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span>: startsWith<span style="color:#f92672">(</span>matrix.os, <span style="color:#e6db74">&#39;ubuntu&#39;</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>  run: sudo apt-get install -y gcc-10 g++-10 clang-10
</span></span></code></pre></div><p>And then how I used these configurations:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>- name: Configure CMake with GCC
</span></span><span style="display:flex;"><span>  shell: bash
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span>: matrix.compiler <span style="color:#f92672">==</span> <span style="color:#e6db74">&#39;gcc&#39;</span>
</span></span><span style="display:flex;"><span>  working-directory: <span style="color:#e6db74">${</span>{github.workspace<span style="color:#e6db74">}</span><span style="color:#f92672">}</span>/build
</span></span><span style="display:flex;"><span>  run: cmake $GITHUB_WORKSPACE/test -DCMAKE_BUILD_TYPE<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>{ matrix.type <span style="color:#e6db74">}</span><span style="color:#f92672">}</span> -DCMAKE_C_COMPILER<span style="color:#f92672">=</span>gcc-10 -DCMAKE_CXX_COMPILER<span style="color:#f92672">=</span>g++-10
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>- name: Configure CMake with Clang <span style="color:#f92672">(</span>Ubuntu<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>  shell: bash
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span>: <span style="color:#f92672">(</span>matrix.compiler <span style="color:#f92672">==</span> <span style="color:#e6db74">&#39;clang&#39;</span><span style="color:#f92672">)</span> <span style="color:#f92672">&amp;&amp;</span> startsWith<span style="color:#f92672">(</span>matrix.os, <span style="color:#e6db74">&#39;ubuntu&#39;</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>  working-directory: <span style="color:#e6db74">${</span>{github.workspace<span style="color:#e6db74">}</span><span style="color:#f92672">}</span>/build
</span></span><span style="display:flex;"><span>  run: cmake $GITHUB_WORKSPACE/test -DCMAKE_BUILD_TYPE<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>{ matrix.type <span style="color:#e6db74">}</span><span style="color:#f92672">}</span> -DCMAKE_C_COMPILER<span style="color:#f92672">=</span>clang-10 -DCMAKE_CXX_COMPILER<span style="color:#f92672">=</span>clang++-10
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>- name: Configure CMake with Clang <span style="color:#f92672">(</span>Windows<span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>  shell: bash
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span>: <span style="color:#f92672">(</span>matrix.compiler <span style="color:#f92672">==</span> <span style="color:#e6db74">&#39;clang&#39;</span><span style="color:#f92672">)</span> <span style="color:#f92672">&amp;&amp;</span> startsWith<span style="color:#f92672">(</span>matrix.os, <span style="color:#e6db74">&#39;windows&#39;</span><span style="color:#f92672">)</span>
</span></span><span style="display:flex;"><span>  working-directory: <span style="color:#e6db74">${</span>{github.workspace<span style="color:#e6db74">}</span><span style="color:#f92672">}</span>/build
</span></span><span style="display:flex;"><span>  run: cmake $GITHUB_WORKSPACE/test -DCMAKE_BUILD_TYPE<span style="color:#f92672">=</span><span style="color:#e6db74">${</span>{ matrix.type <span style="color:#e6db74">}</span><span style="color:#f92672">}</span> -T ClangCL
</span></span></code></pre></div><p>My build matrix is pretty extensive too:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>strategy:
</span></span><span style="display:flex;"><span>  matrix:
</span></span><span style="display:flex;"><span>    os: <span style="color:#f92672">[</span>ubuntu-latest, windows-latest, macOS-latest<span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    type: <span style="color:#f92672">[</span>Debug, RelWithDebInfo, MinSizeRel, Release<span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    compiler: <span style="color:#f92672">[</span>default, clang, gcc<span style="color:#f92672">]</span>
</span></span><span style="display:flex;"><span>    exclude:
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">{</span>os: <span style="color:#e6db74">&#34;macOS-latest&#34;</span>, compiler: <span style="color:#e6db74">&#34;clang&#34;</span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">{</span>os: <span style="color:#e6db74">&#34;windows-latest&#34;</span>, compiler: <span style="color:#e6db74">&#34;gcc&#34;</span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">{</span>os: <span style="color:#e6db74">&#34;macOS-latest&#34;</span>, compiler: <span style="color:#e6db74">&#34;gcc&#34;</span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">{</span>os: <span style="color:#e6db74">&#34;ubuntu-latest&#34;</span>, compiler: <span style="color:#e6db74">&#34;default&#34;</span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#f92672">{</span>os: <span style="color:#e6db74">&#34;ubuntu-latest&#34;</span>, compiler: <span style="color:#e6db74">&#34;default&#34;</span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>runs-on: <span style="color:#e6db74">${</span>{ matrix.os <span style="color:#e6db74">}</span><span style="color:#f92672">}</span>
</span></span></code></pre></div><p>And all in all this lets me build for the three desktop platforms, using five
different compiler toolchains.</p>
<p>Even though this let me ditch Travis I couldn&rsquo;t ditch appveyor in the process. I
would have liked to have a single CI integration as that&rsquo;d have made maintaining
everything easier, but GitHub Actions does not allow you to test with older
Visual Studio installations.</p>
<p>Quite a few of my users love the older Visual Studio&rsquo;s and won&rsquo;t upgrade under
any circumstances, and so I&rsquo;ve
<a href="https://github.com/sheredom/subprocess.h/blob/master/appveyor.yml">kept appveyor around</a>
to ensure this path is tested.</p>
<h2 id="utesth">utest.h</h2>
<p>In <a href="https://github.com/sheredom/utest.h">utest.h</a> I removed the
<code>#include &lt;winbase.h&gt;</code> entirely. This meant that the huge headers that were
pulled in as part of including utest.h on windows were no longer required, which
sped up compile time on the Windows platform.</p>
<h2 id="utf8h">utf8.h</h2>
<p>In <a href="https://github.com/sheredom/utf8.h">utf8.h</a> I added some new helper
functions <code>utf8makevalid</code> and <code>utf8rcodepoint</code> - allowing you to sanitize a
potentially invalid UTF-8 string by replacing malformed codepoints with an ASCII
replacement, and allowing you to reverse iterate through the string.</p>
<p>I also fixed a long standing bug whereby the Greek Capital Theta symbol &lsquo;ϴ&rsquo; does
not have a uniform mapping from upper to lower case, or vice-versa. This means
that if you did the dance of doing upper -&gt; lower -&gt; upper you <em>could</em> have a
different string than you started with (but the fix means I correctly handle
that letter&rsquo;s encoding).</p>
<h2 id="jsonh">json.h</h2>
<p>In <a href="https://github.com/sheredom/json.h">json.h</a> I added all the fun JSON tests
from the <a href="https://github.com/nst/JSONTestSuite">JSONTestSuite</a> project, and
fixed any and all the corner case bugs this uncovered. Mostly I was incorrectly
finding an end-of-file and assuming the JSON to be valid (without checking that
strings/objects/arrays were actually closed correctly). I also took the
opportunity to add clang sanitizer tests as since json.h uses a single
allocation to handle the entire JSON DOM, there was a greater chance of trashing
problems. Luckily there are zero issues with the library under its current
testing load - nice!</p>
<p>I also added a new function <code>json_extract_value</code> which lets you pull out a value
from a JSON DOM into a new allocation. This is useful if you want to get a bit
of a DOM and do something with just that (you could free the original allocation
for instance).</p>
<h2 id="subprocessh">subprocess.h</h2>
<p>In <a href="https://github.com/sheredom/subprocess.h">subprocess.h</a> I fixed two fun
issues:</p>
<ul>
<li>On Linux if you did not specify the <code>subprocess_option_inherit_environment</code>
option then you had to have a qualified path to the executable (either a full
path with the starting &lsquo;/&rsquo;, or a relative path like &lsquo;./&rsquo;).</li>
<li>I also added a new entry-point <code>subprocess_create_ex</code> that lets users specify
a custom environment to spawn the subprocess with.</li>
</ul>
<h2 id="hashmaph">hashmap.h</h2>
<p>In <a href="https://github.com/sheredom/hashmap.h">hashmap.h</a> I fixed a bug where if you
had three entries that mapped to the same hash, and therefore used the linear
probe part of hashing to find a location. If you removed the middle entry, and
then tried to reinsert the third, it&rsquo;d wrongly make two copies of that entry in
the hash table. The test for this shows the problem nicely:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> hashmap_s hashmap;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> x <span style="color:#f92672">=</span> <span style="color:#ae81ff">42</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> y <span style="color:#f92672">=</span> <span style="color:#ae81ff">13</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> z <span style="color:#f92672">=</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">53</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ASSERT_EQ</span>(<span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">hashmap_create</span>(<span style="color:#ae81ff">4</span>, <span style="color:#f92672">&amp;</span>hashmap));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// These all hash to the same value.
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">ASSERT_EQ</span>(<span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">hashmap_put</span>(<span style="color:#f92672">&amp;</span>hashmap, <span style="color:#e6db74">&#34;000&#34;</span>, <span style="color:#ae81ff">3</span>, <span style="color:#f92672">&amp;</span>x));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ASSERT_EQ</span>(<span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">hashmap_put</span>(<span style="color:#f92672">&amp;</span>hashmap, <span style="color:#e6db74">&#34;002&#34;</span>, <span style="color:#ae81ff">3</span>, <span style="color:#f92672">&amp;</span>y));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ASSERT_EQ</span>(<span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">hashmap_put</span>(<span style="color:#f92672">&amp;</span>hashmap, <span style="color:#e6db74">&#34;007&#34;</span>, <span style="color:#ae81ff">3</span>, <span style="color:#f92672">&amp;</span>z));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ASSERT_EQ</span>(<span style="color:#ae81ff">3u</span>, <span style="color:#a6e22e">hashmap_num_entries</span>(<span style="color:#f92672">&amp;</span>hashmap));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Now we remove the middle value.
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">ASSERT_EQ</span>(<span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">hashmap_remove</span>(<span style="color:#f92672">&amp;</span>hashmap, <span style="color:#e6db74">&#34;002&#34;</span>, <span style="color:#ae81ff">3</span>));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ASSERT_EQ</span>(<span style="color:#ae81ff">2u</span>, <span style="color:#a6e22e">hashmap_num_entries</span>(<span style="color:#f92672">&amp;</span>hashmap));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// And now attempt to insert the last value again. There was a bug where this
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// would insert a new entry incorrectly instead of resolving to the previous
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">// entry.
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">ASSERT_EQ</span>(<span style="color:#ae81ff">0</span>, <span style="color:#a6e22e">hashmap_put</span>(<span style="color:#f92672">&amp;</span>hashmap, <span style="color:#e6db74">&#34;007&#34;</span>, <span style="color:#ae81ff">3</span>, <span style="color:#f92672">&amp;</span>z));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ASSERT_EQ</span>(<span style="color:#ae81ff">2u</span>, <span style="color:#a6e22e">hashmap_num_entries</span>(<span style="color:#f92672">&amp;</span>hashmap));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">hashmap_destroy</span>(<span style="color:#f92672">&amp;</span>hashmap);
</span></span></code></pre></div><p>I also added a new function <code>hashmap_remove_and_return_key</code> which lets you
remove and item and also return the key. Remember that hashmap.h doesn&rsquo;t copy
the memory backing the key, so if you had to allocate memory for the key and
wanted to get the key back so that you could free this memory - this is the
function for you!</p>
<h2 id="github-sponsorship">GitHub Sponsorship</h2>
<p>First off - I <em>don&rsquo;t really need the money from GitHub sponsorship</em>. I&rsquo;ve got a
good job at Unity and my personal projects in C/C++ and Rust are simple labours
of love.</p>
<p>But a few people have asked if I would add a sponsorship option to my GitHub
anyway, because they like my libraries and use them.</p>
<p>So I&rsquo;ve <a href="https://github.com/sponsors/sheredom">added a sponsorship option</a> to my
GitHub for anyone that wants to help me justify the time to keep my libraries
updated, bug free, and great.</p>
]]></description>
    </item>
    
    <item>
      <title>How I Structure My Working Day</title>
      <link>https://www.neilhenning.dev/posts/how-i-structure-my-working-day/</link>
      <pubDate>Mon, 08 Feb 2021 20:30:39 +0100</pubDate>
      <guid>https://www.neilhenning.dev/posts/how-i-structure-my-working-day/</guid>
      <description><![CDATA[<p>The more I&rsquo;ve delved into the darkest corners of optimizing compilers, the more
that incessant urge to optimize things has leeched out into my day to day life.
I&rsquo;ve found myself ever more obsessed over what the most optimal method to do
things is. A few examples:</p>
<ul>
<li>While brushing my teeth twice a day I know I have a full two minutes where I
can make use of my spare hand to do things. Like I might pack the dishwasher,
lock the doors, turn off lights, put stuff into the recycling - anything that
means I&rsquo;ve double buffered another activity while I&rsquo;m stuck brushing.</li>
<li>I got really obsessed with the number of trips from the dishwasher to put
things away, versus the time taken to load up on extra dishes for a lower
number of trips. I kid you not I&rsquo;ve experimented and mostly realised that (if
optimizing for time taken as your primary metric) the number of trips is much
less important than the time taken to load/unload dishes in an individual
trip.</li>
</ul>
<p>One other area of my life where I&rsquo;ve adopted this philosophy is the structure of
my workday. I thought it might be interesting for people to see if there is any
tips in how I lay out my day that they could adopt to optimize their own
experiences also.</p>
<h2 id="booting-up">Booting Up</h2>
<p>The first step in any day is the process of booting up. I follow the same
routine each morning:</p>
<ul>
<li>I wake up.</li>
<li>I use the facilities.</li>
<li>I weigh myself.</li>
<li>I take my dog outside so he can relieve himself.</li>
<li>I put on my running gear.</li>
<li>I make a coffee. Caffeinated. I only have a single with-caffeine coffee each
day as I&rsquo;ve experimented and found it to be the optimal balance of getting
that &lsquo;wake up&rsquo; feeling versus the affect it can have on sleeping at the other
end of the day.</li>
</ul>
<p>Once I&rsquo;ve performed these most basic tasks in a mostly pre-coffee zombie state,
I&rsquo;m ready to load up on the problems of the day.</p>
<h2 id="dealing-with-the-urgents">Dealing with the Urgents</h2>
<p>Once I&rsquo;m at the computer I do a full parse of slack / work email, answering
any of the easy questions and dealing with the easier tasks.</p>
<p>Then I tend to filter through to see if there are any urgent bugs that I need to
take care of. These bugs are generally of the &lsquo;stop the world&rsquo; kind - EG. I&rsquo;d
only drop whatever main feature I&rsquo;m working on for a bug if it is truly some
sort of regression / ship stopper. My number one aim for any of these bugs is to
reproduce them (not always easy) and then give the user a temporary workaround.</p>
<p>Because of the natural cadence of software releases it means that even if I rush
to fix a users issue, there is still some time lag between me fixing it and them
being able to get access to that fix (while everything is tested for release).
Workarounds are a key part to unblock a user while the real fix is deployed.</p>
<h2 id="urgent-bug-or-feature">Urgent Bug or Feature</h2>
<p>Once I&rsquo;ve loaded up on a specific urgent bug to fix, or a feature I am
developing, I spend thirty minutes or so acclimatizing myself to the issue.</p>
<p>If it&rsquo;s a bug - can I reproduce it? Can I check our logs? Can I use a debug build
of our Burst compiler to give me more information? Generally at this stage I&rsquo;m
only trying to work out what is the <em>cause</em> not what the fix is.</p>
<p>If it&rsquo;s a feature - I&rsquo;m just paging back in what I was doing the day before and
trying to get started up again. I have long followed a philosophy of lacing
<code>#error</code>&rsquo;s throughout my code before I leave it for the night so that the next
day it won&rsquo;t compile but I&rsquo;ve left some breadcrumbs for where my thinking was
the night before. Again - all I&rsquo;m trying to do here is page back in all the
problems I was trying to solve at this stage, not do any actual work.</p>
<h2 id="run-run-run">Run Run Run</h2>
<p>Then I go for a run. I grab my dog (he runs with me every day!) grab my
headphones, and listen to any of my favourite podcasts while I&rsquo;m exercising. I
do at least a three mile run every day, and try to run at least thirty miles a
week. What is important at this stage is to get into the monotony of the
exercise, don&rsquo;t think about work, enjoy the podcast and get a sweat on.</p>

<img src="/images/BenjiAndMeRunning2.jpg"  alt="Benji and myself running"  class="center"  style="border-radius: 8px;"    />


<p>There is now a pretty hefty set of scientific evidence that states that the
<em>right kind</em> of distraction from a problem actually helps you solve it (for
instance <a href="https://www.bbc.com/worklife/article/20180605-why-being-easily-distracted-can-be-a-very-good-thing">here is a BBC article about just that</a>.
The TL;DR is that as long as you have some monotonous task like sorting things
(sorting lego blocks by colour, putting the dishes away, hanging out washing on
a washing line, etc) or more broadly where your brain can mostly power off from
any in-focus intensive task, your brain kicks off an asynchronous process in
your head to actually solve the problem while you are doing the thing. This is
why you hear <em>so many stories</em> of people solving problems in the shower, or
waking up with a solution - you are using the same technique.</p>
<p>I&rsquo;ve found myself that by loading up on the problems and then immediately
context switching to exercise, I generally solve them better and faster. I could
sit at the screen for hours and get no-where, or I could go for an hour run and
solve it in the thirty or so minutes after I sit back down. Nearly every time I
<em>engage the crunch like behaviour</em> of trying to power through to a solution it
sets me back on actually solving it - so this technique is something I&rsquo;d
definitely recommend trying.</p>
<h2 id="the-rest-of-my-day">The Rest of My Day</h2>
<p>I get about four or five good hours in a day of active problem solving coding. It
might be more or less for other people, but aslong as I can get some peace, have
my favourite music blaring, and can distract myself occassionally to make a
decaf coffee or throw the frisbee to Benji, I&rsquo;ll get a solid block of good work
done in an average day.</p>

<img src="/images/Benji.jpg"  alt="Benji with a frisbee in his mouth"  class="center"  style="border-radius: 8px;"    />


<p>Since the my team is split mostly between EU / US, I generally have most of my big
meetings in my afternoon. So by that time I&rsquo;m already pretty tired from the
solid work block, and ready to engage in the meeting instead.</p>
<p>When I&rsquo;m done for the night? I&rsquo;m done. I work my eight hours a day, and walk
away from the machine. I like to cook so I generally make dinner as the bridge
between work Neil and home Neil (even though they inhabit the same house!).</p>
]]></description>
    </item>
    
    <item>
      <title>Advent of Code 2020 - Review</title>
      <link>https://www.neilhenning.dev/posts/aoc2020_in_review/</link>
      <pubDate>Thu, 31 Dec 2020 20:50:39 +0100</pubDate>
      <guid>https://www.neilhenning.dev/posts/aoc2020_in_review/</guid>
      <description><![CDATA[<p>I&rsquo;ve always wanted to do the
<a href="https://adventofcode.com/2020">Advent of Code 2020</a> puzzles as a way to wind
down in the run up to Christmas, but never quite got my act in gear to do it.</p>
<p>This year I&rsquo;ve changed that, and I&rsquo;ve pushed all my solutions to my
<a href="https://github.com/sheredom/AOC2020">AOC 2020 repository on GitHub</a>. I thought
that now that I&rsquo;ve completed the challenge, I&rsquo;d do a review mostly of how I used
Rust to complete the challenges and what I found.</p>
<h2 id="rust-lessons-learned">Rust Lessons Learned</h2>
<h3 id="iterators">Iterators</h3>
<p>I really got more comfortable with iterator&rsquo;s and began to reach for <code>map</code>,
<code>fold</code>, <code>filter</code>, etc. the more I went into the puzzles. To begin with I stuck
to what effectively was a &lsquo;safe&rsquo; C-like coding experience - using mutable
variables and loops. The more I went into the challenge I began to use more Rust
things.</p>
<p>The one major downside I did find to iterators is that if they go wrong, you
start to want to debug the body of them and then the closure can become
frustrating. You either introduce a scope into the closure and bung the stuff in
there, or have a seperate method instead of a closure to aid in debugging. Even
still, I did feel many times that having a dumb C-like loop with mutable
variables ended up being a nicer experience when things went wrong.</p>
<h3 id="shadowing-isnt-always-evil">Shadowing Isn&rsquo;t Always Evil</h3>
<p>I&rsquo;ve always felt variable shadowing was an evil that should be stopped. Lets
take C for example here:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">foo</span>(<span style="color:#66d9ef">int</span> a) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (a <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">42</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">int</span> a <span style="color:#f92672">=</span> <span style="color:#ae81ff">13</span>;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> a;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>I really dislike in C that it lets you shadow a local variable with a previously
accessible variable - it just introduces the kind of problems like you see above
where the user <em>probably</em> wanted to return 13 if <code>a &lt; 42</code>, but they declared a
new variable instead. In C-like languages I like to force shadowing to be an
error as a result.</p>
<p>I came into Rust with this same view - shadowing is clearly bad language design!
Except that Rust is uniquely placed to make shadowing <em>sometimes</em> nice:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>fn <span style="color:#a6e22e">foo</span>(a: i32) <span style="color:#f92672">-&gt;</span> i32 {
</span></span><span style="display:flex;"><span>  let mut a <span style="color:#f92672">=</span> a;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> a <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">42</span> {
</span></span><span style="display:flex;"><span>    a <span style="color:#f92672">=</span> <span style="color:#ae81ff">13</span>;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  let a <span style="color:#f92672">=</span> a;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  a
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In this example we can declare a variable mutable, shadow it with another
variable, and then <strong>assign</strong> the original variable to the new variable. All in
a single step! This lets us temporarily make the <code>a</code> we are using mutable to do
things with it. What&rsquo;s even cooler is we can then do the same in reverse after
we have decided <code>a</code> should no longer be mutable.</p>
<p>Before the Rust pedants come out the woodwork, the above should <em>really</em> be
something more like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>fn <span style="color:#a6e22e">foo</span>(a: i32) <span style="color:#f92672">-&gt;</span> i32 {
</span></span><span style="display:flex;"><span>  let a <span style="color:#f92672">=</span> <span style="color:#66d9ef">if</span> a <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">42</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">13</span>
</span></span><span style="display:flex;"><span>  } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>    a
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  a
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>So we can avoid making <code>a</code> mutable at all (but I couldn&rsquo;t evangelise my point
without the much uglier code before!).</p>
<h3 id="its-easy-to-use-crates-maybe-too-easy">It&rsquo;s Easy to Use Crates (maybe too easy&hellip;)</h3>
<p>Using crates is <strong>ridiculously</strong> easy. The number of times I added a crate just
to try solving a problem using it, realised I didn&rsquo;t need it so I then removed
it, and moved on with my solution - was insane. I think that coming from C/C++
languages where I am most fluent has made me supremely dependency adverse, but
with Rust it&rsquo;s so trivial to just try a crate that you get sucked in.</p>
<p>I still think its a useful life skill to always attempt to avoid a dependency
where you might not need one, but if you are to use dependencies then Rust is
definitely what you want to be using for sure.</p>
<h2 id="crates-used">Crates Used</h2>
<h3 id="the-exec_time-crate">The exec_time crate</h3>
<p>For Day 1: Report Repair, I started by using the
<a href="https://crates.io/crates/exec_time">exec_time</a> crate, which I use throughout my
solutions. The crate just prints the time taken to execute whatever method the
included macro is placed on:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#[exec_time]
</span></span></span><span style="display:flex;"><span>fn <span style="color:#a6e22e">run_something</span>() {}
</span></span></code></pre></div><p>Which prints the following to the command line:</p>
<pre tabindex="0"><code>Time run_something: 0 mills
</code></pre><p>The crate was a useful enough way to just dump the time taken in the function,
but there is some bug with mutable arguments that causes the macro to fail. I
worked around this by never passing mutable arguments, but its not a viable
crate to use to be honest.</p>
<h3 id="the-colour-crate">The colour crate</h3>
<p>I also used <a href="https://crates.io/crates/colour">colour</a> crate in my first solution
and all the solutions thereafter. It just lets you print to the command line
with colours, with an easy API:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>red_ln<span style="color:#f92672">!</span>(<span style="color:#e6db74">&#34;RED!&#34;</span>);
</span></span><span style="display:flex;"><span>green_ln<span style="color:#f92672">!</span>(<span style="color:#e6db74">&#34;GREEN!&#34;</span>);
</span></span></code></pre></div><p>I did this <em>solely</em> for festive reasons - Christmas colours are green, red, and
white - this meant that I printed each part 1 solution in red, each part 2
solution in green, and the <code>exec_time</code> crate above prints its timing info in
white text interpersed throughout - very festive!</p>
<h3 id="the-intbits-crate">The intbits crate</h3>
<p>For Day 3: Toboggan Trajectory, I used the
<a href="https://crates.io/crates/intbits">intbits</a> as part of this puzzle solution. The
crate just lets you access bits in an integer with a nice API:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>let mut i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>i.<span style="color:#a6e22e">set_bit</span>(<span style="color:#ae81ff">4</span>, true);
</span></span><span style="display:flex;"><span>assert<span style="color:#f92672">!</span>(i.<span style="color:#a6e22e">bit</span>(<span style="color:#ae81ff">4</span>));
</span></span></code></pre></div><h3 id="the-bit_set-crate">The bit_set crate</h3>
<p>For Day 5: Binary Boarding, I wanted to use an N-wide bitset for this challenge,
to keep data used to a minimum again, and I went with the
<a href="https://crates.io/crates/bit-set">bit_set</a> crate:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>let mut seats <span style="color:#f92672">=</span> BitSet<span style="color:#f92672">::</span><span style="color:#a6e22e">with_capacity</span>(<span style="color:#ae81ff">1000</span>);
</span></span><span style="display:flex;"><span>seats.<span style="color:#a6e22e">insert</span>(<span style="color:#ae81ff">4</span>);
</span></span><span style="display:flex;"><span>assert<span style="color:#f92672">!</span>(seats.<span style="color:#a6e22e">contains</span>(<span style="color:#ae81ff">4</span>));
</span></span></code></pre></div><h3 id="the-itertools-crate">The itertools crate</h3>
<p>For Day 7: Handy Haversacks, I used the
<a href="https://crates.io/crates/itertools">itertools</a> crate which has a really nice
way to get tuples out of an iter:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#a6e22e">let</span> (lhs, rhs) <span style="color:#f92672">=</span> line.<span style="color:#a6e22e">splitn</span>(<span style="color:#ae81ff">2</span>, <span style="color:#e6db74">&#34;some seperator&#34;</span>).<span style="color:#a6e22e">next_tuple</span>().<span style="color:#a6e22e">unwrap</span>();
</span></span></code></pre></div><p>I ended up using this crate <em>everywhere</em> - so that I could use the <code>next_tuple</code>
method on the result of <code>splitn</code> to get a known tuple from the result. It was
very much overkill for what I actually needed, but super useful.</p>
<h3 id="the-num-integer-crate">The num-integer crate</h3>
<p>For Day 13: Shuttle Search I used the
<a href="https://crates.io/crates/num-integer">num-integer</a> crate solely to get access
to the least common multiplier (lcm) method:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>assert_eq<span style="color:#f92672">!</span>(<span style="color:#a6e22e">lcm</span>(<span style="color:#ae81ff">3</span>, <span style="color:#ae81ff">5</span>), <span style="color:#ae81ff">15</span>);
</span></span></code></pre></div><p>This was <em>probably</em> overkill (bringing in the whole crate), but I wanted to use
Rust in all its glory as much as possible.</p>
<h3 id="the-regex-crate">The regex crate</h3>
<p>I&rsquo;ve been told Advent of Code wouldn&rsquo;t be complete without using some form of
regex, and I hadn&rsquo;t actually used regex at all in Rust before. I used the
<a href="https://crates.io/crates/regex">regex</a> crate to accomplish what I needed, and
while I&rsquo;m no further forward in being better with regex than I was before, I did
find the implementation of it using Rust to be pleasant to use (especially when
you need to extract multiple bits from some complicated string).</p>
<h3 id="the-bit_reverse-crate">The bit_reverse crate</h3>
<p>I used the <a href="https://crates.io/crates/bit_reverse">bit_reverse</a> crate for my 20th
days solution - this was the problem I hated solving more than any other in this
years Advent of Code, and I used the bit reverse functionality to quickly get
the bits in an integer in the reverse order. This was a <em>really</em> messy solution
to the problem and honestly I&rsquo;m not that proud of it, but it <strong>did the job</strong>, my
code ran pretty fast, and it served a purpose.</p>
<h2 id="conclusion">Conclusion</h2>
<p>My major takeaway from Advent of Code is that it&rsquo;s a really great way to level
up your usage of a language you already know a little of.</p>
<p>Originally I was going to attempt to use the
<a href="https://ziglang.org/">Zig language</a> to solve the problems - but I knew
<em>nothing</em> of Zig&rsquo;s syntax and tooling, I found the docs a little confusing to
figure out (I was trying to work out how to load a file into a buffer!), and I
quickly realised that I just <strong>wouldn&rsquo;t</strong> complete the Advent of Code challenge
while learning an entire new language and trying to work out the solutions.</p>
<p>With Rust I had been experimenting with things already and knew enough to be
dangerous, but not enough to feel comfortable with it. Advent of Code was
<strong>tremendously</strong> useful for reinforcing a thin level of knowledge of a language
with a more robust appreciation of its quirks.</p>
<p>With that - I&rsquo;m calling time on 2020, tha bliadhna ùr mo chàraidean, and I&rsquo;ll
see you in the new year!</p>
]]></description>
    </item>
    
    <item>
      <title>Advent of Code 2020</title>
      <link>https://www.neilhenning.dev/posts/aoc2020/</link>
      <pubDate>Tue, 01 Dec 2020 19:50:39 +0100</pubDate>
      <guid>https://www.neilhenning.dev/posts/aoc2020/</guid>
      <description><![CDATA[<p>I&rsquo;ve always wanted to do the
<a href="https://adventofcode.com/2020">Advent of Code 2020</a> puzzles as a way to wind
down in the run up to Christmas, but never quite got my act in gear to do it.</p>
<p>This year I&rsquo;m changing that, and I&rsquo;ve just pushed my 1st day&rsquo;s solutions to my
<a href="https://github.com/sheredom/AOC2020">AOC 2020 repository on GitHub</a>. Solution
parameters aside:</p>
<ul>
<li>I&rsquo;m doing this in Rust. I started writing it out in Zig but honestly the docs
are nowhere near as clear as with Rust, and the tooling isn&rsquo;t there. There is
a more general point here about how much effort it takes for languages to
achieve that status (and how <em>much</em> we have Mozilla to thank for doing Rust by
themselves for so blooming long to get it amazing!).</li>
<li>I&rsquo;ve just created a simple command line app that you can do <code>cargo run</code> and
it&rsquo;ll print the solution to the command line.</li>
<li>I&rsquo;m pretty sure there will be a more optimal way to do what I&rsquo;ve done, I&rsquo;m
really using this as a way to polish up my Rust skills some more!</li>
</ul>
<p>You can check out the <a href="https://github.com/sheredom/AOC2020">https://github.com/sheredom/AOC2020</a> if you are interested
in my progress, check in tomorrow for those solutions. Tioraidh bye!</p>
]]></description>
    </item>
    
    <item>
      <title>Exploring Hourglass APIs in Rust</title>
      <link>https://www.neilhenning.dev/posts/hourglass_apis_in_rust/</link>
      <pubDate>Sat, 24 Oct 2020 08:08:47 +0100</pubDate>
      <guid>https://www.neilhenning.dev/posts/hourglass_apis_in_rust/</guid>
      <description><![CDATA[<p>There are two talks on APIs that I think <em>every</em> programmer should watch, learn,
and study from:</p>
<ul>
<li><a href="https://caseymuratori.com/blog_0024">Designing and Evaluating Reusable Components</a>
from <a href="https://twitter.com/cmuratori">Casey Muratori</a>. This
<em>absolutely wonderful</em> talk is the fundamental source for how to design APIs.</li>
<li><a href="https://youtu.be/PVYdHDm0q6Y">Hourglass Interfaces for C++ APIs</a> from
<a href="https://twitter.com/stefanusdutoit">Stefanus Du Toit</a>. This talk discusses
having a rich API for users that is backed by a C API into proprietary code.</li>
</ul>
<p>These two talks give a really good and grounded lesson on fundamental API
design - the choices you make and the ramifications they can have. In
particular, the design challenge and solution of the hourglass API design is a
really nice approach to being able to ship a high functioning API that is backed
by some proprietary software that you don&rsquo;t want to ship. For example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> MyDataOpaque;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">extern</span> <span style="color:#e6db74">&#34;C&#34;</span> MyDataOpaque<span style="color:#f92672">*</span> <span style="color:#a6e22e">mydata_create</span>(<span style="color:#66d9ef">int</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">extern</span> <span style="color:#e6db74">&#34;C&#34;</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">mydata_destroy</span>(MyDataOpaque<span style="color:#f92672">*</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> MyData final {
</span></span><span style="display:flex;"><span>  explicit <span style="color:#a6e22e">MyData</span>(<span style="color:#66d9ef">int</span> someState) <span style="color:#f92672">:</span> <span style="color:#a6e22e">opaque</span>(<span style="color:#a6e22e">mydata_create</span>(someState)) {}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">~</span><span style="color:#a6e22e">MyData</span>() { <span style="color:#a6e22e">mydata_destroy</span>(opaque); }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>private:
</span></span><span style="display:flex;"><span>  MyDataOpaque<span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> opaque;
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p>This is a classic hourglass API in C++ - we&rsquo;ve got the C API that returns some
opaque data, and the hourglass <code>MyData</code> struct lets us expose this to C++ users
in a way they are familiar with. In Stefanus&rsquo; talk he went into detail about how
they also <em>implement</em> the C API in C++ - meaning that both sides of the thin C
API are written in the high level language they enjoy - C++.</p>
<p>This all got me thinking - would this approach be possible in some fashion with
Rust? First the caveats:</p>
<ul>
<li>I <em>suspect</em>, but am not well versed enough with Rust, that using different
versions of Rust to build either side of the hourglass API could cause
explosions. So I&rsquo;m going to assume that both sides are built with the same
version.</li>
<li>I really <em>hope</em> that it is safe to use memory allocating functions (like <code>Box</code>
or <code>Vec</code>) on both Rust sides of a C API.</li>
</ul>
<p>These pretty major caveats aside - is it possible?</p>
<h2 id="the-bottom-of-the-hourglass">The Bottom of the Hourglass</h2>
<p>First we&rsquo;ll implement the bottom of the hourglass - this would be the
proprietary code that you don&rsquo;t want to ship (all your secret sauce might be in
it!).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="color:#75715e">#[repr(C)]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">pub</span> <span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">MyDataOpaque</span> {
</span></span><span style="display:flex;"><span>  some_state: <span style="color:#66d9ef">i32</span>,
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">impl</span> MyDataOpaque {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">pub</span> <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">new</span>(some_state: <span style="color:#66d9ef">i32</span>) -&gt; <span style="color:#a6e22e">MyDataOpaque</span> {
</span></span><span style="display:flex;"><span>    MyDataOpaque { some_state }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#[no_mangle]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">pub</span> <span style="color:#66d9ef">extern</span> <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">mydata_create</span>(some_state: <span style="color:#66d9ef">i32</span>) -&gt; <span style="color:#f92672">*</span><span style="color:#66d9ef">mut</span> MyDataOpaque {
</span></span><span style="display:flex;"><span>  Box::into_raw(Box::new(MyDataOpaque::new(some_state)))
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#[no_mangle]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">pub</span> <span style="color:#66d9ef">extern</span> <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">mydata_destroy</span>(d : <span style="color:#f92672">*</span><span style="color:#66d9ef">mut</span> MyDataOpaque) {
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// This causes the Drop to be called on the box, freeing everything.
</span></span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">let</span> _ <span style="color:#f92672">=</span> <span style="color:#66d9ef">unsafe</span>{ Box::from_raw(d) };
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>It&rsquo;s a quite simple bit of code (for our simple example), but the crux of it is
just some opaque struct, and some unmangled public extern symbols for the
exported C API.</p>
<h2 id="building-the-two-crate-solution">Building the Two Crate Solution</h2>
<p>I wanted a way to build a Rust crate for the above, then build with cargo on a
second crate that uses it. I <strong>did not want</strong> to have a single instantiation of
cargo because I wanted to be 100% sure that I was exercising the export and
import paths of Rust. To do this I used a <code>build.rs</code> like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="color:#66d9ef">use</span> std::env;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">use</span> std::process::Command;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">let</span> out_dir <span style="color:#f92672">=</span> env::var_os(<span style="color:#e6db74">&#34;OUT_DIR&#34;</span>).unwrap();
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">let</span> working_dir <span style="color:#f92672">=</span> env::var_os(<span style="color:#e6db74">&#34;CARGO_MANIFEST_DIR&#34;</span>).unwrap();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Command::new(<span style="color:#e6db74">&#34;cargo&#34;</span>)
</span></span><span style="display:flex;"><span>        .arg(<span style="color:#e6db74">&#34;build&#34;</span>)
</span></span><span style="display:flex;"><span>        .arg(<span style="color:#e6db74">&#34;--manifest-path&#34;</span>)
</span></span><span style="display:flex;"><span>        .arg(<span style="color:#f92672">&amp;</span><span style="color:#a6e22e">format!</span>(
</span></span><span style="display:flex;"><span>            <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">{}</span><span style="color:#e6db74">/MyDataOpaque/Cargo.toml&#34;</span>,
</span></span><span style="display:flex;"><span>            working_dir.to_str().unwrap()
</span></span><span style="display:flex;"><span>        ))
</span></span><span style="display:flex;"><span>        .arg(<span style="color:#e6db74">&#34;--target-dir&#34;</span>)
</span></span><span style="display:flex;"><span>        .arg(<span style="color:#f92672">&amp;</span><span style="color:#a6e22e">format!</span>(<span style="color:#e6db74">&#34;</span><span style="color:#e6db74">{}</span><span style="color:#e6db74">&#34;</span>, out_dir.to_str().unwrap()))
</span></span><span style="display:flex;"><span>        .arg(<span style="color:#e6db74">&#34;--release&#34;</span>)
</span></span><span style="display:flex;"><span>        .status()
</span></span><span style="display:flex;"><span>        .unwrap();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">println!</span>(
</span></span><span style="display:flex;"><span>        <span style="color:#e6db74">&#34;cargo:rustc-link-search=native=</span><span style="color:#e6db74">{}</span><span style="color:#e6db74">/release&#34;</span>,
</span></span><span style="display:flex;"><span>        out_dir.to_str().unwrap()
</span></span><span style="display:flex;"><span>    );
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This build script calls cargo in a sub-folder called <code>MyDataOpaque</code>, builds the
crate, and then adds the built library as a link requirement to our crate.</p>
<h2 id="building-the-top-of-the-hourglass">Building the top of the Hourglass</h2>
<p>So now we&rsquo;ve got a Rust library, exposed via a C API, that we want to write Rust
bindings for.</p>
<p>Just to <em>prove</em> it worked I first tried using <code>cbindgen</code> to generate a C API for
the bottom of the hourglass, and then <code>bindgen</code> to take this C API and generate
FFI bindings for it in the top of the hourglass, but these have a ton of
dependencies (like libclang) that I wasn&rsquo;t happy about. So I instead decided to
just manually write the C API for the top of the hourglass.</p>
<blockquote>
<p>Aside: assuming this approach was viable you could forsee an <code>hourglass_bindgen</code>
crate that did something similar to what <code>cbindgen</code> does, but just writes out
the Rust FFI to the C API instead.</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="color:#75715e">#[repr(C)]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">pub</span> <span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">MyDataOpaque</span> {
</span></span><span style="display:flex;"><span>    _private: [<span style="color:#66d9ef">u8</span>; <span style="color:#ae81ff">0</span>],
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#[link(name = </span><span style="color:#e6db74">&#34;MyDataOpaque&#34;</span><span style="color:#75715e">)]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">extern</span> <span style="color:#e6db74">&#34;C&#34;</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">mydata_create</span>(some_state: <span style="color:#66d9ef">i32</span>) -&gt; <span style="color:#f92672">*</span><span style="color:#66d9ef">mut</span> MyDataOpaque;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">mydata_destroy</span>(opaque: <span style="color:#f92672">*</span><span style="color:#66d9ef">mut</span> MyDataOpaque);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">pub</span> <span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">MyData</span> {
</span></span><span style="display:flex;"><span>    opaque: <span style="color:#f92672">*</span><span style="color:#66d9ef">mut</span> MyDataOpaque,
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">impl</span> MyData {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">pub</span> <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">new</span>(some_state: <span style="color:#66d9ef">i32</span>) -&gt; <span style="color:#a6e22e">MyData</span> {
</span></span><span style="display:flex;"><span>        MyData {
</span></span><span style="display:flex;"><span>            opaque: <span style="color:#a6e22e">unsafe</span> { mydata_create(some_state) },
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">impl</span> Drop <span style="color:#66d9ef">for</span> MyData {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">drop</span>(<span style="color:#f92672">&amp;</span><span style="color:#66d9ef">mut</span> self) {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">unsafe</span> {
</span></span><span style="display:flex;"><span>            mydata_destroy(self.opaque);
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#[cfg(test)]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">mod</span> tests {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">use</span> <span style="color:#66d9ef">super</span>::<span style="color:#f92672">*</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">#[test]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">create_destroy</span>() {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">let</span> _ <span style="color:#f92672">=</span> MyData::new();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As we can see this code is very similar to the C++ example I showed at the
beginning of the post - it wraps a C API in a Rust struct and then can use the
existing safe mechanisms of Rust (like the <code>Drop</code> trait) to ensure safety of the
data used.</p>
<p>And if I run it?</p>
<pre tabindex="0"><code>running 1 test
test tests::create_destroy ... ok
</code></pre><p>It works, nice!</p>
<h2 id="conclusion">Conclusion</h2>
<p>Hourglass APIs appear to work in Rust (minus the caveats above that I&rsquo;ll have to
explore further). I do think that maybe using <code>no_std</code> in the bottom of the
hourglass could mitigate even issues with multiple versions of Rust being used,
but again I&rsquo;ll have to verify it.</p>
<p>You could even forsee of an approach where in the <code>build.rs</code> instead of building
some other crate (whose source you don&rsquo;t want to ship), you could use the
<code>TARGET</code> to fetch the correctly pre-built version from a web service, or maybe
have a bunch of the library versions resident in the crate (obviously the total
crate size limit might become an issue though), and pick between them.</p>
<p>It&rsquo;s pretty awesome to me that this approach looks feasible though!</p>
]]></description>
    </item>
    
    <item>
      <title>Introducing hashmap.h</title>
      <link>https://www.neilhenning.dev/posts/introducing-hashmap-h/</link>
      <pubDate>Sun, 28 Jun 2020 16:28:45 +0100</pubDate>
      <guid>https://www.neilhenning.dev/posts/introducing-hashmap-h/</guid>
      <description><![CDATA[<p>I asked on twitter the other day whether anyone had a hashmap that could work
with string slices - parts of a string that are <strong>not</strong> null-terminated and thus
have to have an explicit length to accompany the pointer.</p>
<p>I didn&rsquo;t get any responses on this so I commented with a follow-up that I had
grabbed some code written a few years back by the awesome
<a href="https://twitter.com/petewarden">Pete Warden</a> of Google fame, and morphed it
into what I required:</p>
<blockquote>
<p>Authors note: this part used to contain a tweet, But Hellish Tusk / Space Karen / Elon Musk butchered the platform so it is now gone.</p>
</blockquote>
<p>Much to my surprise Pete was happy not only for me to do these modifications,
but also since he was no longer maintaining the hashmap code he&rsquo;d happily
redirect users to any effort I put together:</p>
<blockquote>
<p>Authors note: this part used to contain a tweet, But Hellish Tusk / Space Karen / Elon Musk butchered the platform so it is now gone.</p>
</blockquote>
<p>So I&rsquo;ve done the work and I&rsquo;m now introducing my latest library, <strong>nearly
entirely not written by me</strong>,
<a href="https://github.com/sheredom/hashmap.h">hashmap.h</a>!</p>
<h2 id="null-terminated-to-slices">Null-Terminated to Slices</h2>
<p>So Pete&rsquo;s code was pretty solid as is. The main difference was that it relied on
null-terminated strings as the key, whereas I wanted to use string slices. My
first modification was to change the entry points that used a key to instead
take a key and a length. So <code>hashmap_put</code> went from:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">extern</span> <span style="color:#66d9ef">int</span> <span style="color:#a6e22e">hashmap_put</span>(<span style="color:#66d9ef">map_t</span> in, <span style="color:#66d9ef">char</span><span style="color:#f92672">*</span> key, <span style="color:#66d9ef">any_t</span> value);
</span></span></code></pre></div><p>To:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>HASHMAP_WEAK <span style="color:#66d9ef">int</span> <span style="color:#a6e22e">hashmap_put</span>(<span style="color:#66d9ef">struct</span> hashmap_s <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> hashmap,
</span></span><span style="display:flex;"><span>                             <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> key,
</span></span><span style="display:flex;"><span>                             <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">unsigned</span> len,
</span></span><span style="display:flex;"><span>                             <span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> value);
</span></span></code></pre></div><p>You&rsquo;ll notice that I also went <code>const</code> mad (and again wished that <code>const</code> was
the default and <code>mutable</code> or <code>mut</code> was required on variables - sigh!), and
removed the typedef for <code>any_t</code>. The last point is just a general stylistic
thing I have for my libraries - I really dislike that APIs like <code>Windows.h</code>
abstract you so far away from the underlying types with all the SHOUTY CASE
<code>LDPWORD</code>&rsquo;s and such, that I generally try and have no typedef&rsquo;s if I can get
away with it.</p>
<h2 id="supports-utf-8-keys">Supports UTF-8 Keys</h2>
<p>Pete&rsquo;s code also used the <code>string.h</code> ASCII-string functions of C to compare
whether the key ever matched. Since I wanted to use this hashmap in conjunction
with UTF-8 strings (using my <a href="https://github.com/sheredom/utf8.h">utf8.h</a>
library) I instead used <code>memcmp</code>. Now that I have an explicit length for the
string slice this became possible.</p>
<h2 id="single-header">Single Header</h2>
<p>The last major change I made was to smush the hashmap.c and hashmap.h files
together into a single header. I am pretty obsessed with single headers as a way
to get round the botched nature of C and C++&rsquo;s package story (or lack thereof).
This meant leveraging some exists hacks to stop the compiler complaining about
multiple function definitions (by using weak function references instead).</p>
<h2 id="the-license">The License</h2>
<p>Pete&rsquo;s code was already marked explicitly public domain - do what you want with
it. I&rsquo;ve found over the years that while public domain is all fine and well,
having an explicit license like the <a href="https://unlicense.org/">unlicense</a> or the
<a href="https://creativecommons.org/share-your-work/public-domain/cc0/">CC0</a> can make
lawyers happy because there is at least some legal text to reference. It also
makes GitHub&rsquo;s license scraping happier because these licenses are already ones
that it knows about.</p>
<p>So I&rsquo;ve licensed this header under the unlicense - it matches what my existing
single-header projects use and is something that my users already favour.</p>
<h2 id="hashmap-all-the-things">Hashmap All The Things</h2>
<p>So I&rsquo;m pretty happy with the code I <em>mostly</em> did not write - and I hope that my
packaging and testing of the header allows it to be more widely useful to some
of you fine folks out there.</p>
<p>A big thanks again to Pete Warden for writing this code and being so gracious
about me making these changes. I hope this proves useful to some of you out
there too.</p>
]]></description>
    </item>
    
    <item>
      <title>Asynchronous Reading in subprocess.h</title>
      <link>https://www.neilhenning.dev/posts/subprocess-h-async-reading/</link>
      <pubDate>Fri, 26 Jun 2020 13:11:31 +0100</pubDate>
      <guid>https://www.neilhenning.dev/posts/subprocess-h-async-reading/</guid>
      <description><![CDATA[<p>One hotly requested feature for my single header C/C++ process spawning and
management library <a href="https://github.com/sheredom/subprocess.h">subprocess.h</a> was
the ability to read from the standard output or error of a spawned process while
it was still executing. In
<a href="https://github.com/sheredom/subprocess.h/pull/24">this PR</a> I&rsquo;ve added support
for this, but it requires some change of behaviour in your code if you want to
use it.</p>
<h2 id="c-files-and-asynchronous-reading">C FILE&rsquo;s and Asynchronous Reading</h2>
<p>I use a really <em>clever hack</em> to give my users a standard C FILE handle with
which they can read the standard output and error, and write to the standard
input of any processes they spawn. This is immensely powerful because it means
anyone using my API can use an already familiar paradigm to interact with the
processes they spawn. Users could <code>fprintf</code> to the standard input of a spawned
process, or call <code>fgets</code> to read from the standard output or error. While I love
this feature - it causes a complication when trying to support asynchronous
reading.</p>
<p>For the normal process spawning on Windows I was using <code>CreatePipe</code> to map a
<code>HANDLE</code> on the parent process to <code>HANDLE</code> that&rsquo;ll be used for the standard
pipes on the spawned process. A <code>CreatePipe</code> is also known as an anonymous pipe
in Windows lingo - and it turns out you cannot sync from this pipe until the
spawned process has complete. But there is another mechanism called a named pipe
using the <code>CreateNamedPipe</code> call that can help us here.</p>
<p>Named pipes support an additional flag on creation <code>FILE_FLAG_OVERLAPPED</code> that
lets you get at the data from the pipe before the other end of the pipe has been
closed. I thought <em>&lsquo;Great! I&rsquo;ll use this et voila! Everything will work!&rsquo;</em>. It
didn&rsquo;t.</p>
<p>The problem is that if you use the overlapped creation flags to a named pipe you
cannot then do the <em>clever hack</em> anymore to get a C FILE that reads from this.
It&rsquo;ll just hang forever.</p>
<p>So instead I&rsquo;ve introduced some new helpers methods <code>subprocess_read_stdout</code> and
<code>subprocess_read_stderr</code> that use the correct APIs on each operating system to
allow for asynchronous reading from a pipe.</p>
<p>Note that while the main problems for this feature have been with Windows
support and the example below is Windows specific - the feature supports all
three major desktop platforms. Worry not!</p>
<h2 id="example">Example</h2>
<p>As an example of how we can use this I&rsquo;ve wrote up the following little example
that works on Windows (no reason why it couldn&rsquo;t work on other operating
systems, I just used Windows for the test):</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>() {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> commandLine[] <span style="color:#f92672">=</span> {<span style="color:#e6db74">&#34;ping&#34;</span>, <span style="color:#e6db74">&#34;-t&#34;</span>, <span style="color:#e6db74">&#34;www.bbc.net.uk&#34;</span>, <span style="color:#ae81ff">0</span>};
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">struct</span> subprocess_s process;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">unsigned</span> bytes_read;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (<span style="color:#ae81ff">0</span> <span style="color:#f92672">!=</span> <span style="color:#a6e22e">subprocess_create</span>(
</span></span><span style="display:flex;"><span>    commandLine,
</span></span><span style="display:flex;"><span>    subprocess_option_inherit_environment <span style="color:#f92672">|</span> subprocess_option_enable_async,
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&amp;</span>process)) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">fprintf</span>(stderr, <span style="color:#e6db74">&#34;subprocess_create failed!&#34;</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">do</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">char</span> buffer[<span style="color:#ae81ff">1024</span>] <span style="color:#f92672">=</span> {<span style="color:#ae81ff">0</span>};
</span></span><span style="display:flex;"><span>    bytes_read <span style="color:#f92672">=</span> <span style="color:#a6e22e">subprocess_read_stdout</span>(<span style="color:#f92672">&amp;</span>process, buffer, <span style="color:#66d9ef">sizeof</span>(buffer));
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">printf</span>(<span style="color:#e6db74">&#34;Read %u bytes - &#39;%s&#39;</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, bytes_read, buffer);
</span></span><span style="display:flex;"><span>  } <span style="color:#66d9ef">while</span> (bytes_read <span style="color:#f92672">!=</span> <span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This will loop infinitely reading from the ping command with the <code>-t</code> option
specified. It&rsquo;ll read the output from ping as it is flushed and spit out what it
read and the number of bytes.</p>
<pre tabindex="0"><code>Read 42 bytes - &#39;
Pinging www.bbc.net.uk [212.58.237.253] &#39;
Read 24 bytes - &#39;with 32 bytes of data:
&#39;
Read 27 bytes - &#39;Reply from 212.58.237.253: &#39;
Read 27 bytes - &#39;bytes=32 time=22ms TTL=53
&#39;
Read 27 bytes - &#39;Reply from 212.58.237.253: &#39;
Read 27 bytes - &#39;bytes=32 time=22ms TTL=53
&#39;
</code></pre><p>A few things:</p>
<ul>
<li>Note the new <code>subprocess_create</code> option <code>subprocess_option_enable_async</code>. This
is needed to setup the pipe for being able to read from it asynchronously. If
you use this option you should refrain from using <code>subprocess_stdout</code> or
<code>subprocess_stderr</code> to read from the spawned process - they will <strong>not</strong> work.</li>
<li>Note the new function <code>subprocess_read_stdout</code> to read from the standard
output of the spawned process. It&rsquo;ll return non-zero while there is any data
still to be read. When the child process terminates then it&rsquo;ll return 0
signalling the end.</li>
</ul>
<p>One additional thing to bear in mind is that the <code>subprocess_read_stdout</code> and
<code>subprocess_read_stderr</code> functions are blocking. If you want to read from both
of these simultaneously then it is recommended that you either:</p>
<ul>
<li>Spawn a thread for one or both to read from it. It is thread safe to read from
both pipes of a spawned process at the same time.</li>
<li>Or use the <code>subprocess_option_combined_stdout_stderr</code> option if you just want
the full contents of both pipes both don&rsquo;t care to differentiate from either
pipes output.</li>
</ul>
<p>I hope you find this new functionality useful.</p>
<p>An additional gentle reminder that you can stay tuned for future updates by
using the <a href="https://www.neilhenning.dev/index.xml">RSS</a> feed.</p>
]]></description>
    </item>
    
    <item>
      <title>Adding fixtures to ubench.h</title>
      <link>https://www.neilhenning.dev/posts/adding_fixtures_ubench_h/</link>
      <pubDate>Sun, 21 Jun 2020 12:08:47 +0100</pubDate>
      <guid>https://www.neilhenning.dev/posts/adding_fixtures_ubench_h/</guid>
      <description><![CDATA[<p>One thing that was missing from ubench.h (intentionally to keep the initial
code drop simple) was fixtures. In
<a href="https://github.com/sheredom/ubench.h/pull/4">this PR</a> I&rsquo;ve added them.</p>
<p>So what are fixtures and why should you use them?</p>
<h2 id="what-are-fixtures">What are fixtures?</h2>
<p>Fixtures are a way to setup and teardown state that doesn&rsquo;t contribute to the
timing of the actual benchmark itself:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">// First you declare a struct that contains the state you need.
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> foo {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">unsigned</span> size;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">char</span><span style="color:#f92672">*</span> foo;
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Then you setup the benchmark state - using the ubench_fixture implicit field.
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">UBENCH_F_SETUP</span>(foo) {
</span></span><span style="display:flex;"><span>  ubench_fixture<span style="color:#f92672">-&gt;</span>size <span style="color:#f92672">=</span> <span style="color:#ae81ff">1024</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">1024</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">128</span>;
</span></span><span style="display:flex;"><span>  ubench_fixture<span style="color:#f92672">-&gt;</span>foo <span style="color:#f92672">=</span> (<span style="color:#66d9ef">char</span><span style="color:#f92672">*</span>)<span style="color:#a6e22e">malloc</span>(ubench_fixture<span style="color:#f92672">-&gt;</span>size);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// In the teardown you can free up anything you allocated.
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">UBENCH_F_TEARDOWN</span>(foo) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">free</span>(ubench_fixture<span style="color:#f92672">-&gt;</span>foo);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// And then declare the benchmarks that use the state.
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">UBENCH_F</span>(foo, bar) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">UBENCH_DO_NOTHING</span>(ubench_fixture<span style="color:#f92672">-&gt;</span>foo);
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">memset</span>(ubench_fixture<span style="color:#f92672">-&gt;</span>foo, <span style="color:#ae81ff">0</span>, ubench_fixture<span style="color:#f92672">-&gt;</span>size);
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">UBENCH_DO_NOTHING</span>(ubench_fixture<span style="color:#f92672">-&gt;</span>foo);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// You can declare multiple benchmarks that use the same fixture too.
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">UBENCH_F</span>(foo, haz) {
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As you can see setting up and declaring a fixture isn&rsquo;t difficult.</p>
<h2 id="why-you-should-use-them">Why you should use them?</h2>
<p>Let&rsquo;s take the counter example to the fixture above - using the non-fixture
approach:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#a6e22e">UBENCH</span>(foo, bar) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">unsigned</span> size <span style="color:#f92672">=</span> <span style="color:#ae81ff">1024</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">1024</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">128</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">char</span><span style="color:#f92672">*</span> foo <span style="color:#f92672">=</span> (<span style="color:#66d9ef">char</span><span style="color:#f92672">*</span>)<span style="color:#a6e22e">malloc</span>(size);
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">UBENCH_DO_NOTHING</span>(foo);
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">memset</span>(foo, <span style="color:#ae81ff">0</span>, size);
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">UBENCH_DO_NOTHING</span>(foo);
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">free</span>(foo);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And if we look at the results of both these tests we can see that the
non-fixture one runs like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>[<span style="color:#f92672">==========</span>] Running <span style="color:#ae81ff">1</span> benchmarks.
</span></span><span style="display:flex;"><span>[ RUN      ] foo.bar
</span></span><span style="display:flex;"><span>[       OK ] foo.<span style="color:#a6e22e">bar</span> (mean <span style="color:#ae81ff">15.506</span>ms, confidence interval <span style="color:#f92672">+-</span> <span style="color:#ae81ff">1.553863</span><span style="color:#f92672">%</span>)
</span></span><span style="display:flex;"><span>[<span style="color:#f92672">==========</span>] <span style="color:#ae81ff">1</span> benchmarks ran.
</span></span><span style="display:flex;"><span>[  PASSED  ] <span style="color:#ae81ff">1</span> benchmarks.
</span></span></code></pre></div><p>Whereas the fixture one runs like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>[<span style="color:#f92672">==========</span>] Running <span style="color:#ae81ff">1</span> benchmarks.
</span></span><span style="display:flex;"><span>[ RUN      ] foo.bar
</span></span><span style="display:flex;"><span>[       OK ] foo.<span style="color:#a6e22e">bar</span> (mean <span style="color:#ae81ff">4.125</span>ms, confidence interval <span style="color:#f92672">+-</span> <span style="color:#ae81ff">0.844092</span><span style="color:#f92672">%</span>)
</span></span><span style="display:flex;"><span>[<span style="color:#f92672">==========</span>] <span style="color:#ae81ff">1</span> benchmarks ran.
</span></span><span style="display:flex;"><span>[  PASSED  ] <span style="color:#ae81ff">1</span> benchmarks.
</span></span></code></pre></div><p>So we can see that the average time for the fixtured one is about 4x faster than
the non-fixtured one - because it hasn&rsquo;t timed the malloc/free cost per
benchmark. This means that if you really only care about what memset costs
you&rsquo;ve now got a much more accurate way to get that.</p>
<p>This is where fixtures are really great - hide the cost of setting up the data
for your benchmark from the thing you actually want to benchmark.</p>
<h2 id="one-last-thing">One last thing&hellip;</h2>
<p>One thing that <em>might</em> not be obvious is that fixtured tests can have a wall
clock time that is longer than the non-fixtured variants. For the examples above
the non-fixture one runs in:</p>
<pre tabindex="0"><code>real 0m0.592s
user 0m0.368s
sys  0m0.177s
</code></pre><p>Whereas the fixture benchmark runs in:</p>
<pre tabindex="0"><code>real 0m3.631s
user 0m3.508s
sys  0m0.071s
</code></pre><p>So why is this? In general the longer running a benchmark is the more accurate
the result will be - so because we&rsquo;re measuring less things in the actual
benchmark samples the framework is having to run more of them to get an accurate
result.</p>
<p>Just thought you might appreciate the heads up!</p>
]]></description>
    </item>
    
    <item>
      <title>I&#39;m now 99% Confident in ubench.h</title>
      <link>https://www.neilhenning.dev/posts/switching_ubench_h_to_confidence_interval/</link>
      <pubDate>Sat, 20 Jun 2020 19:21:42 +0100</pubDate>
      <guid>https://www.neilhenning.dev/posts/switching_ubench_h_to_confidence_interval/</guid>
      <description><![CDATA[<p>So I recently created a new single header C/C++ library for benchmarking your
code - <a href="https://github.com/sheredom/ubench.h">ubench.h</a>.</p>
<p>It&rsquo;s funny how as soon as you push something public you realise all the flaws in
it - but that&rsquo;s fine! Software (like people) should grow and develop as it gets
older.</p>
<p>The way I was trying to gauge the accuracy of the result from multiple benchmark
runs was somewhat&hellip; broken. In
<a href="https://github.com/sheredom/ubench.h/pull/3">this PR</a> I&rsquo;ve switched to using a
confidence interval, and I&rsquo;ll now explain why.</p>
<h2 id="the-broken-approach">The Broken Approach</h2>
<p>So I&rsquo;ve never studied statistics in any capacity. I&rsquo;d always followed the
believe that statisticians were like demi-lawyers - good at manipulating the
same set of &lsquo;facts&rsquo; to tell whatever story they want.</p>
<p>But ever since I watched the rather awesome
<a href="https://twitter.com/despair">Elan Ruskin</a> talk about
<a href="https://www.gdcvault.com/play/1023323/Three-Statistical-Tests-Every-Game">statistical tests for games</a>
I realised I needed to level up.</p>
<p>So the first thing I learned about was standard deviation - well really I
had to re-learn this because I&rsquo;m pretty certain I got taught it in high school
and immediately forgot it&hellip; For those uninitiated the standard deviation gives
you a measure of how variable the average of a set of data is. Let&rsquo;s say you&rsquo;ve
got 10 recordings of something - the average is just the sum of all items
divided by the number of recordings, otherwise know as the mean.</p>
<p>You then use this mean, subtract it from each of the original values, square
them, divide by the number of iterations and then take the sqrt of that:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">ubench_int64_t</span> ns[iterations];
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">ubench_int64_t</span> avg_ns <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> iterations; i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>  avg_ns <span style="color:#f92672">+=</span> ns[i];
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>avg_ns <span style="color:#f92672">/=</span> iterations;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> iterations; i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">double</span> v <span style="color:#f92672">=</span> ns[i] <span style="color:#f92672">-</span> avg_ns;
</span></span><span style="display:flex;"><span>  deviation <span style="color:#f92672">+=</span> v <span style="color:#f92672">*</span> v;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>deviation <span style="color:#f92672">=</span> <span style="color:#a6e22e">sqrt</span>(deviation <span style="color:#f92672">/</span> iterations);
</span></span></code></pre></div><p>Once I had this I then used the standard deviation to measure how variable the
result was. A high standard deviation means that you don&rsquo;t have confidence that
the result you&rsquo;ve recorded is stable enough to be meaningful. Conversely a low
standard deviation makes you confident. Previously I was aiming for a standard
deviation below 2.5% as a gauge of how good the result was.</p>
<p>The problem is that getting a standard deviation below a low margin across many
different types of machines we test on (laptops, desktops, mobiles, consoles,
etc) can be quite difficult. Pre-emption of the running thread might cause a
temporary spike in a given tests result, or you might get a very fast run that
hits no speed bumps and thus runs really fast. These outlier results can
really affect the standard deviation of the result.</p>
<p>Since I didn&rsquo;t know much about stats I <em>wrongly</em> thought that the best way to
cut out the occassional high variance results was to just sort all the runs and
then slice off the top and bottom N items:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">ubench_int64_t</span> ns[iterations];
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">ubench_int64_t</span> avg_ns <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Sort the results.
</span></span></span><span style="display:flex;"><span><span style="color:#a6e22e">qsort</span>(ns, iterations, <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">ubench_int64_t</span>), ubench_sort_func);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (i <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>; i <span style="color:#f92672">&lt;</span> (iterations <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>); i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>  avg_ns <span style="color:#f92672">+=</span> ns[i];
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>avg_ns <span style="color:#f92672">/=</span> (iterations <span style="color:#f92672">-</span> <span style="color:#ae81ff">2</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (i <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>; i <span style="color:#f92672">&lt;</span> (iterations <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>); i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">double</span> v <span style="color:#f92672">=</span> ns[i] <span style="color:#f92672">-</span> avg_ns;
</span></span><span style="display:flex;"><span>  deviation <span style="color:#f92672">+=</span> v <span style="color:#f92672">*</span> v;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>deviation <span style="color:#f92672">=</span> <span style="color:#a6e22e">sqrt</span>(deviation <span style="color:#f92672">/</span> (iterations <span style="color:#f92672">-</span> <span style="color:#ae81ff">2</span>));
</span></span></code></pre></div><p>This would cut off the top and bottom worse skewed results. The problem is that
this didn&rsquo;t really reduce the standard deviation that much in the first place,
and secondly it discounted valuable collected data.</p>
<p>Another problem with the standard deviation is that its not necessarily true
that collecting more data will reduce the deviation itself - just because you
are collecting more data doesn&rsquo;t meant that the data will be any less deviant.</p>
<p>So I needed another approach.</p>
<h2 id="im-99-confident-with-my-interval">I&rsquo;m 99% Confident with my Interval</h2>
<p>If we look at the typical spread of data for any measurement, the data <em>tends</em>
to centre around the average or mean value. This is called the normal
distribution or a bell curve, and generally looks like:</p>

<img src="/images/confidence-interval/bellmouth.jpg"  class="center"  style="border-radius: 8px;"    />


<p>In this chart, x = 0 is the the average, and y is the number of samples that
matched the given value of x. This is what data <em>tends</em> to look like from
benchmarks. We can see that most of the samples (larger y) occurs closer to the
mean, and there is less and less the further we go away. Given I want to cut out
any outliers large or small, what we really want is a way to say <em>&lsquo;Is most of
the data close enough to the average?&rsquo;</em>.</p>
<p>Luckily some people smarter than me have a way to do this - and it is called a
confidence interval. A confidence interval is a way to say <em>&lsquo;If we only care
about X% of the data, how close is that to the average?&rsquo;</em>. For my use case I&rsquo;m
using a 99% confidence interval - EG. I&rsquo;m asking the stats to give me a number
for how close the 99% of the samples that are closest to the average actually
are:</p>

<img src="/images/confidence-interval/with-bars.jpg"  class="center"  style="border-radius: 8px;"    />


<p>We can see in this chart the two extra lines - this is my confidence interval,
I&rsquo;m only wanting to know how close the X% of the values that are occuring within
these bounds are to the average.</p>
<p>Calculating a confidence interval is pretty easy too:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> iterations; i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>  avg_ns <span style="color:#f92672">+=</span> ns[i];
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>avg_ns <span style="color:#f92672">/=</span> iterations;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> iterations; i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">double</span> v <span style="color:#f92672">=</span> ns[i] <span style="color:#f92672">-</span> avg_ns;
</span></span><span style="display:flex;"><span>  deviation <span style="color:#f92672">+=</span> v <span style="color:#f92672">*</span> v;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>deviation <span style="color:#f92672">=</span> <span style="color:#a6e22e">sqrt</span>(deviation <span style="color:#f92672">/</span> iterations);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Confidence is the 99% confidence index - whose magic value is 2.576.
</span></span></span><span style="display:flex;"><span>confidence <span style="color:#f92672">=</span> <span style="color:#ae81ff">2.576</span> <span style="color:#f92672">*</span> deviation <span style="color:#f92672">/</span> <span style="color:#a6e22e">sqrt</span>(iterations);
</span></span></code></pre></div><p>Now there is this magic constant <code>2.576</code> - I genuinely have no idea where it
comes from or why it is what it is. But
<a href="https://en.wikipedia.org/wiki/Confidence_interval_">some smart stats people</a>
has done some math stats stuff and&hellip; this is the value I need.</p>
<p>Now instead of aiming for a 2.5% range with my botched standard deviation, I
instead look for a 2.5% range with my 99% confidence interval instead. The
great thing about the confidence interval is the more data you throw at it the
lower it goes. I think this is because you cut out more outliers (the 1%) the
more samples you have, but whatever the reason it means that if I haven&rsquo;t
achieved the 2.5% range I want I can just re-run it with more samples and that
generally does what I want. Nice!</p>
<p>The output from ubench.h has now changed to display the confidence interval too,
and I added a request from <a href="https://twitter.com/zeuxcg">@zeuxcg</a> to change the
displayed timing in ms/s/us where appropriate - which makes it much more
legible:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>[ RUN      ] cpp_my_fixture.strchr
</span></span><span style="display:flex;"><span>[       OK ] cpp_my_fixture.<span style="color:#a6e22e">strchr</span> (mean <span style="color:#ae81ff">4.115</span>ms, confidence interval <span style="color:#f92672">+-</span> <span style="color:#ae81ff">2.039480</span><span style="color:#f92672">%</span>)
</span></span><span style="display:flex;"><span>[ RUN      ] cpp_my_fixture.strrchr
</span></span><span style="display:flex;"><span>[       OK ] cpp_my_fixture.<span style="color:#a6e22e">strrchr</span> (mean <span style="color:#ae81ff">57.057</span>ms, confidence interval <span style="color:#f92672">+-</span> <span style="color:#ae81ff">0.445810</span><span style="color:#f92672">%</span>)
</span></span></code></pre></div><h2 id="conclusion">Conclusion</h2>
<p>So I&rsquo;ve made ubench.h more consistent at profiling and actually used real
mathematically sound statistics rather than my bodged attempt at it - nice! For
my users it&rsquo;ll mean more consistent data and more confidence (har har) that it
is doing the right thing.</p>
]]></description>
    </item>
    
    <item>
      <title>White Guilt and Juneteenth</title>
      <link>https://www.neilhenning.dev/posts/white_guilt_and_juneteenth/</link>
      <pubDate>Fri, 19 Jun 2020 17:01:42 +0100</pubDate>
      <guid>https://www.neilhenning.dev/posts/white_guilt_and_juneteenth/</guid>
      <description><![CDATA[<p>I&rsquo;m currently sitting at home on an unexpected days holiday - for Juneteenth.
The high hiedyins of Unity wanted to give us some space to reflect as a company
on the racial inequality in the world.</p>
<p><strong>And I&rsquo;m sitting here feeling guilty as all heck.</strong> Why should I, as a peely
wally white guy, benefit <strong>yet again</strong> from black voices rightfully pointing out
the utterly unjust situation that we (white folks) have put them through for at
least four hundred years. Shamefully I didn&rsquo;t even <em>know</em> what Juneteenth was
until they announced it was a holiday, and I quickly scuttled over to
<a href="https://en.wikipedia.org/wiki/Juneteenth">wikipedia</a> to read what actually
happened on that day.</p>
<p>To try and shake just a sliver of my guilt I&rsquo;ve donated my wages for today to
the <a href="https://www.stephenlawrence.org.uk/">Stephen Lawrence Charitable Trust</a> to
in some way help towards all the good they do.</p>
<p>I also want to talk a bit about white guilt - why we <strong>should</strong> feel guilty,
and especially the role that Scotland played in and profited from the horrors of
the slave trade, and the ongoing problems with racism and discrimination that
still affect Scotland today.</p>
<h2 id="white-guilt">White Guilt</h2>
<blockquote>
<p>But the one thing the American dream fails to mention, Is I was many steps
ahead to begin with - White Privilege II by Macklemore &amp; Ryan Lewis</p>
</blockquote>
<p>The line above from the great <em>&ldquo;White Privilege II&rdquo;</em> song by Macklemore &amp; Ryan
Lewis was in reference to America but it applies equally to white men
everywhere. We&rsquo;ve had a head start on nearly ever situation we&rsquo;ve been involved
in and didn&rsquo;t realise because that&rsquo;s just how things went for us. We&rsquo;d been born
white and thus benefitted from a racist system. We&rsquo;d been born male which meant
we benefitted from a sexist system. We&rsquo;ve had job offers, higher wages,
promotions, lenient police intervention, and the list goes on.</p>
<p>If we are assertive and egotistical we&rsquo;re praised as leaders while the system
has actively punished black people and woman for showing the same traits that
are so valued in white men.</p>
<p>And the worst bit about all of this for me personally is that <em>because</em> this
discrimination didn&rsquo;t affect me personally in any way I was a passive ally to a
broken system.</p>
<p>So I&rsquo;ve got white guilt - specifically white <strong>man</strong> guilt - and it is right
that I do. I&rsquo;ve implicitly benefitted from a system that was rigged in my favour
and I was too wrapped up in my own ego to realise.</p>
<h2 id="scotland-and-slavery">Scotland and Slavery</h2>
<p>David Hayman made a fantastic program for BBC Scotland -
<a href="https://www.bbc.co.uk/programmes/b0bqvv10">Slavery: Scotland&rsquo;s Hidden Shame</a>.
In it, David goes into depth about all the horrible ways that Scotland directly
benefitted from slavery (lots of people here owned slaves as a
<em>&lsquo;good investment&rsquo;</em>), and also how Scots themselves disproportionately made up
the staff employed in managing the slave trade (from the physicians on the
boats to those doing the paperwork).</p>
<p>We Scots have to acknowledge the part our country played in this through
education and introspection. In high school history, the lessons I was taught
consisted of a walk through all the times we won against the English in war,
how France is the Auld Ally and our friend, and then it skipped forward to the
industrial revolution and the slum-like conditions the families lived in. The
period of failed colonisation (see the hilariously badly planned
<a href="https://en.wikipedia.org/wiki/Darien_scheme">Panama colony</a> - including taking
winter kilts to the tropics), the reasons we went into union with England
(Scotland was so poorly managed we went bankrupt), and the subsequent
involvement of Scots in the slave trade were all massive missing parts of my
education.</p>
<p>Another fact that people aren&rsquo;t taught here is that the racist and facist KKK
(who truly should be considered a terrorist organisation I don&rsquo;t even understand
how they can exist) was
<a href="https://www.theguardian.com/education/2002/jan/19/highereducation.historybooks1">founded by Scots</a>.</p>
<p>It&rsquo;s important that we get taught these lessons.</p>
<h2 id="scotland-today">Scotland Today</h2>
<p>Scotland today is a country that is trying to be an outward looking and
welcoming country. We talk about welcoming refugees and being open to people
from all backgrounds and faiths. And yet two days ago our First Minister had to
<a href="https://www.bbc.co.uk/news/uk-scotland-glasgow-west-53086488">condemn racist thugs</a>
on the streets of our biggest city Glasgow.</p>
<p>Scotland has a <em>long</em> history of discrimination. At least where I&rsquo;m
from south of Glasgow, there have been multiple waves of immigrants in the past
few hundred years that have caused discrimination to ramp up. My own family has
heavy Irish roots - having fled either during the potato famine or when the
republican movement flared up in Northern Ireland. There was a huge movement of
Italians post World War II that settled in Glasgow and the surrounding areas.
There are decent communities of incomers from Bangladesh, India, Pakistan, and
Turkey too.</p>
<p>And each of these groups faced persecution. The Irish, being predominantly
catholic incomers, met with hostility of the
<a href="https://en.wikipedia.org/wiki/Orange_Order">Orange Order</a> and had derogatory
phrases like <em>&ldquo;Fenian Scum!&rdquo;</em> hurled at them, the Italians were called
<em>&ldquo;Tallies&rdquo;</em> and faced an anti-Italian fervour, and anyone who looked even
<em>slightly</em> like they were from the Middle East or East Asia was called a
<em>&ldquo;Paki&rdquo;</em>.</p>
<p>I was from a catholic family in a <em>very</em> protestant town, and before the age of
16 I was:</p>
<ul>
<li>Petrol bombed.</li>
<li>Chased with Samurai swords.</li>
<li>Had bricks thrown at me.</li>
<li>Involved in many altercations of the fisticuff kind.</li>
</ul>
<p>Every walk home from school was a gauntlet of &lsquo;what would happen today&rsquo;. If I
wore the colour green on a day where the Orange Order were doing one of their
nonsense &lsquo;parades&rsquo; (they march and play flutes, followed by a rowdy crowd of
drunk racists looking for a fight) I&rsquo;d have to run - fast.</p>
<p>I have never <em>once</em> witnessed overt racism against black people here, but I&rsquo;ve
seen plenty of people who have had <em>&ldquo;Paki&rdquo;</em> thrown in their face in my time. I
thought things here had got better, or at least I had hoped. But when you hear
the things that the racist thugs above said it is clear we&rsquo;ve still got a ways
to go.</p>
<h2 id="what-can-white-people-do">What Can White People Do</h2>
<p>There are some things we white men can do to help correct the historial wrongs
we&rsquo;ve inadvertently took part in:</p>
<ul>
<li>Make space for black and other under-represented groups. We need to put our
elbows out and use our privilege as a way to pull others up.</li>
<li>Push for diversity in hiring. This requires having hard conversations with
your direct management, but also using company wide meetings that allow
questions of the high hiedyins as an opportunity to ask about diversity.</li>
<li>Try to seek out people who don&rsquo;t look like you and engage with them. My twitter and
social circles are predominantly white and male, and for too long I put this
down to <em>&ldquo;Well these are just the people in the industry I know so&hellip;&rdquo;</em>. This
was <em>wrong</em> of me and I need to do better.</li>
<li>Speak up when you see injustice in the world and your workplace. The white
man privilege we&rsquo;ve always had gives us a shield against most of the
repercussions that under-represented groups would face if they speak out.</li>
<li>Where possible donate to groups that help the black community.</li>
<li>Arrest Brett Hankison, Jonathan Mattingly, and Myles Cosgrove for the murder
of Breonna Taylor.</li>
</ul>
<p>Let us try and make a better world for everyone, together. We&rsquo;re all the better
when we&rsquo;re in it together.</p>
]]></description>
    </item>
    
    <item>
      <title>Introducing ubench.h</title>
      <link>https://www.neilhenning.dev/posts/introducing_ubench_h/</link>
      <pubDate>Mon, 15 Jun 2020 19:21:42 +0100</pubDate>
      <guid>https://www.neilhenning.dev/posts/introducing_ubench_h/</guid>
      <description><![CDATA[<p>Ever since I worked on my amazing little single-header C/C++ library <a href="https://github.com/sheredom/utest.h/">utest.h</a>, which mimics enough of Google&rsquo;s googletest framework but <a href="https://www.neilhenning.dev/posts/utest-h-performance/">in a significantly leaner footprint</a> (and a single header!), I&rsquo;ve wanted something similar for doing benchmarking. Google has their own benchmarking library <a href="https://github.com/google/benchmark">Google benchmark</a>, but it fails a couple of key tests that I have for libraries:</p>
<ul>
<li>It isn&rsquo;t a single header library.</li>
<li>It doesn&rsquo;t support C benchmarks.</li>
<li>It is <em>huge</em>.</li>
<li>It has a build process that results in a non trivial integration process.</li>
</ul>
<p>While none of these are a death knell for an otherwise incredibly useful library, it just didn&rsquo;t meet enough of the requirements for my own uses.</p>
<p>So I&rsquo;ve wrote my own - <a href="https://github.com/sheredom/ubench.h">ubench.h</a>.</p>
<h2 id="introducing-ubenchh">Introducing ubench.h</h2>
<p>So given all the infrastructure I had already worked out to get my utest.h library, I could re-use a significant amount of the code. I started by copying the code from utest.h and doing a rename of <code>UTEST</code> -&gt; <code>UBENCH</code> and <code>utest</code> -&gt; <code>ubench</code>. Next up, I removed all the code that wasn&rsquo;t required from testing - all the asserts and expects that make up a unit testing framework. I also removed <a href="https://github.com/sheredom/utest.h/#define-a-fixtured-testcase">fixture</a> and <a href="https://github.com/sheredom/utest.h/#define-an-indexed-testcase">indexed</a> testcases because I wanted to push for a minimally viable product to begin with.</p>
<h2 id="ubench">UBENCH</h2>
<p>To declare a benchmark you use the <code>UBENCH</code> macro:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;ubench.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">UBENCH</span>(foo, bar) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">usleep</span>(<span style="color:#ae81ff">100</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">1000</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The macro takes two parameters - the set of the benchmark, and the name of the individual benchmark. In the body of the benchmark you specify the code you want to profile - in this case I&rsquo;m just sleeping for a certain amount of time as a good no-op example.</p>
<p>In one file you then need to specify the <code>UBENCH_MAIN()</code> - this macro will define the <code>main</code> function of your executable, define all the global state we require, and call into ubench.h to run the benchmarks:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;ubench.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">UBENCH_MAIN</span>()
</span></span></code></pre></div><p>You can alternatively call the <code>ubench_main</code> function yourself if you want to use your own <code>main</code> function instead. First you need to specify the state for ubench.h:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#a6e22e">UBENCH_STATE</span>();
</span></span></code></pre></div><p>And then when you are ready to call into the ubench.h framework do:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">int</span> <span style="color:#a6e22e">main</span>(<span style="color:#66d9ef">int</span> argc, <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> argv[]) {
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// do your own thing
</span></span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> <span style="color:#a6e22e">ubench_main</span>(argc, argv);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Note - you need to specify <code>UBENCH_MAIN</code> or <code>UBENCH_STATE</code> in a single source file only.</p>
<h2 id="command-line-output">Command Line Output</h2>
<p>The command line output for the library is similar to utest.h and thus also similar to googletest&rsquo;s output:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>[<span style="color:#f92672">==========</span>] Running <span style="color:#ae81ff">1</span> benchmarks.
</span></span><span style="display:flex;"><span>[ RUN      ] foo.bar
</span></span><span style="display:flex;"><span>[       OK ] foo.<span style="color:#a6e22e">bar</span> (<span style="color:#ae81ff">102289906</span>ns <span style="color:#f92672">+-</span> <span style="color:#ae81ff">1.751264</span><span style="color:#f92672">%</span>)
</span></span><span style="display:flex;"><span>[<span style="color:#f92672">==========</span>] <span style="color:#ae81ff">1</span> benchmarks ran.
</span></span><span style="display:flex;"><span>[  PASSED  ] <span style="color:#ae81ff">1</span> benchmarks
</span></span></code></pre></div><p>The one notable difference is how tests pass/fail, and the additional of <code>+- 1.751264%</code> to the timing information. Benchmarks are only useful if the repeated runs of them result in similar numbers. You need to run a benchmark a number of times and then get an average of the result. The problem is that the average can be vastly affected by huge outliers in the data set (EG. was the test ran from a cold start with dirty caches?) which can drastically affect the reliability of your results. To combat this, the benchmarks are recorded multiple times in multiple passes. Only when the standard deviation of the test is lower than 2.5 percent (a good initial value for a reliable and reproducible result) can the benchmark be seen as being useful. The <code>+- 1.751264%</code> is the standard deviation that was recorded for that example. If after a number of runs the variance of the runs does not conform to a small enough deviation then the benchmark is regarded to have failed, and is reported as such.</p>
<h2 id="ubench_do_nothing">UBENCH_DO_NOTHING</h2>
<p>Benchmarks are best when they are simple enough to record a single simple thing, that gives good reproducible results. One thing that defeats this is that compilers are so handy now at removing dead code - optimizing away the very thing you want to measure! To get around this I&rsquo;ve included the <code>UBENCH_DO_NOTHING</code> macro, which takes a pointer argument and looks, to the compiler, like it will trash the memory within (read and write it). This way the compiler shouldn&rsquo;t optimize out the data you are using and thus the code that you are using to produce it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#a6e22e">UBENCH</span>(<span style="color:#66d9ef">do</span>, nothing) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">char</span> a[<span style="color:#ae81ff">8</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">1024</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">1024</span>];
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">char</span> b[<span style="color:#ae81ff">8</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">1024</span> <span style="color:#f92672">*</span> <span style="color:#ae81ff">1024</span>];
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">UBENCH_DO_NOTHING</span>(a);
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">memcpy</span>(b, a, <span style="color:#66d9ef">sizeof</span>(a));
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">UBENCH_DO_NOTHING</span>(b);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The above makes the compiler think that <code>a</code> is getting some data placed within it, and then after the <code>memcpy</code> that something is being done with <code>b</code>. The end result is we can get a meaningful performance number for how expensive the <code>memcpy</code> is.</p>
<h2 id="summary">Summary</h2>
<p>The library is already simple yet useful for measuring some stuff - but I obviously want to do more. Fixtures are the obvious addition - you may want some state to be initialized once and then we profile the modifications of the data on its own rather than alongside the cost of initialization / destruction. I&rsquo;d also like to give the user more options for controlling how many times the benchmark is run to get a low enough standard deviation.</p>
<p>But I think as a programmer our number one job is to get something simple done and then use it in production. Production always helps shuffle out the actual missing things you need from the code rather than in the abstract up front trying to work out the full set of requirements. I hope the library proves useful to some of you out there, and you can keep track of the progress on GitHub at <a href="https://github.com/sheredom/ubench.h">https://github.com/sheredom/ubench.h</a>.</p>
]]></description>
    </item>
    
    <item>
      <title>Simple C Command Line Parser</title>
      <link>https://www.neilhenning.dev/posts/simple-c-command-line-parser/</link>
      <pubDate>Sun, 31 May 2020 12:36:33 +0100</pubDate>
      <guid>https://www.neilhenning.dev/posts/simple-c-command-line-parser/</guid>
      <description><![CDATA[<p>I&rsquo;ve been feeling a little overwhelmed by the languages I generally code in (C#, C++, Rust) and wanted to get my teeth into something a bit simpler again (obviously C!). One thing I&rsquo;ve never been that happy with in C was the lack of a good command line argument parser. There is a great <a href="https://github.com/nothings/single_file_libs#argv">list of option parsers</a> that <a href="https://twitter.com/nothings">@nothings</a> has curated over the years, but most of them are C++, and the ones for C are just a bit underwhelming to me.</p>
<p>Since the thing I&rsquo;m working on requires a command line application I thought <em>&lsquo;Why not write my own?&rsquo;</em> and herein lies the fun little trip I took.</p>
<h1 id="the-requirements">The Requirements</h1>
<p>So I want something that was:</p>
<ul>
<li>Written in C entirely.</li>
<li>Does not dynamically allocate any memory to store the arguments.</li>
<li>Can automatically generate the <code>--help</code> output for the supported options.</li>
</ul>
<p>To keep things simple I decided that short form options and long form options would have a defined structure:</p>
<ul>
<li>They can take no args and are of the form of <code>-h</code> and <code>--help</code>.</li>
<li>Or if they take an argument they are structured like <code>-o &lt;arg&gt;</code> or <code>--output=&lt;arg&gt;</code>.</li>
<li>They can only be specified zero or one times.</li>
</ul>
<p>I wasn&rsquo;t aiming to make some library that I could parachute into any project, more that I just wanted something simple that I could own myself.</p>
<h1 id="abusing-include-files">Abusing Include Files</h1>
<p>I <em>really</em> dislike anything that causes me to copy and paste code around. My distaste stems from the fact that you regularly want to then update all N places where you copied something, and it becomes onerous to keep these in check. Concretely for doing a command line parser, I didn&rsquo;t want to copy and paste code any time I added a new command line option.</p>
<p>Instead I wanted some way I could define all my options in a standard format and the rest of the tooling would pick this up and turn it into what I wanted. The only real way to do this in C is with the preprocessor. Since I knew that I&rsquo;d be wanting to use the same list of options for multiple purposes (EG. I&rsquo;d want to use them to parser <code>argv</code> but also print out their descriptions for <code>--help</code>), I decided to use an include file - a <code>.inc</code>. In general the notion for <code>.inc</code> files is that they have some preprocessor macro in their body that the includer defines before including the <code>.inc</code> file. Then they can include the <code>.inc</code> file multiple times and change what the macro does. This means that unlike most includes, <code>.inc</code> files <strong>do not</strong> have include guards / pragma once to stop multiple includes of them - because including it multiple times is <em>exactly</em> what we want to do.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#ifndef OPTION
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#error OPTION(short-name, long-name, number-of-trailing-args, description) was not defined!
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#endif
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">OPTION</span>(o, output, <span style="color:#ae81ff">1</span>, <span style="color:#e6db74">&#34;the output file to write to&#34;</span>)
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">OPTION</span>(h, help, <span style="color:#ae81ff">0</span>, <span style="color:#e6db74">&#34;print all the options and exit&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#undef OPTION
</span></span></span></code></pre></div><p>Here is my really simple <code>options.inc</code> that I used. It firstly includes a little if check to ensure that the required <code>OPTION</code> macro was specified, with a description of how the macro is intended to be used. Then it contains the list of the options that I have. At present just two options - one to specify where the output of the tool will go, and the other to display the help message and exit. Note the minor quality of life thing whereby the <code>.inc</code> file undefined the <code>OPTION</code> macro - this just saves you either doing it yourself after each include of the <code>.inc</code> file, or having the compiler warn about multiply defines macros!</p>
<p>Now that I have this I can use it to actually implement the parsing.</p>
<h1 id="parsing-argv">Parsing Argv</h1>
<p>So the first thing I wanted to ensure was that my <code>OPTION</code> macros were not malformed - specifically that the &rsquo;number-of-trailing-args&rsquo; was either 0 or 1. Even though I&rsquo;m the only one working on this and I hopefully shouldn&rsquo;t be dumb, I&rsquo;ve found over the years that any notion that you won&rsquo;t be dumb in some way is generally disproven. We are all stupid meatbags at times and so while you are hyper aware of the constraints it is best to be as defensive a coder as possible. Your future self will thank you!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#define OPTION(s, l, n, d)                                                     \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  bootstrap_assert(n &lt;= 1,                                                     \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">                   &#34;option&#34; #s &#34;/&#34; #l &#34; must have 0 or 1 trailing arguments&#34;);
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;options.inc&#34;</span><span style="color:#75715e">
</span></span></span></code></pre></div><p>So you can see that I just <code>#define</code> the <code>OPTION</code> macro and in this instance make it call my custom assert. Then I just have to include the <code>.inc</code> file and it&rsquo;ll do this for every option I&rsquo;ve defined.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span> <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> arg_is_set <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;set&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define OPTION(s, l, n, d) const char *arg_##s = 0;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;options.inc&#34;</span><span style="color:#75715e">
</span></span></span></code></pre></div><p>Next I needed a location to store the results of each of my variable. Using the same pattern again I can define variables of the form <code>arg_h</code> for the help argument, <code>arg_o</code> for the output, etc. For arguments that do not have any arguments I added a single <code>arg_is_set</code> here too - this we will use later to check whether the argument was set or not.</p>
<p>Now to the parser. This one is a bit of a mouthful I&rsquo;ll just warn you up front - it actually shows one of the big downsides to code generation with the preprocessor in C/C++ in that code in preprocessors is very difficult to debug within both compiler errors and when using a debugger. So remember that I didn&rsquo;t want <em>any</em> runtime memory allocation. So the one place you generally would use this is for positional arguments. Think of things like the list of files you&rsquo;d pass to a compiler, you can have N of these and they don&rsquo;t require options to be passed in. To get this to work I&rsquo;m going to reuse <code>argv</code> to store the list of the positional arguments. Since each positional argument always arrived in <code>argv</code> in the first place, it stands to reason that they can definitely fit!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>  <span style="color:#66d9ef">int</span> positional_arguments <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>; i <span style="color:#f92672">&lt;</span> argc; i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define OPTION(s, l, n, d)                                                     \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  {                                                                            \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    if (0 == strcmp(&#34;-&#34; #s, argv[i])) {                                        \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">      bootstrap_assert(arg_##s == 0, &#34;option&#34; #s &#34;/&#34; #l                        \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">                                     &#34; cannot be specified multiple times&#34;);   \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">      if (n == 0) {                                                            \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">        arg_##s = arg_is_set;                                                  \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">      } else {                                                                 \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">        bootstrap_assert((i + 1) &lt; argc, &#34;trailing argument for option&#34; #s     \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">                                         &#34;/&#34; #l &#34; was not provided&#34;);          \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">        arg_##s = argv[i + 1];                                                 \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">        i++;                                                                   \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">        continue;                                                              \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">      }                                                                        \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    } else if (0 == strncmp((n == 0) ? &#34;--&#34; #l : &#34;--&#34; #l &#34;=&#34;, argv[i],         \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">                            strlen(&#34;--&#34; #l &#34;=&#34;))) {                            \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">      bootstrap_assert(arg_##s == 0, &#34;option&#34; #s &#34;/&#34; #l                        \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">                                     &#34; cannot be specified multiple times&#34;);   \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">      if (n == 0) {                                                            \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">        arg_##s = arg_is_set;                                                  \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">      } else {                                                                 \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">        arg_##s = argv[i] + strlen(&#34;--&#34; #l &#34;=&#34;);                               \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">        continue;                                                              \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">      }                                                                        \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    }                                                                          \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  }
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;options.inc&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Otherwise if we didn&#39;t find our option then it is a position argument!
</span></span></span><span style="display:flex;"><span>    argv[positional_arguments<span style="color:#f92672">++</span>] <span style="color:#f92672">=</span> argv[i];
</span></span><span style="display:flex;"><span>  }
</span></span></code></pre></div><p>So let&rsquo;s break down the above:</p>
<ul>
<li>First I do the check for the small option form <code>s</code>, by string comparing <code>&quot;-&quot; #s</code> against the argument.
<ul>
<li>I then check if the option has been specified before which I&rsquo;m not handling.</li>
<li>If the option has zero trailing arguments, then just set the global variable for <code>arg_##s</code> to the <code>arg_is_set</code> helper I defined before.</li>
<li>If the option has one trailing argument, then I check there is definitely been a provided argument (EG. someone didn&rsquo;t have <code>-o</code> at the end of the argument list!).</li>
<li>And store the value in <code>argv[i + 1]</code> into the variable for the option.</li>
<li>I need to bump <code>i</code> to skip the next argument because we&rsquo;ve consumed it as the trailing argument of this one.</li>
<li>And then <code>continue</code>, this just gives us a nice easy way to skip the backup code to store the argument as a positional one.</li>
</ul>
</li>
<li>Next I do the check for the long form <code>l</code> - which requires a slightly different string compare. Because long form options that take an argument come like <code>--output=&lt;arg&gt;</code> I need to check if the option had a trailing argument, and then use a <code>strncmp</code> for this.
<ul>
<li>The only other difference is when there is a trailing argument I need to <strong>not</strong> bump <code>i</code> this time - because the argument is included in the option. To get at the argument we just get the pointer to the first character after the <code>--output=</code> - by using <code>strlen</code>.</li>
</ul>
</li>
<li>And then the fallback case is to just store the argument into the start of <code>argv</code> as a positional argument.</li>
</ul>
<h1 id="using-the-parsed-options">Using the Parsed Options</h1>
<p>So the first obvious way to use the options is to print the help:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (arg_h) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">printf</span>(<span style="color:#e6db74">&#34;usage bootstrap&#34;</span>);
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define OPTION(s, l, n, d)                                                     \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  if (n == 0) {                                                                \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    printf(&#34; [ %s | %s ]&#34;, &#34;-&#34; #s, &#34;--&#34; #l);                                   \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  } else {                                                                     \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    printf(&#34; [ %s &lt;arg&gt; | %s=&lt;arg&gt; ]&#34;, &#34;-&#34; #s, &#34;--&#34; #l);                       \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  }
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;options.inc&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">printf</span>(<span style="color:#e6db74">&#34; &lt;args&gt;</span><span style="color:#ae81ff">\n\n</span><span style="color:#e6db74">&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define OPTION(s, l, n, d)                                                     \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  if (n == 0) {                                                                \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    printf(&#34; %s | %s %s\n&#34;, &#34;-&#34; #s, &#34;--&#34; #l, d);                               \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  } else {                                                                     \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    printf(&#34; %s &lt;arg&gt; | %s=&lt;arg&gt; %s\n&#34;, &#34;-&#34; #s, &#34;--&#34; #l, d);                   \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  }
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;options.inc&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span>  }
</span></span></code></pre></div><p>Breaking this down I:</p>
<ul>
<li>Check that the <code>arg_h</code> variable is non-null - which means the user requested help.</li>
<li>Use an <code>OPTION</code> macro to print the short usage guide - something like <code>usage bootstrap [ -o &lt;arg&gt; | --output=&lt;arg&gt; ] [ -h | --help ] &lt;args&gt;</code>.</li>
<li>Then I use a second macro to print the longer usage guide with the descriptions.</li>
</ul>
<p>In the end this produces a help like:</p>
<pre tabindex="0"><code>usage bootstrap [ -o &lt;arg&gt; | --output=&lt;arg&gt; ] [ -h | --help ] &lt;args&gt;

 -o &lt;arg&gt; | --output=&lt;arg&gt; the output file to write to
 -h | --help print all the options and exit
</code></pre><p>The only thing that&rsquo;d make this nicer would be to align the descriptions. But for now its good enough for me.</p>
<p>Just to test that all the options were set and the positional arguments were stored like I expected, I added a second macro during debugging:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#define OPTION(s, l, n, d)                                                     \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  fprintf(stderr, &#34;%s = %s\n&#34;, #s, (arg_##s != 0) ? arg_##s : &#34;not set&#34;);
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;options.inc&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">fprintf</span>(stderr, <span style="color:#e6db74">&#34;Positional arguments:</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; i <span style="color:#f92672">&lt;</span> positional_arguments; i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">fprintf</span>(stderr, <span style="color:#e6db74">&#34;%s</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, argv[i]);
</span></span><span style="display:flex;"><span>  }
</span></span></code></pre></div><p>All this does is print whether each option was set or not, and then the list of positional arguments we recovered from the command line.</p>
<p>In total this is around 100 lines of C and does what I want in a very simple and easily controlled manner. I&rsquo;m very happy to be able to go back to basics and write some fun C code like this from time to time!</p>
]]></description>
    </item>
    
    <item>
      <title>utest.h Now Supports Whole Program Optimization</title>
      <link>https://www.neilhenning.dev/posts/utest-h-supports-wpo/</link>
      <pubDate>Wed, 27 May 2020 06:20:33 +0100</pubDate>
      <guid>https://www.neilhenning.dev/posts/utest-h-supports-wpo/</guid>
      <description><![CDATA[<p>A user of utest.h posted an <a href="https://github.com/sheredom/utest.h/issues/31">intruiging issue</a> that on an release build with Visual Studio my unit testing framework for C/C++, <a href="https://github.com/sheredom/utest.h">utest.h</a>, no tests were being ran. But on a debug build they were. Before I even got to the issue they worked out that whole program optimization was causing the issue and closed it themselves.</p>
<p>But this got me thinking - there is no reason why my library shouldn&rsquo;t work with whole program optimization enabled, so why was this behaving badly?</p>
<h1 id="visual-studios-whole-program-optimization">Visual Studio&rsquo;s Whole Program Optimization</h1>
<p>To enable whole program optimization in Visual Studio requires the <code>/GL</code> option on the <code>cl.exe</code> compiler, and <code>/LTCG</code> on the <code>link.exe</code>. What this does is effectively defer some of the optimizations and optimization ability to link time. At link time it can then perform optimizations across multiple individual compilation units to (in theory!) result in a more optimal resulting executable.</p>
<p>In CMake you can enable this for an executable like so:</p>
<pre tabindex="0"><code>if(&#34;${CMAKE_CXX_COMPILER_ID}&#34; STREQUAL &#34;MSVC&#34;)
  target_compile_options(utest_test_wpo PRIVATE &#34;$&lt;$&lt;CONFIG:RELEASE&gt;:/GL&gt;&#34;)
  target_link_options(utest_test_wpo PRIVATE &#34;$&lt;$&lt;CONFIG:RELEASE&gt;:/LTCG&gt;&#34;)
endif()
</code></pre><p>What the above does is turn on the option <em>only</em> for release builds, for the given target. The first thing I did when trying to work out this issue was to duplicate the existing tests I had for utest, and build a separate target <code>utest_test_wpo</code>. I used the above CMake to turn on the whole program optimization, configured CMake to use release and got the following output:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>[<span style="color:#f92672">==========</span>] Running <span style="color:#ae81ff">0</span> test cases.
</span></span><span style="display:flex;"><span>[<span style="color:#f92672">==========</span>] <span style="color:#ae81ff">0</span> test cases ran.
</span></span><span style="display:flex;"><span>[ PASSED ] <span style="color:#ae81ff">0</span> tests.
</span></span></code></pre></div><p>So this matched what the user found at least!</p>
<h1 id="the-problem">The Problem</h1>
<p>So the issue boils down to a clever little trick I use in utest.h - how it discovers test. Now for those that aren&rsquo;t aware my utest.h library looks for tests in a specific format:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#a6e22e">UTEST</span>(from, c) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ASSERT_TRUE</span>(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And allows you to run them. This works <em>across</em> C or C++ files - if you have <code>T</code> tests spread across <code>F</code> files, when you run the produced executable it&rsquo;ll run all <code>T</code> tests - even though they started in separate files. I don&rsquo;t use any custom magic to make this work - so how can I cross compilation units to work out what to run?</p>
<p>I use an idiom that is <em>awful</em> and <em>awesome</em> in equal measures - global constructors. For those used to C++ you&rsquo;ll be aware that global variables can have constructors to initialize their state. It is general wisdom among those of us burned by the feature to either a) not use global variable constructors at all, or b) if you do make them dumb as possible. This is because the order that all global variables will be initialized is undefined - and thus any interdependency between these variables could cause problems.</p>
<p>What is less well known is that the three major C compilers have ways to add global constructors in C code.</p>
<p>Clang/GCC both support the following:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">f</span>(<span style="color:#66d9ef">void</span>) <span style="color:#a6e22e">__attribute__</span>((constructor));
</span></span></code></pre></div><p>You just tag a function as being a <code>constructor</code> using the attribute mechanism, and it&rsquo;ll be run during the globals initialization phase.</p>
<p>MSVC (Visual Studio) is a little more complicated, but you can achieve the same thing with:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">void</span> <span style="color:#66d9ef">__cdecl</span> <span style="color:#a6e22e">f</span>(<span style="color:#66d9ef">void</span>);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">__declspec</span>(<span style="color:#a6e22e">allocate</span>(<span style="color:#e6db74">&#34;.CRT$XCU&#34;</span>)) <span style="color:#66d9ef">void</span>(<span style="color:#66d9ef">__cdecl</span> <span style="color:#f92672">*</span> f_)(<span style="color:#66d9ef">void</span>) <span style="color:#f92672">=</span> f;
</span></span></code></pre></div><p>What this does is add a function pointer to a special section <code>.CRT$XCU</code> - where all the global initializers are placed. On startup the compiler will run through this list of function pointers to initialize all the global state. It&rsquo;s aesthetically uglier than the Clang/GCC approach, but it works!</p>
<p>With this key piece of technology we can then use global constructors for each of the <code>UTEST</code> tests to register themselves with a global registry of &rsquo;tests that can be run&rsquo;, effectively just appending themselves to a malloc&rsquo;ed region. And this is <strong>fast</strong> - on my 2017 MacBook Pro it takes around 50ms to initialize 502 tests for running, around 99us per test. As an aside, I did an <a href="https://www.neilhenning.dev/posts/utest-h-performance/">expose of the performance of utest.h</a> and TL;DR it&rsquo;s blindingly fast.</p>
<p>Back to the problem - remember the problem? MSVC with whole program optimization was not running any tests? So for all intents and purposes these global constructors, the function pointer <code>f_</code> above, are not actually used in my code. What I mean is that I don&rsquo;t ever manually call <code>f_</code> myself, it is just registered and shoved in the global initializer section. So under whole program optimization the compiler comes along and says &lsquo;Oh hey! All these variables are doing stuff and we don&rsquo;t use them? Get rid!&rsquo;, meaning that none of the global constructors are then ran, and as a result none of the tests will register themselves with the global test registry and so it looks like there is nothing to run.</p>
<p>Pretty smart of the compiler in some respects, but now we need to defeat it.</p>
<h1 id="the-solution">The Solution</h1>
<p>I was recently made aware of a funky feature of the MSVC compiler thanks to an investigation I did into using rpmalloc with LLVM to improve compile times on multithreaded workloads on Windows. <a href="https://twitter.com/maniccoder">@maniccoder</a>, who knows a thing or two about allocators, gave me <a href="https://twitter.com/maniccoder/status/1250775765672701954?s=20">this gist</a> on how to do it. The part that was new to me though was:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">// Make sure symbols are not purged in linker
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#pragma comment(linker, &#34;/include</span><span style="color:#75715e">:_rpmllinit_&#34;)</span><span style="color:#75715e">
</span></span></span></code></pre></div><p>So you can use a special MSVC specific pragma to pass options to the linker, and those options can include a special option to <strong>always</strong> preserve a symbol even if the compiler thinks it is dead. Seems relevant! Now since my <code>UTEST</code> test fixtures use the preprocessor, I cannot use the <code>#pragma</code> variant because it would be invoked at the wrong place. But I knew I could use the <code>__pragma()</code> variant to do the same thing within the preprocessed macro&rsquo;s body.</p>
<p>So my global test initializer before this change was:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#define UTEST_INITIALIZER(f)                                                   \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  static void __cdecl f(void);                                                 \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  __declspec(allocate(&#34;.CRT$XCU&#34;)) void(__cdecl * f##_)(void) = f;             \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  static void __cdecl f(void)
</span></span></span></code></pre></div><p>And so I just added the <code>__pragma()</code> line to preserve the symbol:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#define UTEST_INITIALIZER(f)                                                   \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  static void __cdecl f(void);                                                 \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  __pragma(comment(linker, &#34;/include</span><span style="color:#75715e">:&#34; #f &#34;_&#34;));                               \</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  __declspec(allocate(&#34;.CRT$XCU&#34;)) void(__cdecl * f##_)(void) = f;             \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  static void __cdecl f(void)
</span></span></span></code></pre></div><p>And it worked - kinda. So the above worked for all global initializers from tests in a C function compiled for Win64 - 64-bit. It failed for 32-bit executable builds, and for C++ code.</p>
<p>So starting with the C++ tests I realised that even though I&rsquo;ve compiled the <code>f_</code> function pointer with the <code>__cdecl</code> calling convention, I hadn&rsquo;t actually stopped the compiler mangling the variable name which would change the symbol name.</p>
<p>So to fix this I added another macro:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#if defined(__cplusplus)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define UTEST_C_FUNC extern &#34;C&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#else
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define UTEST_C_FUNC
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#endif
</span></span></span></code></pre></div><p>That uses <code>extern &quot;C&quot;</code> when C++ is being used, and then modified the initializer to:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#define UTEST_INITIALIZER(f)                                                   \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  static void __cdecl f(void);                                                 \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  __pragma(comment(linker, &#34;/include</span><span style="color:#75715e">:&#34; #f &#34;_&#34;));                               \</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  UTEST_C_FUNC __declspec(allocate(&#34;.CRT$XCU&#34;)) void(__cdecl * f##_)(void) = f;\
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  static void __cdecl f(void)
</span></span></span></code></pre></div><p>Note that it doesn&rsquo;t matter what the signature of the <code>f</code> function itself is, only that the function pointer global variable does not end up with a mangled name. This fixed the C++ specific link failure.</p>
<p>For the 32-bit windows it was a little funky - but I had a vague memory in my head of dealing with this in a previous life. Basically 32-bit symbols are prepended with an extra underscore <code>_</code> on the symbol name. I don&rsquo;t actually know why this is the case to be honest, but I&rsquo;ve hit this issue before. So to fix that I added:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#if defined(_WIN64)
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define UTEST_SYMBOL_PREFIX
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#else
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#define UTEST_SYMBOL_PREFIX &#34;_&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">#endif
</span></span></span></code></pre></div><p>Which will have an additional underscore only on 32-bit builds using MSVC, and then changed the initializer to:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#define UTEST_INITIALIZER(f)                                                   \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  static void __cdecl f(void);                                                 \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  __pragma(comment(linker, &#34;/include</span><span style="color:#75715e">:&#34; UTEST_SYMBOL_PREFIX #f &#34;_&#34;));           \</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  UTEST_C_FUNC __declspec(allocate(&#34;.CRT$XCU&#34;)) void(__cdecl * f##_)(void) = f;\
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  static void __cdecl f(void)
</span></span></span></code></pre></div><p>Which fixed all my build problems. Now utest.h supports whole program optimization correctly.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>[<span style="color:#f92672">==========</span>] Running <span style="color:#ae81ff">502</span> test cases.
</span></span><span style="display:flex;"><span>[ RUN      ] utest_cmdline.filter_with_list
</span></span><span style="display:flex;"><span>[       OK ] utest_cmdline.<span style="color:#a6e22e">filter_with_list</span> (<span style="color:#ae81ff">4155002</span>ns)
</span></span><span style="display:flex;"><span>[ RUN      ] c.ASSERT_TRUE
</span></span><span style="display:flex;"><span>[       OK ] c.<span style="color:#a6e22e">ASSERT_TRUE</span> (<span style="color:#ae81ff">77</span>ns)
</span></span><span style="display:flex;"><span>[ RUN      ] c.ASSERT_FALSE
</span></span><span style="display:flex;"><span>[       OK ] c.<span style="color:#a6e22e">ASSERT_FALSE</span> (<span style="color:#ae81ff">53</span>ns)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#f92672">==========</span>] <span style="color:#ae81ff">502</span> test cases ran.
</span></span><span style="display:flex;"><span>[  PASSED  ] <span style="color:#ae81ff">502</span> tests.
</span></span></code></pre></div>]]></description>
    </item>
    
    <item>
      <title>How to Test Rust Command Line Applications</title>
      <link>https://www.neilhenning.dev/posts/rust-lit/</link>
      <pubDate>Sun, 26 Apr 2020 13:44:14 +0100</pubDate>
      <guid>https://www.neilhenning.dev/posts/rust-lit/</guid>
      <description><![CDATA[<p>Testing command line applications in Rust is something that I found was a bit of a grey area. The main documentation for Rust has a section <a href="https://rust-cli.github.io/book/tutorial/testing.html#testing-cli-applications-by-running-them">Testing CLI applications by running them</a> which explains how they suggest you test command lines applications:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="color:#66d9ef">use</span> std::process::Command;  <span style="color:#75715e">// Run programs
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">use</span> assert_cmd::prelude::<span style="color:#f92672">*</span>; <span style="color:#75715e">// Add methods on commands
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">use</span> predicates::prelude::<span style="color:#f92672">*</span>; <span style="color:#75715e">// Used for writing assertions
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#[test]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">file_doesnt_exist</span>() -&gt; Result<span style="color:#f92672">&lt;</span>(), Box<span style="color:#f92672">&lt;</span>std::error::Error<span style="color:#f92672">&gt;&gt;</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">let</span> <span style="color:#66d9ef">mut</span> cmd <span style="color:#f92672">=</span> Command::cargo_bin(<span style="color:#e6db74">&#34;grrs&#34;</span>)<span style="color:#f92672">?</span>;
</span></span><span style="display:flex;"><span>    cmd.arg(<span style="color:#e6db74">&#34;foobar&#34;</span>)
</span></span><span style="display:flex;"><span>        .arg(<span style="color:#e6db74">&#34;test/file/doesnt/exist&#34;</span>);
</span></span><span style="display:flex;"><span>    cmd.assert()
</span></span><span style="display:flex;"><span>        .failure()
</span></span><span style="display:flex;"><span>        .stderr(predicate::<span style="color:#66d9ef">str</span>::contains(<span style="color:#e6db74">&#34;No such file or directory&#34;</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Ok(())
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Basically you use a <code>#[test]</code> inside an integration test (in the <code>tests</code> folder) which uses a <code>std::process</code> to spawn the command line tool you&rsquo;ve developed. This works, but it has two failings in my opinion:</p>
<ol>
<li>If you want to test the same command line tool with multiple inputs (maybe you want to test that it fails in a specific way?) you&rsquo;re probably going to add a bunch of tests and include all the boiler plate code to call them.</li>
<li>There isn&rsquo;t a really clean way to check that complex output from your application appears as expected.</li>
</ol>
<p>I&rsquo;m coming from the background of writing compilers, where the state of the art for testing is <a href="https://llvm.org/docs/CommandGuide/lit.html">LLVM&rsquo;s Lit</a> - a tester that combined with the LLVM tool <code>FileCheck</code> lets you do awesome things like:</p>
<pre tabindex="0"><code>; RUN: opt &lt; %s -constprop -S | FileCheck %s

; CHECK-LABEL: shift_undef_64
define void @shift_undef_64(i64* %p) {
  %r1 = lshr i64 -1, 4294967296 ; 2^32
  ; CHECK: store i64 undef
  store i64 %r1, i64* %p

  %r2 = ashr i64 -1, 4294967297 ; 2^32 + 1
  ; CHECK: store i64 undef
  store i64 %r2, i64* %p

  %r3 = shl i64 -1, 4294967298 ; 2^32 + 2
  ; CHECK: store i64 undef
  store i64 %r3, i64* %p

  ret void
}
</code></pre><p>Basically it is:</p>
<ul>
<li>Running a program of your choosing with the options that you want.</li>
<li>The current file is fed as input to the program.</li>
<li>Then the output is parsed through <code>FileCheck</code> which also takes the same input.</li>
<li>And it uses special <code>CHECK:</code> statements hidden in comments to assert that the output matches some of the stuff that we expect.</li>
</ul>
<p>This lets us perform some pretty impressive checks that the output matches what we want, and crucially lets us <strong>not</strong> check some things, which is pretty useful for the things we don&rsquo;t care about.</p>
<p>I&rsquo;m currently working on a compiler framework written in Rust for the craic. I&rsquo;m not yet at the point where I want to link y&rsquo;all to the bodgey code and it is in no way usable in any way, shape, or form yet. But one thing I wanted was to be able to unit test the compiler framework by using the command line tools similar to how LLVM did it above. This will let me generate a huge number of tests in a really easy to extend format - I know this because I&rsquo;ve used LLVM&rsquo;s tooling for years and can attest it is very powerful.</p>
<h2 id="attempt-1---use-llvms-lit">Attempt 1 - Use LLVM&rsquo;s Lit?</h2>
<p>So my first though was just to use LLVM&rsquo;s lit tool directly. This quickly fell apart as an idea for a number of reasons:</p>
<ul>
<li>The actual lit tooling is a bunch of python scripts, and I don&rsquo;t want to require anything else beyond Rust.</li>
<li>The tool that <em>actually</em> does the heavy lifting in lit is the <code>FileCheck</code> tool, which is an executable shipped with LLVM.</li>
<li>The <code>FileCheck</code> executable is only included in an LLVM you build yourself - you can&rsquo;t just get it with an LLVM install.</li>
</ul>
<p>So all in all this didn&rsquo;t seem like a good way to integrate this sort of testing with Rust. So I was about to try and roll my own when I noticed a really awesome crate <a href="https://crates.io/crates/lit">lit</a>, so I decided to investigate using it.</p>
<h2 id="the-lit-crate">The lit crate</h2>
<p>So first of all, we need to use the crate. And since we <em>only</em> require the crate for testing we do:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span>[<span style="color:#a6e22e">dev-dependencies</span>]
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">lit</span> = <span style="color:#e6db74">&#34;0.3.4&#34;</span>
</span></span></code></pre></div><p>Next up we want to add an integration test that uses this. An integration test can depend on the entire main crate you are developing. In my case I&rsquo;ve got a library (<code>yair-io</code>) and two executables (<code>yair-as</code> and <code>yair-dis</code>) that use it, and I want to drive these from the integration test. The way you do it is like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="color:#66d9ef">extern</span> <span style="color:#66d9ef">crate</span> lit;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">#[cfg(test)]</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">mod</span> tests {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">use</span> std::env;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">use</span> std::env::consts;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">use</span> std::path::PathBuf;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">bin_dir</span>() -&gt; <span style="color:#a6e22e">PathBuf</span> {
</span></span><span style="display:flex;"><span>        env::current_exe()
</span></span><span style="display:flex;"><span>            .ok()
</span></span><span style="display:flex;"><span>            .map(<span style="color:#f92672">|</span><span style="color:#66d9ef">mut</span> path<span style="color:#f92672">|</span> {
</span></span><span style="display:flex;"><span>                path.pop();
</span></span><span style="display:flex;"><span>                path.pop();
</span></span><span style="display:flex;"><span>                path
</span></span><span style="display:flex;"><span>            })
</span></span><span style="display:flex;"><span>            .unwrap()
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">yair_as_exe</span>() -&gt; String {
</span></span><span style="display:flex;"><span>        bin_dir()
</span></span><span style="display:flex;"><span>            .join(<span style="color:#a6e22e">format!</span>(<span style="color:#e6db74">&#34;yair-as</span><span style="color:#e6db74">{}</span><span style="color:#e6db74">&#34;</span>, env::consts::<span style="color:#66d9ef">EXE_SUFFIX</span>))
</span></span><span style="display:flex;"><span>            .to_str()
</span></span><span style="display:flex;"><span>            .unwrap()
</span></span><span style="display:flex;"><span>            .to_string()
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">yair_dis_exe</span>() -&gt; String {
</span></span><span style="display:flex;"><span>        bin_dir()
</span></span><span style="display:flex;"><span>            .join(<span style="color:#a6e22e">format!</span>(<span style="color:#e6db74">&#34;yair-dis</span><span style="color:#e6db74">{}</span><span style="color:#e6db74">&#34;</span>, env::consts::<span style="color:#66d9ef">EXE_SUFFIX</span>))
</span></span><span style="display:flex;"><span>            .to_str()
</span></span><span style="display:flex;"><span>            .unwrap()
</span></span><span style="display:flex;"><span>            .to_string()
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">#[test]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">lit</span>() {
</span></span><span style="display:flex;"><span>        lit::run::tests(<span style="color:#f92672">|</span>config<span style="color:#f92672">|</span> {
</span></span><span style="display:flex;"><span>            config.add_search_path(<span style="color:#e6db74">&#34;tests/lit&#34;</span>);
</span></span><span style="display:flex;"><span>            config.add_extension(<span style="color:#e6db74">&#34;ya&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            config.constants.insert(<span style="color:#e6db74">&#34;yair_as&#34;</span>.to_owned(), yair_as_exe());
</span></span><span style="display:flex;"><span>            config.constants.insert(<span style="color:#e6db74">&#34;yair_dis&#34;</span>.to_owned(), yair_dis_exe());
</span></span><span style="display:flex;"><span>        })
</span></span><span style="display:flex;"><span>        .expect(<span style="color:#e6db74">&#34;Lit tests failed&#34;</span>);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>So lets break this down:</p>
<ul>
<li>We use the same <code>#[cfg(test)]</code> that we&rsquo;d expect from a Rust test.</li>
<li>And we have a single <code>#[test]</code> tagged function that&rsquo;ll run our lit tests.</li>
<li>The <code>lit()</code> function calls into the lit crate to run the tests (<code>lit::run::tests</code>).
<ul>
<li>We need to tell it where our test cases live by using <code>add_search_path</code> to point it at the folder containing your text files to run.</li>
<li>And also what file extensions we want to consider ok for testing by using <code>add_extension</code>. In my case my human-readable IR files are like <code>foo.ya</code> so the extension is just <code>ya</code>.</li>
<li>And then we need to create some variables that map to where the executables built by rust are located. I add two constants for <code>yair_as</code> and <code>yair_dis</code> to map to where the actual executables exist on disk. To get these locations I use a helper function <code>bin_dir</code> to work out where these executables will be placed on the file-system based on where the integration test is on the file-system.</li>
</ul>
</li>
</ul>
<p>Note you can add any other constants you want here too for use in the lit scripts. So if you wanted to get the OS being used in the scripts you could add <code>config.constants.insert(&quot;os&quot;.to_owned(), consts::OS.to_owned());</code> for instance.</p>
<p>Now we&rsquo;ve got this you can run <code>cargo test</code> and it&rsquo;ll have a new integration test that&rsquo;ll run your lit tests! But since you don&rsquo;t have a single actual test yet, nothing will actually run yet.</p>
<p>So let&rsquo;s look at an example of how to write a test case for lit that&rsquo;ll be picked up by the above integration test.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">// RUN: @yair_as @file | @yair_dis -
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// CHECK: mod &#34;😀&#34; {
</span></span></span><span style="display:flex;"><span>mod <span style="color:#e6db74">&#34;😀&#34;</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// CHECK: fn foo(a : u8, b : &lt;u8, 2&gt;) : &lt;u8, 2&gt; {
</span></span></span><span style="display:flex;"><span>  fn <span style="color:#a6e22e">foo</span>(a: u8, b: <span style="color:#f92672">&lt;</span>u8, <span style="color:#ae81ff">2</span><span style="color:#f92672">&gt;</span>) <span style="color:#f92672">:</span> <span style="color:#f92672">&lt;</span>u8, <span style="color:#ae81ff">2</span><span style="color:#f92672">&gt;</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// CHECK: b0(v2 : u8, v3 : &lt;u8, 2&gt;):
</span></span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">bar</span>(a: u8, b: <span style="color:#f92672">&lt;</span>u8, <span style="color:#ae81ff">2</span><span style="color:#f92672">&gt;</span>)<span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// CHECK: [[name:\w+]] = insert v3, v2, 1
</span></span></span><span style="display:flex;"><span>      c <span style="color:#f92672">=</span> insert b, a, <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// CHECK: ret $$name
</span></span></span><span style="display:flex;"><span>      ret c
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>So let&rsquo;s break down what I&rsquo;ve done piece by piece:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">// RUN: @yair_as @file | @yair_dis -
</span></span></span></code></pre></div><p>The first line tells the lit crate how to run this test case by using the <code>RUN:</code> statement. To access constants in lit you use the <code>@foo</code> syntax, so in our case to access the <code>yair-as</code> tool that I setup previously to map to the constant <code>yair_as</code> I use <code>@yair_as</code> to run it. There is a special constant that represents the path to the current file - <code>@file</code>. My <code>yair-as</code> assembler tool takes a positional argument for the input file, so what we are doing here is assembling the current file using my tool, and spitting out the output to the default which is stdout. This produces the binary representation of my intermediate representation, which is kinda hard to test! So what I&rsquo;m doing is roundtripping it back out via the dissassembler <code>yair-dis</code> (mapped to the <code>@yair_dis</code> constant) and then we can check that the output of the disassembler, which is human readable, matches what the input was.</p>
<p>You&rsquo;ll note that there is a pipe operator between the two tools, passing the stdout from one into the stdin of the other. Also, the stdout from the total run is what is fed into the lit checks to follow. Also - we <strong>do not</strong> have a separate <code>FileCheck</code> tool like LLVM uses - which is awesome! It just works, which I really appreciate.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">// CHECK: mod &#34;😀&#34; {
</span></span></span><span style="display:flex;"><span>mod <span style="color:#e6db74">&#34;😀&#34;</span> {
</span></span></code></pre></div><p>Next up I have a module 😀 being declared, and I make sure that this is output correctly. You&rsquo;ll notice that the rest of the file follows a similar pattern - some statements in the original IR matched with some <code>CHECK:</code>&rsquo;s that ensure that the output was correct. You don&rsquo;t <em>have</em> to check every line, you could check no lines if you wanted to - but this sparse matching of the output to ensure that some parts of it match what you want is so powerful.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">// CHECK: [[name:\w+]] = insert v3, v2, 1
</span></span></span><span style="display:flex;"><span>c <span style="color:#f92672">=</span> insert b, a, <span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// CHECK: ret $$name
</span></span></span><span style="display:flex;"><span>ret c
</span></span></code></pre></div><p>You can also use some more powerful features of checks - variables. Basically you can check that something you&rsquo;ve matched on earlier appears later in the file. So in the above example I am storing the name of the result from the <code>insert</code> instruction into the variable <code>name</code>, and then getting that name in the subsequent check using <code>$$name</code>. This means that if I changed the naming convention at a later date everything would keep working with the test case - nice!</p>
<p>Lastly - the output from <code>cargo test</code> of lit is as follows:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>running <span style="color:#ae81ff">1</span> test
</span></span><span style="display:flex;"><span>PASS :: tests/lit/var/basic.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/var/array.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/var/struct.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/var/vector.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/var/export.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/fn/one_arg.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/fn/bad_export.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/fn/one_arg_body.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/fn/export.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/fn/no_args.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/mod/multiple_modules.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/mod/bad_fn_or_var.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/mod/simple.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/mod/missing_closing_brace.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/mod/bad_quoted.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/mod/unicode.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/mod/empty.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/mod/missing_opening_brace.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/mod/missing_module_name.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/mod/bad_simple.ya
</span></span><span style="display:flex;"><span>PASS :: tests/lit/insts/insert.ya
</span></span><span style="display:flex;"><span>test tests::lit ... ok
</span></span></code></pre></div><p>You can see that it appears like a single running test (because like I said previously we are adding a single integration test that powers the lit runs), but the output from that test is a bunch of runs telling you what passes and what fails. If I manually make a test case fail, the output is like so:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>FAIL :: tests/lit/insts/insert.ya
</span></span><span style="display:flex;"><span>tests/lit/insts/insert.ya:15: could not find match: <span style="color:#e6db74">&#39;something not there&#39;</span>
</span></span><span style="display:flex;"><span>next line: <span style="color:#e6db74">&#39;}&#39;</span>
</span></span></code></pre></div><p>Telling me the line with the <code>CHECK</code> that it could not find.</p>
<h2 id="conclusion">Conclusion</h2>
<p>I really love this crate - it is super useful for testing these kind of applications. Full kudos to <a href="https://github.com/dylanmckay">Dylan McKay</a> for writing such an awesome crate, and I hope I&rsquo;ve convinced a few more people to try it out.</p>
]]></description>
    </item>
    
    <item>
      <title>Fixed Up RSS</title>
      <link>https://www.neilhenning.dev/posts/fixed-up-rss/</link>
      <pubDate>Wed, 01 Apr 2020 19:41:55 +0100</pubDate>
      <guid>https://www.neilhenning.dev/posts/fixed-up-rss/</guid>
      <description><![CDATA[<p>One thing I&rsquo;ve unfortunately neglected for a little while now on my blog was the RSS feed - mostly because I didn&rsquo;t have a clue how to make Hugo do it as I&rsquo;d like. There was a couple of issues:</p>
<ul>
<li>Only the summaries of my posts were fed via RSS - not the full contents. I <em>do not</em> do any sort of content tracking on my site because I don&rsquo;t want to foist vaporware like Google Analytics on my readers, so it really doesn&rsquo;t matter to me whether people read my content from the RSS feed or from the main site - that they read it is enough!</li>
<li>The links from the RSS feed were broken.</li>
<li>I didn&rsquo;t have an explicit link to signify that my site <em>even</em> supported RSS on the main page.</li>
</ul>
<p>Let&rsquo;s look at these in-order.</p>
<h2 id="full-contents-please">Full Contents Please!</h2>
<p>So I wanted full content rather than summaries of my posts on the RSS feed. Luckily Hugo provides a way to intercept and replace the default RSS template with your own custom one. I followed <a href="https://www.godo.dev/tutorials/hugo-full-text-rss/">this guide</a> to try and get it working - but in my RSS reader of choice while the full contents were now being included in the final RSS feed, the HTML tags were being displayed wrongly. I scratched my head for a long while over this before I realised that with RSS 2.0 there are two ways to encode HTML data within an RSS description - and my reader only liked the <code>CDATA</code> approach.</p>
<p>What I ended up with was the following:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#75715e">&lt;!--https://www.godo.dev/tutorials/hugo-full-text-rss/--&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!--https://raw.githubusercontent.com/gohugoio/hugo/master/tpl/tplimpl/embedded/templates/_default/rss.xml--&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{{- $pctx := . -}}
</span></span><span style="display:flex;"><span>{{- if .IsHome -}}{{ $pctx = .Site }}{{- end -}}
</span></span><span style="display:flex;"><span>{{- $pages := slice -}}
</span></span><span style="display:flex;"><span>{{- if or $.IsHome $.IsSection -}}
</span></span><span style="display:flex;"><span>{{- $pages = $pctx.RegularPages -}}
</span></span><span style="display:flex;"><span>{{- else -}}
</span></span><span style="display:flex;"><span>{{- $pages = $pctx.Pages -}}
</span></span><span style="display:flex;"><span>{{- end -}}
</span></span><span style="display:flex;"><span>{{- $limit := .Site.Config.Services.RSS.Limit -}}
</span></span><span style="display:flex;"><span>{{- if ge $limit 1 -}}
</span></span><span style="display:flex;"><span>{{- $pages = $pages | first $limit -}}
</span></span><span style="display:flex;"><span>{{- end -}}
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;rss</span> <span style="color:#a6e22e">version=</span><span style="color:#e6db74">&#34;2.0&#34;</span> <span style="color:#a6e22e">xmlns:atom=</span><span style="color:#e6db74">&#34;http://www.w3.org/2005/Atom&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;channel&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;title&gt;</span>{{ if eq  .Title  .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}<span style="color:#f92672">&lt;/title&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;link&gt;</span>{{ .Permalink }}<span style="color:#f92672">&lt;/link&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;description&gt;</span>Recent content {{ if ne  .Title  .Site.Title }}{{ with .Title }}in {{.}} {{ end }}{{ end }}on {{ .Site.Title }}<span style="color:#f92672">&lt;/description&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;generator&gt;</span>Hugo -- gohugo.io<span style="color:#f92672">&lt;/generator&gt;</span>{{ with .Site.LanguageCode }}
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;language&gt;</span>{{.}}<span style="color:#f92672">&lt;/language&gt;</span>{{end}}{{ with .Site.Author.email }}
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;managingEditor&gt;</span>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}<span style="color:#f92672">&lt;/managingEditor&gt;</span>{{end}}{{ with .Site.Author.email }}
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;webMaster&gt;</span>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}<span style="color:#f92672">&lt;/webMaster&gt;</span>{{end}}{{ with .Site.Copyright }}
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;copyright&gt;</span>{{.}}<span style="color:#f92672">&lt;/copyright&gt;</span>{{end}}{{ if not .Date.IsZero }}
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;lastBuildDate&gt;</span>{{ .Date.Format &#34;Mon, 02 Jan 2006 15:04:05 -0700&#34; | safeHTML }}<span style="color:#f92672">&lt;/lastBuildDate&gt;</span>{{ end }}
</span></span><span style="display:flex;"><span>    {{ with .OutputFormats.Get &#34;RSS&#34; }}
</span></span><span style="display:flex;"><span>      {{ printf &#34;<span style="color:#f92672">&lt;atom:link</span> <span style="color:#a6e22e">href=</span><span style="color:#e6db74">%q</span> <span style="color:#a6e22e">rel=</span><span style="color:#e6db74">\&#34;self\&#34;</span> <span style="color:#a6e22e">type=</span><span style="color:#e6db74">%q</span> <span style="color:#f92672">/&gt;</span>&#34; .Permalink .MediaType | safeHTML }}
</span></span><span style="display:flex;"><span>    {{ end }}
</span></span><span style="display:flex;"><span>    {{ range $pages }}
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;item&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;title&gt;</span>{{ .Title }}<span style="color:#f92672">&lt;/title&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;link&gt;</span>{{ .Permalink }}<span style="color:#f92672">&lt;/link&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;pubDate&gt;</span>{{ .Date.Format &#34;Mon, 02 Jan 2006 15:04:05 -0700&#34; | safeHTML }}<span style="color:#f92672">&lt;/pubDate&gt;</span>
</span></span><span style="display:flex;"><span>      {{ with .Site.Author.email }}<span style="color:#f92672">&lt;author&gt;</span>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}<span style="color:#f92672">&lt;/author&gt;</span>{{end}}
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;guid&gt;</span>{{ .Permalink }}<span style="color:#f92672">&lt;/guid&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;description&gt;</span>{{ safeHTML &#34;<span style="color:#75715e">&lt;![CDATA[&#34; }}{{- .Content | safeHTML -}}{{ safeHTML &#34;]]&gt;</span>&#34; }}<span style="color:#f92672">&lt;/description&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/item&gt;</span>
</span></span><span style="display:flex;"><span>    {{ end }}
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/channel&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/rss&gt;</span>
</span></span></code></pre></div><p>With the only thing I changed was the line:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;description&gt;</span>{{ safeHTML &#34;<span style="color:#75715e">&lt;![CDATA[&#34; }}{{- .Content | safeHTML -}}{{ safeHTML &#34;]]&gt;</span>&#34; }}<span style="color:#f92672">&lt;/description&gt;</span>
</span></span></code></pre></div><p>What this does is dump the original HTML content as is (that&rsquo;s what the <code>safeHTML</code> command does) and wrap it in the <code>&lt;![CDATA[</code> and <code>]]&gt;</code> tags. This meant that my content was being displayed correctly.</p>
<p>I then just had to place the above in <code>&lt;root&gt;/layouts/_default/rss.xml</code> et voila, it worked!</p>
<h2 id="links-should-really-work">Links Should Really Work</h2>
<p>All my links in the RSS were broken - the links to my main site and also the links to image content on my main blog. I don&rsquo;t <em>quite</em> know how I forgot to do this (or how my site actually worked for as long as it did), but I had forgotten to specify the <code>baseurl</code> in the <code>config.toml</code>. Just pointing this at my site fixed the issue.</p>
<h2 id="advertising-rss-support">Advertising RSS Support</h2>
<p>Although my site always (poorly) supported RSS, I never advertised it. To solve this I&rsquo;ve just added an RSS badge to the footer of the page to help people find the feed that want it. Nothing fancy, just an image and a link.</p>
<h2 id="wrapping-it-all-up">Wrapping It All Up</h2>
<p>Now I have fully working RSS - and thanks to a very helpful push from an avid reader (thanks Augustin!) I&rsquo;ve also enabled SSL/https on my site - and made it the primary way to view my content. <a href="https://www.gandi.net">My hosting provider Gandi</a> has offered simple SSL integration for a while now, but I had to upgrade my small instance to small+SSL, and I just hadn&rsquo;t gotten round to it. But no more - I now serve secure content by default!</p>
<p>Sorry for any RSS fans that&rsquo;ve been maligned for a while now, but hopefully this post will get my RSS subscriptions to rise now that my content is displayed in all its glory.</p>
<p>You can find the RSS feed at this link <a href="https://www.neilhenning.dev/index.xml">https://www.neilhenning.dev/index.xml</a>.</p>
<p>Tioraidh a chàirdean!</p>
]]></description>
    </item>
    
    <item>
      <title>Lessons of a Remote Worker</title>
      <link>https://www.neilhenning.dev/posts/lessons_of_a_remote_worker/</link>
      <pubDate>Sun, 15 Mar 2020 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/lessons_of_a_remote_worker/</guid>
      <description><![CDATA[<p>Jumping into cold water is always a shocking experience. Being able to calm yourself, acclimatise to the temperature of the water - before you attempt to swim is how you survive.</p>
<p>A ton of people worldwide have just plunged into the icy water of working from home, and since I&rsquo;ve been doing this for six years I have some advice from the good and the bad of what I learned over the time.</p>
<p>In this post I&rsquo;ll attempt to cover some of these lessons to try and help y&rsquo;all who&rsquo;ve had the cold water treatment learn how to swim.</p>
<h2 id="dont-work-in-your-pyjamas">Don&rsquo;t Work In Your Pyjamas</h2>
<p>The number one mistake people make when working from home is to pour yourself out of bed and immediately sit at your new desk and begin work. <strong>Don&rsquo;t do this!</strong></p>
<p>I personally like to get a sweat on every day either out running with my dog or if I&rsquo;m housebound then on my exercise bike. So my routine is that I get up, change into my workout gear, take the dog outside for his morning duties, and make a coffee. This routine takes me around twenty minutes or so and gives me some distance from sleeping Neil to working Neil.</p>
<p>If you aren&rsquo;t an exercise-aholic like myself then I recommend you shower and get changed into &lsquo;work gear&rsquo; before sitting at your new desk.</p>
<h2 id="take-lots-of-regular-breaks">Take Lots of Regular Breaks</h2>
<p>The number one mistake I made when I first started working remotely was to not take enough breaks. If you think back to any office environment you have worked in, I&rsquo;d take a guess that around twenty-five minutes out of every hour has some non-screen interaction. People coming and going as they get a drink / use the toilet / talk to random people about random things. Even if you are one of those introverted headphone wearing office dwellers (like I was) you are still generally getting a ton of visual distractions as people move around you that give you a break from the screen.</p>
<p>When people switch from this to working remotely there is two things that bite - a fear of missing out on interactions that have now moved to chat apps or calls, and a worry that people are convinced you aren&rsquo;t actually working if you don&rsquo;t respond instantly to their direct interactions with you. These two things combined can let you almost become magnetized to your chair.</p>
<p><strong>Don&rsquo;t do this!</strong> Think about the office environment - how many times have you looked for a colleague at their desk and they aren&rsquo;t there. You don&rsquo;t immediately think <em>&lsquo;This bampot is skiving!&rsquo;</em>. The same is true for remote working, so give yourself a break.</p>
<h2 id="trust-your-staff">Trust Your Staff</h2>
<p>I&rsquo;ve already seen a bunch of leads worried that they won&rsquo;t know what their staff are up to, worried they won&rsquo;t work on the right things, worried they will go off into the weeds when the grass just needs cut. I&rsquo;ve seen pitches from extrovert control freaks that all staff should be forced into a continuously running group call for the entire working day to simulate the working environment. What this all boils down to is that you don&rsquo;t trust the people working for you - which honestly <strong>is a much deeper problem than them being at home</strong>. This screams to me of a failure of hiring the wrong person or a failure of not training the person.</p>
<p>When I was at AMD I learned that having an asynchronous way for people to know what you are working on is key. The entire game engineering part of the org I was part of would keep weekly logs on confluence of what we were doing, which let people across the org and actually across the company see what we were doing. This is a great way to keep people updated on what you are doing and also letting you develop side interactions about your work.</p>
<p>When I joined Unity I brought this with me, and keep a running yearly log on all the things I&rsquo;ve been up to. It provides a great way for remote people to feel connected to what other people are doing and have side conversations on the work.</p>
<h2 id="stop-working">Stop Working</h2>
<p>The thing I still struggle with the most isn&rsquo;t a lack of working, it is working too much. When you were in the office and had to leave at five to have dinner with the family, that forced a physical break between you and your ability to work. When the computer is in the same dwelling as you the temptation to say <em>&lsquo;I&rsquo;ll just finish this one other thing that has been annoying me&rsquo;</em> is a fight. Especially when it is a bug you have caused. Just this week at Unity I found two bugs in some complication optimizations I&rsquo;ve been working on, and I found myself itching to keep working on them late into the night because I felt guilty that I was holding up a release of Burst.</p>
<p><strong>Don&rsquo;t do this!</strong> I need to learn this lesson fully myself, but since we all know crunching is bad, crunching in the home can&rsquo;t be any better.</p>
<h2 id="dont-conference-call-during-your-lunch-break">Don&rsquo;t Conference Call During Your Lunch Break</h2>
<p>One thing I definitely advocate is to take your lunch break away from your desk or computer. Get some fresh air, do something else round the house, socialize with your equally quarantined partner / cat / Rocket League friends.</p>
<p>One thing I think you should never never never do is have some form of <em>&lsquo;Let&rsquo;s all eat lunch together on a conference call to scratch the social itch.&rsquo;</em>. It is totally ok to have a social-only set of interactions with your co-workers, but that should be on the companies time. Think back to when you are in the office - how much time in a day do you spend during company time interacting with your co-workers about non-company things? Think of all the watercooler or coffee-making moments where you have a five minute stop and chat. You don&rsquo;t clock out to do this, so why should you sacrifice your contractually allowed lunch break to recreate the same just because you are remote?</p>
<p>Like I said before, I use my lunch break to get out of the house. I walk the dog, go for a run, exercise on my bike. Hell I&rsquo;ve even taken a bath in my lunch hour. Do <em>anything</em> you can to get away from the desk for an hour.</p>

  <figure class="center" >
    <img src="/images/BenjiAndMeRunning.jpg"  alt="Picture of Benji and I out running"   style="border-radius: 8px;"  />
    
      <figcaption class="center"  style="color: white;" >Out in the fresh air with Benji!</figcaption>
    
  </figure>


<h2 id="lean-into-your-new-super-power">Lean Into Your New Super Power</h2>
<p>I found working from home to be utterly liberating. I&rsquo;m a highly socially capable introvert - anyone who has met me will know I am life-and-soul of any party, but I naturally want to be away in the wilds with my dog away from people. I need a huge period of time to recharge from social interactions - a week away for work would need two months for me to recover.</p>
<p>For me the ability to go full focus when I started working from home was so empowering. I could go into a zen like zone that I&rsquo;d never been able to in the office. I honestly reckon that I was operating about 10% of my peak performance when I was in the office. My productivity and happiness at how I&rsquo;m getting to really think through the problems I get to work on has been super charged since I&rsquo;ve been remote. Remote working <em>is my super power</em> - it&rsquo;s how I get to be as good at what I do as I am.</p>
<h2 id="dont-let-real-life-invade-your-work">Don&rsquo;t Let Real Life Invade Your Work</h2>
<p>It&rsquo;s so easy for real life to invade your work when you are at home. This was a hard adjustment for me and my partner. <em>&lsquo;Oh you are at home so you can do X around the house!&rsquo;</em> - no, no you can&rsquo;t. It&rsquo;s very easy to see that because the person is at home they can do the dishes, clean the home, look after the kids, whatever. It&rsquo;s super key that you resist this urge otherwise you won&rsquo;t succeed at home. It is better to just have a blanket ban on doing <em>anything</em> around the house during work hours that you wouldn&rsquo;t have been able to do in the office, at least to start with. Have a seperation of work-you and home-you - even though they are sharing the same location!</p>
<h2 id="take-advantage-of-the-lack-of-commute">Take Advantage of the Lack of Commute</h2>
<p>If you are like the average office worker you&rsquo;ll have somewhere around an hour commute built into your day. Now you&rsquo;ve just got that time back to do what you want with. Read books, learn a language, play Witcher III some more, build Lego with the kids - whatever you always wanted to do but didn&rsquo;t have time? Now is the time to do it. So liberating to get that dead time back!</p>
<h2 id="summary">Summary</h2>
<p>This isn&rsquo;t an exhaustive list of all the things that&rsquo;ll make remote working work for you - just a meandering list of some of the things I&rsquo;ve learned along the way. For me working from home has been a game changer in my life. I&rsquo;m happier, healthier, I got a dog that I get to spend every minute of the day with, I bought a house in the stunning Isle of Skye with views to die for, and live in a close knit community. I&rsquo;ve built social interactions outwith my work colleagues into my life which let me broaden my view points.</p>
<p>If you are in an enforced Coronavirus-derived work from home then I encourage you to lean into it and see if its for you. I realise that some extroverted people will miss the chaos of the office, but if you&rsquo;ve been one of those introverts that has been forced to live in the extroverted world <em>this is the time</em> to see if working from home would allow you to be happier, healthier, and honestly a better worker. It worked for me at least!</p>
]]></description>
    </item>
    
    <item>
      <title>Extracting the json.h README.md Code Samples For Compiling</title>
      <link>https://www.neilhenning.dev/posts/json_h_readme_md/</link>
      <pubDate>Wed, 15 Jan 2020 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/json_h_readme_md/</guid>
      <description><![CDATA[<p>One thing that has always worried me with writing C samples in documentation for
my single-header libraries is that you can&rsquo;t be 100% sure that they will compile
successfully. You can always extract them and run them, but you might change
them and forget to re-test. Having this be automatic is so powerful. Rust has
<a href="https://doc.rust-lang.org/rustdoc/documentation-tests.html">this feature</a> built
in to the ecosystem so that all code samples are testing automagically.</p>
<p>So I wondered - is there anyway to do something similar for my single-header
libraries? I decided to try with <a href="https://github.com/sheredom/json.h">json.h</a>.</p>
<h2 id="the-code-samples">The Code Samples</h2>
<p>I want to have more and more code samples to show how easy the library is to
use, but the big one there currently is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span> <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span> json[] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;{</span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74">a</span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74"> : true, </span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74">b</span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74"> : [false, null, </span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74">foo</span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74">]}&#34;</span>;
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> root <span style="color:#f92672">=</span> <span style="color:#a6e22e">json_parse</span>(json, <span style="color:#a6e22e">strlen</span>(json));
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(root<span style="color:#f92672">-&gt;</span>type <span style="color:#f92672">==</span> json_type_object);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_object_s<span style="color:#f92672">*</span> object <span style="color:#f92672">=</span> (<span style="color:#66d9ef">struct</span> json_object_s<span style="color:#f92672">*</span>)root<span style="color:#f92672">-&gt;</span>payload;
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(object<span style="color:#f92672">-&gt;</span>length <span style="color:#f92672">==</span> <span style="color:#ae81ff">2</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_object_element_s<span style="color:#f92672">*</span> a <span style="color:#f92672">=</span> object<span style="color:#f92672">-&gt;</span>start;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_string_s<span style="color:#f92672">*</span> a_name <span style="color:#f92672">=</span> a<span style="color:#f92672">-&gt;</span>name;
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">0</span> <span style="color:#f92672">==</span> <span style="color:#a6e22e">strcmp</span>(a_name<span style="color:#f92672">-&gt;</span>string, <span style="color:#e6db74">&#34;a&#34;</span>));
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(a_name<span style="color:#f92672">-&gt;</span>string_size <span style="color:#f92672">==</span> <span style="color:#a6e22e">strlen</span>(<span style="color:#e6db74">&#34;a&#34;</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> a_value <span style="color:#f92672">=</span> a<span style="color:#f92672">-&gt;</span>value;
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(a_value<span style="color:#f92672">-&gt;</span>type <span style="color:#f92672">==</span> json_type_true);
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(a_value<span style="color:#f92672">-&gt;</span>payload <span style="color:#f92672">==</span> NULL);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_object_element_s<span style="color:#f92672">*</span> b <span style="color:#f92672">=</span> a<span style="color:#f92672">-&gt;</span>next;
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(b<span style="color:#f92672">-&gt;</span>next <span style="color:#f92672">==</span> NULL);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_string_s<span style="color:#f92672">*</span> b_name <span style="color:#f92672">=</span> b<span style="color:#f92672">-&gt;</span>name;
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">0</span> <span style="color:#f92672">==</span> <span style="color:#a6e22e">strcmp</span>(b_name<span style="color:#f92672">-&gt;</span>string, <span style="color:#e6db74">&#34;b&#34;</span>));
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(b_name<span style="color:#f92672">-&gt;</span>string_size <span style="color:#f92672">==</span> <span style="color:#a6e22e">strlen</span>(<span style="color:#e6db74">&#34;b&#34;</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> b_value <span style="color:#f92672">=</span> b<span style="color:#f92672">-&gt;</span>value;
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(b_value<span style="color:#f92672">-&gt;</span>type <span style="color:#f92672">==</span> json_type_array);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_array_s<span style="color:#f92672">*</span> array <span style="color:#f92672">=</span> (<span style="color:#66d9ef">struct</span> json_array_s<span style="color:#f92672">*</span>)b_value<span style="color:#f92672">-&gt;</span>payload;
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(array<span style="color:#f92672">-&gt;</span>length <span style="color:#f92672">==</span> <span style="color:#ae81ff">3</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_array_element_s<span style="color:#f92672">*</span> b_1st <span style="color:#f92672">=</span> array<span style="color:#f92672">-&gt;</span>start;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> b_1st_value <span style="color:#f92672">=</span> b_1st<span style="color:#f92672">-&gt;</span>value;
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(b_1st_value<span style="color:#f92672">-&gt;</span>type <span style="color:#f92672">==</span> json_type_false);
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(b_1st_value<span style="color:#f92672">-&gt;</span>payload <span style="color:#f92672">==</span> NULL);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_array_element_s<span style="color:#f92672">*</span> b_2nd <span style="color:#f92672">=</span> b_1st<span style="color:#f92672">-&gt;</span>next;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> b_2nd_value <span style="color:#f92672">=</span> b_2nd<span style="color:#f92672">-&gt;</span>value;
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(b_2nd_value<span style="color:#f92672">-&gt;</span>type <span style="color:#f92672">==</span> json_type_null);
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(b_2nd_value<span style="color:#f92672">-&gt;</span>payload <span style="color:#f92672">==</span> NULL);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_array_element_s<span style="color:#f92672">*</span> b_3rd <span style="color:#f92672">=</span> b_2nd<span style="color:#f92672">-&gt;</span>next;
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(b_3rd<span style="color:#f92672">-&gt;</span>next <span style="color:#f92672">==</span> NULL);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> b_3rd_value <span style="color:#f92672">=</span> b_3rd<span style="color:#f92672">-&gt;</span>value;
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(b_3rd_value<span style="color:#f92672">-&gt;</span>type <span style="color:#f92672">==</span> json_type_string);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#66d9ef">struct</span> json_string_s<span style="color:#f92672">*</span> string <span style="color:#f92672">=</span> (<span style="color:#66d9ef">struct</span> json_string_s<span style="color:#f92672">*</span>)b_3rd_value<span style="color:#f92672">-&gt;</span>payload;
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">0</span> <span style="color:#f92672">==</span> <span style="color:#a6e22e">strcmp</span>(string<span style="color:#f92672">-&gt;</span>string, <span style="color:#e6db74">&#34;foo&#34;</span>));
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">assert</span>(string<span style="color:#f92672">-&gt;</span>string_size <span style="color:#f92672">==</span> <span style="color:#a6e22e">strlen</span>(<span style="color:#e6db74">&#34;foo&#34;</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#75715e">/* Don&#39;t forget to free the one allocation! */</span>
</span></span><span style="display:flex;"><span> <span style="color:#a6e22e">free</span>(root);
</span></span></code></pre></div><p>I want to be able to parse the
<a href="https://github.com/sheredom/json.h/blob/master/README.md">README.md</a>, extract
the code samples, turn them into a test for use with my utest.h library will
run. I already use CMake for building just the unit-tests, and so given I
already use it and I&rsquo;m pretty familiar with it (despite its glaring flaws), I
wondered if I could use it to do the extraction.</p>
<h2 id="cmake-of-horrors">CMake of Horrors</h2>
<p>So CMake has
<a href="https://cmake.org/cmake/help/latest/command/string.html#regular-expressions">built-in regex string support</a>
so I thought could I use that to do the extraction? The one big issue is that
CMake only supports greedy matching of regex - meaning that I have to be super
careful when searching for start/end tokens with which to match.</p>
<p>First of all we need to read the whole file into a CMake variable:</p>
<pre tabindex="0"><code>file(READ ${CMAKE_CURRENT_SOURCE_DIR}/../README.md readme_md)
</code></pre><p>CMake has this wonderfully messed up method for differentiating between strings
and lists - where a list in CMake terminology is just a string that has
semi-colons within it. The problem is that code samples in languages like C use
semi-colons as end of statement terminators - which will cause us issues. The
best way I&rsquo;ve found around this is to change the semi-colons to some symbol that
wouldn&rsquo;t appear in the original source. I used the &lsquo;@&rsquo; symbol for this since
there isn&rsquo;t an operator in C for it:</p>
<pre tabindex="0"><code>string(REPLACE &#34;;&#34; &#34;@&#34; readme_md &#34;${readme_md}&#34;)
</code></pre><p>Ok now we have the string as a real string (non-list) we can extract the code
samples themselves. You&rsquo;ll notice that in the README.md all code samples begin
with &ldquo;```c&rdquo; and end with &ldquo;```&rdquo;. So we can use this to look for our code.</p>
<p>As I said earlier CMake is <em>greedy</em> when it comes to regex, which means if we
used the more natural &ldquo;.*&rdquo; we&rsquo;d match from the very first code sample to the
very last in the file. Not ideal. Instead we need to use the more constrained
search of &ldquo;```c[^`]*```&rdquo; - search for the start pattern, and then all
symbols except a &ldquo;`&rdquo; until we get to our end. This stores each match as a list
entry into the variable <code>snippets</code> - meaning we have introdued some semi-colons
into the string too:</p>
<pre tabindex="0"><code>string(REGEX MATCHALL &#34;```c[^`]*```&#34; snippets &#34;${readme_md}&#34;)
</code></pre><p>Now to help us be able to test the examples we want to be able to compile each
of the code snippets in isolation from each other. I first attempted to create
a <code>UTEST(foo, bar)</code> wrapper around each snippet, but I could not figure out how
to create these wrappers such that they would be unique. What I mean is that the
first snippet would be <code>UTEST(generated, snippet0)</code> the next
<code>UTEST(generated, snippet1)</code>, etc.  For the life of me I couldn&rsquo;t work out how
this was possible. So instead I just wrapped each snippet into its own braced
region which guaranteed their isolation.</p>
<pre tabindex="0"><code>string(REPLACE &#34;```c&#34; &#34;{&#34; snippets ${snippets})
string(REPLACE &#34;```&#34; &#34;}\n\n&#34; snippets ${snippets})
</code></pre><p>Now all we need to do is remove the semi-colons that were added for the lists,
and then turn all &ldquo;@&rdquo; symbols we introduced before back into semi-colons:</p>
<pre tabindex="0"><code>string(REPLACE &#34;;&#34; &#34;&#34; snippets &#34;${snippets}&#34;)
string(REPLACE &#34;@&#34; &#34;;&#34; snippets &#34;${snippets}&#34;)
</code></pre><p>And then we just need to write out the file into some location for inclusion:</p>
<pre tabindex="0"><code>file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generated.h &#34;${snippets}&#34;)
</code></pre><h2 id="sample-generatedh">Sample generated.h</h2>
<p>For the current master json.h, the <code>generated.h</code> file is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_value_s <span style="color:#f92672">*</span><span style="color:#a6e22e">json_parse</span>(
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>src,
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">size_t</span> src_size);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_value_s {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>payload;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">size_t</span> type;
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_value_s <span style="color:#f92672">*</span><span style="color:#a6e22e">json_parse_ex</span>(
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>src,
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">size_t</span> src_size,
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">size_t</span> flags_bitset,
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span>(<span style="color:#f92672">*</span>alloc_func_ptr)(<span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>, <span style="color:#66d9ef">size_t</span>),
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>user_data,
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">struct</span> json_parse_result_s <span style="color:#f92672">*</span>result);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">enum</span> json_parse_flags_e {
</span></span><span style="display:flex;"><span>  json_parse_flags_default <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>,
</span></span><span style="display:flex;"><span>  json_parse_flags_allow_trailing_comma <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x1</span>,
</span></span><span style="display:flex;"><span>  json_parse_flags_allow_unquoted_keys <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x2</span>,
</span></span><span style="display:flex;"><span>  json_parse_flags_allow_global_object <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x4</span>,
</span></span><span style="display:flex;"><span>  json_parse_flags_allow_equals_in_object <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x8</span>,
</span></span><span style="display:flex;"><span>  json_parse_flags_allow_no_commas <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x10</span>,
</span></span><span style="display:flex;"><span>  json_parse_flags_allow_c_style_comments <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x20</span>,
</span></span><span style="display:flex;"><span>  json_parse_flags_deprecated <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x40</span>,
</span></span><span style="display:flex;"><span>  json_parse_flags_allow_location_information <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x80</span>,
</span></span><span style="display:flex;"><span>  json_parse_flags_allow_single_quoted_strings <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x100</span>,
</span></span><span style="display:flex;"><span>  json_parse_flags_allow_hexadecimal_numbers <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x200</span>,
</span></span><span style="display:flex;"><span>  json_parse_flags_allow_leading_plus_sign <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x400</span>,
</span></span><span style="display:flex;"><span>  json_parse_flags_allow_leading_or_trailing_decimal_point <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x800</span>,
</span></span><span style="display:flex;"><span>  json_parse_flags_allow_inf_and_nan <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x1000</span>,
</span></span><span style="display:flex;"><span>  json_parse_flags_allow_multi_line_strings <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x2000</span>,
</span></span><span style="display:flex;"><span>  json_parse_flags_allow_simplified_json <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>      (json_parse_flags_allow_trailing_comma <span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>       json_parse_flags_allow_unquoted_keys <span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>       json_parse_flags_allow_global_object <span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>       json_parse_flags_allow_equals_in_object <span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>       json_parse_flags_allow_no_commas),
</span></span><span style="display:flex;"><span>  json_parse_flags_allow_json5 <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>      (json_parse_flags_allow_trailing_comma <span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>       json_parse_flags_allow_unquoted_keys <span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>       json_parse_flags_allow_c_style_comments <span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>       json_parse_flags_allow_single_quoted_strings <span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>       json_parse_flags_allow_hexadecimal_numbers <span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>       json_parse_flags_allow_leading_plus_sign <span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>       json_parse_flags_allow_leading_or_trailing_decimal_point <span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>       json_parse_flags_allow_inf_and_nan <span style="color:#f92672">|</span>
</span></span><span style="display:flex;"><span>       json_parse_flags_allow_multi_line_strings)
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span> json[] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;{</span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74">a</span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74"> : true, </span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74">b</span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74"> : [false, null, </span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74">foo</span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74">]}&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> root <span style="color:#f92672">=</span> <span style="color:#a6e22e">json_parse</span>(json, <span style="color:#a6e22e">strlen</span>(json));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(root<span style="color:#f92672">-&gt;</span>type <span style="color:#f92672">==</span> json_type_object);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_object_s<span style="color:#f92672">*</span> object <span style="color:#f92672">=</span> (<span style="color:#66d9ef">struct</span> json_object_s<span style="color:#f92672">*</span>)root<span style="color:#f92672">-&gt;</span>payload;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(object<span style="color:#f92672">-&gt;</span>length <span style="color:#f92672">==</span> <span style="color:#ae81ff">2</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_object_element_s<span style="color:#f92672">*</span> a <span style="color:#f92672">=</span> object<span style="color:#f92672">-&gt;</span>start;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_string_s<span style="color:#f92672">*</span> a_name <span style="color:#f92672">=</span> a<span style="color:#f92672">-&gt;</span>name;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">0</span> <span style="color:#f92672">==</span> <span style="color:#a6e22e">strcmp</span>(a_name<span style="color:#f92672">-&gt;</span>string, <span style="color:#e6db74">&#34;a&#34;</span>));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(a_name<span style="color:#f92672">-&gt;</span>string_size <span style="color:#f92672">==</span> <span style="color:#a6e22e">strlen</span>(<span style="color:#e6db74">&#34;a&#34;</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> a_value <span style="color:#f92672">=</span> a<span style="color:#f92672">-&gt;</span>value;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(a_value<span style="color:#f92672">-&gt;</span>type <span style="color:#f92672">==</span> json_type_true);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(a_value<span style="color:#f92672">-&gt;</span>payload <span style="color:#f92672">==</span> NULL);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_object_element_s<span style="color:#f92672">*</span> b <span style="color:#f92672">=</span> a<span style="color:#f92672">-&gt;</span>next;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(b<span style="color:#f92672">-&gt;</span>next <span style="color:#f92672">==</span> NULL);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_string_s<span style="color:#f92672">*</span> b_name <span style="color:#f92672">=</span> b<span style="color:#f92672">-&gt;</span>name;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">0</span> <span style="color:#f92672">==</span> <span style="color:#a6e22e">strcmp</span>(b_name<span style="color:#f92672">-&gt;</span>string, <span style="color:#e6db74">&#34;b&#34;</span>));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(b_name<span style="color:#f92672">-&gt;</span>string_size <span style="color:#f92672">==</span> <span style="color:#a6e22e">strlen</span>(<span style="color:#e6db74">&#34;b&#34;</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> b_value <span style="color:#f92672">=</span> b<span style="color:#f92672">-&gt;</span>value;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(b_value<span style="color:#f92672">-&gt;</span>type <span style="color:#f92672">==</span> json_type_array);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_array_s<span style="color:#f92672">*</span> array <span style="color:#f92672">=</span> (<span style="color:#66d9ef">struct</span> json_array_s<span style="color:#f92672">*</span>)b_value<span style="color:#f92672">-&gt;</span>payload;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(array<span style="color:#f92672">-&gt;</span>length <span style="color:#f92672">==</span> <span style="color:#ae81ff">3</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_array_element_s<span style="color:#f92672">*</span> b_1st <span style="color:#f92672">=</span> array<span style="color:#f92672">-&gt;</span>start;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> b_1st_value <span style="color:#f92672">=</span> b_1st<span style="color:#f92672">-&gt;</span>value;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(b_1st_value<span style="color:#f92672">-&gt;</span>type <span style="color:#f92672">==</span> json_type_false);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(b_1st_value<span style="color:#f92672">-&gt;</span>payload <span style="color:#f92672">==</span> NULL);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_array_element_s<span style="color:#f92672">*</span> b_2nd <span style="color:#f92672">=</span> b_1st<span style="color:#f92672">-&gt;</span>next;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> b_2nd_value <span style="color:#f92672">=</span> b_2nd<span style="color:#f92672">-&gt;</span>value;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(b_2nd_value<span style="color:#f92672">-&gt;</span>type <span style="color:#f92672">==</span> json_type_null);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(b_2nd_value<span style="color:#f92672">-&gt;</span>payload <span style="color:#f92672">==</span> NULL);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_array_element_s<span style="color:#f92672">*</span> b_3rd <span style="color:#f92672">=</span> b_2nd<span style="color:#f92672">-&gt;</span>next;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(b_3rd<span style="color:#f92672">-&gt;</span>next <span style="color:#f92672">==</span> NULL);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> b_3rd_value <span style="color:#f92672">=</span> b_3rd<span style="color:#f92672">-&gt;</span>value;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(b_3rd_value<span style="color:#f92672">-&gt;</span>type <span style="color:#f92672">==</span> json_type_string);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_string_s<span style="color:#f92672">*</span> string <span style="color:#f92672">=</span> (<span style="color:#66d9ef">struct</span> json_string_s<span style="color:#f92672">*</span>)b_3rd_value<span style="color:#f92672">-&gt;</span>payload;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">0</span> <span style="color:#f92672">==</span> <span style="color:#a6e22e">strcmp</span>(string<span style="color:#f92672">-&gt;</span>string, <span style="color:#e6db74">&#34;foo&#34;</span>));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(string<span style="color:#f92672">-&gt;</span>string_size <span style="color:#f92672">==</span> <span style="color:#a6e22e">strlen</span>(<span style="color:#e6db74">&#34;foo&#34;</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">/* Don&#39;t forget to free the one allocation! */</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">free</span>(root);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span> json[] <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;{</span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74">a</span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74"> : true, </span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74">b</span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74"> : [false, null, </span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74">foo</span><span style="color:#ae81ff">\&#34;</span><span style="color:#e6db74">]}&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> root <span style="color:#f92672">=</span> <span style="color:#a6e22e">json_parse</span>(json, <span style="color:#a6e22e">strlen</span>(json));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_object_s<span style="color:#f92672">*</span> object <span style="color:#f92672">=</span> <span style="color:#a6e22e">json_value_as_object</span>(root);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(object <span style="color:#f92672">!=</span> NULL);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(object<span style="color:#f92672">-&gt;</span>length <span style="color:#f92672">==</span> <span style="color:#ae81ff">2</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_object_element_s<span style="color:#f92672">*</span> a <span style="color:#f92672">=</span> object<span style="color:#f92672">-&gt;</span>start;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_string_s<span style="color:#f92672">*</span> a_name <span style="color:#f92672">=</span> a<span style="color:#f92672">-&gt;</span>name;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">0</span> <span style="color:#f92672">==</span> <span style="color:#a6e22e">strcmp</span>(a_name<span style="color:#f92672">-&gt;</span>string, <span style="color:#e6db74">&#34;a&#34;</span>));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(a_name<span style="color:#f92672">-&gt;</span>string_size <span style="color:#f92672">==</span> <span style="color:#a6e22e">strlen</span>(<span style="color:#e6db74">&#34;a&#34;</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> a_value <span style="color:#f92672">=</span> a<span style="color:#f92672">-&gt;</span>value;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(<span style="color:#a6e22e">json_value_is_true</span>(a_value));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_object_element_s<span style="color:#f92672">*</span> b <span style="color:#f92672">=</span> a<span style="color:#f92672">-&gt;</span>next;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(b<span style="color:#f92672">-&gt;</span>next <span style="color:#f92672">==</span> NULL);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_string_s<span style="color:#f92672">*</span> b_name <span style="color:#f92672">=</span> b<span style="color:#f92672">-&gt;</span>name;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">0</span> <span style="color:#f92672">==</span> <span style="color:#a6e22e">strcmp</span>(b_name<span style="color:#f92672">-&gt;</span>string, <span style="color:#e6db74">&#34;b&#34;</span>));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(b_name<span style="color:#f92672">-&gt;</span>string_size <span style="color:#f92672">==</span> <span style="color:#a6e22e">strlen</span>(<span style="color:#e6db74">&#34;b&#34;</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_array_s<span style="color:#f92672">*</span> array <span style="color:#f92672">=</span> <span style="color:#a6e22e">json_value_as_array</span>(b<span style="color:#f92672">-&gt;</span>value);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(array<span style="color:#f92672">-&gt;</span>length <span style="color:#f92672">==</span> <span style="color:#ae81ff">3</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_array_element_s<span style="color:#f92672">*</span> b_1st <span style="color:#f92672">=</span> array<span style="color:#f92672">-&gt;</span>start;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> b_1st_value <span style="color:#f92672">=</span> b_1st<span style="color:#f92672">-&gt;</span>value;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(<span style="color:#a6e22e">json_value_is_false</span>(b_1st_value));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_array_element_s<span style="color:#f92672">*</span> b_2nd <span style="color:#f92672">=</span> b_1st<span style="color:#f92672">-&gt;</span>next;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_value_s<span style="color:#f92672">*</span> b_2nd_value <span style="color:#f92672">=</span> b_2nd<span style="color:#f92672">-&gt;</span>value;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(<span style="color:#a6e22e">json_value_is_null</span>(b_2nd_value));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_array_element_s<span style="color:#f92672">*</span> b_3rd <span style="color:#f92672">=</span> b_2nd<span style="color:#f92672">-&gt;</span>next;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(b_3rd<span style="color:#f92672">-&gt;</span>next <span style="color:#f92672">==</span> NULL);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">struct</span> json_string_s<span style="color:#f92672">*</span> string <span style="color:#f92672">=</span> <span style="color:#a6e22e">json_value_as_string</span>(b_3rd<span style="color:#f92672">-&gt;</span>value);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(string <span style="color:#f92672">!=</span> NULL);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">0</span> <span style="color:#f92672">==</span> <span style="color:#a6e22e">strcmp</span>(string<span style="color:#f92672">-&gt;</span>string, <span style="color:#e6db74">&#34;foo&#34;</span>));
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">assert</span>(string<span style="color:#f92672">-&gt;</span>string_size <span style="color:#f92672">==</span> <span style="color:#a6e22e">strlen</span>(<span style="color:#e6db74">&#34;foo&#34;</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">/* Don&#39;t forget to free the one allocation! */</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">free</span>(root);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>I wanted to keep normal <code>assert.h</code> assert&rsquo;s in the sample source, but I also
want these to be turned into my utest.h <code>ASSERT_TRUE</code> macros, so I just use the
preprocessor to define these over, and include the source into the test:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#define assert(x) ASSERT_TRUE(x)
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">UTEST</span>(generated, readme) {
</span></span><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;generated.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And the output when I run?</p>
<pre tabindex="0"><code>[ RUN      ] generated.readme
[       OK ] generated.readme (9715ns)
</code></pre><p>A pass!</p>
<h2 id="conclusion">Conclusion</h2>
<p>Ok - it is not as nice as what Rust has built-in, but it works! I can now modify
the README.md and be sure that the code compiles correctly. I even found a bug
in the sample in the process, so well worth the work. Just a shame I had to
invest in <a href="https://github.com/sheredom/json.h/pull/68">proper demonology</a> to
support this within the C eco-system.</p>
]]></description>
    </item>
    
    <item>
      <title>C89 &amp; Single Header json.h</title>
      <link>https://www.neilhenning.dev/posts/json-h-updates/</link>
      <pubDate>Thu, 02 Jan 2020 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/json-h-updates/</guid>
      <description><![CDATA[<p>I&rsquo;ve been working on my various C/C++ single header libraries some over the
Christmas break, and while I already did an
<a href="https://www.neilhenning.dev/posts/library-updates/">update on my work</a>, I decided
to leave <a href="https://github.com/sheredom/json.h">json.h</a> for its own post.</p>
<h2 id="c89-support">C89 Support</h2>
<p>One requested thing over the years has been C89 support, and I was reluctant to
do this mostly out of sheer laziness. I&rsquo;d have to convert a bunch of comments
over and remove my use of long long. This was my <em>entire</em> reasons for not doing
it, which was dumb in hindsight. So I&rsquo;ve
<a href="https://github.com/sheredom/json.h/commit/14a36a8424273556f88e799a7a7f534d09089c59">got it working now</a> for the people that really really care.</p>
<h2 id="single-header-support">Single Header Support</h2>
<p>I always maintained that having one header and one source file was the best
design decision for the library. It is a big implementation in the source file,
and I mostly have a distaste for having a header file where you have to do some
preprocessor define in a single source file.</p>
<p>But single headers are so super useful for users to just copy the one file and
ship it.</p>
<p>So <a href="https://github.com/sheredom/json.h/commit/22dead46037551c9a29a1a6229ea2f38dc01e1fb">I&rsquo;ve done made the change to bring it into a separate header</a>.</p>
<p>This will definitely result in a slower compile time when bringing in the
header, but I realised that in reality you will probably only include json.h in
a single file when you are interacting with the JSON. So it seemed fine overall
for this as a compromise.</p>
]]></description>
    </item>
    
    <item>
      <title>Some Miscellaneous Library Improvements</title>
      <link>https://www.neilhenning.dev/posts/library-updates/</link>
      <pubDate>Wed, 01 Jan 2020 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/library-updates/</guid>
      <description><![CDATA[<p>I&rsquo;ve been working on my various C/C++ single header libraries some over the
Christmas break, and I thought I&rsquo;d just jot down the improvements I&rsquo;ve made in a
post.</p>
<h2 id="processh---subprocessh">process.h -&gt; subprocess.h</h2>
<p>I&rsquo;ve had a long standing complaint that the name <code>process.h</code> conflicted with a
Windows system header. I&rsquo;ve decided (after a good three years of indecision mind
you) to just
<a href="https://github.com/sheredom/subprocess.h/pull/13">rename the header and the entry points</a>
to <code>subprocess.h</code> instead.</p>
<p>This isn&rsquo;t a perfect solution, but it avoids me having to namespace my headers
using my own name (which as a Scotsman I just can&rsquo;t quite stomach for some
reason).</p>
<h2 id="utesth">utest.h</h2>
<p>I added the ability to assert/expect on pointers types, which was a longstanding
annoyance. So the following now works:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">int</span><span style="color:#f92672">*</span> a, <span style="color:#f92672">*</span>b;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ASSERT_EQ</span>(a, b);
</span></span></code></pre></div><p>I&rsquo;ve also made it so that on GCC/Clang with C, or with C++11 using auto, you can
perform checks on void-pointers, and things of array type:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">static</span> <span style="color:#66d9ef">int</span> data[<span style="color:#ae81ff">42</span>];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span><span style="color:#f92672">*</span> a;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ASSERT_EQ</span>(a, data);
</span></span></code></pre></div><p>I also made the testing of the <code>--list-tests</code> option that was contributed by
<a href="https://github.com/ldrumm">ldrumm</a> (which required spawning a
separate process) work on Windows and macOS too by using my
<a href="https://github.com/sheredom/subprocess.h">subprocess.h</a>.</p>
<p>I also added a product page for <a href="https://www.neilhenning.dev/utest_h/">utest.h</a> to
help me try and advertise it more greatly for people than before.</p>
<h2 id="utf8h">utf8.h</h2>
<p>I fixed <a href="https://github.com/sheredom/utf8.h/issues/60">a bug</a> with <code>utf8casecmp</code>
in my UTF-8 parsing library and added some extra tests to stop the regression
happening again.</p>
<p>The &lsquo;bug&rsquo; wasn&rsquo;t <em>really a bug</em> in that the function behaved in a similar
fashion to the specification of the GNU extension <code>strcasecmp</code> that it is based
on, but it made sense to make <code>utf8casecmp</code> match what <code>strcasecmp</code> does.</p>
]]></description>
    </item>
    
    <item>
      <title>utest.h</title>
      <link>https://www.neilhenning.dev/utest_h/</link>
      <pubDate>Wed, 01 Jan 2020 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/utest_h/</guid>
      <description><![CDATA[<p>Anyone who has used the <a href="https://github.com/google/googletest">googletest</a>
library with a complex C++ codebase will know how powerful this form of unit
testing can be for productivity. While the library has a ton of features and is
seriously powerful, there are a number of technical deficits that come with it:</p>
<ul>
<li>It only works with modern C++.</li>
<li>It has a complex build system integration, with multiple source files and
headers.</li>
<li><a href="https://www.neilhenning.dev/posts/utest-h-performance/">The startup time of using googletest is terrible</a>.</li>
</ul>
<p>So with all this in mind I wrote my own library -
<a href="https://github.com/sheredom/utest.h">utest.h</a>. The library is:</p>
<ul>
<li>9x faster than googletest.</li>
<li>Works with C and C++.</li>
<li>Works with mixing C <em>and</em> C++ in the same testing application (very useful if
you want to test a C++ and C API to your code).</li>
<li>Has test fixtures.</li>
<li>Allows filtering of test cases.</li>
<li>Compiles with <code>-Wall -Werror -Weverything</code>.</li>
</ul>
<p>Lets look at an example application:</p>
<p>In a single file (C or C++, it doesn&rsquo;t matter) you need to need to call the
macro <code>UTEST_MAIN()</code> to create the main method for the application.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;utest.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">UTEST_MAIN</span>()
</span></span></code></pre></div><p>Note this doesn&rsquo;t <em>need</em> to be in a separate C/C++ file to the actual tests!</p>
<p>Then we&rsquo;ll have two files - a C and a C++ file just to show that it works.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;utest.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">UTEST</span>(from, c) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ASSERT_TRUE</span>(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;utest.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">UTEST</span>(from, cpp) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ASSERT_EQ</span>(true, false);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Now we&rsquo;ll compile this all together with clang and show the output.</p>

  <figure class="center" >
    <img src="/images/utest_h.gif"  alt="Terminal example of using utest.h"   style="border-radius: 8px;"  />
    
      <figcaption class="center"  style="color: white;" >Terminal example of using utest.h</figcaption>
    
  </figure>


<p>Anyone who is familiar with googletest will notice that I&rsquo;ve intentionally kept
the output similar (even colour highlighted) to stop any mental gymnastics that
could be involved.</p>
<p>Lastly the license - the code is as close to public domain as I could get in
a license, using the <a href="https://unlicense.org">unlicense</a> to let any of you do
basically anything you want with it.</p>
]]></description>
    </item>
    
    <item>
      <title>FPSCEV - Improving the Range Analysis</title>
      <link>https://www.neilhenning.dev/posts/fpscev-improved-range/</link>
      <pubDate>Sat, 29 Jun 2019 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/fpscev-improved-range/</guid>
      <description><![CDATA[<p>In this post, we&rsquo;ll improve our floating-point scalar evolution (fpscev) to do a better job at evaluating the range of some of the more complex intrinsics we analyze.</p>
<p>This post is the latest in a series about my experimentations with floating-point scalar evolution, you really want to read them in order:</p>
<ul>
<li><a href="https://www.neilhenning.dev/posts/fpscev/">An Experimental Floating-Point Scalar Evolution</a></li>
<li><a href="https://www.neilhenning.dev/posts/fpscev-fast-math-propagation/">Using Floating-Point Scalar Evolution to Propagate Fast-Math Flags</a></li>
<li><a href="https://www.neilhenning.dev/posts/fpscev-inst-simplify/">Using Floating-Point Scalar Evolution to Simplify Instructions</a></li>
</ul>
<p>The fpscev pass changes discussed in this post is available <a href="https://github.com/sheredom/fpscev/commit/e32e04ce9f229ca27ef40213c4ec695efc1a7cc2">on github here</a>.</p>
<h1 id="improving-the-range">Improving the Range</h1>
<p>When I wrote the first draft of the fpscev analysis, any functionality that LLVM&rsquo;s <a href="https://llvm.org/doxygen/classllvm_1_1APFloat.html#a9fccce07c15282e9fd964254f21d81c7">APFloat</a> did not contain I simply assumed the worst case for the range of the input (-NaN..NaN unless fast-math flags were specified). For instance, the code used to evaluate the range of exp2 was:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>FPSCEV <span style="color:#a6e22e">fpscev</span>(inst.getType());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Exp always has a positive result.
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> APFloat zero <span style="color:#f92672">=</span> APFloat<span style="color:#f92672">::</span>getZero(fpscev.min.getSemantics(), false);
</span></span><span style="display:flex;"><span>fpscev.min <span style="color:#f92672">=</span> zero;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> FastMathFlags flags <span style="color:#f92672">=</span> inst.getFastMathFlags();
</span></span><span style="display:flex;"><span>fpscev.max <span style="color:#f92672">=</span> applyFastMathFlags(fpscev.max, flags);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>fpse.map[<span style="color:#f92672">&amp;</span>inst] <span style="color:#f92672">=</span> fpscev;
</span></span></code></pre></div><p>I could do no better because APFloat did not contain an exp2 call that I could make use of to evaluate the range. After having some twitter discussions with the rather awesome <a href="https://twitter.com/marc_b_reynolds/status/1137820453777657858">Marc B. Reynolds</a>, I realised I should revisit my assumption on the ranges of some of these intrinsics to see if I couldn&rsquo;t make a better guess than what was there.</p>
<h1 id="exp2">Exp2</h1>
<p>For exponentials with a base of 2 as I&rsquo;ve already stated there isn&rsquo;t an LLVM APFloat function that I can just call into. There is something sort of similar that I can use though to estimate the range such that we can return something better than 0..NaN! LLVM APFloat does contain a <a href="https://llvm.org/doxygen/classllvm_1_1APFloat.html#ab6f3e137b277266516df5fd9eb692719">scalbn</a> definition for APFloat. Scalbn allows you to efficiently multiply a value by 2-to-the-power-of another value - <code>x * 2^y</code>. If <code>x</code> <em>just happened</em> to be 1.0 - then we are effectively calculating <code>2^y</code>. This just so happens to be exp2! The one downside is that we can only specify a <code>y</code> that is an integer - so we will lose some precision on the range by doing this.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>FPSCEV <span style="color:#a6e22e">exp2Bounds</span>(FPSCEV fpscev) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> fltSemantics <span style="color:#f92672">&amp;</span>semantics <span style="color:#f92672">=</span> fpscev.getSemantics();
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> APFloat one <span style="color:#f92672">=</span> getOne(semantics);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">bool</span> losesInfo;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (fpscev.min.isFinite()) {
</span></span><span style="display:flex;"><span>    fpscev.min.roundToIntegral(APFloat<span style="color:#f92672">::</span>rmTowardNegative);
</span></span><span style="display:flex;"><span>    fpscev.min.convert(APFloat<span style="color:#f92672">::</span>IEEEdouble(), APFloat<span style="color:#f92672">::</span>rmTowardNegative,
</span></span><span style="display:flex;"><span>                       <span style="color:#f92672">&amp;</span>losesInfo);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">int</span> power <span style="color:#f92672">=</span> <span style="color:#66d9ef">static_cast</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">int</span><span style="color:#f92672">&gt;</span>(fpscev.min.convertToDouble());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    fpscev.min <span style="color:#f92672">=</span> scalbn(one, power, APFloat<span style="color:#f92672">::</span>rmTowardNegative);
</span></span><span style="display:flex;"><span>  } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>    fpscev.min <span style="color:#f92672">=</span> APFloat<span style="color:#f92672">::</span>getInf(semantics, true);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (fpscev.max.isFinite()) {
</span></span><span style="display:flex;"><span>    fpscev.max.roundToIntegral(APFloat<span style="color:#f92672">::</span>rmTowardPositive);
</span></span><span style="display:flex;"><span>    fpscev.max.convert(APFloat<span style="color:#f92672">::</span>IEEEdouble(), APFloat<span style="color:#f92672">::</span>rmTowardPositive,
</span></span><span style="display:flex;"><span>                       <span style="color:#f92672">&amp;</span>losesInfo);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">int</span> power <span style="color:#f92672">=</span> <span style="color:#66d9ef">static_cast</span><span style="color:#f92672">&lt;</span><span style="color:#66d9ef">int</span><span style="color:#f92672">&gt;</span>(fpscev.max.convertToDouble());
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    fpscev.max <span style="color:#f92672">=</span> scalbn(one, power, APFloat<span style="color:#f92672">::</span>rmTowardPositive);
</span></span><span style="display:flex;"><span>  } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>    fpscev.max <span style="color:#f92672">=</span> APFloat<span style="color:#f92672">::</span>getInf(semantics, false);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> fpscev;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The approach I take is:</p>
<ol>
<li>Round the minimum range value down to the next whole integer, the maximum range up to the next whole integer.</li>
<li>Convert them to doubles rounding the values away from zero again (this only really matters in the case where we are evaluating a quad-precision number that isn&rsquo;t fully representable in 64-bits of precision).</li>
<li>Convert these doubles to integer (as scalbn takes an int <code>y</code>). I rely on the fact that compilers generally round an overflowing double to INT_MAX/INT_MIN which will easily create an infinity/-infinity when we raise that value by the power of 2.</li>
<li>Then use scalbn like I stated above to create the bounds.</li>
<li>Note: I only attempt this approach at all if the min/max value were finite in the first place.</li>
</ol>
<p>Lets have a look at the range of this exp2 value plotted across some key values to understand how accurate our evaluation is:</p>

<img src="/images/fpscev-range/exp2.png"  class="center"  style="border-radius: 8px;"    />


<p>The chart above firstly shows that the <em>actual</em> value of exp2 if we could calculate it correctly lies inclusively within the calculated min/max ranges we&rsquo;ve established using scalbn. So the result is always <strong>correct</strong>. You can also see that the higher the input value to the exp2 function, the more imprecise our range analysis becomes (as exp2 gets more, well, <em>exponential</em> the higher the input value this is to be expected).</p>
<p>All in all - this is pretty good! Much better than always returning a range of 0..NaN anyway.</p>
<h1 id="log2">Log2</h1>
<p>For log2 I explored a similar idea to the solution I used for exp2 above. While LLVM APFloat doesn&rsquo;t have a suitable log2 equivalent function, it does have <a href="https://en.cppreference.com/w/cpp/numeric/math/ilogb">ilogb</a> though. The ilogb function effectively extracts the exponent from the floating-point number without fudging it like which happens with frexp (frexp always returns a number between 0.5..1, and so has to fudge the exponent it returns to make sure of that). Because ilogb loses the fractional part of our floating-point number, we can use ilogb of the minimum-range to get the lower bound of our result. For the upper bound, we use ilogb and then add one onto it - this rounds up the estimation to the next highest whole number.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>FPSCEV <span style="color:#a6e22e">log2Bounds</span>(FPSCEV fpscev) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> fltSemantics <span style="color:#f92672">&amp;</span>semantics <span style="color:#f92672">=</span> fpscev.getSemantics();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// If the full range is negative, always returns a NaN.
</span></span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (fpscev.isAllNegative()) {
</span></span><span style="display:flex;"><span>    APFloat nan <span style="color:#f92672">=</span> APFloat<span style="color:#f92672">::</span>getNaN(semantics, false);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> FPSCEV(nan, nan, false);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> APInt ilogbMin(<span style="color:#ae81ff">32</span>, ilogb(fpscev.min));
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// We do +1 here so we round the range up.
</span></span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> APInt ilogbMax(<span style="color:#ae81ff">32</span>, ilogb(fpscev.max) <span style="color:#f92672">+</span> <span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  APFloat values[<span style="color:#ae81ff">2</span>] <span style="color:#f92672">=</span> {getFromInt(semantics, ilogbMin, true),
</span></span><span style="display:flex;"><span>                       getFromInt(semantics, ilogbMax, true)};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// If the input is entirely greater than zero, we can use ilogb to get a much
</span></span></span><span style="display:flex;"><span>  <span style="color:#75715e">// firmer estimate on the log result.
</span></span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (fpscev.isGreaterThan(APFloat<span style="color:#f92672">::</span>getZero(semantics))) {
</span></span><span style="display:flex;"><span>    fpscev.min <span style="color:#f92672">=</span> getMinimum(values);
</span></span><span style="display:flex;"><span>    fpscev.max <span style="color:#f92672">=</span> getMaximum(values);
</span></span><span style="display:flex;"><span>  } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>    fpscev.min <span style="color:#f92672">=</span> APFloat<span style="color:#f92672">::</span>getInf(semantics, true);
</span></span><span style="display:flex;"><span>    fpscev.max <span style="color:#f92672">=</span> values[<span style="color:#ae81ff">1</span>];
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// Can&#39;t be sure about this because we&#39;re getting very vague bounds, so wipe
</span></span></span><span style="display:flex;"><span>  <span style="color:#75715e">// it.
</span></span></span><span style="display:flex;"><span>  fpscev.isInteger <span style="color:#f92672">=</span> false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> fpscev;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Lets have a look at the chart for this to show how good our bounds are:</p>

<img src="/images/fpscev-range/log2.png"  class="center"  style="border-radius: 8px;"    />


<p>As can be seen - the actual result is entirely within our calculated min/max range, and because logarithms grow <em>so</em> slowly the range isn&rsquo;t so bad (as compared to our exponential prediction from before).</p>
<h1 id="log--log10">Log &amp; Log10</h1>
<p>Logarithms have some very fun rules - one of which is the change of base formula. For those unfamiliar, any log can be transfered into any other log calculation by log<!-- raw HTML omitted -->a<!-- raw HTML omitted -->(x) = log<!-- raw HTML omitted -->b<!-- raw HTML omitted -->(x) / log<!-- raw HTML omitted -->b<!-- raw HTML omitted -->(a). This means we can use the calculation of the bounds we already discovered for log2 to calulate a bound for any other log! I use this same trick for log and log10 - so I&rsquo;ll just cover log here to keep this succinct.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">template</span> <span style="color:#f92672">&lt;&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> FPScalarEvolutionPass<span style="color:#f92672">::</span>visitIntrinsic<span style="color:#f92672">&lt;</span>Intrinsic<span style="color:#f92672">::</span>log<span style="color:#f92672">&gt;</span>(
</span></span><span style="display:flex;"><span>    IntrinsicInst <span style="color:#f92672">&amp;</span>inst) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FastMathFlags fmf <span style="color:#f92672">=</span> inst.getFastMathFlags();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  FPSCEV fpscev <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>      fpse.getFPSCEV(inst.getOperand(<span style="color:#ae81ff">0</span>))<span style="color:#f92672">-&gt;</span>cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  fpscev <span style="color:#f92672">=</span> log2Bounds(fpscev);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// We are calculating log(x), but we only have ilogb (which gives us an
</span></span></span><span style="display:flex;"><span>  <span style="color:#75715e">// effective lower bound of log2(x)). To convert this bound into log(x) by
</span></span></span><span style="display:flex;"><span>  <span style="color:#75715e">// multiplying it by log(2).
</span></span></span><span style="display:flex;"><span>  APFloat <span style="color:#a6e22e">converter</span>(
</span></span><span style="display:flex;"><span>      <span style="color:#ae81ff">0.693147180559945309417232121458176568075500134360255254120</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">bool</span> losesInfo;
</span></span><span style="display:flex;"><span>  converter.convert(fpscev.getSemantics(), APFloat<span style="color:#f92672">::</span>rmNearestTiesToEven,
</span></span><span style="display:flex;"><span>                    <span style="color:#f92672">&amp;</span>losesInfo);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  fpscev.min.multiply(converter, APFloat<span style="color:#f92672">::</span>rmTowardNegative);
</span></span><span style="display:flex;"><span>  fpscev.max.multiply(converter, APFloat<span style="color:#f92672">::</span>rmTowardPositive);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  fpse.map[<span style="color:#f92672">&amp;</span>inst] <span style="color:#f92672">=</span> fpscev.cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>I basically calculate the log2 range of the input, and then use the change of base formula for logarithms to turn this into the bounds for log instead. Lets look at the chart:</p>

<img src="/images/fpscev-range/log.png"  class="center"  style="border-radius: 8px;"    />


<p>Pretty good! The bounds follow a similar trajectory to the previous log2 calculation, but in this newer range of log.</p>
<h1 id="pow">Pow</h1>
<p>Anyone who has tried to implement <code>pow(x, y)</code> will know that there is a common hack that gets touted as some miracle solution to this calculation - turning <code>pow(x, y)</code> into <code>exp2(y * log2(x))</code>. There are numerous reasons why this <em>isn&rsquo;t generally a good idea</em> (the precision loss is terrible when you do the <code>y * log2(x)</code>, you have to handle a negative <code>x</code> to an integer <code>y</code> that might be odd/even and this affects the sign of the result, etc) - but since we have no alterative and we are ok to lose a bit of precision as long as we lose the precision correctly (EG. as long as we always grow the range through precision loss rather than accidentally shrink it).</p>
<p>Pow has a lot of chances to go awry (fractional bases, fractional powers, negatives) - so I play it very safe:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#75715e">// For pow we use exp2(y * log2(x)) to get the best bounds we can hope for.
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">template</span> <span style="color:#f92672">&lt;&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> FPScalarEvolutionPass<span style="color:#f92672">::</span>visitIntrinsic<span style="color:#f92672">&lt;</span>Intrinsic<span style="color:#f92672">::</span>pow<span style="color:#f92672">&gt;</span>(
</span></span><span style="display:flex;"><span>    IntrinsicInst <span style="color:#f92672">&amp;</span>inst) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FastMathFlags fmf <span style="color:#f92672">=</span> inst.getFastMathFlags();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FPSCEV xFpscev <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>      fpse.getFPSCEV(inst.getOperand(<span style="color:#ae81ff">0</span>))<span style="color:#f92672">-&gt;</span>cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FPSCEV yFpscev <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>      fpse.getFPSCEV(inst.getOperand(<span style="color:#ae81ff">1</span>))<span style="color:#f92672">-&gt;</span>cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  FPSCEV log2Fpscev <span style="color:#f92672">=</span> log2Bounds(xFpscev);
</span></span><span style="display:flex;"><span>  FPSCEV fpscevs[<span style="color:#ae81ff">4</span>] <span style="color:#f92672">=</span> {log2Fpscev, log2Fpscev, log2Fpscev, log2Fpscev};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  fpscevs[<span style="color:#ae81ff">0</span>].min.multiply(yFpscev.min, APFloat<span style="color:#f92672">::</span>rmTowardNegative);
</span></span><span style="display:flex;"><span>  fpscevs[<span style="color:#ae81ff">0</span>].max.multiply(yFpscev.min, APFloat<span style="color:#f92672">::</span>rmTowardNegative);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  fpscevs[<span style="color:#ae81ff">1</span>].min.multiply(yFpscev.max, APFloat<span style="color:#f92672">::</span>rmTowardNegative);
</span></span><span style="display:flex;"><span>  fpscevs[<span style="color:#ae81ff">1</span>].max.multiply(yFpscev.max, APFloat<span style="color:#f92672">::</span>rmTowardNegative);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  fpscevs[<span style="color:#ae81ff">2</span>].min.multiply(yFpscev.min, APFloat<span style="color:#f92672">::</span>rmTowardPositive);
</span></span><span style="display:flex;"><span>  fpscevs[<span style="color:#ae81ff">2</span>].max.multiply(yFpscev.min, APFloat<span style="color:#f92672">::</span>rmTowardPositive);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  fpscevs[<span style="color:#ae81ff">3</span>].min.multiply(yFpscev.max, APFloat<span style="color:#f92672">::</span>rmTowardPositive);
</span></span><span style="display:flex;"><span>  fpscevs[<span style="color:#ae81ff">3</span>].max.multiply(yFpscev.max, APFloat<span style="color:#f92672">::</span>rmTowardPositive);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  fpscevs[<span style="color:#ae81ff">0</span>] <span style="color:#f92672">=</span> exp2Bounds(fpscevs[<span style="color:#ae81ff">0</span>]);
</span></span><span style="display:flex;"><span>  fpscevs[<span style="color:#ae81ff">1</span>] <span style="color:#f92672">=</span> exp2Bounds(fpscevs[<span style="color:#ae81ff">1</span>]);
</span></span><span style="display:flex;"><span>  fpscevs[<span style="color:#ae81ff">2</span>] <span style="color:#f92672">=</span> exp2Bounds(fpscevs[<span style="color:#ae81ff">2</span>]);
</span></span><span style="display:flex;"><span>  fpscevs[<span style="color:#ae81ff">3</span>] <span style="color:#f92672">=</span> exp2Bounds(fpscevs[<span style="color:#ae81ff">3</span>]);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  FPSCEV result;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  result.min <span style="color:#f92672">=</span> getMinimum({fpscevs[<span style="color:#ae81ff">0</span>].min, fpscevs[<span style="color:#ae81ff">0</span>].max, fpscevs[<span style="color:#ae81ff">1</span>].min,
</span></span><span style="display:flex;"><span>                           fpscevs[<span style="color:#ae81ff">1</span>].max, fpscevs[<span style="color:#ae81ff">2</span>].min, fpscevs[<span style="color:#ae81ff">2</span>].max,
</span></span><span style="display:flex;"><span>                           fpscevs[<span style="color:#ae81ff">3</span>].min, fpscevs[<span style="color:#ae81ff">3</span>].max});
</span></span><span style="display:flex;"><span>  result.max <span style="color:#f92672">=</span> getMaximum({fpscevs[<span style="color:#ae81ff">0</span>].min, fpscevs[<span style="color:#ae81ff">0</span>].max, fpscevs[<span style="color:#ae81ff">1</span>].min,
</span></span><span style="display:flex;"><span>                           fpscevs[<span style="color:#ae81ff">1</span>].max, fpscevs[<span style="color:#ae81ff">2</span>].min, fpscevs[<span style="color:#ae81ff">2</span>].max,
</span></span><span style="display:flex;"><span>                           fpscevs[<span style="color:#ae81ff">3</span>].min, fpscevs[<span style="color:#ae81ff">3</span>].max});
</span></span><span style="display:flex;"><span>  result.isInteger <span style="color:#f92672">=</span> false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  fpse.map[<span style="color:#f92672">&amp;</span>inst] <span style="color:#f92672">=</span> result.cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The approach is basically:</p>
<ol>
<li>Get the log2 bounds of the input <code>x</code>.</li>
<li>Multiply this by the bounds for <code>y</code> resulting in 8 multiplications for the whole space of the pairings.</li>
<li>Feed these multiplications into the exp2 bounds.</li>
<li>Then work out the minimum/maximum of all the resulting values.</li>
</ol>
<p>This gets us a very imprecise result, as the following chart shows:</p>

<img src="/images/fpscev-range/pow.png"  class="center"  style="border-radius: 8px;"    />


<p>It&rsquo;s really very <em>terribly</em> imprecise - we are losing so much precision by the fact our exp and log are so very imprecise too. While this isn&rsquo;t great - it is <em>still</em> better than having pow always return -NaN..NaN - at least we have some semblance of a range!</p>
<h1 id="sqrt">Sqrt</h1>
<p>Sqrt is one of the few functions that the C stdlib version is required to have 0.5 ulp (EG. the same precision as basic mathematical operators like + or -). This means, as long as we carefully round the min/max ranges as we translate from the APFloat to double, we can use the C stdlib sqrt implementation for our range calculation - huzzah!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>FPSCEV <span style="color:#a6e22e">sqrtBounds</span>(FPSCEV fpscev) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> fltSemantics <span style="color:#f92672">&amp;</span>semantics <span style="color:#f92672">=</span> fpscev.getSemantics();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// If the full range is negative, always returns a NaN.
</span></span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (fpscev.isAllNegative()) {
</span></span><span style="display:flex;"><span>    APFloat nan <span style="color:#f92672">=</span> APFloat<span style="color:#f92672">::</span>getNaN(semantics, false);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> FPSCEV(nan, nan, false);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">bool</span> losesInfo;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (fpscev.isAllNonNegative()) {
</span></span><span style="display:flex;"><span>    fpscev.min.convert(APFloat<span style="color:#f92672">::</span>IEEEdouble(), APFloat<span style="color:#f92672">::</span>rmTowardNegative,
</span></span><span style="display:flex;"><span>                       <span style="color:#f92672">&amp;</span>losesInfo);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Get the next number less than the current (unless we are zero).
</span></span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>fpscev.min.isZero()) {
</span></span><span style="display:flex;"><span>      fpscev.min.next(true);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    fpscev.min <span style="color:#f92672">=</span> APFloat(std<span style="color:#f92672">::</span>sqrt(fpscev.min.convertToDouble()));
</span></span><span style="display:flex;"><span>    fpscev.min.convert(semantics, APFloat<span style="color:#f92672">::</span>rmTowardNegative, <span style="color:#f92672">&amp;</span>losesInfo);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// If the whole fpscev is not negative, it means max must be positive.
</span></span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>fpscev.isAllNegative()) {
</span></span><span style="display:flex;"><span>    fpscev.max.convert(APFloat<span style="color:#f92672">::</span>IEEEdouble(), APFloat<span style="color:#f92672">::</span>rmTowardPositive,
</span></span><span style="display:flex;"><span>                       <span style="color:#f92672">&amp;</span>losesInfo);
</span></span><span style="display:flex;"><span>    fpscev.max.next(false);
</span></span><span style="display:flex;"><span>    fpscev.max <span style="color:#f92672">=</span> APFloat(std<span style="color:#f92672">::</span>sqrt(fpscev.max.convertToDouble()));
</span></span><span style="display:flex;"><span>    fpscev.max.convert(semantics, APFloat<span style="color:#f92672">::</span>rmTowardPositive, <span style="color:#f92672">&amp;</span>losesInfo);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  fpscev.isInteger <span style="color:#f92672">=</span> false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span> fpscev;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The basic approach is that we:</p>
<ol>
<li>Check if the entire fpscev is not negative (meaning that min is definitely going to produce a non-NaN result).</li>
<li>If so - convert the minimum value to APFloat&rsquo;s double representation. This just allows us to convert to double using the <code>convertToDouble</code> method.</li>
<li>If the converted value is not 0, then we move it over to the next smallest floating-point value using the <code>next</code> method (akin to <code>nextafter</code> in C).</li>
<li>Convert to double, use std::sqrt, then convert back, rounding towards negative as we convert back to the original semantics (ensuring we grow the min range on ties).</li>
<li>Check if the fpscev is not all negative (meaning that max is definitely going to produce a non-NaN result).</li>
<li>Do the same approach as for min, but use <code>next</code> to move the value up, and convert with rounding towards positive as we convert back (to grow the range).</li>
</ol>
<p>This means we might get a <em>slightly</em> off result, but the result will be pretty strongly bound to what sqrt would produce.</p>
<p>For instance, for an input between 0..511, we produce an output range of:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">22.6053104</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><p>Which is much better than the 0..NaN we have previously.</p>
<h1 id="conclusion">Conclusion</h1>
<p>With this improvement I&rsquo;ve managed to really tighten up some of the functions I couldn&rsquo;t get a good handle on previously.</p>
<p>In the next post I&rsquo;m going to look at if it is possible to make our fpscev&rsquo;s aware of where they are used, and see if we can&rsquo;t constrain the range even further. Watch this space!</p>
]]></description>
    </item>
    
    <item>
      <title>Farewell AMD / Hello Unity</title>
      <link>https://www.neilhenning.dev/posts/last-day-amd/</link>
      <pubDate>Fri, 21 Jun 2019 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/last-day-amd/</guid>
      <description><![CDATA[<p>Announcement time - today is my last day at AMD. I&rsquo;ll be taking a few weeks off, before starting a new gig at Unity mid-July.</p>
<p>It is also the end of my five year involvement in Vulkan &amp; SPIR-V - having contributed to both specifications since 2014.</p>
<p>I&rsquo;ve very much enjoyed my time in this slice of the industry, but it was time for a new challenge.</p>
<h1 id="farewell-amd">Farewell AMD</h1>
<p>I&rsquo;ve been at AMD a little over a year now - and it has been an interesting challenge. I was brought in to improve the performance of the LLVM compiler stack (LLPC) as compared to the legacy Shader Compiler (SC). All-in during my time there I improved the LLVM stack by just over 2x performance across a raft of key shaders, which I am pretty proud of.</p>
<p>I also implemented a bunch of fun shader extensions in the stack which was a lot of fun (VK_EXT_buffer_device_address, VK_KHR_vulkan_memory_model, and quite few secret-sauce ones still to come!).</p>
<p>I think the stack is in a good state going forward.</p>
<p>As always - there is <em>always</em> a few things about any employment that aren&rsquo;t as great. AMD is an <em>old</em> company, 50 years old this year. Some of the internal systems feel about that old too. Doing expenses is a pain - the system is archaic and frustrating, getting new hardware wasn&rsquo;t always as easy as it could be, and I wasn&rsquo;t quite prepared for cross-team politics that a big company like AMD is going to have.</p>
<p>The other thing I <em>really wish</em> I had asked about before I start was how code is actually written. Perforce was the main version control system I used while at AMD, and I find perforce to be an unmitigated disaster for software development. I genuinely think I was at about 10% of my peak productivity.</p>
<p>I think coming from a relatively small company like Codeplay (about 85 people when I left) who had much leaner systems and which individuals could easily move the needle left me a little ill-prepared for the reality of a big companies. You live and learn - I am now much wiser.</p>
<p>That being said - I still did some good and enjoyable work, made some positive changes, and made some good friends. AMD has a bunch of really talented staff that move mountains to make good changes.</p>
<h1 id="farewell-khronos">Farewell Khronos</h1>
<p>I&rsquo;ve been working on the Vulkan &amp; SPIR-V specifications for about five years now, and I was instrumental in getting a bunch of really important features (most notably the subgroup operations in Vulkan 1.1 / SPIR-V 1.3) through. People often mock design-by-committee for arguing over what they see as death-by-over-design - but I found the whole standards process to be a really amazing collaboration between what are effectively enemy companies. They fact you have so many eyes on the same set of specifications means that you get a much better and more rounded result.</p>
<p>I&rsquo;ll miss my weekly phone calls discussing the ins and outs of how shaders execute on all the fun hardware we make them work on. There is some good features that I worked on in Khronos to come to developers in future - I look forward to people getting to use some of my final specification work!</p>
<h1 id="im-bursting-to-tell-you-what-is-next">I&rsquo;m Bursting to Tell You What Is Next</h1>
<p>Even though I&rsquo;ve looked about 70 years old since I was 15 - I&rsquo;m not retiring or anything like that!</p>
<p>I&rsquo;ve decided to join <a href="https://unity.com">Unity</a> to work on the <a href="https://unity.com/dots#burst-compiler">Burst Compiler</a>. The Burst Compiler is something that is <em>incredibly</em> interesting to me as a compiler engineer - lets take a language and add all the constraints we require to reduce it to a performance-orientated subset, and make a compiler that can make this code run <em>fast</em>. After some initial discussions with <a href="https://twitter.com/lucasmeijer">Lucas Meijer</a>, and many conversations with <a href="https://twitter.com/deplinenoise">Andreas Fredriksson</a> and <a href="https://twitter.com/xoofx">Alexandre Mutel</a> I was 100% convinced. The chance to make such a big difference to so many developers lives is such a huge appeal to me personally - I always want my code to make a positive impact to as many people as I can. I also get to focus much more heavily on LLVM which is a technology I love to work with too - super excited!</p>
<p>A couple of weeks to relax (I have some extensive gardening still to do) and then I&rsquo;ll be onboarding at Unity and getting to grips with all the future fun there is to have. I&rsquo;ll keep y&rsquo;all posted!</p>
]]></description>
    </item>
    
    <item>
      <title>Using Floating-Point Scalar Evolution to Simplify Instructions</title>
      <link>https://www.neilhenning.dev/posts/fpscev-inst-simplify/</link>
      <pubDate>Thu, 20 Jun 2019 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/fpscev-inst-simplify/</guid>
      <description><![CDATA[<p>In this post, we&rsquo;ll use floating-point scalar evolution (fpscev) to simplify instructions based on any range data we&rsquo;ve managed to deduce.</p>
<p>This post is the latest in a series about my experimentations with floating-point scalar evolution, you really want to read the them in order:</p>
<ul>
<li><a href="https://www.neilhenning.dev/posts/fpscev/">An Experimental Floating-Point Scalar Evolution</a></li>
<li><a href="https://www.neilhenning.dev/posts/fpscev-fast-math-propagation/">Using Floating-Point Scalar Evolution to Propagate Fast-Math Flags</a></li>
</ul>
<p>The LLVM optimization pass discussed in this post is available <a href="https://github.com/sheredom/fpscev/commit/efce1ce5f2649ddf447b3a6fb76bdd457284f775">on github here</a>.</p>
<h1 id="instruction-simplification">Instruction Simplification</h1>
<p>LLVM is missing a bunch of instruction simplification surrounding floating-point - precisely because it is missing the fpscev analysis.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> tail call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.sqrt.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span></code></pre></div><p>In the above example, lets say we have deduced that <code>%f</code> is always negative. The <a href="https://en.cppreference.com/w/c/numeric/math/sqrt">rules for sqrt</a> state that if the input is negative, the output is NaN. LLVM cannot spot this code because it cannot deduce the range of <code>%f</code>.</p>
<p>Another example is with the minnum/maxnum/minimum/maximum intrinsics:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> tail call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.minnum.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2)
</span></span></code></pre></div><p>If <code>%f2</code> was strictly less than <code>%f</code>, then we could replace this call with <code>%f2</code> <em>since it is always less than</em>. Again LLVM cannot spot this.</p>
<p>LLVM <em>does</em> have some pseudo floating-point evaluations surrounding the fcmp and all the various round-to-integer intrinsics. For instance the following fcmp:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>b <span style="color:#f92672">=</span> fcmp oeq <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f2
</span></span></code></pre></div><p>Will be simplified to the constant false if the compiler has locally worked out that <code>%f</code> can never be equal to <code>%f2</code>.</p>
<p>This is great that LLVM has some insight into these values - but I&rsquo;d still argue having a single mechanism based around the fpscev analysis would be more fruitful in the long term for optimizations.</p>
<h1 id="overview-of-the-pass">Overview of the Pass</h1>
<p>The new pass I&rsquo;ve added is <code>FPInstSimplifyPass</code> (see <a href="https://github.com/sheredom/fpscev/blob/master/fpscev.cpp#L1585">https://github.com/sheredom/fpscev/blob/master/fpscev.cpp#L1585</a>) - it runs over a function using an <code>InstVisitor</code>, and uses the fpscev analysis to simplify instructions and intrinsics.</p>
<p>The main purpose of this pass is to try and remove instructions or replace instructions with more simple variants where knowing the range of the inputs lets us deduce a more simple form.</p>
<p>For example, lets say we have a simple code snippet of the form:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define i1 <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">fcmp_oeq_false</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fadd <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2, <span style="color:#ae81ff">16.0</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>b <span style="color:#f92672">=</span> fcmp oeq <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f3, <span style="color:#f92672">%</span>f
</span></span><span style="display:flex;"><span>  ret i1 <span style="color:#f92672">%</span>b
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Because <code>%f3</code> and <code>%f</code> cannot overlap (and neither can be NaN), their values can never compare equal. LLVM already manages to optimize this to:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define i1 <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">fcmp_oeq_false</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  ret i1 false
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>It does this in a roundabout way though - it turns the floating-point operations above into integer operations (in the float-to-int pass), and then relies on scalar evolution of integers to optimize the code.</p>
<p>Another case, this time with something that fails to optimize with LLVM:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define i1 <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">fcmp_ole_true</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fadd <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2, <span style="color:#ae81ff">15.0</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>b <span style="color:#f92672">=</span> fcmp ole <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f3
</span></span><span style="display:flex;"><span>  ret i1 <span style="color:#f92672">%</span>b
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>LLVM turns this into:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define i1 <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">fcmp_ole_true</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span><span style="color:#ae81ff">1</span> <span style="color:#f92672">=</span> zext i4 <span style="color:#f92672">%</span>i to i32
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span><span style="color:#ae81ff">2</span> <span style="color:#f92672">=</span> zext i4 <span style="color:#f92672">%</span>i2 to i32
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f31 <span style="color:#f92672">=</span> add nuw nsw i32 <span style="color:#f92672">%</span><span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">15</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>b2 <span style="color:#f92672">=</span> icmp uge i32 <span style="color:#f92672">%</span>f31, <span style="color:#f92672">%</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>  ret i1 <span style="color:#f92672">%</span>b2
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>A little weird - but it basically canonicalizes the ordered-less-than-equal into an ordered-greater-than-equal (and swaps the operands), and then converts this into integer operations like it did above. For some reason LLVM won&rsquo;t optimize this further (even though I think integer scalar-evolution should be able to?).</p>
<p>I personally think for both the above cases LLVM shouldn&rsquo;t be converting them to use integers, and I suspect it does this only so that scalar evolution can help with optimization. Instead, my fpscev analysis can be used to optimize <em>both</em> the cases above. Lets take a look!</p>
<h2 id="floating-point-comparison">Floating-Point Comparison</h2>
<p>Lets start our floating-point comparison optimization by looking at the example that LLVM doesn&rsquo;t do a fantastic job of above:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define i1 <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">fcmp_ole_true</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fadd <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2, <span style="color:#ae81ff">15.0</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>b <span style="color:#f92672">=</span> fcmp ole <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f3
</span></span><span style="display:flex;"><span>  ret i1 <span style="color:#f92672">%</span>b
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In this example <code>%f</code> is always ordered-less-than-equal to <code>%f3</code> because <code>%f3</code> is in the range [15.0..30.0] and <code>%f</code> is in the range [0.0..15.0].</p>
<p>Using my fpscev analysis we can use the range of these values to fold this fcmp away:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span>FastMathFlags fmf <span style="color:#f92672">=</span> inst.getFastMathFlags();
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> FPSCEV xFpscev <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>    fpse<span style="color:#f92672">-&gt;</span>getFPSCEV(inst.getOperand(<span style="color:#ae81ff">0</span>))<span style="color:#f92672">-&gt;</span>cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">const</span> FPSCEV yFpscev <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>    fpse<span style="color:#f92672">-&gt;</span>getFPSCEV(inst.getOperand(<span style="color:#ae81ff">1</span>))<span style="color:#f92672">-&gt;</span>cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>CmpInst<span style="color:#f92672">::</span>Predicate predicate <span style="color:#f92672">=</span> CmpInst<span style="color:#f92672">::</span>BAD_FCMP_PREDICATE;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">switch</span> (inst.getPredicate()) {
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">default</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">case</span> CmpInst<span style="color:#f92672">::</span>FCMP_OLE:
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>xFpscev.isNaN() <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">!</span>yFpscev.isNaN()) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (xFpscev.isLessThanEqual(yFpscev)) {
</span></span><span style="display:flex;"><span>      predicate <span style="color:#f92672">=</span> CmpInst<span style="color:#f92672">::</span>FCMP_TRUE;
</span></span><span style="display:flex;"><span>    } <span style="color:#66d9ef">else</span> <span style="color:#a6e22e">if</span> (xFpscev.isGreaterThan(yFpscev)) {
</span></span><span style="display:flex;"><span>      predicate <span style="color:#f92672">=</span> CmpInst<span style="color:#f92672">::</span>FCMP_FALSE;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span><span style="color:#75715e">// all the other cases...
</span></span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (predicate <span style="color:#f92672">!=</span> CmpInst<span style="color:#f92672">::</span>BAD_FCMP_PREDICATE) {
</span></span><span style="display:flex;"><span>  inst.setPredicate(predicate);
</span></span><span style="display:flex;"><span>  modified <span style="color:#f92672">=</span> true;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Since LLVM already has logic to handle folding FCMP_TRUE and FCMP_FALSE away, I just modify the predicate of the existing fcmp operation and will let LLVM handle the rest.</p>
<p>The resulting code after applying this optimization is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define i1 <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">fcmp_ole_true</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fadd <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2, <span style="color:#ae81ff">1.500000e+01</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>b <span style="color:#f92672">=</span> fcmp true <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f3
</span></span><span style="display:flex;"><span>  ret i1 <span style="color:#f92672">%</span>b
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>As can be seen the fcmp ole has become an fcmp true - the optimization has correctly noted that the compare would always return true. Note that because this is an ordered compare we had to be careful with NaNs. You&rsquo;ll notice that I had a check on both the fpscev&rsquo;s to the fcmp to see whether either of them were NaN - and not apply the optimization if so. This is another case where my fpscev analysis, precisely because it is very good at detecting no-NaN situations, allows us to perform a greater set of optimizations across a broader set of input values.</p>
<h2 id="intrinsics">Intrinsics</h2>
<p>The other case where I try and use fpscev analysis to simplify instructions is with intrinsics. LLVM is pretty poor at folding floating-point min/max operations for instance, and fpscev allows us to perform similar optimizations as with fcmp on these.</p>
<p>One thing that sucks with LLVM&rsquo;s InstVisitor is that it doesn&rsquo;t have a nice way to iterate through intrinsics. The best method I&rsquo;ve found is to do something like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">visitIntrinsicInst</span>(IntrinsicInst <span style="color:#f92672">&amp;</span>inst) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">switch</span> (inst.getIntrinsicID()) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">default</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">case</span> Intrinsic<span style="color:#f92672">::</span>sqrt:
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// do something!
</span></span></span></code></pre></div><p>But this means you end up with uber-functions containing a ton of implementation detail on each intrinsic. Also the fact that everything inhabits a big switch statement means that it is easy to fall foul of C++&rsquo;s insane switch fallthrough default.</p>
<p>To get around this I&rsquo;ve used some <em>very basic</em> templates to let us have each intrinsic optimization in its own function, and using a macro to reduce duplicating the intrinsic id:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> FPInstSimplifyPass<span style="color:#f92672">::</span>visitIntrinsicInst(IntrinsicInst <span style="color:#f92672">&amp;</span>inst) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">switch</span> (inst.getIntrinsicID()) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">default</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span><span style="color:#75715e">#define INTRINSIC_VISIT(x)                                                     \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  case x:                                                                      \
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    return visitIntrinsic&lt;x&gt;(inst)
</span></span></span><span style="display:flex;"><span>    INTRINSIC_VISIT(Intrinsic<span style="color:#f92672">::</span>sqrt);
</span></span><span style="display:flex;"><span>    INTRINSIC_VISIT(Intrinsic<span style="color:#f92672">::</span>pow);
</span></span><span style="display:flex;"><span>    INTRINSIC_VISIT(Intrinsic<span style="color:#f92672">::</span>fabs);
</span></span><span style="display:flex;"><span>    INTRINSIC_VISIT(Intrinsic<span style="color:#f92672">::</span>minnum);
</span></span><span style="display:flex;"><span>    INTRINSIC_VISIT(Intrinsic<span style="color:#f92672">::</span>maxnum);
</span></span><span style="display:flex;"><span>    INTRINSIC_VISIT(Intrinsic<span style="color:#f92672">::</span>minimum);
</span></span><span style="display:flex;"><span>    INTRINSIC_VISIT(Intrinsic<span style="color:#f92672">::</span>maximum);
</span></span><span style="display:flex;"><span>    INTRINSIC_VISIT(Intrinsic<span style="color:#f92672">::</span>copysign);
</span></span><span style="display:flex;"><span>    INTRINSIC_VISIT(Intrinsic<span style="color:#f92672">::</span>floor);
</span></span><span style="display:flex;"><span>    INTRINSIC_VISIT(Intrinsic<span style="color:#f92672">::</span>ceil);
</span></span><span style="display:flex;"><span>    INTRINSIC_VISIT(Intrinsic<span style="color:#f92672">::</span>trunc);
</span></span><span style="display:flex;"><span>    INTRINSIC_VISIT(Intrinsic<span style="color:#f92672">::</span>rint);
</span></span><span style="display:flex;"><span>    INTRINSIC_VISIT(Intrinsic<span style="color:#f92672">::</span>nearbyint);
</span></span><span style="display:flex;"><span>    INTRINSIC_VISIT(Intrinsic<span style="color:#f92672">::</span>round);
</span></span><span style="display:flex;"><span><span style="color:#75715e">#undef INTRINSIC_VISIT
</span></span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This just lets me have all the intrinsics above inhabit their own function which makes debugging much easier (at least for me). Note - I use this pattern pseudo-regularly in C++ and I always recommend that you do not provide a default implementation of <code>visitIntrinsic</code>. Doing this means you&rsquo;ll get a linker error if you forget to explicitly add the visit method for that intrinsic.</p>
<h2 id="square-root">Square Root</h2>
<p>For the sqrt intrinsic the main thing we can do is with negative inputs. A negative input to a sqrt always results in a NaN.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">template</span> <span style="color:#f92672">&lt;&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> FPInstSimplifyPass<span style="color:#f92672">::</span>visitIntrinsic<span style="color:#f92672">&lt;</span>Intrinsic<span style="color:#f92672">::</span>sqrt<span style="color:#f92672">&gt;</span>(
</span></span><span style="display:flex;"><span>    IntrinsicInst <span style="color:#f92672">&amp;</span>inst) {
</span></span><span style="display:flex;"><span>  FastMathFlags fmf <span style="color:#f92672">=</span> inst.getFastMathFlags();
</span></span><span style="display:flex;"><span>  Value <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> x <span style="color:#f92672">=</span> inst.getOperand(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FPSCEV xFpscev <span style="color:#f92672">=</span> fpse<span style="color:#f92672">-&gt;</span>getFPSCEV(x)<span style="color:#f92672">-&gt;</span>cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// If the input is all negative, the result is NaN.
</span></span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (xFpscev.isAllNegative()) {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// If the instruction cannot return NaNs, replace it with undef.
</span></span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (inst.hasNoNaNs()) {
</span></span><span style="display:flex;"><span>      inst.replaceAllUsesWith(UndefValue<span style="color:#f92672">::</span>get(inst.getType()));
</span></span><span style="display:flex;"><span>    } <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>      inst.replaceAllUsesWith(ConstantFP<span style="color:#f92672">::</span>getNaN(inst.getType()));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    toRemoves.push_back(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>So the code above gets the fpscev for the input, checks if all the values of it are negative, and then removes the sqrt entirely if so.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">sqrt_all_negative</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.copysign.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#66d9ef">float</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1.0</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.sqrt.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f3
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In the above example we can see that the input to sqrt is always negative, and so my optimization will turn the code into:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">sqrt_all_negative</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.copysign.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#66d9ef">float</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">1.000000e+00</span>)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#ae81ff">0x7FF8000000000000</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>EG. always returning a NaN.</p>
<p>There is another case we have to be wary of - what if the sqrt intrinsic has a no-NaNs fast-math flag specified?</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">sqrt_all_negative_nnan</span>(i4 <span style="color:#f92672">%</span>i) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> fneg <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call nnan <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.sqrt.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f3
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In this case - the user has specifically said that sqrt <em>cannot</em> produce a NaN, but we know 100% that a NaN is being produced. This is called a <a href="https://www.llvm.org/docs/LangRef.html#poison-values">poison value</a> in LLVM. LLVM does not have a way to specifically create a poison value, so in the above case I replace the sqrt with an undef instead:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">sqrt_all_negative_nnan</span>(i4 <span style="color:#f92672">%</span>i) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> fneg <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> undef
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="x-to-the-power-of-y">X to the Power of Y</h2>
<p>The pow intrinsic is something that I couldn&rsquo;t get a great handle on its range for fpscev due to the complexity of the function. One thing I can do though is deduce the range of Y - the value we are promoting X to the power of. LLVM has a companion intrinsic powi - X to the power of integer Y. I&rsquo;ve implemented the pow/powi functions for OpenCL-level ulp requirements in a past life, and I know one of the complications of pow is that if you have a fractional component to the value you are raising to the power of, this increases the complexity of the calculation. Knowning that the power you are raising to is entirely integer (as is the case with powi) lets math library writers do some fun optimizations (I vaguely recall having at least 20% faster calls to powi versus pow when I worked on this many years ago!).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">template</span> <span style="color:#f92672">&lt;&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> FPInstSimplifyPass<span style="color:#f92672">::</span>visitIntrinsic<span style="color:#f92672">&lt;</span>Intrinsic<span style="color:#f92672">::</span>pow<span style="color:#f92672">&gt;</span>(
</span></span><span style="display:flex;"><span>    IntrinsicInst <span style="color:#f92672">&amp;</span>inst) {
</span></span><span style="display:flex;"><span>  FastMathFlags fmf <span style="color:#f92672">=</span> inst.getFastMathFlags();
</span></span><span style="display:flex;"><span>  Value <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> x <span style="color:#f92672">=</span> inst.getOperand(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>  Value <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> y <span style="color:#f92672">=</span> inst.getOperand(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FPSCEV xFpscev <span style="color:#f92672">=</span> fpse<span style="color:#f92672">-&gt;</span>getFPSCEV(x)<span style="color:#f92672">-&gt;</span>cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FPSCEV yFpscev <span style="color:#f92672">=</span> fpse<span style="color:#f92672">-&gt;</span>getFPSCEV(y)<span style="color:#f92672">-&gt;</span>cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// If y is an integer
</span></span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (yFpscev.isInteger) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> fltSemantics <span style="color:#f92672">&amp;</span>semantics <span style="color:#f92672">=</span> xFpscev.min.getSemantics();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// 2^24 is the last integer number that we can fully represent in both
</span></span></span><span style="display:flex;"><span>    <span style="color:#75715e">// floating-point and i32.
</span></span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> APInt <span style="color:#a6e22e">minInt</span>(<span style="color:#ae81ff">32</span>, <span style="color:#f92672">-</span>(<span style="color:#ae81ff">1</span> <span style="color:#f92672">&lt;&lt;</span> <span style="color:#ae81ff">24</span>), true);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> APInt <span style="color:#a6e22e">maxInt</span>(<span style="color:#ae81ff">32</span>, <span style="color:#ae81ff">1</span> <span style="color:#f92672">&lt;&lt;</span> <span style="color:#ae81ff">24</span>, true);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// If y is between min/max int, we can use powi instead of pow!
</span></span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (yFpscev.isGreaterThanEqual(getFromInt(semantics, minInt, true)) <span style="color:#f92672">&amp;&amp;</span>
</span></span><span style="display:flex;"><span>        yFpscev.isLessThanEqual(getFromInt(semantics, maxInt, true))) {
</span></span><span style="display:flex;"><span>      IRBuilder<span style="color:#f92672">&lt;&gt;</span> irb(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>      StringRef <span style="color:#a6e22e">yName</span>(y<span style="color:#f92672">-&gt;</span>getName());
</span></span><span style="display:flex;"><span>      Twine <span style="color:#a6e22e">name</span>(yName, <span style="color:#e6db74">&#34;.i32cast&#34;</span>);
</span></span><span style="display:flex;"><span>      Value <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> yCast <span style="color:#f92672">=</span> irb.CreateFPToSI(y, irb.getInt32Ty(), name);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      Instruction <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> powi <span style="color:#f92672">=</span> irb.CreateIntrinsic(
</span></span><span style="display:flex;"><span>          Intrinsic<span style="color:#f92672">::</span>powi, inst.getType(), {x, yCast}, <span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>      powi<span style="color:#f92672">-&gt;</span>takeName(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      <span style="color:#75715e">// Copy the fpscev information from the original instruction onto the new.
</span></span></span><span style="display:flex;"><span>      fpse<span style="color:#f92672">-&gt;</span>copyFPSCEVFromValue(powi, <span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      inst.replaceAllUsesWith(powi);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      toRemoves.push_back(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The two conditions we need to pass if we can convert pow to powi is that Y <strong>must</strong> be an integer-hiding in a floating-point (which fpscev tracks), and that this integer <strong>must</strong> be less than 2^24. 2^24 is an interesting value because it just so happens to be the last integer value that can be represented without conversion loss in a 32-bit floating-point.</p>
<p>Once these two conditions are met, we can convert Y to a signed integer, and then call the powi intrinsic instead.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">pow</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, i25 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> sitofp i25 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.pow.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f3
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The above becomes:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">pow</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, i25 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> sitofp i25 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2.i32cast <span style="color:#f92672">=</span> fptosi <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2 to i32
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.powi.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, i32 <span style="color:#f92672">%</span>f2.i32cast)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f3
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>After this optimization is applied.</p>
<h2 id="floating-point-absolute-value">Floating-Point Absolute Value</h2>
<p>Abosolute value can be simplified if the value it was performing the absolute of was already positive.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">template</span> <span style="color:#f92672">&lt;&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> FPInstSimplifyPass<span style="color:#f92672">::</span>visitIntrinsic<span style="color:#f92672">&lt;</span>Intrinsic<span style="color:#f92672">::</span>fabs<span style="color:#f92672">&gt;</span>(
</span></span><span style="display:flex;"><span>    IntrinsicInst <span style="color:#f92672">&amp;</span>inst) {
</span></span><span style="display:flex;"><span>  FastMathFlags fmf <span style="color:#f92672">=</span> inst.getFastMathFlags();
</span></span><span style="display:flex;"><span>  Value <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> x <span style="color:#f92672">=</span> inst.getOperand(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FPSCEV xFpscev <span style="color:#f92672">=</span> fpse<span style="color:#f92672">-&gt;</span>getFPSCEV(x)<span style="color:#f92672">-&gt;</span>cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// If the input is all not negative, we can just use the input.
</span></span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (xFpscev.isAllNonNegative()) {
</span></span><span style="display:flex;"><span>    inst.replaceAllUsesWith(x);
</span></span><span style="display:flex;"><span>    toRemoves.push_back(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>We just check if the input x was all not negative, and if so replace the fabs intrinsic with the value being fed to fabs. This means the following example:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">fabs_already_positive</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.copysign.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#66d9ef">float</span> <span style="color:#ae81ff">1.0</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.fabs.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f3
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Can be folded to:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">fabs_already_positive</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.copysign.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#66d9ef">float</span> <span style="color:#ae81ff">1.0</span>)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="minimums-and-maximums">Minimum&rsquo;s and Maximum&rsquo;s</h2>
<p>For both minnum/maxnum/minimum/maximum I perform a similar optimization - so I&rsquo;ll just look at maxnum here for the sake of brevity.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">template</span> <span style="color:#f92672">&lt;&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> FPInstSimplifyPass<span style="color:#f92672">::</span>visitIntrinsic<span style="color:#f92672">&lt;</span>Intrinsic<span style="color:#f92672">::</span>maxnum<span style="color:#f92672">&gt;</span>(
</span></span><span style="display:flex;"><span>    IntrinsicInst <span style="color:#f92672">&amp;</span>inst) {
</span></span><span style="display:flex;"><span>  FastMathFlags fmf <span style="color:#f92672">=</span> inst.getFastMathFlags();
</span></span><span style="display:flex;"><span>  Value <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> x <span style="color:#f92672">=</span> inst.getOperand(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>  Value <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> y <span style="color:#f92672">=</span> inst.getOperand(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FPSCEV xFpscev <span style="color:#f92672">=</span> fpse<span style="color:#f92672">-&gt;</span>getFPSCEV(x)<span style="color:#f92672">-&gt;</span>cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FPSCEV yFpscev <span style="color:#f92672">=</span> fpse<span style="color:#f92672">-&gt;</span>getFPSCEV(y)<span style="color:#f92672">-&gt;</span>cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// If one of the inputs is always less than the other, we fold away the
</span></span></span><span style="display:flex;"><span>  <span style="color:#75715e">// intrinsic.
</span></span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (xFpscev.isGreaterThanEqual(yFpscev)) {
</span></span><span style="display:flex;"><span>    inst.replaceAllUsesWith(x);
</span></span><span style="display:flex;"><span>    toRemoves.push_back(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>  } <span style="color:#66d9ef">else</span> <span style="color:#a6e22e">if</span> (yFpscev.isGreaterThanEqual(xFpscev)) {
</span></span><span style="display:flex;"><span>    inst.replaceAllUsesWith(y);
</span></span><span style="display:flex;"><span>    toRemoves.push_back(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>For maxnum, if we know that either of the inputs are always greater than or equal to the other value (assuming that neither of them are NaNs), we can replace the call to maxnum with the input that is guaranteed to dominate the other.</p>
<p>This means that the following code:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">maxnum_x</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fadd <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2, <span style="color:#ae81ff">16.0</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f4 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.maxnum.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f3, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f4
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Is folded to:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">maxnum_x</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fadd <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2, <span style="color:#ae81ff">1.600000e+01</span>
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f3
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Removing the call to maxnum entirely! This same optimization technique is applied to all four of the min/max intrinsics as I previously stated.</p>
<h2 id="copy-sign">Copy Sign</h2>
<p>The intrinsic copysign has a few interesting optimization avenues.</p>
<ul>
<li>If the input and the output have the same sign, then the intrinsic is a no-op.</li>
<li>If the input and output always have opposite signs, then we are really just negating the input X.</li>
<li>If the input Y whom we are copying the sign from is always positive, then we are really just calling fabs on the input X.</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">template</span> <span style="color:#f92672">&lt;&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> FPInstSimplifyPass<span style="color:#f92672">::</span>visitIntrinsic<span style="color:#f92672">&lt;</span>Intrinsic<span style="color:#f92672">::</span>copysign<span style="color:#f92672">&gt;</span>(
</span></span><span style="display:flex;"><span>    IntrinsicInst <span style="color:#f92672">&amp;</span>inst) {
</span></span><span style="display:flex;"><span>  FastMathFlags fmf <span style="color:#f92672">=</span> inst.getFastMathFlags();
</span></span><span style="display:flex;"><span>  Value <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> x <span style="color:#f92672">=</span> inst.getOperand(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>  Value <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> y <span style="color:#f92672">=</span> inst.getOperand(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FPSCEV xFpscev <span style="color:#f92672">=</span> fpse<span style="color:#f92672">-&gt;</span>getFPSCEV(x)<span style="color:#f92672">-&gt;</span>cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FPSCEV yFpscev <span style="color:#f92672">=</span> fpse<span style="color:#f92672">-&gt;</span>getFPSCEV(y)<span style="color:#f92672">-&gt;</span>cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> ((xFpscev.isAllNonNegative() <span style="color:#f92672">&amp;&amp;</span> yFpscev.isAllNonNegative()) <span style="color:#f92672">||</span>
</span></span><span style="display:flex;"><span>      (xFpscev.isAllNegative() <span style="color:#f92672">&amp;&amp;</span> yFpscev.isAllNegative())) {
</span></span><span style="display:flex;"><span>    inst.replaceAllUsesWith(x);
</span></span><span style="display:flex;"><span>    toRemoves.push_back(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>  } <span style="color:#66d9ef">else</span> <span style="color:#a6e22e">if</span> ((xFpscev.isAllNonNegative() <span style="color:#f92672">&amp;&amp;</span> yFpscev.isAllNegative()) <span style="color:#f92672">||</span>
</span></span><span style="display:flex;"><span>             (xFpscev.isAllNegative() <span style="color:#f92672">&amp;&amp;</span> yFpscev.isAllNonNegative())) {
</span></span><span style="display:flex;"><span>    IRBuilder<span style="color:#f92672">&lt;&gt;</span> irb(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>    Value <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> value <span style="color:#f92672">=</span> irb.CreateFNeg(x);
</span></span><span style="display:flex;"><span>    value<span style="color:#f92672">-&gt;</span>takeName(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Copy the fpscev information from the original instruction onto the new.
</span></span></span><span style="display:flex;"><span>    fpse<span style="color:#f92672">-&gt;</span>copyFPSCEVFromValue(value, <span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (Instruction <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> otherInst <span style="color:#f92672">=</span> dyn_cast<span style="color:#f92672">&lt;</span>Instruction<span style="color:#f92672">&gt;</span>(value)) {
</span></span><span style="display:flex;"><span>      otherInst<span style="color:#f92672">-&gt;</span>setFastMathFlags(inst.getFastMathFlags());
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    inst.replaceAllUsesWith(value);
</span></span><span style="display:flex;"><span>    toRemoves.push_back(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>  } <span style="color:#66d9ef">else</span> <span style="color:#a6e22e">if</span> (yFpscev.isAllNonNegative()) {
</span></span><span style="display:flex;"><span>    IRBuilder<span style="color:#f92672">&lt;&gt;</span> irb(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>    Instruction <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> fabs <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>        irb.CreateUnaryIntrinsic(Intrinsic<span style="color:#f92672">::</span>fabs, x, <span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>    fabs<span style="color:#f92672">-&gt;</span>takeName(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Copy the fpscev information from the original instruction onto the new.
</span></span></span><span style="display:flex;"><span>    fpse<span style="color:#f92672">-&gt;</span>copyFPSCEVFromValue(fabs, <span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>    inst.replaceAllUsesWith(fabs);
</span></span><span style="display:flex;"><span>    toRemoves.push_back(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Above we can see the three cases of optimizations we can apply - which matches to five variants of copysign we could see in the wild. The following example has all five of these cases:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">copysign_both_positive</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.copysign.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f3
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">copysign_both_negative</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fneg <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f4 <span style="color:#f92672">=</span> fneg <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f5 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.copysign.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f3, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f4)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f5
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">copysign_both_opposite_0</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fneg <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f4 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.copysign.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f3)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f4
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">copysign_both_opposite_1</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fneg <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f4 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.copysign.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f3, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f4
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">copysign_y_positive</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, i4 <span style="color:#f92672">%</span>i) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.copysign.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f3
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And after my optimization is applied:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">copysign_both_positive</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">copysign_both_negative</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fneg <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f4 <span style="color:#f92672">=</span> fneg <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f3
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">copysign_both_opposite_0</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fneg <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f4 <span style="color:#f92672">=</span> fsub <span style="color:#66d9ef">float</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">0.000000e+00</span>, <span style="color:#f92672">%</span>f2
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f4
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">copysign_both_opposite_1</span>(i4 <span style="color:#f92672">%</span>i, i4 <span style="color:#f92672">%</span>i2) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i2 to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fneg <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f4 <span style="color:#f92672">=</span> fsub <span style="color:#66d9ef">float</span> <span style="color:#f92672">-</span><span style="color:#ae81ff">0.000000e+00</span>, <span style="color:#f92672">%</span>f3
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f4
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">copysign_y_positive</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, i4 <span style="color:#f92672">%</span>i) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.fabs.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f3
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Note: I don&rsquo;t <em>really understand</em> why LLVM has produced fsub from -0 instead of fneg when I used the IRBuilder here - but it should effectively be the same thing.</p>
<h2 id="floating-point-rounding">Floating-Point Rounding</h2>
<p>The rounding intrinsics floor/ceil/trunc/rint/nearbyint/round can all be folded to their input if the input is already an integer (because if the input is a whole number, rounding will do nothing). Since the optimization for each intrinsic is the same, lets just look at round:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span><span style="color:#66d9ef">template</span> <span style="color:#f92672">&lt;&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">void</span> FPInstSimplifyPass<span style="color:#f92672">::</span>visitIntrinsic<span style="color:#f92672">&lt;</span>Intrinsic<span style="color:#f92672">::</span>round<span style="color:#f92672">&gt;</span>(
</span></span><span style="display:flex;"><span>    IntrinsicInst <span style="color:#f92672">&amp;</span>inst) {
</span></span><span style="display:flex;"><span>  FastMathFlags fmf <span style="color:#f92672">=</span> inst.getFastMathFlags();
</span></span><span style="display:flex;"><span>  Value <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> x <span style="color:#f92672">=</span> inst.getOperand(<span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FPSCEV xFpscev <span style="color:#f92672">=</span> fpse<span style="color:#f92672">-&gt;</span>getFPSCEV(x)<span style="color:#f92672">-&gt;</span>cloneWithFastMathFlags(fmf);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// If the input is already an integer, floor is a no-op.
</span></span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (xFpscev.isInteger) {
</span></span><span style="display:flex;"><span>    inst.replaceAllUsesWith(x);
</span></span><span style="display:flex;"><span>    toRemoves.push_back(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The code is simple - if the input is an integer, replace the intrinsic with the input. This will fold code like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">round_already_integer</span>(i4 <span style="color:#f92672">%</span>i) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.round.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>To:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">round_already_integer</span>(i4 <span style="color:#f92672">%</span>i) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i4 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Note these are optimizations that LLVM will do in very simple cases anyway (like the above example) - but LLVM will fall apart once you start to hit more complex variants. As I&rsquo;ve said before - removing these piecemeal optimizations in LLVM and unifying them around the more correct fpscev analysis seems like a better approach for the long term.</p>
<h1 id="conclusion">Conclusion</h1>
<p>With this pass we&rsquo;ve started to really get into the fun with fpscev - instruction simplification. Being able to fold away complex code for more simpler variants is what I got into the compiler business for in the first place, and with fpscev we have a great extra tool to do that.</p>
<p>In the next post I&rsquo;ll look at refining the range of some of the more complex fpscev intrinsics by using some advice from the rather fantastic <a href="https://twitter.com/marc_b_reynolds/status/1137820453777657858">Marc B. Reynolds</a> to reduce the calculated ranges. Look forward to seeing you there!</p>
]]></description>
    </item>
    
    <item>
      <title>Using Floating-Point Scalar Evolution to Propagate Fast-Math Flags</title>
      <link>https://www.neilhenning.dev/posts/fpscev-fast-math-propagation/</link>
      <pubDate>Wed, 12 Jun 2019 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/fpscev-fast-math-propagation/</guid>
      <description><![CDATA[<p>As a follow-up to my post <a href="https://www.neilhenning.dev/posts/fpscev/">An Experimental Floating-Point Scalar Evolution</a>, I&rsquo;ve started looking into using my previous analysis to actually change the LLVM IR for the better.</p>
<p>The LLVM optimization pass discussed in this post is available <a href="https://github.com/sheredom/fpscev/commit/514fd8e77b2f848fe08057385c6e26a49c09b6f8">on github here</a>.</p>
<h1 id="fast-math-flags">Fast-Math Flags</h1>
<p>LLVM has a way of encoding the <a href="https://www.llvm.org/docs/LangRef.html#fast-math-flags">fast-math flags</a> on various floating-point operations. These flags let the compiler assume something about the operation, which generally allows more performance.</p>
<p>Of these flags, there are two that can use my previous floating-point scalar evolution (fpscev) analysis to propagate through other instructions - no-NaNs and no-inifinites.</p>
<p>This can change the assembly that gets spit out of the compiler in noticable ways - being able to assume that you won&rsquo;t ever see a NaN or an infinity means more optimal paths could be taken. For instance, let us look at the difference between some fcmp&rsquo;s, with and without the fast-math flags.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>; Normal <span style="color:#a6e22e">fcmp</span> (as would be generated by a C<span style="color:#f92672">/</span>C<span style="color:#f92672">++</span> a <span style="color:#f92672">&lt;</span> b check)
</span></span><span style="display:flex;"><span>define i1 <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">a</span>(<span style="color:#66d9ef">float</span>, <span style="color:#66d9ef">float</span>)  {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span><span style="color:#ae81ff">3</span> <span style="color:#f92672">=</span> fcmp olt <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span><span style="color:#ae81ff">0</span>, <span style="color:#f92672">%</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>  ret i1 <span style="color:#f92672">%</span><span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>; Same fcmp as above but with fast<span style="color:#f92672">-</span>math flags
</span></span><span style="display:flex;"><span>define i1 <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">b</span>(<span style="color:#66d9ef">float</span>, <span style="color:#66d9ef">float</span>)  {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span><span style="color:#ae81ff">3</span> <span style="color:#f92672">=</span> fcmp nnan ninf olt <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span><span style="color:#ae81ff">0</span>, <span style="color:#f92672">%</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>  ret i1 <span style="color:#f92672">%</span><span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>; The equivalent unordered less than check <span style="color:#66d9ef">for</span> comparison
</span></span><span style="display:flex;"><span>define i1 <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">c</span>(<span style="color:#66d9ef">float</span>, <span style="color:#66d9ef">float</span>)  {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span><span style="color:#ae81ff">3</span> <span style="color:#f92672">=</span> fcmp ult <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span><span style="color:#ae81ff">0</span>, <span style="color:#f92672">%</span><span style="color:#ae81ff">1</span>
</span></span><span style="display:flex;"><span>  ret i1 <span style="color:#f92672">%</span><span style="color:#ae81ff">3</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>If the above is compiled for a generic aarch64 target (64-bit ARM), I get:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>a:                                      <span style="color:#75715e">// @a
</span></span></span><span style="display:flex;"><span>        fcmp    s0, s1
</span></span><span style="display:flex;"><span>        cset    w0, mi
</span></span><span style="display:flex;"><span>        ret
</span></span><span style="display:flex;"><span>b:                                      <span style="color:#75715e">// @b
</span></span></span><span style="display:flex;"><span>        fcmp    s0, s1
</span></span><span style="display:flex;"><span>        cset    w0, lt
</span></span><span style="display:flex;"><span>        ret
</span></span><span style="display:flex;"><span>c:                                      <span style="color:#75715e">// @c
</span></span></span><span style="display:flex;"><span>        fcmp    s0, s1
</span></span><span style="display:flex;"><span>        cset    w0, lt
</span></span><span style="display:flex;"><span>        ret
</span></span></code></pre></div><p>And as can be seen the code for b &amp; c is identical, but a is different. The compiler is generating the same code for an unordered less than compare as it would for an ordered less than compare with the fast-math flags we specified.</p>
<p><em>One sidenote here: even if there was zero impact to codegen currently I still follow a firm philosophy that the more information you can give a compiler the better the results will be over time. I run into this issue a ton during my day job as a compiler engineer where frontends won&rsquo;t encode all the information they know about because &rsquo;the compiler did not do anything with it anyway so who cares&rsquo;. What happens in the end is a chicken and egg problem - the frontends won&rsquo;t give the information because nothing is done with it, and the middle/backends do not optimize in the presence of information because the frontends don&rsquo;t generate it&hellip; So more information is <strong>always</strong> a good idea in my book.</em></p>
<h1 id="overview-of-the-pass">Overview of the Pass</h1>
<p>The new pass I&rsquo;ve added is <code>FastMathPropagationPass</code> (see <a href="https://github.com/sheredom/fpscev/blob/master/fpscev.cpp#L1384">https://github.com/sheredom/fpscev/blob/master/fpscev.cpp#L1384</a>) - it runs over a function using an <code>InstVisitor</code>, and uses the fpscev analysis to propagate nnan and ninf if the inputs &amp; outputs of certain operations could not contain NaNs or infinities.</p>
<p>There are only a few instructions that we can propagate fast-math flags through, so lets run through them all in turn.</p>
<h2 id="floating-point-comparison">Floating-Point Comparison</h2>
<p>Like in the example above - the first obvious case for fast-math propagation is in floating-point comparison. We&rsquo;ve already seen a difference in codegen when these flags are specified, so greater minds than myself have already thought about the optimal mapping of these instructions in the various backends (I say hopefully!).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>b <span style="color:#f92672">=</span> fcmp olt <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f2
</span></span></code></pre></div><p>For the above fcmp statement - if <code>%f</code> and <code>%f2</code> are both definitely not a NaN when I evaluate their range, I can set the nnan flag. If they are both not infinity, I can set the ninf flag.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>b <span style="color:#f92672">=</span> fcmp nnan olt <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f2
</span></span></code></pre></div><h2 id="floating-point-negation">Floating-Point Negation</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> fneg <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f
</span></span></code></pre></div><p>For negation - I can propagate if <code>%f</code> was nnan or ninf onto the fneg itself.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> fneg nnan ninf <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f
</span></span></code></pre></div><h2 id="floating-point-binary-operators">Floating-Point Binary Operators</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fadd <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f2
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f4 <span style="color:#f92672">=</span> fsub <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f2
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f5 <span style="color:#f92672">=</span> fmul <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f2
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f6 <span style="color:#f92672">=</span> fdiv <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#ae81ff">4.000000e+08</span>
</span></span></code></pre></div><p>For the binary-operators fadd, fsub, fmul, and fdiv, to save me from putting in logic in the pass to re-understand the intricacies of the operation itself, I simply look at the fpscev for the input operands <em>and</em> the fpscev of the instruction itself. If each of the inputs <em>and</em> the instruction are not NaN or not infinity, we can set the nnan/ninf flags.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">visitBinaryOperator</span>(BinaryOperator <span style="color:#f92672">&amp;</span>inst) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">switch</span> (inst.<span style="color:#a6e22e">getOpcode</span>()) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">default</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span>;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">case</span> Instruction<span style="color:#f92672">::</span>FAdd:
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">case</span> Instruction<span style="color:#f92672">::</span>FSub:
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">case</span> Instruction<span style="color:#f92672">::</span>FMul:
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">case</span> Instruction<span style="color:#f92672">::</span>FDiv:
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">case</span> Instruction<span style="color:#f92672">::</span>FRem:
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">break</span>;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FPSCEV <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> xFpscev <span style="color:#f92672">=</span> fpse<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">getFPSCEV</span>(inst.<span style="color:#a6e22e">getOperand</span>(<span style="color:#ae81ff">0</span>));
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FPSCEV <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> yFpscev <span style="color:#f92672">=</span> fpse<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">getFPSCEV</span>(inst.<span style="color:#a6e22e">getOperand</span>(<span style="color:#ae81ff">1</span>));
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FPSCEV <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> fpscev <span style="color:#f92672">=</span> fpse<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">getFPSCEV</span>(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (fpscev<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">isFinite</span>() <span style="color:#f92672">&amp;&amp;</span> xFpscev<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">isFinite</span>() <span style="color:#f92672">&amp;&amp;</span> yFpscev<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">isFinite</span>()) {
</span></span><span style="display:flex;"><span>    inst.<span style="color:#a6e22e">setHasNoInfs</span>(true);
</span></span><span style="display:flex;"><span>    modified <span style="color:#f92672">=</span> true;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span>fpscev<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">isNaN</span>() <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">!</span>xFpscev<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">isNaN</span>() <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">!</span>yFpscev<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">isNaN</span>()) {
</span></span><span style="display:flex;"><span>    inst.<span style="color:#a6e22e">setHasNoNaNs</span>(true);
</span></span><span style="display:flex;"><span>    modified <span style="color:#f92672">=</span> true;
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>This lets us optimize the above operations if the fpscev has a smaller range.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fadd nnan ninf <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f2
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f4 <span style="color:#f92672">=</span> fsub nnan ninf <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f2
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f5 <span style="color:#f92672">=</span> fmul nnan ninf <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f2
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f6 <span style="color:#f92672">=</span> fdiv nnan ninf <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#ae81ff">4.000000e+08</span>
</span></span></code></pre></div><h2 id="floating-point-intrinsics">Floating-Point Intrinsics</h2>
<p>For all the floating-point intrinsics that can take fast-math flags, I follow a similar approach to how I handle binary operators.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">void</span> <span style="color:#a6e22e">visitIntrinsicInst</span>(IntrinsicInst <span style="color:#f92672">&amp;</span>inst) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">bool</span> atLeastOneFP <span style="color:#f92672">=</span> false;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">bool</span> allFinite <span style="color:#f92672">=</span> true;
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">bool</span> allNotNaN <span style="color:#f92672">=</span> true;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">for</span> (Value <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> arg : inst.<span style="color:#a6e22e">args</span>()) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> FPSCEV <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> fpscev <span style="color:#f92672">=</span> fpse<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">getFPSCEV</span>(arg);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (fpscev) {
</span></span><span style="display:flex;"><span>      atLeastOneFP <span style="color:#f92672">=</span> true;
</span></span><span style="display:flex;"><span>      allFinite <span style="color:#f92672">=</span> allFinite <span style="color:#f92672">&amp;&amp;</span> fpscev<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">isFinite</span>();
</span></span><span style="display:flex;"><span>      allNotNaN <span style="color:#f92672">=</span> allNotNaN <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">!</span>fpscev<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">isNaN</span>();
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> FPSCEV <span style="color:#f92672">*</span><span style="color:#66d9ef">const</span> fpscev <span style="color:#f92672">=</span> fpse<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">getFPSCEV</span>(<span style="color:#f92672">&amp;</span>inst);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (fpscev) {
</span></span><span style="display:flex;"><span>    atLeastOneFP <span style="color:#f92672">=</span> true;
</span></span><span style="display:flex;"><span>    allFinite <span style="color:#f92672">=</span> allFinite <span style="color:#f92672">&amp;&amp;</span> fpscev<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">isFinite</span>();
</span></span><span style="display:flex;"><span>    allNotNaN <span style="color:#f92672">=</span> allNotNaN <span style="color:#f92672">&amp;&amp;</span> <span style="color:#f92672">!</span>fpscev<span style="color:#f92672">-&gt;</span><span style="color:#a6e22e">isNaN</span>();
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> (atLeastOneFP) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (allFinite) {
</span></span><span style="display:flex;"><span>      inst.<span style="color:#a6e22e">setHasNoInfs</span>(true);
</span></span><span style="display:flex;"><span>      modified <span style="color:#f92672">=</span> true;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (allNotNaN) {
</span></span><span style="display:flex;"><span>      inst.<span style="color:#a6e22e">setHasNoNaNs</span>(true);
</span></span><span style="display:flex;"><span>      modified <span style="color:#f92672">=</span> true;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Basically loop over all the arguments to the intrinsic, if any have a fpscev (which all floating-point values should already have), and then record if the argument could be a NaN or infinity. Then do the same for the <em>result</em> fpscev to make sure the result conforms too.</p>
<p>Then, if I have seen at least one floating-point argument or result, <em>and</em> they are not NaN or infinity, I can set the fast-math flags.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call nnan ninf <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.fma.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2, <span style="color:#66d9ef">float</span> <span style="color:#ae81ff">4.000000e+00</span>)
</span></span></code></pre></div><p>This lets us handle all the floating-point intrinsics I had previously identified correctly and propagate the fast-math flags onto them.</p>
<h1 id="conclusion">Conclusion</h1>
<p>So now I&rsquo;ve got a pass that uses my fpscev analysis to change the IR - hopefully for the better!</p>
<p>One place where this kind of propagation could be super useful is when inlining has taken place. Lets assume I have a function:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">called_func</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>x, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>y)  {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> fmul <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>x, <span style="color:#f92672">%</span>y
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> fadd <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#ae81ff">1.0</span>
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">func</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>x, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>y)  {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> call nnan ninf <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">called_func</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>x, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>y)
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And lets look at the function after inlining:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">func</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>x, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>y) {
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f.i <span style="color:#f92672">=</span> fmul <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>x, <span style="color:#f92672">%</span>y
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2.i <span style="color:#f92672">=</span> fadd <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f.i, <span style="color:#ae81ff">1.000000e+00</span>
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2.i
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>You can see that the nnan and ninf flags on the original call are lost after inlining - <code>%x</code> and <code>%y</code> were not NaN and not infinity, so the fmul and fadd could have the nnan/ninf flags on them. We could make an inliner change that would use my fpscev pass to propagate the information even after inlining has taken place - which could be super powerful!</p>
<p>In the next post I&rsquo;ll look at the next of my optimization ideas - instruction simplification using the fpscev ranges. Stay tuned for some really cool optimizations investigations to come.</p>
]]></description>
    </item>
    
    <item>
      <title>An Experimental Floating-Point Scalar Evolution</title>
      <link>https://www.neilhenning.dev/posts/fpscev/</link>
      <pubDate>Sun, 09 Jun 2019 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/fpscev/</guid>
      <description><![CDATA[<p>The TL;DR - after a conversation at EuroLLVM with <a href="https://twitter.com/stephentyrone">Steve Canon</a> about how LLVM is missing scalar evolution analysis for floating-point, I&rsquo;ve spent some spare time hacking on a new LLVM analysis pass - fpscev (Floating-Point SCalar EVolution) - available <a href="https://github.com/sheredom/fpscev">here at github</a>. The pass will analyze floating-point operations in a function and work out if there are any constraints on the range of these values, information which can be used to better optimize code.</p>
<h1 id="what-is-scalar-evolution">What is Scalar Evolution?</h1>
<p>Scalar evolution lets a compiler understand the scope of a value throughout a
program. The classic place that scalar evolution is used in compiler
optimizations is with respect to loop index variables to let a compiler infer
the number of loop iterations that a loop will perform.</p>
<p>Scalar evolution can also be used to fold branches away. Imagine you have code
like:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (i <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">4</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// Do a million lines of awful code that will bloat you executable!
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And lets say that via scalar evolution we know that <code>i</code> could <em>never</em> be less
than 4. That allows the compiler to remove the entire if branch as it will never
be hit!</p>
<h1 id="why-floating-point-scalar-evolution">Why Floating-Point Scalar Evolution?</h1>
<p>Many floating-point algorithms can be vastly improved if we know the scope of
the inputs to math functions are. Lots of high performance code that game
developers throw through compiler stacks will use many operations that could
benefit from knowing a little more about the value of the float.</p>
<p>A great use of this would be something like the following:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">float</span> f <span style="color:#f92672">=</span> ...; <span style="color:#75715e">// definitely not NaN or Infinity
</span></span></span><span style="display:flex;"><span>f <span style="color:#f92672">=</span> <span style="color:#a6e22e">sin</span>(f); <span style="color:#75715e">// because f wasn&#39;t NaN or Infinity f is now in the range [-1..1]
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span><span style="color:#a6e22e">isfinite</span>(f)) {
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">// Do a million lines of awful code that will bloat you executable!
</span></span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>In the example above that if check should always return false - but the compiler
doesn&rsquo;t have enough information to know that.</p>
<p>If we look at the latest (as of the time of writing) version of LLVM from trunk
SVN (9.0.0svn) and how it handles the above:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>define <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">func</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span><span style="color:#ae81ff">0</span>) {
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">1</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span><span style="color:#ae81ff">2</span> <span style="color:#f92672">=</span> tail call nnan ninf <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.sin.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span><span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span><span style="color:#ae81ff">3</span> <span style="color:#f92672">=</span> tail call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.fabs.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span><span style="color:#ae81ff">2</span>)
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span><span style="color:#ae81ff">4</span> <span style="color:#f92672">=</span> fcmp ueq <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span><span style="color:#ae81ff">3</span>, <span style="color:#ae81ff">0x7FF0000000000000</span>
</span></span><span style="display:flex;"><span>  br i1 <span style="color:#f92672">%</span><span style="color:#ae81ff">4</span>, label <span style="color:#f92672">%</span><span style="color:#ae81ff">5</span>, label <span style="color:#f92672">%</span><span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">5</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span><span style="color:#ae81ff">6</span> <span style="color:#f92672">=</span> ... ; <span style="color:#66d9ef">do</span> something complicated
</span></span><span style="display:flex;"><span>  br label <span style="color:#f92672">%</span><span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ae81ff">7</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span><span style="color:#ae81ff">8</span> <span style="color:#f92672">=</span> phi <span style="color:#66d9ef">float</span> [ <span style="color:#f92672">%</span><span style="color:#ae81ff">2</span>, <span style="color:#f92672">%</span><span style="color:#ae81ff">1</span> ], [ <span style="color:#f92672">%</span><span style="color:#ae81ff">6</span>, <span style="color:#f92672">%</span><span style="color:#ae81ff">5</span> ]
</span></span><span style="display:flex;"><span>  ret <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span><span style="color:#ae81ff">8</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Even with the additional <em>fast-math</em> flags &rsquo;nnan&rsquo; (no NaNs) and &rsquo;ninf&rsquo; (no
Infinity) on the call stored into <code>%2</code> - the compiler cannot deduce that the
branch in <code>%4</code> is redundant.</p>
<p>This is all because LLVM&rsquo;s scalar evolution only cares about <em>integers</em>. This
generally makes sense - scalar evolution came about because of loops, and loops
have integer indices (for the most part&hellip;). What if we extended some similar
techniques as found in scalar evolution to floating-point - what optimization
opportunites we could open up?</p>
<h1 id="the-approach">The Approach</h1>
<p>The overall approach that I&rsquo;ve taken is to classify all operations that produce a floating-point result as having a result within a given range. We will keep track of the minimum (down to -NaN), the maximum (up to +NaN) and whether the value is an integer (whole number hiding in a floating-point) or not.</p>
<p>The analysis runs as a function pass that iterates on the basic blocks of that function in a reverse post-order traversal - which ensures that for graphs of basic blocks that are <em>not</em> loops, we will always have classified an input float before it is used.</p>
<p>To keep things simple - no attempt has been made to classify floating-point values that are persistant around a loop - any phi node can attempt to classify a float which has not been identified yet, and thus will have to make a default worst-case assumption on the float.</p>
<p>Lets now run through the list of instructions that we will analyze, and I&rsquo;ll explain what the analysis pass does for each.</p>
<h2 id="signed-integer-to-floating-point">Signed Integer to Floating-Point</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> sitofp i8 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span></code></pre></div><p>The <code>sitofp</code> instruction converts a signed integer to a floating-point value. Given that integers have a constrained range with respect to their integer size, we can make some assumptions on all integers as to what their maximum and minimum values are. To get an even better insight into their value, I use the existing scalar evolution analysis (which only works for integers) to query the range of the input integer and propagate this to the float. The smallest integer value is rounded towards negative when converting and the largest integer value is rounded towards positive, to ensure that even for the integer numbers that are not fully representable in their floating-point equivalents - we account for the worst-case behaviour of any rounding mode the system supports.</p>
<p>In the above example, because <code>%i</code> has a signed range of <code>[-128..127]</code> we can infer that <code>%f</code> also has this range, and we record that <code>%f</code> is an integer (hiding in a float).</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span><span style="color:#ae81ff">128</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">127</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><h2 id="unsigned-integer-to-floating-point">Unsigned Integer to Floating-Point</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> uitofp i3 <span style="color:#f92672">%</span>i to <span style="color:#66d9ef">float</span>
</span></span></code></pre></div><p>Much like for the signed equivalent above, we know that <code>%i</code> has an unsigned range of <code>[0..7]</code> and so <code>%f</code> also has this range and is an integer.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">7</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><h2 id="floating-point-truncation">Floating-Point Truncation</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> fptrunc <span style="color:#66d9ef">double</span> <span style="color:#f92672">%</span>d to <span style="color:#66d9ef">float</span>
</span></span></code></pre></div><p>For floating-point truncation - the range of the truncated value is the same as the range of the larger value we are truncating from. The only exceptions will be if the larger number is not fully representable in the smaller data type.</p>
<p>If we assume that <code>%d</code> above came from an already constrained number, we can see that the constraints have passed from <code>%d</code> to <code>%f</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span><span style="color:#ae81ff">128</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">127</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><h2 id="floating-point-extension">Floating-Point Extension</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> fpext half <span style="color:#f92672">%</span>h to <span style="color:#66d9ef">float</span>
</span></span></code></pre></div><p>For floating-point extension - the approach mirrors that of truncation. We simply pass the original constrained range onto the larger type.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#ae81ff">4.5</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">42.42</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><h2 id="selects">Selects</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>d <span style="color:#f92672">=</span> select i1 <span style="color:#f92672">%</span>b, <span style="color:#66d9ef">double</span> <span style="color:#ae81ff">0.0</span>, <span style="color:#66d9ef">double</span> <span style="color:#f92672">%</span>in
</span></span></code></pre></div><p>Selecting between two values yields a range that is the intersection of the two original ranges.</p>
<p>In the above example <code>%in</code> is a value that when classifying we could deduce no information about. Think of values sourced from loads or passed in as function parameters. So the range of <code>%in</code> is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span>NaN
</span></span><span style="display:flex;"><span>max: NaN
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><p>This means that the result of the selection is the same range - EG. the range of the 0.0 is merged with the range of <code>%in</code> which just so happens to already contain 0.0.</p>
<h2 id="phis">PHIs</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> phi <span style="color:#66d9ef">float</span> [<span style="color:#f92672">%</span>a, <span style="color:#f92672">%</span>true], [<span style="color:#f92672">%</span>b, <span style="color:#f92672">%</span>false]
</span></span></code></pre></div><p>PHIs merge their ranges together in a similar fashion to selects. So for the above phi the range of <code>%f</code> is the intersection of the ranges of <code>%a</code> and <code>%b</code>. To keep the algorithm simple though, I&rsquo;ve purposefully not handled any arguments to a PHI that we haven&rsquo;t seen before. Since we iterate through the basic blocks in a reverse post order traversal, the only time we will see a value to a PHI that we haven&rsquo;t seen before is in loops where the PHI value has yet to be parsed:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>loop:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> phi <span style="color:#66d9ef">float</span> [<span style="color:#ae81ff">0.0</span>, <span style="color:#f92672">%</span>entry], [<span style="color:#f92672">%</span>f2, <span style="color:#f92672">%</span>loop]
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> fadd <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#ae81ff">1.0</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">%</span>c <span style="color:#f92672">=</span> fcmp oge <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2, <span style="color:#ae81ff">42.0</span>
</span></span><span style="display:flex;"><span>  br i1 <span style="color:#f92672">%</span>c, label <span style="color:#f92672">%</span>loop, label <span style="color:#f92672">%</span>merge
</span></span></code></pre></div><p>In the example above <code>%f2</code> has not been encountered when we are classifying the PHI node in <code>%f</code>, and thus we have to assume the worst case for <code>%f</code> that <code>%f2</code> could be any floating-point number.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span>NaN
</span></span><span style="display:flex;"><span>max: NaN
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><h2 id="floating-point-negate">Floating-Point Negate</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> fneg <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f
</span></span></code></pre></div><p>Negate is a fun one - because in any cases where we know that the input is all positive or all negative we know for sure that the output is exactly the opposite range.</p>
<p>Lets assume that <code>%f</code> is in the range <code>[0..4000.12]</code>, and thus <code>%f2</code> is the negative of this range:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span><span style="color:#ae81ff">4000.12</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#f92672">-</span><span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><h2 id="floating-point-addition">Floating-Point Addition</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>  <span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fadd <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f2
</span></span></code></pre></div><p>The addition of two numbers has a linear result across the range. So to evaluate the full range of the addition we need to perform eight adds - we need to add the min/max from the first operand to the min/max of the second operand. We need to be careful of the worst case behaviour with respect to rounding also, so we need to perform all these additions under both round to negative and round to positive rounding modes (thus the eight adds).</p>
<p>LLVM&rsquo;s APFloat class supports all this for us, we just leverage it.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">638.1</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><h2 id="floating-point-subtraction">Floating-Point Subtraction</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fsub <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f2
</span></span></code></pre></div><p>Subtraction follows the same idea as addition - eight subtractions with the min/max of both operands.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span><span style="color:#ae81ff">127</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">511</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><h2 id="floating-point-multiplication">Floating-Point Multiplication</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fmul <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f2
</span></span></code></pre></div><p>Multiplication is the same as addition and subtraction - use LLVM&rsquo;s APFloat to multiply the min/max of both operands.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">64897</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><h2 id="floating-point-division">Floating-Point Division</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> fdiv <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#f92672">%</span>f2
</span></span></code></pre></div><p>Division is an interesting one because there are three domains of interest outwith any NaNs:</p>
<ol>
<li>Could the denominator be zero? This can produce infinities.</li>
<li>Could the denominator be between minus one and one? This <em>grows</em> the range of the output.</li>
<li>Could the denominator be exclusively outwith the range minus one and one? This <em>shrinks</em> the range.</li>
</ol>
<p>For my evaluation I care most about 1. and 3. - if the denominator could be zero I need my range to encompass all finite and infinite numbers, and if the denominator will always cause the range to <em>shrink</em> I calculate the division on the bounds and use that as the new constrained range.</p>
<p>Let us assume that <code>%f</code> in the above example is in the range <code>[0..511.0]</code>, and that <code>%f2</code> is a single value <code>400000000.0</code>. The resulting range for <code>%f3</code> is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>FPSCEV: <span style="color:#ae81ff">0x7fe02e006698</span><span style="color:#f92672">:</span>
</span></span><span style="display:flex;"><span>min: <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">1.27750002E-6</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><p>Another interesting point with division is the fast-math flag allow reciprocal (arcp). This flags lets a division operation to be replaced with x * (1 / y) - EG. you take the reciprocal of y (with intermediate rounding) and multiply that by x. Lots of hardware has efficient reciprocals, and so this optimization can be very powerful for performance. The problem with this optimization for us is that the intermediate rounding of x presents an issue with the range of the output. To combat this - if arcp is being used we have to perform four division operations for the reciprocal with each value from the range of y being calculate with each of the most biased rounding modes, and then these reciprocals are combined with the range of x using a further sixteen multiplies. We need sixteen multiplies because we need to multiply all four of the reciprocal calculations with the two ranges of x for each of the two most biased rounding modes - resulting in the sixteen operations. At the end of this we just calculate the min and max of all these values to get our final range.</p>
<p>If we apply arcp to the division operation above, our new resulting range for <code>%f3</code> is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">1.27750013E-6</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><p>Which as you can see is slightly larger in the maximum resulting value because of the intermediate rounding.</p>
<h2 id="floating-point-remainder">Floating-Point Remainder</h2>
<p>Floating-point remainder is an operation that I&rsquo;ve avoided - simply because LLVM&rsquo;s APFloat does not contain a method for calculating the remainder with a provided rounding mode.</p>
<p>The only optimizations I propagate through remainder are the fast-math flags.</p>
<h2 id="arbitrary-calls">Arbitrary Calls</h2>
<p>LLVM lets you place fast-math flags on arbitrary calls.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f <span style="color:#f92672">=</span> call nnan <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">some_called_func</span>()
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> call nnan ninf <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span><span style="color:#a6e22e">some_called_func</span>()
</span></span></code></pre></div><p>For the above two calls, the range of <code>%f</code> will not contain NaNs, and the range of <code>%f2</code> is strictly finite - EG. no NaNs or infinities.</p>
<h2 id="square-root">Square Root</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.sqrt.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span></code></pre></div><p>LLVM&rsquo;s APFloat does not contain a sqrt operation. So all I could do with sqrt was to check if the range was entirely negative and thus a NaN would be produced. If the range contains positives and negatives, then the largest output range could be NaN, and the smallest output range could always be zero for a sufficiently small input. Otherwise if the range is entirely finite and positive, the best I could do for now was to say that the output range is at least as small as the input range, and I wipe all knowledge of whether the input was an integer because the likelyhood of an integer input being a perfect square is small enough that I didn&rsquo;t currently care.</p>
<p>If <code>%f</code> in the above example is an integer in the range <code>[0.0..511.0]</code>, then the range for <code>%f2</code> is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">511</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><p>Or - if the range is entirely negative the result is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: NaN
</span></span><span style="display:flex;"><span>max: NaN
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><h2 id="x-to-the-power-of-integer-y">X To the Power of Integer Y</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.powi.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, i32 <span style="color:#f92672">%</span>i)
</span></span></code></pre></div><p>For x to the power of an integer y, we again don&rsquo;t have anything in LLVM&rsquo;s APFloat to help us here. But we can make some assumptions on the output if either <code>%f</code> or <code>%i</code> all have the same sign. Firstly - I only optimize if x is entirely a positive number. This is because negative x will cause the sign of the result to oscillate depending on whether the input integer y is odd or even. Next if y is always negative and x is greater than or equal to one, we know that the output range will at most be as large as the input range. And lastly if y is always positive then if x is less than one the output is between zero and one, otherwise if x is one or greater then the result will be between the minimum of one and the original range of x (because x^0 == 1.0), and the maximum will be infinity.</p>
<p>For instance, lets say that <code>%i</code> above is in the range <code>[0..255]</code> and <code>%f</code> is in the range <code>[0..65535]</code>, the range of <code>%f2</code> is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#f92672">+</span>Inf
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><p>We could greatly reduce this range if we had an equivalent of pow for an APFloat in LLVM!</p>
<h2 id="cosine-and-sine">Cosine and Sine</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.cos.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.sin.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span></code></pre></div><p>The two trignometric functions cos and sin are great candidates for analysis. Both functions will return a result in the range <code>[-1..1]</code> if the input value is finite.</p>
<h2 id="exponentials">Exponentials</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.exp.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.exp2.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span></code></pre></div><p>The two exponential functions LLVM provides are hard to provide a maximum bound to because we don&rsquo;t have functions in APFloat to perform the calculation. But we do know that exponential always provides a positive result, so we set the minimum to zero for the output range, and the maximum to the largest the fast-math flags let us support (so worst case NaN, otherwise infinity or the largest positive number).</p>
<h2 id="logarithms">Logarithms</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.log.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.log10.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f4 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.log2.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span></code></pre></div><p>A similar problem with logarithm is that we don&rsquo;t have functions in APFloat that can help us here. But there are some properties of logs that we can check:</p>
<ol>
<li>I check if the input is entirely negative, which always produces a NaN.</li>
<li>If the input is always positive but could be zero, then the minimum value could be a negative infinity.</li>
<li>If the input is less than one but not zero, then the minimum value could go as low as the largest negative representable number.</li>
<li>Otherwise if the input is greater than or equal to one, the minimum value is zero.</li>
</ol>
<p>Since I don&rsquo;t have a way to calculate the log of the input, the maximum range is poorly chosen as the same as the input - which will nearly always be hugely bigger than the actual maximum could be if we had a way to calculate it!</p>
<p>If we assume that <code>%f</code> is definitely not negative, then the output range is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span>Inf
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">511</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><h2 id="fused-multiply-and-add">Fused Multiply and Add</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.fma.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2, <span style="color:#66d9ef">float</span> <span style="color:#ae81ff">4.0</span>)
</span></span></code></pre></div><p>Fused multiply and add does not intermediately round the multiplied values before combining the additive. Luckily APFloat has a function for calculating this that takes a rounding mode, so we can use a similar approach to our addition above, except that we need sixteen operations for min and max we calculate - we need to perform four multiplications with two additions for the two most biased rounding modes.</p>
<p>If we assume that <code>%f</code> above has a range of <code>[0..511]</code> and <code>%f2</code> has a range of <code>[-511..0]</code>, then the resulting range of the fma is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span><span style="color:#ae81ff">261117</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><h2 id="floating-point-absolute-value">Floating-Point Absolute Value</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.fabs.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span></code></pre></div><p>The absolute value of a number is just the range of the input with its sign reversed. This one took me an embarassingly long time to get right, as I&rsquo;ll illustrate with a fun little range. Let&rsquo;s say that <code>%f</code> is in the range <code>[-4..1.5]</code>, what I did originally was to wipe the sign from the range and then recalculate which of the new values was min/max. The resulting range was <em>incredibly wrong</em>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#ae81ff">1.5</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><p>The fix was trivial though - if the original range contained positive and negative numbers it thus passed through zero, and the minimum result would be zero also. After applying this fix the range correctly was:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">4</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><h2 id="minimums-and-maximums">Minimums and Maximums</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.minnum.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2)
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f4 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.maxnum.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2)
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f5 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.minimum.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2)
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f6 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.maximum.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2)
</span></span></code></pre></div><p>LLVM provides two variants of minimum/maximum calculations - they only really differ in how they handle NaNs. Minnum and maxnum match libm&rsquo;s fmin/fmax, whereas minimum and maximum match IEEE 754-2018.</p>
<p>Lets assume that <code>%f</code> is in the range <code>[0..511]</code> and <code>%f2</code> is in the range <code>[-256..255]</code>.</p>
<p>Minnum&rsquo;s range is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span><span style="color:#ae81ff">256</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">255</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><p>Maxnum&rsquo;s range is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">511</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><p>Minimum&rsquo;s range is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span><span style="color:#ae81ff">256</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">255</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><p>Maximum&rsquo;s range is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span><span style="color:#ae81ff">256</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">255</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><h2 id="copy-sign">Copy Sign</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.copysign.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f, <span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f2)
</span></span></code></pre></div><p>Copy sign just copies the sign of <code>%f2</code> to <code>%f</code>. The interesting ranges are:</p>
<ol>
<li>If <code>%f2</code> contains positive and negative numbers, I wipe the sign the minimum and maximum ranges of <code>%f</code>, find the largest of these for the new maximum, and flip the sign for the new minimum.</li>
<li>If <code>%f</code> contains positive and negative numbers, I do the same a 1.</li>
<li>If <code>%f2</code> is all negative then the result is always negative.</li>
<li>if <code>%f2</code> is all positive then the result is always positive.</li>
</ol>
<p>Let us assume that <code>%f</code> is in the range <code>[0..511]</code> and <code>%f2</code> is in the range <code>[-256..255]</code>. This would mean our output range would be:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span><span style="color:#ae81ff">511</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">511</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">0</span>
</span></span></code></pre></div><h2 id="rounding">Rounding</h2>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#f92672">%</span>f2 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.floor.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f3 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.ceil.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f4 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.trunc.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f5 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.rint.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f6 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.nearbyint.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span><span style="display:flex;"><span><span style="color:#f92672">%</span>f7 <span style="color:#f92672">=</span> call <span style="color:#66d9ef">float</span> <span style="color:#960050;background-color:#1e0010">@</span>llvm.round.<span style="color:#a6e22e">f32</span>(<span style="color:#66d9ef">float</span> <span style="color:#f92672">%</span>f)
</span></span></code></pre></div><p>LLVM has various functions that essentially boil down to <em>&ldquo;Round this floating-point to an integer with various rounding modes&rdquo;</em>. For each of these functions I use the APFloat&rsquo;s <code>roundToIntegral</code> to handle them.</p>
<p>Let us assume that <code>%f</code> is in the range <code>[-32768.5039..32768.5039]</code>.</p>
<p>For floor the output range is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span><span style="color:#ae81ff">32769</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">32768</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><p>For ceil the output range is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span><span style="color:#ae81ff">32768</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">32769</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><p>For trunc the output range is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span><span style="color:#ae81ff">32768</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">32768</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><p>For rint the output range is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span><span style="color:#ae81ff">32769</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">32769</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><p>For nearbyint the output range is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span><span style="color:#ae81ff">32769</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">32769</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><p>For round the output range is:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>min: <span style="color:#f92672">-</span><span style="color:#ae81ff">32769</span>
</span></span><span style="display:flex;"><span>max: <span style="color:#ae81ff">32769</span>
</span></span><span style="display:flex;"><span>isInteger: <span style="color:#ae81ff">1</span>
</span></span></code></pre></div><p>Note that all of the results are always integer too.</p>
<h1 id="fast-math-flags">Fast-Math Flags</h1>
<p>LLVM supports <a href="https://llvm.org/docs/LangRef.html#id1027">fast-math flags</a> that allows the compiler to assume some properties about the input floating-point. For each of the functions above, the fast-math flags no-NaNs, no-infinities, and no signed zeros are propagated onto the inputs before the calculations of their range, and also propagated onto the output to constrain the range further.</p>
<h1 id="all-the-missing-parts">All The Missing Parts</h1>
<p>Even though I&rsquo;ve done a quite extensive analysis on the input, there are lots of missing parts. These can be categorized into a few main areas:</p>
<ol>
<li>Any function that is missing from APFloat (like exponentials) means I make a really poor guess at the range&rsquo;s constraint. If these functions could be added this analysis would get better.</li>
<li>I make no attempt to handle the fast-math flag <em>approximate function</em> (afn). In actual fact given there are no range constraints on what an operation with afn is tagged with, I really should modify the optimization to set the range to NaN if afn is used in any function. This would suck because afn is meant to be used to allow more optimizations of the function, so to make it that our range analysis gets <em>much worse</em> when it is present seems backwards. I think the only way to solve this would be to provide some limitations on the range - like we could still require that afn on trig functions would definitely return a result in the range <code>[-1..1]</code>.</li>
<li>I almost wonder whether I would have been better tracking the NaN/infinity separately from the range itself - some functions like sin/cos can return NaN or something in the range <code>[-1..1]</code> - and if this was fed into an operation with no-NaNs specified then we could assume a much tighter range for that function.</li>
<li>Potentially track disjoint ranges to let us have a better guess - means a lot more data per FPSCEV though.</li>
<li>Integrate with the integer SCEV itself? I didn&rsquo;t do this because SCEV is huge and scary and anything that changes it this drastically would probably break all of LLVM. But if you convert a floating-point to an integer and you have FPSCEV information, I could translate that back into some better SCEV information on the integer too.</li>
</ol>
<h1 id="conclusions">Conclusions</h1>
<p>So doing this analysis wasn&rsquo;t trivial - but the results are pretty cool! We can now perform lots more analysis on floating-point values in LLVM.</p>
<p>In my next blog I&rsquo;ll use this analysis to start actually optimizing some fun little programs, and see what is now possible with this extra information.</p>
]]></description>
    </item>
    
    <item>
      <title>Comparing utest.h against googletest and jctest</title>
      <link>https://www.neilhenning.dev/posts/utest-h-performance/</link>
      <pubDate>Wed, 01 May 2019 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/utest-h-performance/</guid>
      <description><![CDATA[<p>For those that don&rsquo;t know - the favourite single-header C/C++ library that I&rsquo;ve ever created is my <a href="https://github.com/sheredom/utest.h">unit test helper - utest.h</a>. The main features are:</p>
<ul>
<li>Single header (duh).</li>
<li>Works with C <em>and</em> C++.</li>
<li>Allows a single executable to be created with both C <em>and</em> C++ tests linked in.</li>
<li>Blindingly fast to compile and run.</li>
</ul>
<p>After reading <a href="http://www.sizeofvoid.com/2019/04/13/replacing-googletest-with-jctest/">this post</a> on another attempt at a <a href="https://github.com/google/googletest">googletest</a> replacement <a href="https://github.com/JCash/jctest">jctest</a>, and all the awesome analysis that Matthias included comparing the compile and runtime performance of jctest as compared to googletest, it suddenly hit me that I haven&rsquo;t actually provided my performance analysis in any blog to show how good utest.h holds up against googletest (which was my original motivation for creating my own library). So lets start analysing utest.h against googletest, but also since jctest is the new kid of the block (or at least <em>new kid to me</em>) I&rsquo;ve ran the tests against all three libraries.</p>
<h1 id="feature-parity">Feature Parity</h1>
<p>The three libraries contain roughly the same set of <em>base</em> features - EG. the things you would need to add a bunch of tests and run them. There are some differentiation points that are worth calling out.</p>
<table>
	<thead>
			<tr>
					<th style="text-align: center">Feature</th>
					<th style="text-align: center">Googletest</th>
					<th style="text-align: center">jctest</th>
					<th style="text-align: center">utest.h</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: center">C</td>
					<td style="text-align: center">✘</td>
					<td style="text-align: center">✘</td>
					<td style="text-align: center">✔</td>
			</tr>
			<tr>
					<td style="text-align: center">C++98</td>
					<td style="text-align: center">✘</td>
					<td style="text-align: center">✔</td>
					<td style="text-align: center">✔</td>
			</tr>
			<tr>
					<td style="text-align: center">C++11</td>
					<td style="text-align: center">✔</td>
					<td style="text-align: center">✔</td>
					<td style="text-align: center">✔</td>
			</tr>
			<tr>
					<td style="text-align: center">Basic tests</td>
					<td style="text-align: center">✔</td>
					<td style="text-align: center">✔</td>
					<td style="text-align: center">✔</td>
			</tr>
			<tr>
					<td style="text-align: center">Fixture tests</td>
					<td style="text-align: center">✔</td>
					<td style="text-align: center">✔</td>
					<td style="text-align: center">✔</td>
			</tr>
			<tr>
					<td style="text-align: center">Parameterized tests</td>
					<td style="text-align: center">✔</td>
					<td style="text-align: center">✔</td>
					<td style="text-align: center">✘</td>
			</tr>
			<tr>
					<td style="text-align: center">Supports complex test filtering</td>
					<td style="text-align: center">✔</td>
					<td style="text-align: center">✘</td>
					<td style="text-align: center">✔</td>
			</tr>
			<tr>
					<td style="text-align: center">Single header</td>
					<td style="text-align: center">✘</td>
					<td style="text-align: center">✔*</td>
					<td style="text-align: center">✔</td>
			</tr>
			<tr>
					<td style="text-align: center">Supports one billion additional features I&rsquo;ve never needed</td>
					<td style="text-align: center">✔</td>
					<td style="text-align: center">✘</td>
					<td style="text-align: center">✘</td>
			</tr>
	</tbody>
</table>
<p><em>*: needs a single file to contain #define JC_TEST_IMPLEMENTATION</em></p>
<p>So as can be shown in the table - for the base features you need from a unit testing framework, each of the three libraries covers most of the bases required. If you want to use my utest.h library you will give up parameterized tests (although I do have <a href="https://github.com/sheredom/utest.h#define-an-indexed-testcase">indexed tests</a> that allow you to do most of what parameterized tests do!), but you do get the ability to test C-only code to.</p>
<h1 id="lines-of-code-loc">Lines of Code (loc)</h1>
<p>The googletest library is heavy in C++, heavy in includes and a lot of code. On the other hand jctest <a href="https://github.com/JCash/jctest/blob/master/src/jc_test.h#L8">claims to be under 1000 loc</a> (although <a href="https://github.com/JCash/jctest/blob/master/src/jc_test.h#L1478">the header file is 1478 loc</a>, maybe he is meaning without comments?). My own utest.h is <a href="https://github.com/sheredom/utest.h/blob/master/utest.h#L856">a mere 856 loc</a>.</p>
<p>If we look at lines of code after preprocessing we can really see the difference between the libraries.</p>

<img src="/images/utest-h-performance/lines_of_code.jpg"  class="center"  style="border-radius: 8px;"    />


<p>Some caveats:</p>
<ul>
<li>googletest has two rows in the chart - this is because it is the only library that has source files. The cost of adding googletest to your project is effectively <code>78209 + N * 58801</code> where <code>N</code> is the number of source test files you are using.</li>
<li>jctest has two rows in the chart - this is because even though it is a single source library, a single C++ source file must have the <code>#define JC_TEST_IMPLEMENTATION</code> to bring in the actual implementation. The cost of adding jctest to your project is effectively <code>3718 + (N - 1) * 2541</code>.</li>
<li>the cost of adding utest.h to your project is effectively <code>5201 * N</code> for C files and <code>5405 * N</code> for C++ files.</li>
</ul>
<p>You can see that jctest is the smallest in terms of lines of code, at nearly half the lines of code of utest.h once preprocessing has taken place. But both jctest and utest.h are over 10x than googletest.</p>
<h1 id="compile-time">Compile Time</h1>
<p>One of the points heavily emphasised in the jctest blog was the compile time improvements from switching away from googletest. Avoiding the STL and thus the include bloat seems to have been the main benefit for jctest in improving its compile time performance against googletest. My own utest.h uses a bunch of the same techniques as jctest to improve performance - avoid headers where you can and use nothing from the STL.</p>
<p>To compare compile time performance I&rsquo;ve added simple test cases that include the header for the library and have a single test case defined.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#75715e">#include</span> <span style="color:#75715e">&#34;utest.h&#34;</span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">UTEST</span>(test, x) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">ASSERT_TRUE</span>(<span style="color:#ae81ff">1</span>);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">UTEST_MAIN</span>();
</span></span></code></pre></div><p>I&rsquo;ve used the default compile options to clang on MacOS (<code>Apple LLVM version 9.1.0 (clang-902.0.39.1)</code>), and ran it in <a href="https://crates.io/crates/hyperfine">hyperfine</a> to get stable results.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>clang -c -Iutest.h/ compile_tests/utest.c
</span></span></code></pre></div><p>So with all this in mind, lets look at the compile time performance of the three libraries!</p>

<img src="/images/utest-h-performance/compile_time.jpg"  class="center"  style="border-radius: 8px;"    />


<p>You can see the correlation very clearly to the lines of code - we can see that both jctest and utest.h perform significantly better than googletest in cost to compile. Both libs are nearly 10x faster to compile than googletest in this simple test. Wowser, that&rsquo;s a big difference.</p>
<p>There is very little difference between utest.h and jctest in time to compile - jctest is marginally faster to compile when not defining the implementation, but slower when defining the implementation.</p>
<h1 id="run-time">Run Time</h1>
<p>To measure the time it takes for each unit testing framework to run, I added 5000 test cases to a single file, and then ran 3 configurations of these tests:</p>
<ul>
<li>Filter for a single test case defined in the 5000 (this pattern is often used during development when iterating on a single failure).</li>
<li>Test 5000 passing tests (no failures).</li>
<li>Test 5000 failing tests (they all fail).</li>
</ul>
<p>I choose 5000 tests simply because it was the lowest number with which I could get repeatable runs through hyperfine without statistical anonmalies.</p>

<img src="/images/utest-h-performance/run_time.jpg"  class="center"  style="border-radius: 8px;"    />


<p>And the results look pretty good! Lets do some analysis:</p>
<ul>
<li>utest.h is just blindingly fast compared to the other two libraries - roughly 5x faster than jctest and 4x-9x faster than googletest depending on whether you are looking at the all pass / all fail cases.</li>
<li>googletest is <em>really slow</em> at dealing with failing test cases.</li>
<li>googletest beats jctest when all cases pass and also when filtering the test case.</li>
</ul>
<p>So I did some digging, and it looks like utest.h is so much faster because, and you could probably have guessed this, I avoided any C++. To handle test cases in utest.h I didn&rsquo;t have the ability to use classes to define the test case, and thus I had to resort to functions and taking pointers-to-functions to handle the test case registration. Both jctest and googletest resort to defining classes with virtual members (mostly as a way to handle test case fixtures), but this means <em>there is inherently extra bloat because of C++</em>.</p>
<p>If you want to compare the code of jctest vs utest.h in godbolt.org here are some links:</p>
<ul>
<li>utest.h - <a href="https://godbolt.org/z/Kmfl2w">https://godbolt.org/z/Kmfl2w</a></li>
<li>jctest - <a href="https://godbolt.org/z/XawJ0l">https://godbolt.org/z/XawJ0l</a></li>
</ul>
<h1 id="conclusion">Conclusion</h1>
<p>All three of the libraries are pretty good in all honesty - googletest has a bazillion features but they come at a heavy compile time cost, jctest fixes the compile time cost but still has some run time overhead, and my own utest.h gives you C/C++ with fast compile and run times. I think my utest.h is the best library (but which author of a useful tool wouldn&rsquo;t inherently think that?) but the real winner is the open source projects that make use of any of these libraries to improve the quality of their software.</p>
]]></description>
    </item>
    
    <item>
      <title>Switching my blog to Hugo</title>
      <link>https://www.neilhenning.dev/posts/switching-to-hugo/</link>
      <pubDate>Sun, 17 Feb 2019 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/switching-to-hugo/</guid>
      <description><![CDATA[<p>I&rsquo;ve long been frustrated with wordpress as the way I post content on my blog:</p>
<ul>
<li>It is bloated and slow to load pages.</li>
<li>Requires an SQL server for content which is mostly static.</li>
<li>I find the editor unintuitive.</li>
<li>Code samples never quite displayed correctly.</li>
</ul>
<p>I&rsquo;ve been looking at <a href="https://gohugo.io">Hugo</a> for a while now as I love the idea of static site generator, but everytime in the past I tried to switch to it in the past but I was frustrated by the export to hugo plugin for wordpress being broken.</p>
<p>This weekend I decided to take another crack at doing the switch and thankfully found this wonderful <a href="https://gomakethings.com/migrating-from-wordpress-to-hugo/">blog post</a> by <a href="https://twitter.com/ChrisFerdinandi">Chris Ferdinandi</a> explaining that the Jekyll exporter will allow us to export our content and get it to work in Hugo!</p>
<p>So I installed the export to Jekyll plugin, exported my site, and got to work. The Jekyll exporter gives you just the content of your site, which in my case boiled down to a folder for my blog, the <a href="https://www.neilhenning.dev/lifelog/">life log</a> page where I keep all the happenings I&rsquo;ve been doing in my career, and a wp-content folder with all the images and pdfs that I&rsquo;ve shared on the site previously.</p>
<p>To pull these over in Hugo I first downloaded the hugo from the website <a href="https://gohugo.io">https://gohugo.io</a>.</p>
<p>Next I created a new site with:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>mkdir neilhenning.dev
</span></span><span style="display:flex;"><span>cd neilhenning.dev
</span></span><span style="display:flex;"><span>hugo new site .
</span></span></code></pre></div><p>This just creates a default site ready to take my content. Hugo keeps all the pages in the &lsquo;content&rsquo; folder, and all the images and pdfs in the &lsquo;static&rsquo; folder. So I moved all my blogs over into content, all my images and pdfs into static, and now I need to find a theme I like. Hugo has <a href="https://themes.gohugo.io">tons of themes</a>. I wanted a minimal, fast and responsive theme, so I narrowed down to only those tagged &lsquo;Minimal&rsquo;, and then found a theme called <a href="https://themes.gohugo.io/hugo-theme-terminal/">Terminal</a> by <a href="https://radoslawkoziel.pl">Radek Kozieł</a> that was really simple and clean. I didn&rsquo;t like everything about the theme, but I liked the fact the theme was clean enough that I&rsquo;d be able to add a static/style.css to override the few things I wanted to change.</p>
<p>Since I am tracking my site in git, I used this point to track what I had in git, and add the submodule for the terminal repository:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>git init .
</span></span><span style="display:flex;"><span>git commit -am <span style="color:#e6db74">&#34;Heyo, gaia?&#34;</span>
</span></span><span style="display:flex;"><span>git submodule add https://github.com/panr/hugo-theme-terminal.git themes/terminal
</span></span></code></pre></div><p>And then edited my config.toml using the <a href="https://github.com/panr/hugo-theme-terminal/blob/master/exampleSite/config.toml">example site from the terminal</a> as my default.</p>
<p>I host my websites with <a href="https://www.gandi.net">gandi</a>, who require the website when tracked with git to be in the htdocs folder, so the first addition to my config was to add:</p>
<pre tabindex="0"><code>publishDir = &#34;htdocs&#34;
</code></pre><p>This just instructs Hugo that when you build the website to place all the built content in the htdocs folder instead of the default.</p>
<p>Now felt like a good time to check how my site was going, and so I ran the local server command to see how it looked:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>hugo server
</span></span></code></pre></div><p>This hosts a website at //localhost:1313/ that you can view in your browser. I loaded it up in Safari, and heyo! My site displayed. As soon as I went into any of the content I started to notice some problems though.</p>
<p>For instance all the images were not pointing at the wp-content folder that my site had, they were instead being routed through some weird wordpress domain prior to loading from my site. To get this to work I did the incredibly annoying thing of searching for <code>&lt;img</code> tags and replacing them with the built-in <a href="https://github.com/panr/hugo-theme-terminal/blob/master/README.md#built-in-shortcodes">image shortcodes</a> that the terminal theme uses.</p>
<p>I went through all the content, pointed it at the <code>/wp-content/uploads/*</code> folder of the content I had pulled over from wordpress.</p>
<p>I next wanted to ensure that all the links to my original site on wordpress would be correctly redirected to my new hugo-built site. I have a lot of popular incoming links that people use regularly, and so to have these suddenly 404 seemed terrible. I first remapped all the <code>permalink:</code> to <code>aliases:</code> (not sure why I needed this, but permalink definitely did not work&hellip;) and then I tried to follow the links as they would have been incoming from my original wordpress - and it didn&rsquo;t work. I don&rsquo;t exactly remember why I decided to try this, but I noticed that all the blogs that were exported by wordpress began with the date, then the original title of the blog. So I decided to remove the date from the .md, retried the link in my browser, and voila the original links worked! I have zero idea why this worked, but I then ran over all the other blogs and removed the dates to ensure the original links would work.</p>
<p>Now my site was basically done, the links worked, the images and pdfs were all avoiding the weird wordpress redirects, and I only had to mess with the theme itself. The minor few things I disliked with the theme were that the content was not centered, so I found that the class was called &lsquo;container&rsquo;, and I decided to center it and make the border which previously only appeared on the right, to appear on the left too:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-css" data-lang="css"><span style="display:flex;"><span>.<span style="color:#a6e22e">container</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">border-left</span>: <span style="color:#ae81ff">1</span><span style="color:#66d9ef">px</span> <span style="color:#66d9ef">solid</span> hsla(<span style="color:#ae81ff">0</span>,<span style="color:#ae81ff">0</span><span style="color:#66d9ef">%</span>,<span style="color:#ae81ff">100</span><span style="color:#66d9ef">%</span>,<span style="color:#ae81ff">.1</span>);
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">margin</span>: <span style="color:#ae81ff">0</span> <span style="color:#66d9ef">auto</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>The second thing I disliked was the colour used. Luckily the theme makes used of a variant <code>--accent</code> to choose the single colour used in the theme:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-css" data-lang="css"><span style="display:flex;"><span>:<span style="color:#a6e22e">root</span> {
</span></span><span style="display:flex;"><span>  --accent: <span style="color:#ae81ff">#BF76EC</span>;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>I remapped this to a purple colour that I&rsquo;ve used in other forms, and noticed that everything but the dates on the posts to the new colour. It seems because the dates use a slightly opaque colour it was specified separately, so I decided to change that colour to use the variable <code>--accent</code> too, which unified the colour across the theme.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-css" data-lang="css"><span style="display:flex;"><span>.<span style="color:#a6e22e">post-meta</span> {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">color</span>: <span style="color:#a6e22e">var</span>(<span style="color:#f92672">--</span>accent);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And that is it! My blog was ported over to Hugo, in a simple and fast theme that I liked, and I was finally out of the clutches of wordpress. A few people reached out to me and asked that I write up how I did my porting so they could follow suit - so hopefully this rough guide can help a few of you!</p>
]]></description>
    </item>
    
    <item>
      <title>Introducing bump_alloc - my new Rust crate</title>
      <link>https://www.neilhenning.dev/posts/introducing-bump_alloc-my-new-rust-crate/</link>
      <pubDate>Sun, 03 Feb 2019 17:02:09 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/introducing-bump_alloc-my-new-rust-crate/</guid>
      <description><![CDATA[<p>I&rsquo;ve been continuing my foray into Rust, and one thing I&rsquo;ve been interested in is <!-- raw HTML omitted -->global allocators<!-- raw HTML omitted --> - Rust&rsquo;s builtin support for switching the allocator used by an application.</p>
<p>One thing I&rsquo;ve been wanting to try for a while is to see if a <!-- raw HTML omitted -->bump allocator<!-- raw HTML omitted --> used in conjunction with a short running application could result in performance gains. I couldn&rsquo;t find while perusing <!-- raw HTML omitted -->crates.io<!-- raw HTML omitted --> any crate that added a global allocator that just bumps, so I&rsquo;ve written my own - <!-- raw HTML omitted -->bump_alloc<!-- raw HTML omitted -->.</p>
<h3 id="what-is-a-bump-allocator">What is a bump allocator?</h3>
<p>A bump allocator is a simple allocator where every new allocation is sourced from a ‘bump&rsquo; of the previously allocated value.</p>
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;background-color: green; color: white;&quot;&gt;
  &lt;strong&gt;Allocation 1&lt;/strong&gt;
&lt;/td&gt;

&lt;td style=&quot;background-color: green; color: white;&quot;&gt;
  &lt;strong&gt;Allocation 2&lt;/strong&gt;
&lt;/td&gt;

&lt;td&gt;
  &amp;#8230;
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<p>When an allocated region is done with, and we <!-- raw HTML omitted -->dealloc<!-- raw HTML omitted --> it (free/delete the memory in the language of C/C++), the memory is <strong>not actually freed</strong>.</p>
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;background-color: red; color: white;&quot;&gt;
  &lt;del&gt;Allocation 1&lt;/del&gt;
&lt;/td&gt;

&lt;td style=&quot;background-color: green; color: white;&quot;&gt;
  Allocation 2
&lt;/td&gt;

&lt;td&gt;
  &amp;#8230;
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<p>This means our bump allocator is effectively lossy with memory - we have no way to retrieve and reuse memory that was not required anymore. But the whole point of a bump allocator is that there is a class of applications that are short lived or constrained with their memory usage that we are happy to trade off not being able to reuse previously allocated memory for a little extra performance in the application.</p>
<h3 id="how-to-use">How to use?</h3>
<p>In your Cargo.toml you simply add:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And then in your Rust application or library you simply include the allocator like:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>By default the bump allocator will reserve one gigabyte of allocatable memory for its use. But crucially we are not actually <em>allocating</em> one gigabyte of memory, we are simply reserving the ability to allocate that much by using **mmap **on Unix-based systems, and <strong>VirtualAlloc</strong> on Windows systems.</p>
<p>If you need more memory, you can use:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Which will reserve the number of bytes of memory as you require - so in the example above four megabytes will be reserved.</p>
<p>If you go over the amount of memory reserved then <!-- raw HTML omitted -->handle_alloc_error<!-- raw HTML omitted --> is called and the application will stop.</p>
<h3 id="how-is-the-performance">How is the performance?</h3>
<p>So what started me thinking about the performance characteristics of a bump allocator was LLVM&rsquo;s <!-- raw HTML omitted -->FileCheck<!-- raw HTML omitted -->. For those who don&rsquo;t know - it is part of LLVM&rsquo;s testing framework, and basically checks that the compiler&rsquo;s output matched what was expected. The FileCheck application is short lived, and runs a thousand or more times for a single run of LLVM&rsquo;s testing. This sounded like a perfect little application for me to use with a bump allocator.</p>
<p>I hooked up LLVM&rsquo;s FileCheck to build the C++ application via Rust and using the <!-- raw HTML omitted -->cc<!-- raw HTML omitted --> crate, routing calls to new/delete into Rust&rsquo;s global allocator via my <!-- raw HTML omitted -->cpp_new<!-- raw HTML omitted --> crate, and finally using my bump_alloc crate to replace the global allocator with my bump. I then compared the performance of this application versus LLVM&rsquo;s build FileCheck using a torture test of my creation - a 500,000 line random assortment of characters that I&rsquo;ll input into FileCheck:</p>
<!-- raw HTML omitted -->
<p>And use a regex CHECK: to see if the output matches:</p>
<!-- raw HTML omitted -->
<p>The results of comparing LLVM&rsquo;s FileCheck versus my own bump allocated variant were taken using <!-- raw HTML omitted -->hyperfine<!-- raw HTML omitted -->, and are as follows:</p>
<!-- raw HTML omitted -->
<pre><code>&lt;th&gt;
  bump_alloc FileCheck (s)
&lt;/th&gt;

&lt;th&gt;
  difference (%)
&lt;/th&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td&gt;
  10.536
&lt;/td&gt;

&lt;td&gt;
  105.62%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<p>So we&rsquo;re 1.05x faster for just changing the memory allocation strategy! So now that we know we can go some amount faster by just changing the allocator, we need to understand how much extra memory are we using to achieve this:</p>
<!-- raw HTML omitted -->
<pre><code>&lt;th&gt;
  bump_alloc FileCheck (megabytes)
&lt;/th&gt;

&lt;th&gt;
  difference (%)
&lt;/th&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td&gt;
  400.805
&lt;/td&gt;

&lt;td&gt;
  175.3%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<p>So we are using quite a bit more memory to achieve this modest performance increase - 1.75x more!</p>
<h3 id="conclusion">Conclusion</h3>
<p>We can achieve some performance improvement in short running applications by using a bump allocator (as others have found before me, I&rsquo;m not claiming to have invented the technique), but obviously there are costs to memory for doing this. There are definitely a class of applications that will benefit from using my new <!-- raw HTML omitted -->bump_alloc<!-- raw HTML omitted --> crate, and I hope the crate proves useful to a bunch of you. The crate is available under the permissible <!-- raw HTML omitted -->CC0 1.0 Universal<!-- raw HTML omitted --> license, so please get downloading!</p>
]]></description>
    </item>
    
    <item>
      <title>2018 Review</title>
      <link>https://www.neilhenning.dev/posts/2018-review/</link>
      <pubDate>Mon, 31 Dec 2018 22:32:12 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/2018-review/</guid>
      <description><![CDATA[<p>2018 has been a very busy year for me personally, and I thought for the sake of my own memory of the events I&rsquo;d do a review of the things I&rsquo;ve managed to achieve this year.</p>
<h3 id="vulkan-11--spir-v-13--subgroup-operations">Vulkan 1.1 / SPIR-V 1.3 &amp; Subgroup Operations</h3>
<p>The single biggest item that I shipped this year was adding subgroup operations to Vulkan 1.1 and SPIR-V 1.3. It took just under two years of wrangling with all the hardware vendors to get a set of functionality that we could expose on all Vulkan 1.1 implementations. As part of adding this I wrote the Vulkan specification, SPIR-V specification, Vulkan conformance tests, glslang (both GLSL and HLSL frontends), and also wrote a very well received <!-- raw HTML omitted -->Vulkan Subgroup Tutorial<!-- raw HTML omitted --> (one of the highest viewed posts on the Khronos site to date!). Since joining AMD I&rsquo;ve also been pleasantly surprised by the number of titles including some form of subgroup operations in their shaders - as the power they give the developer to get the most out of our hardware is immense.</p>
<h3 id="joined-amd">Joined AMD</h3>
<p>Having spent about eleven years at <!-- raw HTML omitted -->Codeplay I left to join AMD<!-- raw HTML omitted --> as an LLVM compiler engineer / Khronos representative / performance-junkie. I&rsquo;ve managed to keep up with my work in the Khronos Group as the Vulkan/SPIR-V representative for AMD, meaning that I am bringing all my experience within Khronos and the relationships I&rsquo;ve built up to play with my new focus on AMD&rsquo;s hardware.</p>
<p>It is pretty awesome that I&rsquo;m also able to more publicly work and contribute with the LLVM technology stack. I&rsquo;ve been using LLVM in graphics driver stacks since 2010, but all the projects were under NDA as I was contracting for hardware customers during my time at Codeplay. It has often been frustrating to have as much experience with LLVM as I have, but be unable to get enough traction within the community to fix things because of the NDA&rsquo;ed nature of my previous work. That has changed since I joined AMD though - I have committed significant performance optimisations to our AMDGPU backend and also some bug fixes into the core of LLVM proper:</p>
<ul>
<li><!-- raw HTML omitted -->[AMDGPU] support image load/store a16<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->[AMDGPU] Extend the SI Load/Store optimizer to combine more things.<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->[AMDGPU] Change the l1 flush instruction for AMDPAL/MESA3D.<!-- raw HTML omitted --></li>
<li><a href="https://reviews.llvm.org/rL346128">[AMDGPU] Fix the new atomic optimizer in pixel shaders.</a></li>
<li><a href="https://reviews.llvm.org/rL348937">[AMDGPU] Extend the SI Load/Store optimizer to combine more things.</a></li>
<li><a href="https://reviews.llvm.org/rL345962">[AMDGPU] UBSan bug fix for r345710</a></li>
<li><a href="https://reviews.llvm.org/rL345710">[AMDGPU] support image load/store a16</a></li>
<li><a href="https://reviews.llvm.org/rL344128">Fix an ordering bug in the scalarizer.</a></li>
<li><a href="https://reviews.llvm.org/rL343973">[AMDGPU] Add an AMDGPU specific atomic optimizer.</a></li>
</ul>
<p>I&rsquo;ve also been making changes in our LLPC Vulkan compiler stack to get significantly more performance:</p>
<ul>
<li>Added a <a href="https://github.com/GPUOpen-Drivers/llpc/blob/dev/patch/llpcPatchPeepholeOpt.cpp">peephole optimization pass</a> that helped gain significant performance improvements (mostly by reducing VGPR pressure across control flow) in the compiler.</li>
<li>Fixed up the <a href="https://github.com/GPUOpen-Drivers/llpc/blob/dev/patch/llpcPatchLoopUnrollInfoRectify.cpp">loop unrolling detection</a> to do a much better job at figuring out loop trip counts with multiple exits (more than LLVM itself can do).</li>
<li>I solidified the pass manager strategy to <a href="https://github.com/GPUOpen-Drivers/llpc/blob/dev/patch/llpcPatch.cpp#L173">move the optimization passes</a> after all the lowering and patching phases. This means that we can explain to LLVM a lot more about what the code is actually doing, which is super important for things like Loop Invariant Code Motion (LICM) for hoisting things outside of loops.</li>
</ul>
<p>I&rsquo;m incredibly humbled to work for one of the most awesome human beings <!-- raw HTML omitted -->Rys Sommefeldt<!-- raw HTML omitted -->, and work with great people like <!-- raw HTML omitted -->Colin Riley<!-- raw HTML omitted -->, <!-- raw HTML omitted -->Graham Sellers<!-- raw HTML omitted -->, <!-- raw HTML omitted -->Nicolai Hähnle, <!-- raw HTML omitted --><!-- raw HTML omitted -->Matthäus G. Chajdas<!-- raw HTML omitted -->, and many many more. It&rsquo;s great to be back focused on making games fast which is where my real passion is.</p>
<h3 id="leaving-codeplay">Leaving Codeplay</h3>
<p>It&rsquo;d be wrong for me not to include a lament over leaving Codeplay. Codeplay is a great company, full of superbly talented engineers that work on crazy hard problems everyday, and has a very bright future ahead of it. The main reason for me leaving was simply that I wanted to work on games - and Codeplay has been pivoting towards AI and machine learning technologies in recent years (including an <a href="https://www.codeplay.com/portal/04-18-18-codeplay-software-to-receive-investment-to-enable-safe-ai-for-automotive">investment by the Williams F1 team into Codeplay!</a>). So just to finally debunk many of the conspiratorial theories about my switch - I&rsquo;m just not personally invested in ML and wanted to work on games technology where my passion is, and the AMD job gave me the chance to do that. I really do wish all the superbly talented people at Codeplay all the best for their future - and I&rsquo;d very much like to thank <a href="https://twitter.com/codeandrew">Andrew Richards</a> for hiring me, <a href="https://twitter.com/IndigoCoder">Verena Beckham</a> for being a very formative person in educating me in how to actually function in a workplace, and <!-- raw HTML omitted -->Benie<!-- raw HTML omitted -->, <!-- raw HTML omitted -->Alastair Murray<!-- raw HTML omitted -->, <!-- raw HTML omitted -->Pierre-Andre Saulais<!-- raw HTML omitted -->, <!-- raw HTML omitted -->Aaron Dron<!-- raw HTML omitted -->, and many others for making Codeplay such a fun place to work at. Good luck folks!</p>
<h3 id="conclusion">Conclusion</h3>
<p>2018 has been a great year that has pushed me to learn new skills and survive in a new environment. I&rsquo;m super proud of what I&rsquo;ve achieved, and really looking forward to what I&rsquo;ll get to do in 2019.</p>
<p>I hope everyone enjoys their Hogmanay and y&rsquo;all can bring in the bells of 2019 with much joy. Bliadhna Mhath Ùr!</p>
]]></description>
    </item>
    
    <item>
      <title>Baby&#39;s First Crate: cpp_new</title>
      <link>https://www.neilhenning.dev/posts/babys-first-crate-cpp_new/</link>
      <pubDate>Tue, 04 Dec 2018 21:57:20 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/babys-first-crate-cpp_new/</guid>
      <description><![CDATA[<p>So I&rsquo;ve been playing around with Rust in my spare time for a few months now, and have been doing a lot of stuff that bridges C/C++ and Rust content. And one thing that has always bugged me is that I can use a super awesome allocator like jemalloc in Rust, but that the allocations being done via C++ were not being routed into this allocator. So as a tiny baby step into the Rust community, I&rsquo;ve released my first crate <!-- raw HTML omitted -->cpp_new<!-- raw HTML omitted -->. This crate simply maps C++&rsquo;s new/delete/new[]/delete[] via extern “C” functions back into Rust&rsquo;s global allocators.</p>
<p>To use, you simply do:</p>
<!-- raw HTML omitted -->
<p>And Rust will take care of the rest. This allows you to map any C++ allocations in existing content into a single allocator across your C++ and Rust content!</p>
<h2 id="how-it-is-implemented">How It Is Implemented</h2>
<p>To implement the crate there are two source files, the first being <!-- raw HTML omitted -->lib.rs<!-- raw HTML omitted --> which contains two functions rust_cpp_new and rust_cpp_delete. Rust&rsquo;s global allocators use a Layout to allocate memory. A layout is effectively a struct with two usize&rsquo;s in it - one is the size of the memory and the other is the alignment. This is fine for rust_cpp_new, because we can pass this information from the C++ side. But it becomes slightly trickier for rust_cpp_delete, because C++ only provides us with a void* of the ‘memory to free&rsquo;, but Rust expects an identical layout that was used to create the memory to delete it.</p>
<p>To get around this, we don&rsquo;t just allocate the memory as was requested by the user, we also fudge on a little blob of memory just before the allocation we return to the user that contains the Layout.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>While this looks a little confusing - all we are doing is making room for the Layout and storing it. Now when we are freeing memory we need to be careful to undo the fudge and get to the start of the Layout instead of the start of the user provided pointer:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And that&rsquo;s it! Now the second file is <!-- raw HTML omitted -->new.cpp<!-- raw HTML omitted --> - which contains the definitions of C++&rsquo;s new/delete/new[]/delete[].</p>
<p>For both the single-object and array we use the same Rust methods. We also have <strong>no information on the alignment requirements</strong> so we need to choose some value. I&rsquo;ve chosen 16 bytes alignment because that is the alignment that stackoverflow told me some C++ implementations use. It at least covers all the base use cases, and since Layout is two usize&rsquo;s (and thus 16 bytes itself) it means we&rsquo;ve got no wasted bytes in the allocation.</p>
<h3 id="conclusion">Conclusion</h3>
<p>This crate is super simple, super easy to use, and was a nice introduction to how to package up a Rust crate for use. The crate is provided under the <!-- raw HTML omitted -->CC0 1.0 Universal<!-- raw HTML omitted --> public domain and permissible license, and I hope it proves useful to someone!</p>
]]></description>
    </item>
    
    <item>
      <title>So long Codeplay, thanks for all the fish!</title>
      <link>https://www.neilhenning.dev/posts/so-long-codeplay-thanks-for-all-the-fish/</link>
      <pubDate>Fri, 01 Jun 2018 09:22:26 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/so-long-codeplay-thanks-for-all-the-fish/</guid>
      <description><![CDATA[<p>After 11 years since my first internship, and 9 years full time, I&rsquo;m leaving Codeplay to join AMD.</p>
<h2 id="a-brief-history-of-codeplay-and-i">A Brief History of Codeplay and I</h2>
<p>I was a nineteen year old <!-- raw HTML omitted -->ned<!-- raw HTML omitted --> when I started my first internship at Codeplay, and was given the code-monkey job of hand optimizing shaders for an OpenGL ES 2.0 shader compiler, so that Codeplay&rsquo;s compiler engineers could prove the capability of the compiler. Slated to take 10 weeks, I finished the task in 2 weeks and to stave off boredom in the remaining 8 weeks I ended up proving 100% code coverage of the compiler and writing a test generator to break it.</p>
<p>From these humble beginnings I came back for a second internship where I rewrote the <!-- raw HTML omitted -->Testplay<!-- raw HTML omitted --> system so that it&rsquo;d work on Windows &amp; Linux.</p>
<p>When I joined full time, it was with the promise that I&rsquo;d be doing PlayStation 3 development. I shipped my first title (<!-- raw HTML omitted -->NASCAR The Game: 2011<!-- raw HTML omitted -->) and got to make some SPUs very happy in the process. I felt at home doing games technology, but Codeplay&rsquo;s market drifted from primarily in games to doing driver development.</p>
<p>For 5 years I shipped ~7 OpenCL implementations in the mobile &amp; embedded space, becoming an expert in integrating and optimization in LLVM in the process.</p>
<p>Then Vulkan came around, and I knew here was the thing I had been waiting for. Having worked for so long on OpenCL, the deep-seated flaws in the API were very clear to me, and I wanted to be sure that Vulkan did not make the same mistakes. After joining Khronos, I proceeded to get Vulkan 1.0 out the door, then focused primarily on getting the Vulkan 1.1 <!-- raw HTML omitted -->subgroup functionality<!-- raw HTML omitted --> shipped and into developers hands.</p>
<h2 id="amds-enticing-offer">AMD&rsquo;s Enticing Offer</h2>
<p>With my history in Vulkan &amp; SPIR-V, and my LLVM &amp; driver experience - AMD enticed me with an awesome job. I&rsquo;d get to spend 100% of my time doing Vulkan &amp; SPIR-V, I&rsquo;d get to work on the Vulkan driver, I&rsquo;d get to use my skills in LLVM, and I&rsquo;d still be able to work within Khronos to get extensions and functionality that I know developers will love.</p>
<p>The entire brief was summed up by <!-- raw HTML omitted -->Rys<!-- raw HTML omitted --> as <em>‘Make things fast anywhere you want!&rsquo;</em>.</p>
<p>The icing on the cake was the opportunity to work for <!-- raw HTML omitted -->Rys Sommefeldt<!-- raw HTML omitted --> and closely with <!-- raw HTML omitted -->Timothy Lottes<!-- raw HTML omitted --> - two people that are legends in the industry to me.</p>
<p>What more was there to say other than <em>‘Sign me the fuck up!'</em></p>
<h2 id="tldr">TL;DR</h2>
<p>So today, the 1st of June 2018 is my last day at Codeplay. I leave behind many friends and co-workers that I&rsquo;ll naturally miss, I wish you all the best in your continuing careers!</p>
<p>And on the 18th June 2018 I&rsquo;ll start the next chapter in my life at AMD. Super excited doesn&rsquo;t begin to cover it.</p>
]]></description>
    </item>
    
    <item>
      <title>1.22x Performance Improvements in json.h!</title>
      <link>https://www.neilhenning.dev/posts/1-22x-performance-improvements-in-json-h/</link>
      <pubDate>Fri, 11 May 2018 08:27:05 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/1-22x-performance-improvements-in-json-h/</guid>
      <description><![CDATA[<p>I&rsquo;ve been meaning to try out <!-- raw HTML omitted -->Intel&rsquo;s VTune<!-- raw HTML omitted --> now that it has a permanent trial mode (you can renew the 30-day trial license every 30-days without paying!), as I&rsquo;ve long heard people rave about it as a profiling aid. I decided to pick one of my open source C libraries and see what performance problems I could find in the code, and I choose my JSON parser <!-- raw HTML omitted -->json.h<!-- raw HTML omitted -->.</p>
<p>I&rsquo;ve long known that the recursive approach I used in the parser will limit the performance I can get out of the code as compared to some of my <!-- raw HTML omitted -->competitors<!-- raw HTML omitted -->, but I support a metric-ton of extensional functionality (<!-- raw HTML omitted -->simplified JSON<!-- raw HTML omitted --> and <!-- raw HTML omitted -->JSON5<!-- raw HTML omitted --> to name two major extensions that my users love). That being said, while I wasn&rsquo;t in the mood to replace my recursive strategy with a more optimal looping variant, I did want to see if there were any easy wins to be had in the code.</p>
<p>I decided to use the large <!-- raw HTML omitted -->citylots.json<!-- raw HTML omitted --> test file as my benchmark file, and parsed the file twice just to ensure enough work was done to get some good sampling results.</p>
<p>The initial run took 3.106s, averaging 116.5 MB/s throughput. With that baseline, I dived into VTune.</p>
<h2 id="initial-vtune-results">Initial VTune Results</h2>
<p>So I compiled my JSON library using CMake&rsquo;s RelWithDebInfo (<strong>rel</strong>ease <strong>with</strong> <strong>deb</strong>ug <strong>info</strong>) so that PDBs were generated from Visual Studio and I could get meaningful profiling information.</p>
<p>Then I started VTune, added an <em>Analysis Target</em> pointing at my executable, and not knowing a great deal about VTune decided to stick with an <em>Analysis Type</em> of Basic Hotspots and see where that took me.</p>

<img src="/wp-content/uploads/2018/05/PreSummary.png"  class="center"  style="border-radius: 8px;"    />


<p>So VTune says that my CPU time was 3.061s (which matches closely to what I recorded out-with VTune), and has noted the most costly functions in terms of execution time. So I went to the source of the most expensive function there, and looked at the assembly view that VTune gives you, and I found something bad, something very bad!</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Can you notice what heinous crime I have committed? Lets look at the assembly as captured from VTune for the switch statement above:</p>

<img src="/wp-content/uploads/2018/05/PreDoubleLoad.png"  class="center"  style="border-radius: 8px;"    />


<p>Now its not obvious from the switch statement, but every execution of that switch is actually performing two loads, <strong>every iteration of the loop</strong>. Why? Because the compiler doesn&rsquo;t realise that state-&gt;offset cannot be modified outwith the function, and thus it could just cache the value of it into a register and use that!</p>
<p>This is the kind of dumb optimization that it is so easy to miss but so painful for performance when you do miss it. I reworked the code above such that:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And this changed reduced the time in json_parse_number from 0.670s to 0.422s - 1.59x faster!</p>
<h2 id="using-the-same-trick-elsewhere">Using The Same Trick Elsewhere</h2>
<p>Given the big performance win that helping the compiler realise state can live in registers got me, I decided to propagate the change into some other JSON functions that had tight inner loops that would most benefit from the same improvement:</p>
<ul>
<li>json_get_number_size from 0.355s to 0.184s - 1.93x faster</li>
<li>json_get_string_size from 0.175s to 0.115s - 1.52x faster</li>
<li>json_parse_string from 0.191s to 0.137s - 1.39x faster</li>
<li>json_skip_whitespace from 0.473s to 0.354s - 1.34x faster</li>
</ul>
<p>Nice little win with a single optimization trick right there.</p>
<h2 id="two-loops-are-better-than-one">Two Loops Are Better Than One</h2>
<p>The next function that caused me concern was json_skip_all_skippables. This jankily named function will skip whitespace and C-style comments if the user has enabled the C-style comment optional extension.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>When I checked in VTune I noticed that the if branch within the do/while loop was taking more time than it should, and I suddenly realised - the compiler was reloading state-&gt;flags_bitset every iteration of the loop because the compiler does not know that this value will never change during parsing! Big doh moment here. To fix this, I moved the if statement outside the loop, and instead had two separate loops, one that handled C-style comments and one that did not. This simple change meant that json_skip_all_skippables went from 0.289s to 0.257s - a 1.12x speedup!</p>
<h2 id="help-a-branch-out">Help a Branch Out</h2>
<p>Sometimes branches can confuse a compiler, and json_parse_number had a doozy of a branch.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>The switch statement should break out of the switch and the while when it is hit, so to do this I set end to 1, and then checked end == 0 in the loop condition. The compiler wasn&rsquo;t smart enough to skip the end == 0 check on the first iteration for starters, and then it really managed to confuse itself on subsequent iterations. To fix this, I moved the end variable into the loop, and then after the switch statement I check if we&rsquo;ve to end and break the main loop.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>This subtle change meant much better generated code, and shaved a couple of milliseconds off of json_parse_number!</p>
<h2 id="remove-a-useless-ternary">Remove a Useless Ternary</h2>
<p>In json_parse_string I support the quoting of strings by either using single (‘) or double (“) quotes - depending on an extension flag. The code was:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>The optimizer got very confused by the is_single_quote ternary being in the while loop. Given that the quote to use won&rsquo;t be changing iteration to iteration of the loop, I did the simple change to store the quote to compare against at the head of the loop instead:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>I also noticed that if a string begins, it will definitely have at least one iteration in the body of it (otherwise when we earlier called json_get_string_size it would have exited with an error for the user). This meant that I could change the while loop to a do/while loop which aids the codegen too. These changes shaved another few milliseconds off of the execution time.</p>
<h2 id="cache-more-things">Cache More Things!</h2>
<p>I took stock of where I had got to, and decided to do a second sweep of each of the most costly functions to see if there was something I had missed - and of course there was. So previously I had cached just the offset and size from the state object I pass between functions, but I soon realised that I should be caching the src pointer and data pointers too. This helped explain to the compiler that the pointers wouldn&rsquo;t be changing during the body of the functions and their values could remain in registers from the entire functions! I also cached flags_bitset when it was used more than once in the body of the functions - again to stop it running away to memory and back for a constant value that would never be changing.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>This meant there was a lot more constant state at the start of my functions, but less unnecessary accesses during the functions themselves.</p>
<h2 id="one-evening-optimizing-got-us-where">One Evening Optimizing Got Us Where?</h2>
<p>So after all the changes above, I reduced the total time taken for the citylots.json file from 3.106s to 2.548s, a nice 1.22x faster than before! The throughput going from 116.5 MB/s to 142.1 MB/s as a result.</p>
<p>I still don&rsquo;t understand a ton of what VTune offers so I&rsquo;ll have to keep tinkering, but I&rsquo;m happy that it helped me identify some easy wins in my JSON parser anyway. The code for the upgrades is in two commits <!-- raw HTML omitted -->c4b0b90<!-- raw HTML omitted --> and <!-- raw HTML omitted -->e38fd53<!-- raw HTML omitted --> if you want to take a look.</p>
]]></description>
    </item>
    
    <item>
      <title>Optimizing LLVM IR from the C API</title>
      <link>https://www.neilhenning.dev/posts/optimizing-llvm-ir-from-the-c-api/</link>
      <pubDate>Thu, 05 Apr 2018 20:35:55 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/optimizing-llvm-ir-from-the-c-api/</guid>
      <description><![CDATA[<p>After my previous post on <!-- raw HTML omitted -->how to read &amp; write LLVM bitcode<!-- raw HTML omitted -->, I thought I&rsquo;d follow it up with a post on actually modifying LLVM bitcode files after you&rsquo;ve read them. LLVM comes with extensive built-in optimization passes, but also plenty of scope to do your own optimizations too.</p>
<p>First off, remember that that when we parse an LLVM bitcode file, we get an LLVM module. So what exactly <em>is</em> an LLVM module?</p>
<p>An LLVM module is basically a collection of global variables and functions. Functions contain basic-blocks. The simplest way to think about a basic block is a scope in a C/C++ file:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>In the above example, we have three basic-blocks. There is always an <em>entry</em> basic-block, one that is tied to the function itself. Then that basic-block can branch to one or more other basic-blocks. Each basic-block contains one or more instructions.</p>
<p>So now we know the basics of how LLVM is put together, lets look at actually doing an optimization. Just to keep with something trivial, lets do constant folding. Constant folding is when you have an instruction that takes only constant arguments, and so you can replace the instruction with a single constant value instead:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>In the above example you really don&rsquo;t want the compiler to actually do 13 + 42 at runtime, what you want is that it instead uses the constant 55 instead. LLVM already has this sort of optimization, but lets do it ourselves to work through the process.</p>
<p>We&rsquo;ll integrate our new code into the parser I used in my last blog post. Looking back at how we got our LLVM module:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>So we have our LLVM module, now lets start to look for instructions that use constant arguments. So given an LLVM module, we first have to walk the functions within that module:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Then, we walk the basic-blocks of each function:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And finally we walk the instructions in each basic-block:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>So now we are walking every instruction, of every basic-block, of every function, in our module. Now we need to identify instructions that we want to investigate. Just to keep things simple, we&rsquo;ll only try and fold binary operators - things like + - * /.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Once we know we&rsquo;ve got a binary operator, we know we&rsquo;ve got exactly two operands:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And to check if we have constant operands or not we simply do:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>So if allConstant is true, we know we can fold the binary operator. To fold the operation, we look at the opcode of the binary operator - this identifies which binary operator it actually is. Then, we turn the binary operator into a constant expression which does the same thing. LLVM will do all the hard work for us when we create a constant expression with known constant values - it&rsquo;ll do the constant folding we want for us.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Now we have our replacement value for the binary operator, we can replace the original instruction with the new constant:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And that&rsquo;s it! Lets run this on a simple example I&rsquo;ve knocked together:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>We can run our code and everything… explodes? You&rsquo;ll get some horrific segfault deep in LLVM and run away screaming, if you didn&rsquo;t know what the cause is. Basically when hacking with an LLVM module, you&rsquo;ve got to be <em>super</em> careful about deleting instructions, basic-blocks or functions while you are still iterating through the lists. You either need to store all the values and do all the replacements after you&rsquo;ve finished with the iterators, or handle the replacements very carefully.</p>
<p>So the way I do it when iterating using the C API is to remember the last instruction in the instruction stream, and then if I happen to replace the current instruction and delete it, I know I can look at the last instruction and pick up the remainder of the instruction stream from there.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>So now we are correctly handling the case where we are removing instructions within the instruction stream. So if we compile and run everything again, what do we get? So for the example I showed above, after I&rsquo;ve run my bitcode read -&gt; constant fold -&gt; bitcode write, I get the following LLVM IR:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Nice! That looks like much more optimal code.</p>
<p>I will note that this is not how real LLVM passes work (they are full C++ with classes and templates), but it does allow you to easily work with LLVM IR yourself.</p>
<p>I&rsquo;ve updated my <!-- raw HTML omitted -->llvm_bc_parse_example<!-- raw HTML omitted --> to <!-- raw HTML omitted -->include this optimization code<!-- raw HTML omitted -->.</p>
<p>I hope this proves useful to any budding compiler engineers who want to start tinkering with LLVM!</p>
]]></description>
    </item>
    
    <item>
      <title>How to read &amp;#038; write LLVM bitcode</title>
      <link>https://www.neilhenning.dev/posts/how-to-read-write-llvm-bitcode/</link>
      <pubDate>Thu, 29 Mar 2018 20:57:22 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/how-to-read-write-llvm-bitcode/</guid>
      <description><![CDATA[<p>I&rsquo;ve read multiple posts on social media now complaining about how scary LLVM is to get to grips with. It doesn&rsquo;t help that the repository is ginormous, there are frequently hundreds of commits a day, the mailing list is nearly impossible to keep track of, and the resulting executables are topping 40Mb now…</p>
<p>Those tidbits aside - LLVM is <em>super</em> easy to work with once you get to grips with the beast that it is. To help aid people in using LLVM, I thought I&rsquo;d put together the most trivial no-op example you can do with LLVM - parsing one of LLVM&rsquo;s intermediate representation files (known as bitcode, file extension .bc) and then writing it back out.</p>
<p>Firstly, lets go through some high level LLVM terms:</p>
<ul>
<li>LLVM&rsquo;s main abstraction for user code is the <em>Module</em>. It&rsquo;s a class that contains all the functions, global variables, and instructions for the code you or other users write.</li>
<li>Bitcode files are effectively a serialization of an LLVM Module such that it can be reconstructed in a different program later.</li>
<li>LLVM uses <em>MemoryBuffer</em> objects to handle data that comes from files, stdin, or arrays.</li>
</ul>
<p>For my example, we&rsquo;ll use the LLVM C API - a more stable abstraction ontop of LLVM&rsquo;s core C++ headers. The C API is really useful if you&rsquo;ve got code that you want to work with multiple versions of LLVM, it&rsquo;s significantly more stable than the LLVM C++ headers. (An aside, I use LLVM extensively for my job and nearly every week some LLVM C++ header change will break our code. I&rsquo;ve never had the C API break my code.)</p>
<p>First off, I&rsquo;m going to assume you&rsquo;ve pulled LLVM, built and installed it. Some simple steps to do this:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>After doing the above, you&rsquo;ll have an LLVM install in <!-- raw HTML omitted -->/build/install!</p>
<p>So for our little executable I&rsquo;ve used CMake. CMake is by far the easiest way to integrate with LLVM as it is the build system LLVM also uses.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>So now we&rsquo;ve got our CMake setup, and we can use our existing LLVM install, we can now get working on our actual C code!</p>
<p>So to use the LLVM C API there is one header you basically always need:</p>
<!-- raw HTML omitted -->
<p>And two extra headers we need for our executable are the bitcode reader and writer:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Now we create our main function. I&rsquo;m assuming here that we always take exactly 2 command line arguments, the first being the input file, the second being the output file. LLVM has a system whereby if a file named ‘-‘ is provided, that means read from stdin or write to stdout, so I decided to support that too:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>So first we parse the input file. We&rsquo;ll create an LLVM memory buffer object from either stdin, or a filename:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>So after this code, memoryBuffer will be usable to read our bitcode file into an LLVM module. So lets create the module!</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Once we&rsquo;ve got our module, we no longer need the memory buffer, so we can free up the memory straight away. And that&rsquo;s it! We&rsquo;ve managed to take an LLVM bitcode file, deserialize it into an LLVM module, which we <em>could</em> (I&rsquo;m not going to in this blog post at least!) fiddle with. So lets assume you&rsquo;ve done all you wanted with the LLVM module, and want to write the sucker back out to a bitcode file again.</p>
<p>The approach is orthogonal to the reading approach, we look for the special filename ‘-‘ and handle accordingly:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Lastly, we should be good citizens and clean up our garbage, so also delete the module to:</p>
<!-- raw HTML omitted -->
<p>And that&rsquo;s it! You are now able to parse and then write an LLVM bitcode file. I&rsquo;ve put the full example up here on GitHub - <!-- raw HTML omitted --><a href="https://github.com/sheredom/llvm_bc_parsing_example">https://github.com/sheredom/llvm_bc_parsing_example</a><!-- raw HTML omitted -->.</p>
<p>Maybe I&rsquo;ll do a follow-up post at some point taking you through the basics of how to do things to an LLVM module, but for now, adieu!</p>
]]></description>
    </item>
    
    <item>
      <title>Adding Latin and Greek support to utf8.h!</title>
      <link>https://www.neilhenning.dev/posts/adding-latin-and-greek-support-to-utf8-h/</link>
      <pubDate>Sun, 11 Feb 2018 22:37:06 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/adding-latin-and-greek-support-to-utf8-h/</guid>
      <description><![CDATA[<p>I&rsquo;ve had a lot of people using my unicode library <!-- raw HTML omitted -->utf8.h<!-- raw HTML omitted --> since its release - thanks to all who&rsquo;ve found the library useful and provided feedback!</p>
<p>One of the things that I&rsquo;d scrimped on previously was my support for case-insensitive comparisons for letters beyond those in ASCII. I knew little about this, but when <!-- raw HTML omitted -->a user requested<!-- raw HTML omitted --> that my library also supported accented latin characters, and later greek symbols, I jumped to the occassion to add support.</p>
<p>The following utf8 functions utf8casecmp, utf8ncasecmp, utf8casestr, utf8isupper, utf8islower, utf8lwr, and utf8upr, have been modified to support the Latin-1 Supplement, Latin Extended-A, Latin Extended-B, and Greek &amp; Coptic unicode sections. I&rsquo;ve also added two new functions utf8lwrcodepoint and utf8uprcodepoint that&rsquo;ll make a single codepoint upper or lower case.</p>
<p>The main logic of how you convert between the lower and upper cases is both <em>slightly concise</em> and <em>utterly disgusting</em>. Lets take a look at the code to convert a lower case codepoint to an upper case.</p>
<p>For ASCII characters, and also some Latin and Greek, the upper case codepoints are simply 32 places below the lower case ones:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>The next set of codepoints are offset by 1 between the lower and upper cased variants. Depending on whether the lower case codepoint was odd or even, we have two if statements that handle both cases:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And lastly, for all other codepoints in the ranges that don&rsquo;t have <em>any sane approach whatsoever</em>, we&rsquo;ll fire them all into a single big switch statement:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>With the above, we can handle all the lower/upper case variants for the Latin and Greek characters requested!</p>
<p>I hope these additions are found to be useful to my users, and if you&rsquo;ve got any requests yourself feel free <a href="https://github.com/sheredom/utf8.h/issues/new">to file them here</a>.</p>
]]></description>
    </item>
    
    <item>
      <title>Introducing process.h!</title>
      <link>https://www.neilhenning.dev/posts/introducing-process-h/</link>
      <pubDate>Sun, 24 Dec 2017 16:45:36 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/introducing-process-h/</guid>
      <description><![CDATA[<p>I&rsquo;ve long been after a cross-platform way to launch processes and interact with them for use from C &amp; C++. After a brief scouring of the interwebs, I didn&rsquo;t find any that matched my criteria:</p>
<ul>
<li>No build system dependencies.</li>
<li>Works in C and C++.</li>
<li>Works on Windows, Linux and macOS.</li>
<li>Single header (or at least single header / single source file).</li>
</ul>
<p>So I did what I always do when confronted with this issue - I wrote my own!</p>
<p><!-- raw HTML omitted -->process.h<!-- raw HTML omitted --> is a cross-platform C &amp; C++ single header library that works on Windows, Linux and macOS. It contains six functions that let you:</p>
<ul>
<li>Launch a process (<!-- raw HTML omitted -->process_create<!-- raw HTML omitted -->).</li>
<li>Get the stdin, stdout, and stderr FILE objects of the launched process to feed/read from the child (<!-- raw HTML omitted -->process_stdin<!-- raw HTML omitted -->, <!-- raw HTML omitted -->process_stdout<!-- raw HTML omitted -->, and <!-- raw HTML omitted -->process_stderr<!-- raw HTML omitted -->).</li>
<li>Wait on a launched process to finish (<!-- raw HTML omitted -->process_join<!-- raw HTML omitted -->).</li>
<li>Destroy a process (<!-- raw HTML omitted -->process_destroy<!-- raw HTML omitted -->).</li>
</ul>
<p>There are some gotchas to know about:</p>
<ul>
<li>Waiting a process will close the FILE associated with the stdin of the child. I need to do this so that any process that is waiting and reading the entire contents of the stdin can finish.</li>
<li>You can destroy a process before it has completed - this will close the stdin, stdout, and stderr of the child process and free the handle of the child process. This will allow a child process to outlive the parent process if required - you need to call process_join before process_destroy if you want to wait and then destroy the launched process.</li>
</ul>
<p>Hopefully this proves useful to some of my followers! I&rsquo;ve <!-- raw HTML omitted -->recorded some todos<!-- raw HTML omitted --> of things I want to add to the library (which will include an interface change at a later date) - so stay tuned.</p>
]]></description>
    </item>
    
    <item>
      <title>Cross compiling Sollya to Windows with Emscripten</title>
      <link>https://www.neilhenning.dev/posts/cross-compiling-sollya-to-windows-with-emscripten/</link>
      <pubDate>Mon, 13 Nov 2017 10:31:51 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/cross-compiling-sollya-to-windows-with-emscripten/</guid>
      <description><![CDATA[<p>One component of Codeplay&rsquo;s <!-- raw HTML omitted -->ComputeAorta<!-- raw HTML omitted --> that I manage is our high precision maths library Abacus.</p>
<p>One major component of Abacus, and in fact all math libraries, are a requirement to have <!-- raw HTML omitted -->remez reduced polynomial approximations<!-- raw HTML omitted --> of functions. In the past we&rsquo;ve made use of <!-- raw HTML omitted -->Maple<!-- raw HTML omitted -->, <!-- raw HTML omitted -->Mathematica<!-- raw HTML omitted -->, <!-- raw HTML omitted -->lolremez<!-- raw HTML omitted -->, our own fork of lolremez, and to be honest none of them have been satisfactory to our needs. We want a scriptable solution that we can use to bake the generated polynomials automatically into Abacus with minimal user intervention.</p>
<p>I was lucky enough to be involved in a <!-- raw HTML omitted -->twitter thread<!-- raw HTML omitted --> with <!-- raw HTML omitted -->Marc B. Reynolds<!-- raw HTML omitted --> where he pointed me at Sollya. It&rsquo;s Linux only which sucks (I&rsquo;m primarily a Windows developer), but I fired up a VM and tried it out - and I&rsquo;ve got to say, its pretty darn good! The non-Windows support is a big issue though, so how to fix that?</p>
<h3 id="enter-stage-left---emscripten">Enter stage left - Emscripten!</h3>
<p>So I&rsquo;ve known about <!-- raw HTML omitted -->Emscripten<!-- raw HTML omitted --> for a while, but never had a really compelling reason to use it. I suddenly thought <em>‘I wonder if I could use Emscripten to compile Sollya to JavaScript, then use <!-- raw HTML omitted -->Node.js<!-- raw HTML omitted --> to run it on Windows?&rsquo;</em>.</p>
<p>Yep, you are right, I&rsquo;m mad. This <strong>can&rsquo;t</strong> be a good way to take software meant for Linux and cross compile it for Windows, right? That just made me all the more curious to see if it could work.</p>
<h3 id="sollya-and-all-its-dependencies">Sollya and all its dependencies</h3>
<p>Sollya requires a bunch of different projects to work: <a href="http://xmlsoft.org/">libxml2</a>, <!-- raw HTML omitted -->GMP<!-- raw HTML omitted -->, <a href="http://www.mpfr.org">MPFR</a>, <a href="http://mpfi.gforge.inria.fr/">MPFI</a>, <a href="https://github.com/fplll">fplll</a>, and lastly <a href="http://sollya.gforge.inria.fr">Sollya</a> itself. So I first downloaded all of these, built them all from source, and built Sollya using gcc on Linux - just to test that I could build it.</p>
<p>Then, using Emscripten&rsquo;s emconfigure (which you place before the typical linux call to ./configure) it replaces any compiler usage with the Emscripten compiler emcc, we can try and build Sollya again but for JavaScript!</p>
<p>So I started with libxml2, which worked! And then onto GMP - and explosions. Some stack overflowing pointed me to <!-- raw HTML omitted -->Compiling GMP/MPFR with Emscripten<!-- raw HTML omitted --> which states that for some reason (I didn&rsquo;t dig into why) Emscripten couldn&rsquo;t compile GMP if the host platform was not 32 bits. I looked at the answer where it suggests you chroot and thought <em>‘that seems like a lot of work to mess with my current 64-bit VM that I do other things on, I&rsquo;ll fire up a new VM to mess with&rsquo;</em>. But since I&rsquo;m creating a new VM anyway, I decided to just create a 32-bit Ubuntu VM and use that instead (which meant less configuration work on my part).</p>
<p>So with my 32-bit VM, I started the whole process of compiling libxml2, gmp, mpfr, mpfi, fplll (wow I&rsquo;m on a roll!) and finally I get to Sollya and… it failed.</p>
<h3 id="sollya-and-dlopen">Sollya and dlopen</h3>
<p>Sollya makes use of dlopen, and thus the ./configure script in Sollya will check that dlopen is a command that works on the target platform. The problem is, ./configure doesn&rsquo;t use the correct signature for the dlopen call - it just does:</p>
<!-- raw HTML omitted -->
<p>and then ensures that the linker doesn&rsquo;t complain when this is linked against -ldl. The signature of dlopen is:</p>
<!-- raw HTML omitted -->
<p>and Emscripten looks for that <strong>exact</strong> signature, and complains if the function doesn&rsquo;t have the correct number and type of arguments. This meant as far as ./configure was concerned, the system didn&rsquo;t have dlopen (even though Emscripten can stub implement it), and it failed.</p>
<p>Ever the hacker, I just decided to patch the ./configure to not error out:</p>
<!-- raw HTML omitted -->
<p>tried to build again, and Sollya built!</p>
<h3 id="emscripten-and-bcs">Emscripten and .bc&rsquo;s</h3>
<p>Emscripten seems to output an LLVM bitcode (.bc) file by default - and I couldn&rsquo;t work out how to tell emconfigure to output a JavaScript file instead.</p>
<p>So what I did was take the bitcode file that was in <em>‘sollya&rsquo;</em> and used emcc directly to turn this into a JavaScript file.</p>
<p>emcc complained if the input bitcode file wasn&rsquo;t named <!-- raw HTML omitted -->.bc, so I first renamed it to sollya.bc:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>and I got a whopping 27MB JavaScript file out!</p>
<p>Next I used node to run this JavaScript against a simple test script I wrote:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>and ran Node.js:</p>
<!-- raw HTML omitted -->
<p>and it ran!</p>
<p>But it kept on running, like infinite-loop running - the thing just never stopped. I was getting a ton of <em>‘sigaction not implemented&rsquo;</em> messages, so I wondered if Sollya was doing something really ugly with signals to handle exiting from a script. I thought about digging into it, then realised Sollya has an explicit <em>‘quit;&rsquo;</em> command, so I added that to the bottom of the script:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>and it ran and exited as expected.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>So now I have a JavaScript file that works when I run it through Node.js, but we&rsquo;ve got a couple of issues:</p>
<ul>
<li>The JavaScript is freaking huge!</li>
<li>We don&rsquo;t want to require Node.js to be installed either for our developers.</li>
</ul>
<h3 id="file-size">File size</h3>
<p>Digging into Emscripten I found that there were a couple of options we could use:</p>
<ul>
<li>-O3 - same as all compilers, we can specify that the compiler should optimize the code heavily.</li>
<li>-llvm-lto 2 - this enables all the optimizations to occur on the entire set of bitcode files once they are all linked together. This will allow for a ton more inlining to take place which should help our performance.</li>
</ul>
<p>Adding both these options, the size of the produce sollya.js was 4.1MB! A whopping 6.5x reduction in file size - and its actually optimized properly now too.</p>
<h3 id="creating-a-standalone-windows-binary">Creating a standalone Windows binary?</h3>
<p>So I&rsquo;ve got sollya.js - and I can run this with Node.js on Windows and get actual valid polynomials. But I really want a standalone executable that has no dependencies, is this possible? Searching around, I found out about <!-- raw HTML omitted -->nexe<!-- raw HTML omitted --> - a way to bundle a Node.js application into a single executable. It basically puts Node.js and the JavaScript file into the same executable, and calls Node.js on the JavaScript at runtime. While this isn&rsquo;t _amazing _- would it work?</p>
<p>First off - you have to use nexe on the platform you want to run the end executable on  - so I copied the sollya.js from my VM to my Windows host, and then after installing nexe I ran:</p>
<!-- raw HTML omitted -->
<p>And what do you know - I can run sollya.exe and it works as expected. The downside is that because the executable is shipping an entire copy of Node.js with it - sollya.exe is a whopping 29MB to ship around.</p>
<h3 id="performance">Performance</h3>
<p>I&rsquo;ve compared the natively compiled sollya executable with the JavaScript variant. I ran them 50 times, and averaged out the results.</p>
<!-- raw HTML omitted -->
<pre><code>&lt;th&gt;
  sollyajs
&lt;/th&gt;

&lt;th&gt;
   JS vs Native Performance
&lt;/th&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td&gt;
  4.93946s
&lt;/td&gt;

&lt;td&gt;
  3.6x slower
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<p>So as expected - given that we are running through JavaScript and Node.js, we are 3.6x slower than the natively compiled executable. I&rsquo;m honestly surprised we are not slower (I&rsquo;d heard horror stories of 90x slowdowns with Emscripten) so this seems not too bad to me.</p>
<h3 id="conclusion">Conclusion</h3>
<p>It seems that with Emscripten, in combination with Node.js and Nexe, we can compile a program on Linux to be run entirely on Windows - which is pretty <strong>freaking</strong> cool. There are probably many other more sane ways to do exactly this, but I find it pretty amazing that this is even possible. Now I can ‘natively&rsquo; run a Windows executable which will calculate all the polynomial approximations I need on Windows too - saving our team from having to have a Linux VM when re-generating the polynomials is required.</p>
<h3 id="cmake-script-to-build-sollya-with-emscripten">CMake script to build Sollya with Emscripten</h3>
<p>In case anyone is interested, I use a CMake file to bring in all the dependencies and build Sollya using Emscripten.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></description>
    </item>
    
    <item>
      <title>LLVM &amp;#038; CRT - auto-magically selecting the correct CRT</title>
      <link>https://www.neilhenning.dev/posts/llvm-crt-auto-magically-selecting-the-correct-crt/</link>
      <pubDate>Mon, 06 Nov 2017 12:14:03 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/llvm-crt-auto-magically-selecting-the-correct-crt/</guid>
      <description><![CDATA[<p>LLVM comes with a really useful set of options <strong>LLVM_USE_CRT_<!-- raw HTML omitted --></strong> which allows you to specify a different <strong>C</strong> <strong>R</strong>un<strong>T</strong>ime (CRT) when compiling with Visual Studio. If you want to be able to compile LLVM as a release build, but compile some code that uses it in debug (EG. our <a href="https://www.codeplay.com/products/computesuite/computeaorta">ComputeAorta</a> product that allows customers to implement OpenCL/Vulkan on their hardware insanely quickly), Visual Studio will complain about mixing the differing version of the CRT. By using the <strong>LLVM_USE_CRT_<!-- raw HTML omitted --></strong> option, we can specify that LLVM compiles in a release build, but using a debug CRT.</p>
<p>There is one annoying catch with this though - compiling LLVM can be expensive to build. We&rsquo;ll average 10 minutes build time for a full build of LLVM. We don&rsquo;t want to recompile LLVM, and we don&rsquo;t want to be constantly building different copies of LLVM everytime we pull in the latest commits for 2-4 different versions of the CRT. We want to be able to change a ComputeAorta build from debug/release without having to rebuild LLVM, and we want all this to just work™ without any manual input from a developer.</p>
<h3 id="changing-llvm">Changing LLVM</h3>
<p>So what we need to do is detect which CRT LLVM was built against. My first thought was to allow LLVM to export which CRT it was built against into an LLVM install. LLVM already outputs an <strong>LLVMConfig.cmake</strong> during its install process, so why not just record what CRT was used too? I contacted the <a href="http://lists.llvm.org/pipermail/llvm-dev/2017-July/114923.html">LLVM mailing list asking..</a>. and got no response. I&rsquo;ve found in general if you are not a super active contributor **and **located in the bay area this is a common occurrence. Not wanting to be <em>that guy</em> that nags on the mailing list about things no-one else clearly cares about, how else could I solve it?</p>
<h3 id="detecting-the-crt">Detecting the CRT</h3>
<p>So I reasoned that since the Visual Studio linker could detect and give me a good error message when I was accidentally mixing CRT versions, there must be some information recorded in the library files produced from Visual Studio that said which CRT the library was linked against. Using dumpbin.exe (which is included with Visual Studio) I first called:</p>
<pre tabindex="0"><code>$ dumpbin /? 
Microsoft (R) COFF/PE Dumper Version 14.00.24215.1 
Copyright (C) Microsoft Corporation. All rights reserved. 
 
usage: DUMPBIN [options] [files] 
 
 options: 
 
 /ALL 
 /ARCHIVEMEMBERS 
 /CLRHEADER 
 /DEPENDENTS 
 /DIRECTIVES 
 /DISASM[:{BYTES|NOBYTES}] 
 /ERRORREPORT:{NONE|PROMPT|QUEUE|SEND} 
 /EXPORTS 
 /FPO 
 /HEADERS 
 /IMPORTS[:filename] 
 /LINENUMBERS 
 /LINKERMEMBER[:{1|2}] 
 /LOADCONFIG 
 /NOLOGO 
 /OUT:filename 
 /PDATA 
 /PDBPATH[:VERBOSE] 
 /RANGE:vaMin[,vaMax] 
 /RAWDATA[:{NONE|1|2|4|8}[,#]] 
 /RELOCATIONS 
 /SECTION:name 
 /SUMMARY 
 /SYMBOLS 
 /TLS 
 /UNWINDINFO
</code></pre><p>And through a process of elimination I ran the ‘/DIRECTIVES&rsquo; command against one of the .lib files in LLVM which gave:</p>
<pre tabindex="0"><code>$ dumpbin /DIRECTIVES LLVMCore.lib
Microsoft (R) COFF/PE Dumper Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file LLVMCore.lib

File Type: LIBRARY

   Linker Directives
   -----------------
   /FAILIFMISMATCH:_MSC_VER=1900
   /FAILIFMISMATCH:_ITERATOR_DEBUG_LEVEL=2
   /FAILIFMISMATCH:RuntimeLibrary=MDd_DynamicDebug
   /DEFAULTLIB:msvcprtd
   /FAILIFMISMATCH:_CRT_STDIO_ISO_WIDE_SPECIFIERS=0
   /FAILIFMISMATCH:LLVM_ENABLE_ABI_BREAKING_CHECKS=1
   /DEFAULTLIB:MSVCRTD
   /DEFAULTLIB:OLDNAMES

...
</code></pre><p>And what do you know ‘/FAILIFMISMATCH:RuntimeLibrary=MDd_DynamicDebug&rsquo; is telling the linker to output an error message if the CRT is not the dynamic debug variant! So now I have a method of detecting the CRT from one of LLVM&rsquo;s libraries, how to incorporate that in our build?</p>
<h3 id="cmake-integration">CMake Integration</h3>
<p>LLVM uses CMake for its builds, and thus we also use CMake for our builds. We already include LLVM by specifying the location of an LLVM install like:</p>
<pre tabindex="0"><code>$ cmake -DCA_LLVM_INSTALL_DIR=&amp;lt;directory&amp;gt; .
-- Overriding option &#39;CA_LLVM_INSTALL_DIR&#39; to &#39;&amp;lt;directory&amp;gt;&#39; (default was &#39;&#39;).
</code></pre><p>And then within our CMake we do:</p>
<pre tabindex="0"><code># Setup LLVM/Clang search paths.
list(APPEND CMAKE_MODULE_PATH
  ${CA_LLVM_INSTALL_DIR}/lib/cmake/llvm
  ${CA_LLVM_INSTALL_DIR}/lib/cmake/clang)

# Include LLVM.
include(LLVMConfig)

# Include Clang.
include(ClangTargets)
</code></pre><p>So I added a new <strong>DetectLLVMMSVCCRT.cmake</strong> to our CMake modules and included it just after the ClangTargets include. This does the following:</p>
<ul>
<li>Get the directory of CMAKE_C_COMPILER (always cl.exe in our case).</li>
<li>Look for dumpbin.exe in the same directory.</li>
<li>Get the location of LLVMCore.lib.
<ul>
<li>My reasoning is that most libraries in LLVM <em>could</em> change over time, but the core library of LLVM is unlikely to be moved (I hope!).</li>
</ul>
</li>
<li>Run dumpbin /DIRECTIVES LLVMCore.lib
<ul>
<li>Find the first usage of ‘/FAILIFMISMATCH:RuntimeLibrary='</li>
<li>Get the string that occurs between ‘/FAILIFMISMATCH:RuntimeLibrary=&rsquo; and the next ‘_'</li>
</ul>
</li>
</ul>
<p>And then we&rsquo;ve got the CRT we need to use to build with. To actually set the CRT to use, we can just call LLVM&rsquo;s <strong>ChooseMSVCCRT.cmake</strong> (that ships in an LLVM install), specifying the <strong>LLVM_USE_CRT_<!-- raw HTML omitted --></strong> variables and voila, we&rsquo;ll be using the same CRT as LLVM, and get no linker errors!</p>
<p>The full CMake script is:</p>
<pre tabindex="0"><code>if(NOT CMAKE_SYSTEM_NAME STREQUAL Windows)
  return()
endif()

# Get the directory of cl.exe
get_filename_component(tools_dir &#34;${CMAKE_C_COMPILER}&#34; DIRECTORY)

# Find the dumpbin.exe executable in the directory of cl.exe
find_program(dumpbin &#34;dumpbin.exe&#34; PATHS &#34;${tools_dir}&#34; NO_DEFAULT_PATH)

if(&#34;${dumpbin}&#34; STREQUAL &#34;dumpbin-NOTFOUND&#34;)
  message(WARNING &#34;Could not detect which CRT LLVM was built against - &#34;
                  &#34;could not find &#39;dumpbin.exe&#39;.&#34;)
  return()
endif()

# Get the location in the file-system of LLVMCore.lib
get_target_property(llvmcore LLVMCore LOCATION)

if(&#34;${llvmcore}&#34; STREQUAL &#34;llvmcore-NOTFOUND&#34;)
  message(WARNING &#34;Could not detect which CRT LLVM was built against - &#34;
                  &#34;could not find location of &#39;LLVMCore.lib&#39;.&#34;)
  return()
endif()

# Get the directives that LLVMCore.lib contains
execute_process(COMMAND &#34;${dumpbin}&#34; &#34;/DIRECTIVES&#34; &#34;${llvmcore}&#34;
  OUTPUT_VARIABLE output)

# Find the first directive specifying what CRT to use
string(FIND &#34;${output}&#34; &#34;/FAILIFMISMATCH:RuntimeLibrary=&#34; position)

# Strip away everything but the directive we want to examine
string(SUBSTRING &#34;${output}&#34; ${position} 128 output)

# Remove the directive prefix which we don&#39;t need
string(REPLACE &#34;/FAILIFMISMATCH:RuntimeLibrary=&#34; &#34;&#34; output &#34;${output}&#34;)

# Get the position of the &#39;_&#39; character that breaks the CRT from all else
string(FIND &#34;${output}&#34; &#34;_&#34; position)

# Substring output to be one of the four CRT values: MDd MD MTd MT
string(SUBSTRING &#34;${output}&#34; 0 ${position} output)

# Set all possible CMAKE_BUILD_TYPE&#39;s to the CRT that LLVM was linked against
set(LLVM_USE_CRT_DEBUG &#34;${output}&#34;)
set(LLVM_USE_CRT_RELWITHDEBINFO &#34;${output}&#34;)
set(LLVM_USE_CRT_MINSIZEREL &#34;${output}&#34;)
set(LLVM_USE_CRT_RELEASE &#34;${output}&#34;)

# Include the LLVM cmake module to choose the correct CRT
include(ChooseMSVCCRT)
</code></pre><h3 id="conclusion">Conclusion</h3>
<p>We&rsquo;ve been able to do what we set out to do - auto-magically make our project that uses an LLVM install work reliably even with mixed Debug/Release builds. This has reduced the number of LLVM compiles I do daily by 2x (yay) and also allowed me to stop tracking (and caring) about CRT conflicts and how to avoid them.</p>
]]></description>
    </item>
    
    <item>
      <title>Slides from my Khronos Munich Chapter talk</title>
      <link>https://www.neilhenning.dev/posts/slides-from-my-khronos-munich-chapter-talk/</link>
      <pubDate>Sat, 28 Oct 2017 16:45:11 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/slides-from-my-khronos-munich-chapter-talk/</guid>
      <description><![CDATA[<p>I gave a talk on Friday 13th of October 2017 at the Khronos Munich Chapter titled ‘OpenCL to Vulkan: A Porting Guide’. I covered how to port from the OpenCL API to the Vulkan API, some common problems our customers have faced, and how to fix them. The <a href="https://www.neilhenning.dev/wp-content/uploads/2015/03/OpenCL-to-Vulkan-A-Porting-Guide.pdf">slides are available here</a>.</p>
<p>The talk covered some of the major pitfalls our customers have had in porting OpenCL applications to Vulkan, and also briefly covered the work we did in collaboration with Google and Adobe - <a href="https://github.com/google/clspv">clspv</a>.</p>
<p>I hope the slide deck is useful to those of you who couldn&rsquo;t attend in person.</p>
]]></description>
    </item>
    
    <item>
      <title>I&#39;m speaking at the Munich Khronos Chapter Meeting 13th October 2017</title>
      <link>https://www.neilhenning.dev/posts/im-speaking-at-the-munich-khronos-chapter-meeting-13th-october-2017/</link>
      <pubDate>Thu, 07 Sep 2017 09:56:03 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/im-speaking-at-the-munich-khronos-chapter-meeting-13th-october-2017/</guid>
      <description><![CDATA[<p>Previously I had begun a series of blog posts detailing how to port applications from OpenCL -&gt; Vulkan.</p>
<ol>
<li><!-- raw HTML omitted -->OpenCL -&gt; Vulkan: A Porting Guide (#1)<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->OpenCL -&gt; Vulkan: A Porting Guide (#2)<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->OpenCL -&gt; Vulkan: A Porting Guide (#3)<!-- raw HTML omitted --></li>
</ol>
<p>Instead of continuing this blog series, I&rsquo;m converting the entire contents into a slide deck, and will be presenting it at the <a href="https://www.meetup.com/Khronos-Munchen-Chapter/events/242664238/">Munich Khronos Chapter meeting on the 13th of October 2017</a>.</p>
<p>So please come along and watch myself, and the other great speakers, talk about some fun things you can do with Vulkan!</p>
<p>Look forward to seeing y&rsquo;all there.</p>
]]></description>
    </item>
    
    <item>
      <title>OpenCL -&gt; Vulkan: A Porting Guide (#3)</title>
      <link>https://www.neilhenning.dev/posts/opencl-vulkan-a-porting-guide-3/</link>
      <pubDate>Thu, 29 Jun 2017 16:47:42 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/opencl-vulkan-a-porting-guide-3/</guid>
      <description><![CDATA[<p>Vulkan is the newest kid on the block when it comes to cross-platform, widely supported, GPGPU compute. Vulkan&rsquo;s primacy as the high performance rendering API powering the latest versions of Android, coupled with Windows and Linux desktop drivers from all major vendors means that we have a good way to run compute workloads on a wide range of devices.</p>
<p>OpenCL is the venerable old boy of GPGPU these days - having been around since 2009. A huge variety of software projects have made use of OpenCL as their way to run compute workloads enabling them to speed up their applications.</p>
<p>Given Vulkan&rsquo;s rising prominence, how does one port from OpenCL to Vulkan?</p>
<p>This is a series of blog posts on how to port from OpenCL to Vulkan:</p>
<ol>
<li><!-- raw HTML omitted -->OpenCL -&gt; Vulkan: A Porting Guide (#1)<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->OpenCL -&gt; Vulkan: A Porting Guide (#2)<!-- raw HTML omitted --></li>
</ol>
<p>In this post, we&rsquo;ll cover the different queue synchronization mechanisms in OpenCL and Vulkan.</p>
<h4 id="clfinish-vs-vkwaitforfences">clFinish vs vkWaitForFences</h4>
<p>In the previous post I explained that an OpenCL queue (cl_command_queue) was an amalgamation of two distinct concepts:</p>
<ol>
<li>A collection of workloads to run on some hardware</li>
<li>A thing that will run various workloads and allow interactions between them</li>
</ol>
<p>Whereas Vulkan uses a VkCommandBuffer for 1, and a VkQueue for 2.</p>
<p>One common synchronization users want to do is let a queue execute a bunch of work, and wait for all that work to be done.</p>
<p>In OpenCL, you can wait on all previously submitted commands to a queue by using clFinish.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>In Vulkan, because a queue is just a thing to run workloads on, we instead have to wait on the command buffer itself to complete. This is done via a VkFence which is specified when submitting work to a VkQueue.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>One thing to note is that you can wait on a Vulkan queue to finish all submitted workloads, but remember the difference between Vulkan queues and OpenCL queues. Vulkan queue&rsquo;s are <em>retrieved from</em> a device. If multiple parts of your code (including third party libraries) retrieve the same Vulkan queue and are executing workloads on it, you will end up waiting for someone else&rsquo;s work to complete.</p>
<p>TL;DR - waiting on a queue in Vulkan is not the same as OpenCL.</p>
<h4 id="dependencies-within-a-cl_command_queue--vkcommandbuffer">Dependencies within a cl_command_queue / VkCommandBuffer</h4>
<p>Both OpenCL and Vulkan have mechanisms to ensure a command will only begin executing once another command has completed.</p>
<p>Firstly, remember that an OpenCL command queue by default will be <em>in order</em>. What this means is that by default when you submit commands into an OpenCL command queue each command will only begin executing once the preceding command has completed. While this isn&rsquo;t ideal in a number of situations for performance, it is advantageous for users to get up and running in a safe and quick manner.</p>
<p>OpenCL also allows command queue&rsquo;s to be <em>out of order</em>. This means that commands submitted to a queue are guaranteed to be dispatched <em>in order</em> but that they may run concurrently and/or complete <em>out of order</em>.</p>
<p>Using an <em>out of order</em> OpenCL queue, to get commands to wait on other commands before beginning executing, you use a cl_event to create a dependency between both the commands.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>We can guarantee that if queue above was an <em>out of order</em> queue, the commands would still be executed <em>in order</em> because we expressed the dependency between both commands.</p>
<p>In Vulkan queues are <em>out of order</em>. There is also <strong>no exact matching</strong> mechanism to get two arbitrary commands to depend on one another. Vulkan relies on more knowledge of what you are actually trying to do to create the right kind of synchronization between commands.</p>
<p>The easiest (and in no way more performant) way to map OpenCL code with an event dependency between two commands, or if the OpenCL queue was created <em>in order</em>, is to have separate Vulkan command buffers for each command. While this might seem crude, it&rsquo;ll allow you to use another of Vulkan&rsquo;s synchronization mechanisms to solve the problem - the semaphore.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>A Vulkan semaphore allows you to express dependencies between command buffers. So by placing each command into a command buffer we can use a semaphore between these command buffers to emulate the OpenCL behaviour of _in order _queues and arbitrary command dependencies.</p>
<p>As with everything in Vulkan - the way to get performance is to explain to the driver exactly what you intend to do. In our example where we are copying data from buffer A -&gt; buffer B -&gt; buffer C above, we are basically creating a dependency on our usage of buffer B. The copy from buffer B -&gt; buffer C cannot begin until the copy from buffer A -&gt; buffer B has complete. So Vulkan gives us the tools to tell the driver about this dependency explicitly, and we can use them within a single command buffer.</p>
<p>The most analogous approach to the OpenCL example is to use a Vulkan event to encode the dependency.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Note that we create the event explicitly with Vulkan, unlike in OpenCL where any clEnqueue* command has an optional out_event parameter as the last parameter.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>So to do a similar thing to OpenCL&rsquo;s event chaining semantics we:</p>
<ol>
<li>add our buffer A -&gt; buffer B copy command</li>
<li>set an event that will trigger when <em>all previous commands</em> are complete, in our case the current set of all previous commands is the one existing copy buffer command</li>
<li>wait for the previous event to complete, specifying that all memory operations that performed a write _before _this wait must be resolved, and that all read operations <em>after</em> this event can read them</li>
<li>add our buffer B -&gt; buffer C copy command</li>
</ol>
<p>Now we can be even more explicit with Vulkan and specifically use VK_ACCESS_TRANSFER_READ_BIT and VK_ACCESS_TRANSFER_WRITE_BIT - but I&rsquo;m using the much more inclusive VK_ACCESS_MEMORY_READ_BIT and VK_ACCESS_MEMORY_WRITE_BIT to be clear what OpenCL will be doing implicitly for you as a user.</p>
<h4 id="dependencies-between-multiplecl_command_queues--vkcommandbuffers">Dependencies between multiple cl_command_queue&rsquo;s / VkCommandBuffer&rsquo;s</h4>
<p>When synchronizing between multiple cl_command_queue&rsquo;s in OpenCL we use the exact same mechanism as with one queue.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>The command queue <em>queue2</em> will not begin executing the copy buffer command until the first command queue <em>queue1</em> has completed its execution. Having the same mechanism for creating dependencies within a queue and outwith a queue is a very nice thing from a user perspective - there is <strong>one true way</strong> to create a synchronization between commands in OpenCL.</p>
<p>In Vulkan, when we are wanting to create a dependency between two VkCommandBuffer&rsquo;s the easiest way is to use the semaphore approach I showed above. You could also use a VkEvent that is triggered at the end of one command buffer and waited on at the beginning of another. If you want to amortize the cost of doing multiple submits to the <em>same</em> queue, then use the event approach.</p>
<p>You can also use both of these mechanisms to create dependencies between multiple Vulkan queues. Remember that a Vulkan queue can be thought of as an exposition of some physical concurrency in the hardware, or in other words, running things on two distinct queues concurrently can lead to a performance improvement.</p>
<p>I recommend using a semaphore as the mechanism to encode dependencies between queues for the most part as it is simpler to get right.</p>
<p>The main place where using the event approach is when you have a long command buffer, where after only a few commands you can unblock the concurrently runnable queue to begin execution. In this case you&rsquo;d be better using an event as that will enable the other queue to begin executing much earlier than would previously be possible.</p>
<h4 id="clenqueuebarrierwithwaitlist-vs-vkcmdpipelinebarrier">clEnqueueBarrierWithWaitList vs vkCmdPipelineBarrier</h4>
<p>Both OpenCL and Vulkan have a barrier that acts as a memory and execution barrier. When you have a pattern whereby you have N commands that must have completed execution before another M commands begin, a barrier is normally the answer.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And the corresponding Vulkan:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<h4 id="whats-next">What&rsquo;s next?</h4>
<p>After this monstrous dive into porting OpenCL&rsquo;s synchronization mechanisms to Vulkan, in the next post we&rsquo;ll look at the differences between OpenCL&rsquo;s kernels and Vulkan&rsquo;s pipelines - stay tuned!</p>
]]></description>
    </item>
    
    <item>
      <title>OpenCL -&gt; Vulkan: A Porting Guide (#2)</title>
      <link>https://www.neilhenning.dev/posts/opencl-vulkan-a-porting-guide-2/</link>
      <pubDate>Fri, 16 Jun 2017 13:20:36 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/opencl-vulkan-a-porting-guide-2/</guid>
      <description><![CDATA[<p>Vulkan is the newest kid on the block when it comes to cross-platform, widely supported, GPGPU compute. Vulkan&rsquo;s primacy as the high performance rendering API powering the latest versions of Android, coupled with Windows and Linux desktop drivers from all major vendors means that we have a good way to run compute workloads on a wide range of devices.</p>
<p>OpenCL is the venerable old boy of GPGPU these days - having been around since 2009. A huge variety of software projects have made use of OpenCL as their way to run compute workloads enabling them to speed up their applications.</p>
<p>Given Vulkan&rsquo;s rising prominence, how does one port from OpenCL to Vulkan?</p>
<p>This is a series of blog posts on how to port from OpenCL to Vulkan:</p>
<ol>
<li><a href="https://www.neilhenning.dev/opencl-vulkan-a-porting-guide-1/">OpenCL -&gt; Vulkan: A Porting Guide (#1)</a></li>
</ol>
<p>In this post, we&rsquo;ll cover porting from OpenCL&rsquo;s cl_command_queue to Vulkan&rsquo;s VkQueue.</p>
<h4 id="cl_command_queue---vkcommandbuffer-andvkqueue">cl_command_queue -&gt; VkCommandBuffer and VkQueue</h4>
<p>OpenCL made a poor choice when cl_command_queue was designed. A cl_command_queue is an amalgamation of two very distinct things:</p>
<ol>
<li>A collection of workloads to run on some hardware</li>
<li>A thing that will run various workloads and allow interactions between them</li>
</ol>
<p>Vulkan broke this into the two constituent parts, for 1. we have a VkCommandBuffer, an encapsulation of one or more commands to run on a device. For 2. we have a VkQueue, the thing that will actually run these commands and allow us to synchronize on the result.</p>
<p>Without diving too deeply, Vulkan&rsquo;s approach allows for a selection of commands to be built once, and then run multiple times. For a huge number of compute workloads we run on datasets, we&rsquo;re running the same set of commands thousands of times - and Vulkan allows us to amortise the cost of building up this collection of commands to run.</p>
<p>Back to OpenCL, we use <!-- raw HTML omitted -->clCreateCommandQueue<!-- raw HTML omitted --> (for pre 2.0) / <!-- raw HTML omitted -->clCreateCommandQueueWithProperties<!-- raw HTML omitted --> to create this amalgamated ‘collection of things I want you to run and a way of running them&rsquo;. We&rsquo;ll enable CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE as that is the behaviour of a Vulkan VkQueue (although remember that not all OpenCL devices actually support out of order queues - I&rsquo;m doing this to allow the mental mapping of how Vulkan executes command buffers on queues to bake into your mind).</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>The corresponding object in Vulkan is the VkQueue - which we <em>get</em> from the device, rather than <em>creating</em> as OpenCL does. This is because a queue in Vulkan is more like a physical aspect of the device, rather than some software construct - this isn&rsquo;t mandated in the specification, but its a useful mental model to adopt when thinking about Vulkan&rsquo;s queues.</p>
<p>Remember that when we created our VkDevice we requested which queue families we wanted to use with the device? Now to actually get a queue that supports compute, we have to choose one of the queue family indices that supported compute, and get the corresponding VkQueue from that queue family.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<h4 id="clenqueue-vs-vkcmd">clEnqueue* vs vkCmd*</h4>
<p>To actually execute something on a device, OpenCL uses commands that begin with clEnqueue* - this command will enqueue work onto a command queue and <em>possibly</em> begin execution it. Why possibly? OpenCL is utterly vague on when commands actually begin executing. The specification states that a call to clFlush, clFinish, or clWaitForEvents on an event that is being signalled by a previously enqueued command on a command queue will guarantee that the device has actually begun executing. It is entirely valid that an implementation begin executing work when the clEnqueue* command is called, and equally valid that the implementation delays until a bunch of clEnqueue* commands are in the queue and the corresponding clFlush/clFinish/clWaitForEvents is called.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>In contrast, Vulkan requires us to submit all our commands into a VkCommandBuffer. First we need to create the command buffer.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Now we have our command buffer with which we can queue up commands to execute on a Vulkan queue.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Vulkan gives us many more ways to synchronize on host for when we are complete with our workload. We can specify a VkFence to our queue submission to wait on one of more command buffers in that submit, we can wait for the queue to be idle, or even wait for the entire device to be idle! Fences and command buffers can be reused by calling VkResetFences and VkResetCommandBuffer respectively - note that the command buffer can be reused for an <em>entirely different</em> set of commands to be executed. If you wanted to resubmit the exact same command buffer, you&rsquo;d have to remove VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT flag in the VkCommandBufferBeginInfo struct above.</p>
<p>So a crucial thing to note here - synchronizing on a cl_command_queue is <em>similar</em> to a VkQueue, but the mechanisms are not identical.</p>
<p>We&rsquo;ll cover these queue synchronization mechanisms in more detail in the next post in the series.</p>
]]></description>
    </item>
    
    <item>
      <title>OpenCL -&gt; Vulkan: A Porting Guide (#1)</title>
      <link>https://www.neilhenning.dev/posts/opencl-vulkan-a-porting-guide-1/</link>
      <pubDate>Tue, 06 Jun 2017 19:24:08 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/opencl-vulkan-a-porting-guide-1/</guid>
      <description><![CDATA[<p>Vulkan is the newest kid on the block when it comes to cross-platform, widely supported, GPGPU compute. Vulkan&rsquo;s primacy as the high performance rendering API powering the latest versions of Android, coupled with Windows and Linux desktop drivers from all major vendors means that we have a good way to run compute workloads on a wide range of devices.</p>
<p>OpenCL is the venerable old boy of GPGPU these days - having been around since 2009. A huge variety of software projects have made use of OpenCL as their way to run compute workloads enabling them to speed up their applications.</p>
<p>Given Vulkan&rsquo;s rising prominence, how does one port from OpenCL to Vulkan?</p>
<p>This is part 1 of my guide for how things map between the APIs!</p>
<h4 id="cl_platform_id---vkinstance">cl_platform_id -&gt; VkInstance</h4>
<p>In OpenCL, the first thing you do is get the platform identifiers (using <!-- raw HTML omitted -->clGetPlatformIDs<!-- raw HTML omitted -->).</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Each cl_platform_id is a handle into an individual vendors OpenCL driver - if you had an AMD and NVIDIA implementation of OpenCL on your system, you&rsquo;d get two cl_platform_id&rsquo;s returned.</p>
<p>Vulkan is different here - instead of getting one or more handles to individual vendors implementations, we instead create a single VkInstance (via <!-- raw HTML omitted -->vkCreateInstance<!-- raw HTML omitted -->).</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>This single instance allows us to access <em>multiple</em> vendor implementations of the Vulkan API through a single object.</p>
<h4 id="cl_device_id---vkphysicaldevice">cl_device_id -&gt; VkPhysicalDevice</h4>
<p>In OpenCL, you can query one or more cl_device_id&rsquo;s from each cl_platform_id that we previously queried (via <!-- raw HTML omitted -->clGetDeviceIDs<!-- raw HTML omitted -->). When querying for a device, we can specify a cl_device_type, where you can basically ask the driver to give you its default device (normally a GPU) or for a specific device type. We&rsquo;ll use CL_DEVICE_TYPE_ALL, in that we are instructing the driver to return all the devices it knows about, and we can choose from them.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>The code above is a bit of a mouthful - but it is the easiest way to get every device that the system knows about.</p>
<p>In contrast, since Vulkan gave us a single VkInstance, we query that single instance for all of the VkPhysicalDevice&rsquo;s it knows about (via <!-- raw HTML omitted -->vkEnumeratePhysicalDevices<!-- raw HTML omitted -->). A Vulkan physical device is a link to the <em>actual hardware</em> that the Vulkan code is going to execute on.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>A prominent API design fork can be seen between vkEnumeratePhysicalDevices and clGetDeviceIDs - Vulkan reuses the integer return parameter to the function (the parameter that lets you query the number of physical devices present) to also pass into the driver the number of physical devices we want filled out. In contrast, OpenCL uses an extra parameter for this. These patterns are repeated throughout both APIs.</p>
<h4 id="cl_context---vkdevice">cl_context -&gt; VkDevice</h4>
<p>Here is where it gets trickier between the APIs. OpenCL has a notion of a context - you can think of this object as your way as the user to view and interact with what the system is doing. OpenCL allows multiple device&rsquo;s that belong to a single platform to be shared within a context. In contrast, Vulkan is fixed to having a single physical device per it&rsquo;s ‘context&rsquo;, which Vulkan calls a VkDevice.</p>
<p>To make the porting easier, and because in all honesty I&rsquo;ve yet to see any real use-case or benefit from having multiple OpenCL devices in a single context, we&rsquo;ll make our OpenCL code create it&rsquo;s cl_context using a single cl_device_id (via <!-- raw HTML omitted -->clCreateContext<!-- raw HTML omitted -->).</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>The above highlights the <strong>single biggest travesty in the OpenCL API</strong> - the error code has changed from being something returned from the API call, to an optional pointer parameter at the end of the signature. In API design, I&rsquo;d say this is rule #1 in how not to mess up an API (If you&rsquo;re interested, these are two great API talks <!-- raw HTML omitted -->Designing and Evaluating Reusable Components<!-- raw HTML omitted --> by <!-- raw HTML omitted -->Casey Muratori<!-- raw HTML omitted --> and <!-- raw HTML omitted -->Hourglass Interfaces for C++ APIs<!-- raw HTML omitted --> by <!-- raw HTML omitted -->Stefanus Du Toit<!-- raw HTML omitted -->).</p>
<p>For Vulkan, when creating our VkDevice object, we specifically enable the features we want to use from the device upfront. The easy way to do this is to first call <!-- raw HTML omitted -->vkGetPhysicalDeviceFeatures<!-- raw HTML omitted -->, and then pass the result of this into our create device call, enabling all features that the device supports.</p>
<p>When creating our VkDevice, we need to explicitly request which queues we want to use. OpenCL has no real analogous concept to this - the naive comparison is to compare VkQueue&rsquo;s against cl_command_queue&rsquo;s, but I&rsquo;ll show in a later post that this is a wrong conflation. Suffice to say, for our purposes we&rsquo;ll query for all queues that support compute functionality, as that is <em>almost</em> what OpenCL is doing behind the scenes in the cl_context.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Vulkan&rsquo;s almost <!-- raw HTML omitted -->legendary verbosity<!-- raw HTML omitted --> strikes here - we&rsquo;re having to write a lot more code than the equivalent in OpenCL to get an <em>almost</em> analogous handle. The plus here is that for the Vulkan driver, it can do a lot more upfront allocations because a much higher proportion of its state is known at creation time - that is the fundamental approach of Vulkan, we are trading upfront verbosity for a more efficient application overall.</p>
<p>Ok - so we&rsquo;ve now got the API to the point where we can think about actually using the plethora of hardware available from these APIs! Stay tuned for the next in the series where I&rsquo;ll cover porting from OpenCL&rsquo;s cl_command_queue to Vulkan&rsquo;s VkQueue.</p>
]]></description>
    </item>
    
    <item>
      <title>Adding JSON 5 to json.h</title>
      <link>https://www.neilhenning.dev/posts/adding-json-5-to-json-h/</link>
      <pubDate>Sat, 11 Mar 2017 19:49:48 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/adding-json-5-to-json-h/</guid>
      <description><![CDATA[<p>I&rsquo;ve added <a href="http://json5.org/">JSON 5</a> support to my <a href="https://github.com/sheredom/json.h">json.h</a> library.</p>
<p>For those not in the know, JSON 5 (<a href="http://json5.org/">http://json5.org/</a>) is a modern update to the JSON standard, including some cool features like unquoted keys, single quoted keys and strings, hexdecimal numbers, Infinity and NaN numbers, and c style comments!</p>
<p>As is sticking with the design of my lib - each of the features can be turned on individually if you don&rsquo;t want the full shebang, or just add <strong>json_parse_flags_allow_json5</strong>** **to enable the entire feature set.</p>
<p>The <a href="https://github.com/sheredom/json.h/pull/50">GitHub pull request</a> brings in the functionality, and it is merged into master too!</p>
]]></description>
    </item>
    
    <item>
      <title>Adding loops (MPC -&gt; LLVM for the Neil Language #5)</title>
      <link>https://www.neilhenning.dev/posts/adding-loops-mpc-llvm-for-the-neil-language-5/</link>
      <pubDate>Sun, 16 Oct 2016 18:45:24 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/adding-loops-mpc-llvm-for-the-neil-language-5/</guid>
      <description><![CDATA[<p>This is part of a series, the first four parts of the series can be found at:</p>
<ol>
<li><!-- raw HTML omitted -->Hooking up MPC &amp; LLVM<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->Cleaning up the parser<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->Adding type identifiers<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->Adding branching<!-- raw HTML omitted --></li>
</ol>
<p>In this post, we&rsquo;ll cover how to add loops to our little toy language I&rsquo;m calling Neil - <strong>N</strong>ot <strong>E</strong>xactly an <strong>I</strong>ntermediate <strong>L</strong>anguage.</p>
<p>To keep things simple, I&rsquo;ve decided to add loops of the form:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<h2 id="grammar-changes">Grammar Changes</h2>
<p>We need to add a new kind of statement to the grammar, one for our while loops:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And with this one change, because we have already handled boolean expression in the additions for branching, we can handle our loops.</p>
<h2 id="how-to-handle-loops">How to Handle Loops</h2>
<p>Loops are basically branching - the only caveat is that we are going to branch <em>backwards</em> to previous, already executed, basic blocks.</p>

<img src="/wp-content/uploads/2016/10/loops.png"  class="center"  style="border-radius: 8px;"    />


<p>For every while statement we create two new basic blocks. Whatever basic block we are in (in the above example one called ‘entry&rsquo;) will then conditionally enter the loop by branching either to the ‘while_body&rsquo; block (that will contain any statements within the while loop), or by branching to the ‘while_merge&rsquo; basic block. Within the body of the loop, the ‘while_body&rsquo; basic block will then conditionally (based on the bexp part of the grammar change) loop back to <em>itself</em>, or to the ‘while_merge&rsquo;. This means that all loops converge as the loop finishes - they will always execute ‘while_merge&rsquo; whether the loop is entered or not.</p>
<h2 id="handling-whiles">Handling Whiles</h2>
<p>To handle while statements:</p>
<ul>
<li>we get an LLVMValueRef for the boolean expression - using LLVMBuildICmp or LLVMBuildFCmp to do so</li>
<li>once we have our expression, we increment the scope as all symbols need to be in the new scope level</li>
<li>we create two new basic blocks, one for ‘while_body&rsquo; and one for ‘while_merge'</li>
<li>we use LLVMBuildCondBr to branch, based on the LLVMValueRef for the condition, to either ‘while_body&rsquo; or ‘while_merge'</li>
<li>we then set the LLVMBuilderRef that we are using to build in the ‘while_body&rsquo; basic block</li>
<li>then we lower the statements in the while statement (which will all be placed within the ‘while_body&rsquo; basic block)</li>
<li>and after all statements in the while statement have been processed, we re-evaluate the boolean expression for the while loop, then use LLVMBuildCondBr to conditionally branch to ‘while_merge&rsquo;, or back to ‘while_body&rsquo; if the while loop had more iterations required</li>
<li>and lastly set the LLVMBuilderRef to add any new statements into the ‘while_merge&rsquo; basic block</li>
</ul>
<p>And it really is that simple! All the changes we made previously to handle if statements meant that this was a really easy change to add to the language.</p>
<h2 id="result">Result</h2>
<p>Now our simple example looks like so:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And turns into the following LLVM IR:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>You can check out the full <!-- raw HTML omitted -->GitHub pull request for the feature here<!-- raw HTML omitted -->.</p>
<p>In the next post, we&rsquo;ll look into how we can add support for pointers to the language, stay tuned!</p>
<p> </p>
]]></description>
    </item>
    
    <item>
      <title>Adding branching (MPC -&gt; LLVM for the Neil Language #4)</title>
      <link>https://www.neilhenning.dev/posts/adding-branching-mpc-llvm-for-the-neil-language-4/</link>
      <pubDate>Thu, 06 Oct 2016 11:53:45 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/adding-branching-mpc-llvm-for-the-neil-language-4/</guid>
      <description><![CDATA[<p>This is part of a series, the first three parts of the series can be found at:</p>
<ol>
<li><!-- raw HTML omitted -->Hooking up MPC &amp; LLVM<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->Cleaning up the parser<!-- raw HTML omitted --></li>
<li><!-- raw HTML omitted -->Adding type identifiers<!-- raw HTML omitted --></li>
</ol>
<p>In this post, we&rsquo;ll cover how to add branching support to our little toy language I&rsquo;m calling Neil - <strong>N</strong>ot <strong>E</strong>xactly an <strong>I</strong>ntermediate <strong>L</strong>anguage.</p>
<p>To keep things simple, I&rsquo;ve decided to add branching of the form:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>With the following caveats:</p>
<ul>
<li>we will not support else branches</li>
<li>we will only support &lt;. &lt;=. &gt;, &gt;=, == and != comparison operators</li>
</ul>
<p>With that in mind, lets get adding it to Neil!</p>
<h2 id="grammar-changes">Grammar Changes</h2>
<p>We need a new type of expression for our grammar - a boolean expression. This is an expression that evaluates to boolean (using a comparison operator).</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Our boolean expression (bexp in the grammar) consists of a left expression (lexp), followed by one of the possible six supported comparison operators, followed by another lexp.</p>
<p>Now, we can modify statements in the grammar to add a new statement type for if statements.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And that is all the changes we need to the grammar.</p>
<h2 id="how-to-handle-branches">How to Handle Branches</h2>
<p>When handling branches, we are going to follow a really simple approach.</p>

<img src="/wp-content/uploads/2016/10/foo-1.png"  class="center"  style="border-radius: 8px;"    />


<p>For every if statement, we&rsquo;ll create two new basic blocks. Whatever basic block we are currently in will then conditionally branch between both blocks, in the true case it will branch to the ‘if_true&rsquo; block, and otherwise to the ‘if_merge&rsquo; block. Within the ‘if_true&rsquo; block, when it is has completed its conditional statements, it will <em>always</em> branch to the ‘if_merge&rsquo; block on exit. This has the really nice property that at the end of every branching sequence we always converge to exactly one active basic block for future statements.</p>
<h2 id="changing-the-symbol-table">Changing the Symbol Table</h2>
<p>One thing of note is that in our Neil language, identifiers can be declared at any place a statement could be. This means that we are allowed to create variables within the if statement. The problem is that at present our symbol table assumes that all symbols declared within a function will be active for the duration of the function. We need to change our symbol table to be aware of the scope that a symbol currently inhabits. A really simple way to do this is to track which scope level a symbol was declared within.</p>
<ul>
<li>when we enter a new function or if statement, we need to increment the scope</li>
<li>when we exit the function or if statement, we need to decrement the scope, and remove all symbols declared associated with that scope</li>
<li>when inserting symbols into the symbol table, they will be inserted at the current scope level</li>
</ul>
<p>For simplicity, I use a std::vector of std::map&rsquo;s, each map in the vector corresponding to a scope level. Then, when we are looking for a symbol we first look in the last element of the std::vector for the symbol, before iterating backwards through the vector. This allows us to reference symbols in higher scope levels too.</p>
<h2 id="handling-ifs">Handling Ifs</h2>
<p>To handle if statements:</p>
<ul>
<li>we get an LLVMValueRef for the boolean expression - using LLVMBuildICmp or LLVMBuildFCmp to do so</li>
<li>once we have our expression, we increment the scope as all symbols need to be in the new scope level</li>
<li>we create two new basic blocks, one for ‘if_true&rsquo; and one for ‘if_merge'</li>
<li>we use LLVMBuildCondBr to branch, based on the LLVMValueRef for the condition, to either ‘if_true&rsquo; or ‘if_merge'</li>
<li>we then set the LLVMBuilderRef that we are using to build in the ‘if_true&rsquo; basic block</li>
<li>then we lower the statements in the if statement (which will all be placed within the ‘if_true&rsquo; basic block)</li>
<li>and after all statements in the if statement have been processed, we use LLVMBuildBr to unconditionally branch to ‘if_merge'</li>
<li>and lastly set the LLVMBuilderRef to add any new statements into the ‘if_merge&rsquo; basic block</li>
</ul>
<p>And that&rsquo;s it! It&rsquo;s actually quite a simple set of steps to get branches working when you break it down into the constituent parts.</p>
<h2 id="result">Result</h2>
<p>Now our simple example looks like so:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And turns into the following LLVM IR:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>You can check out the full <!-- raw HTML omitted -->GitHub pull request for the feature here<!-- raw HTML omitted -->.</p>
<p>In the next post, we&rsquo;ll look into how we can add the other form of useful branching to the language - loops! Stay tuned.</p>
]]></description>
    </item>
    
    <item>
      <title>Introducing YARI-V - an experiment on SPIR-V compression</title>
      <link>https://www.neilhenning.dev/posts/introducing-yari-v-an-experiment-on-spir-v-compression/</link>
      <pubDate>Thu, 29 Sep 2016 14:13:54 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/introducing-yari-v-an-experiment-on-spir-v-compression/</guid>
      <description><![CDATA[<p><!-- raw HTML omitted -->SPIR-V<!-- raw HTML omitted --> is a simple binary intermediate language used for graphics shaders and compute kernels. Wearing my work hat (I work at <!-- raw HTML omitted -->Codeplay Software Ltd.<!-- raw HTML omitted -->) I have been contributing to the SPIR-V specification since 2014 as one of the authors. SPIR-V&rsquo;s primary goals are (as according to me):</p>
<ul>
<li>Have a regular binary structure.</li>
<li>Be easily extendable.</li>
<li>Be easy to validate for correctness.</li>
<li>Be easy to produce from compiler toolchains.</li>
<li>Be easy to consume in tools and drivers.</li>
</ul>
<p>To this end, one of the things that SPIR-V has not prioritised is the size of the resultant binaries. The awesome <!-- raw HTML omitted -->@aras_p<!-- raw HTML omitted --> wrote a great summary of the problem (and his tool <!-- raw HTML omitted -->SMOL-V<!-- raw HTML omitted -->) on his blog - <!-- raw HTML omitted -->SPIR-V Compression<!-- raw HTML omitted -->. The <!-- raw HTML omitted -->SMOL-V<!-- raw HTML omitted --> tool is a single C++ header/single C++ source file.</p>
<p>I&rsquo;m a big fan of single C header libraries, and was curious if I could write a similar tool to his own, written in C, but try to use my knowledge of SPIR-V to get me a better compression ratio. In my previous blog posts ‘<!-- raw HTML omitted -->spirv-stats - a tool to output statistics of your SPIR-V shader modules<!-- raw HTML omitted -->‘ and ‘<!-- raw HTML omitted -->spirv-stats update - exposing more information<!-- raw HTML omitted -->‘ I tried to get an in-depth look into what is taking up the most space in the SPIR-V shaders that <!-- raw HTML omitted -->@aras_p<!-- raw HTML omitted --> was using for testing.</p>
<p>Then, I begun writing my own tool for compressing SPIR-V shaders that I&rsquo;m calling <!-- raw HTML omitted -->YARI-V<!-- raw HTML omitted --> (a yari is a type of <!-- raw HTML omitted -->Japanese spear<!-- raw HTML omitted -->, which seemed appropriate as a sister encoding to SPEAR-V).</p>
<p>In the remainder of this post I&rsquo;ll walk you through the steps I took to compress the SPIR-V shaders that <!-- raw HTML omitted -->@aras_p<!-- raw HTML omitted --> was using for testing, and compare and contrast the result of my own library <!-- raw HTML omitted -->YARI-V<!-- raw HTML omitted --> against <!-- raw HTML omitted -->SMOL-V<!-- raw HTML omitted -->.</p>
<h2 id="test-set">Test Set</h2>
<p>I didn&rsquo;t have handy access to some real world shaders like <!-- raw HTML omitted -->@aras_p<!-- raw HTML omitted --> had for his SMOL-V tool - so I simply used the 341 shaders he uses to test SMOL-V against to test YARI-V against. The total size of the uncompressed shaders is 4868.47 kilobytes, and we&rsquo;ll use a percentage on this size when evaluating the compression attempts that were made.</p>
<h2 id="varint-encoding">Varint Encoding</h2>
<p>The first thing I thought to do was use the varint encoding used in <!-- raw HTML omitted -->Google&rsquo;s Protocol Buffers<!-- raw HTML omitted --> for <em>everything</em>. For the uninitiated, SPIR-V is word based - everything is held in 32 bit values. IDs are in the range [1..N), and ID&rsquo;s <em>should</em> start at 1 and increment from there as more IDs are required. This means that for small shaders, most IDs in use are going to be small unsigned integer numbers. Let&rsquo;s take a look at the OpDecorate instruction for an example:</p>
<!-- raw HTML omitted -->
<pre><code>&lt;th style=&quot;text-align: center;&quot; colspan=&quot;2&quot;&gt;
  word count
&lt;/th&gt;

&lt;th style=&quot;text-align: center;&quot; colspan=&quot;2&quot;&gt;
  opcode
&lt;/th&gt;

&lt;th style=&quot;text-align: center;&quot; colspan=&quot;4&quot;&gt;
  &lt;id&gt; target
&lt;/th&gt;

&lt;th style=&quot;text-align: center;&quot; colspan=&quot;4&quot;&gt;
  decoration
&lt;/th&gt;

&lt;th style=&quot;text-align: center;&quot; colspan=&quot;4&quot;&gt;
  literal*
&lt;/th&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;

&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;

&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;

&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;

&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;

&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;

&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;

&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;

&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;

&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;

&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;

&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;

&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;

&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;

&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;

&lt;td style=&quot;text-align: center;&quot;&gt;
  1
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<p>As we can see, the opcode is made up of:</p>
<ul>
<li>two bytes for the word count</li>
<li>two bytes for the opcode</li>
<li>four bytes for the <!-- raw HTML omitted --> to target this decoration with</li>
<li>four bytes for the decoration itself (an enumeration of values in the range [0..N))</li>
<li>four bytes for each optional literal (some decorations can take other values)</li>
</ul>
<p>What I did was take the word count and varint encode that (this value is normally <em>very</em> low for opcodes) - the only opcodes that could have a word count greater than 127 (the magic cutoff to fit within 1 byte using varint encoding) are the ones that take strings (like OpString, OpName, OpMemberName). This meant that word count was taking 1 byte instead of 2 in <em>most</em> cases.</p>
<p>Next, I varint encoded the opcode. Most of the opcodes we use are below the 127 cutoff for varint encoding, so we can encode this as 1 byte instead of 2 again. The worst case to fit within 2 bytes using varint encoding is 16383, and our maximum opcode at present is in the 4000 range, so we shouldn&rsquo;t ever require more bytes than the original encoding by using varint.</p>
<p>Next, the <!-- raw HTML omitted -->. In small shaders it would be normal for all <!-- raw HTML omitted -->&rsquo;s to be less than 127, but even in large shaders <em>most</em> <!-- raw HTML omitted -->&rsquo;s are likely to be lower than the 2 byte boundary for varint - the value 16383. Given that <!-- raw HTML omitted --> took 4 bytes all the time previously, we are saving at least 2 bytes in nearly all the cases we care about.</p>
<p>The decoration used in OpDecorate currently has [0..44) possible values, so this will always fit inside 1 byte of our varint encoding.</p>
<p>And any literal used by the decoration we&rsquo;ll just varint and hope that it&rsquo;ll be worth it.</p>
<p>After doing this for all opcodes in the SPIR-V shaders, we reduced our SPIR-V shader size to:</p>
<blockquote>
<p>2279.97 kilobytes (46.8%)</p>
</blockquote>
<p>So a pretty healthy start for reducing the size of the binaries!</p>
<h2 id="oplabel---opnop">OpLabel &lt;-&gt; OpNop</h2>
<p>So after varint encoding, the next thing I looked at was the output from my spirv-stats tool. It showed that OpLabel was being used 9915 times in our shaders. OpLabel&rsquo;s opcode value is 248 - which means it requires 2 bytes when varint encoded. So I decided to find another opcode whose value was less than 127 and could thus fit within a 1 byte varint value, that wasn&rsquo;t being used within our shaders. OpNop has the value 0, is used no times within our shaders, so I decided to swap the values of these during encoding, and then swap them back during decoding.</p>
<p>The next thing I noticed was that OpLabel has a constant word count - the number of words it takes is the same for every use of the opcode. Given that this is constant, it means we can not encode the value, and simply infer the constant value of the word count during decoding.</p>
<blockquote>
<p>2260.61 kilobytes 46.43%</p>
</blockquote>
<p>This reduced the size by about 19 kilobytes.</p>
<h2 id="finding-moar-things-to-swap">Finding Moar Things to Swap</h2>
<p>After realising that swapping <!-- raw HTML omitted -->&rsquo;s with greater than 127 value with non-used or little-used smaller than 128 values worked, I decided to go through the next set of most used opcodes (as found from spirv-stats) and swap them, and where possible not encode the word count of the opcode if it was a constant.</p>
<p>I first swapped OpFMul &lt;-&gt; OpSourceContinued, and OpFadd with OpSource:</p>
<blockquote>
<p>2246.63 kilobytes 46.15%</p>
</blockquote>
<p>Then I swapped OpBranch and OpSourceExtension, not encoding the word count of OpBranch:</p>
<blockquote>
<p>2236.58 kilobytes 45.94%</p>
</blockquote>
<p>Then I swapped OpFSub and OpUndef, not encoding OpFSub&rsquo;s word count and also not encoding OpFAdd and OpFMul&rsquo;s word count too:</p>
<blockquote>
<p>2217.26 kilobytes 45.54%</p>
</blockquote>
<p>In total another 43 kilobytes shaved off the size!</p>
<h2 id="delta-encoding">Delta Encoding</h2>
<p>SPIR-V uses a compiler intermediate form known as Single-Static-Assignment (SSA for short) which means the results of opcodes are assigned to an <!-- raw HTML omitted --> once, and that <!-- raw HTML omitted --> is never reassigned to. This means that once we go over the 127 value boundary for an <!-- raw HTML omitted -->, we are going to require 2 bytes for every subsequent <!-- raw HTML omitted --> to be encoded.</p>
<p>For the most part, <!-- raw HTML omitted -->&rsquo;s will be linearly increasing the length of the program, EG. for the current opcode we can be quite confident that the previous opcode had the <!-- raw HTML omitted --> of our <!-- raw HTML omitted --> - 1. Given this fact, I delta encoded our <!-- raw HTML omitted --> to the previous known <!-- raw HTML omitted -->. There was a problem though - what if the previous <!-- raw HTML omitted --> used was actually bigger than our <!-- raw HTML omitted -->? This would result in the subtraction creating a large unsigned integer number, which would take 5 bytes to encode! To get round this, I used a lovely little bit twiddling hack called zig-zag encoding (used in Google&rsquo;s Protocol Buffers, but explained really well <!-- raw HTML omitted -->here<!-- raw HTML omitted -->). Zig-zag encoding allows for all integers in the range [-64..64) to be encoded using one byte when combined with our varint encoding, meaning that even if the previous <!-- raw HTML omitted --> was actually larger than our own, we would still hopefully be able to encode the delta from it to our own <!-- raw HTML omitted --> in 1 or 2 bytes (rather than a worst case of 5 bytes).</p>
<p>I also thought I&rsquo;d try delta encoding our types separately. In general the <!-- raw HTML omitted -->&rsquo;s assigned to types are close to each other in the SPIR-V shaders, because types are all declared in one section at the beginning of the shaders. So I thought by delta encoding the types I&rsquo;d also get a nice little compression.</p>
<blockquote>
<p>2111.88 kilobytes 43.38%</p>
</blockquote>
<p>So doing this shaved a lovely 106 kilobytes off of YARI-V encoded size.</p>
<h2 id="never-encode-a-constant-word-count">Never Encode a Constant Word Count</h2>
<p>I&rsquo;d already shown that not encoding the word count where possible would save us at least 1 byte per opcode we could do this for, so I did a pass over all the opcodes in SPIR-V to not encode the word count for all opcodes where the word count was a constant.</p>
<blockquote>
<p>2081.48 kilobytes 42.75%</p>
</blockquote>
<p>This shaved a further 30 kilobytes off our YARI-V encoded size.</p>
<h2 id="fake-opcodes">Fake Opcodes</h2>
<p>I was a little disappointed that never encoding the constant word count only knocked 30 kilobytes off of our encoded size - then I realised, the most used opcodes in our SPIR-V shaders are all variable length (as per the specification). But are they really? I added some output to spirv-stats to show when OpLoad and OpStore had the optional addition Memory Access literal - and it turns out exactly **** of our OpLoad&rsquo;s and OpStore&rsquo;s used this! So for our purposes, OpLoad and OpStore had a constant word count, they just didn&rsquo;t know it.</p>
<p>What I did was split OpLoad into two encoding, OpLoad, and a new <em>fake</em> opcode called OpLoadWithMemoryAccess. I set the value for OpLoadWithMemoryAccess to above 500 (the largest SPIR-V ID in use at present is in the low 300&rsquo;s, so I hope this is safe enough for the time being), and then when encoding both our OpLoad and OpLoadWithMemoryAccess opcodes their word counts are constant (4 for OpLoad, 5 for OpLoadWithMemoryAccess). Doing this allowed me to save 1-2 bytes for each use of OpLoad (which accounts for 16% of the opcodes in our SPIR-V shaders!)</p>
<blockquote>
<p>2032.74 kilobytes 41.75%</p>
</blockquote>
<p>Next I did the same for OpStore, making a new fake opcode OpStoreWithMemoryAccess, and not encoding the now constant word count for OpStore and OpStoreWithMemoryAccess.</p>
<blockquote>
<p>2004.19 41.17%</p>
</blockquote>
<p>In total shaving 77 kilobytes off of our YARI-V encoded size.</p>
<h2 id="more-decorations">More Decorations</h2>
<p>OpDecorate is the third most used opcode with 8.28% of the total opcodes. I added some information to spirv-stats to output how many of the decorations had no literals and how many had one literal (none of the opcodes available today have more than one). 71% of the opcodes have no literals, and 29% have one. So I decided to split OpDecorate into three encodings, one that contains a decoration that has no literals, one that contains a decoration that has exactly one literal, and one that has two or more literals (to future proof the encoder). This allowed me to make all of our uses of OpDecorate have a constant word count, meaning we do not need to encode it. I also swapped these new fake opcodes with OpLine and OpExtension so their <!-- raw HTML omitted -->&rsquo;s were less than 127.</p>
<blockquote>
<p>1996.46 kilobytes 41.01%</p>
</blockquote>
<p>Shaving 8 kilobytes off of the YARI-V encoding.</p>
<h2 id="moar-member-decorations">Moar Member Decorations</h2>
<p>Given the success of splitting OpDecorate, I decided to do the same with OpMemberDecorate, which is the sixth most used opcode in our SPIR-V shaders. 90% of the uses of OpMemberDecorate had 1 literal, so I decided I&rsquo;d split it into three encodings (just like I did with OpDecorate), one that contains a decoration that has no literals, one that contains a decoration that has exactly one literal, and one that has two or more literals. I also swapping these new fake opcodes with OpExtImport and OpMemoryModel.</p>
<p>I also noticed that I wasn&rsquo;t delta encoding the <!-- raw HTML omitted -->&rsquo;s for the new fake OpDecorate or OpMemberDecorate variants, so I did that too.</p>
<blockquote>
<p>1967.65 kilobytes 40.42%</p>
</blockquote>
<p>All of this resulted in shaving a further 29 kilobytes off of our YARI-V encoding.</p>
<h2 id="non-initialised-variables">(Non) Initialised Variables</h2>
<p>I added a check to spirv-stats to see if any of the OpVariables we were declaring had initialisers - **** of them did. So I added a new encoding for OpVariable that has an initializer, which meant I could skip encoding the word count.</p>
<blockquote>
<p>1949.05 kilobytes 40.03%</p>
</blockquote>
<p>I then applied the same logic to OpConstant - all of our constants were using one word for the actual constant (all of our constants were 32 bit integers and floats), so I could split out the encoding for OpConstant if it was encoding a 64 bit integer of double into a separate opcode, allowing me to not output the word count of our OpConstant&rsquo;s.</p>
<blockquote>
<p>1938.48 kilobytes 39.82%</p>
</blockquote>
<p>Shaving 29 kilobytes off of our YARI-V encoding.</p>
<h2 id="access-chains">Access Chains</h2>
<p>To get a pointer into a composite (say an array or struct) we use OpAccessChain to work out what we want to load. I added some information to spirv-stats to output the number of indices being used with OpAccessChain. 78% were using one index (say indexing into an array), 19% were using two indices (used if you were indexing into an array of structs), and 2% were using three indices.</p>
<p>I decided to split OpAccessChain into four encodings, one that contains one index, one that contains two indices, one that contains three indices, and one for all other index combinations. I also swapped these new fake opcodes with OpExecutionMode, OpCapability and OpTypeVoid)</p>
<blockquote>
<p>1919.76 kilobytes 39.43%</p>
</blockquote>
<p>Shaving 19 kilobytes off of our YARI-V encoding.</p>
<h2 id="everyday-im-shuffling">Everyday I&rsquo;m Shuffling</h2>
<p>OpVectorShuffle takes 3.4% of the opcodes in the SPIR-V shader module, but 6% of the size of the module (it&rsquo;s a lot of bytes per opcode hit).</p>
<p>The first thing I noticed was that OpVectorShuffle was working on at most two vec4&rsquo;s (the SPIR-V shaders I&rsquo;m dealing with are used in Vulkan, where 4 element vectors are the maximum). So I decided to split OpVectorShuffle into four encodings; one that contains two components, one that contains three components, one that contains four components, and one for all other component combinations. I also swapped these with gaps in the SPIR-V opcode range at 8, 13 &amp; 18 opcode values</p>
<blockquote>
<p>1910.26 kilobytes 39.24%</p>
</blockquote>
<p>Only 9 kilobytes shaved, which wasn&rsquo;t so great. My next observation was that, when shuffling two vec4&rsquo;s together, the maximum number of states each component literal could be in was 9, in the range [-1..8) - where -1 denotes that we&rsquo;d want a undefined result in that component of the vector. I checked, and none of our encodings of OpVectorShuffle were using -1, so given that all of our literals are less than 8, we can use 3 bits maximum to encode each literal!. I extended the new OpVectorShuffle encodings I had previously made to encode the literals in at most 2 bytes (1 byte for the two literals case, 2 bytes for the three and four cases).</p>
<blockquote>
<p>1892.43 kilobytes 38.87%</p>
</blockquote>
<p>I next checked how many of our OpVectorShuffle&rsquo;s were actually doing a swizzle - EG. they were taking the same vector <!-- raw HTML omitted --> for both vectors, and were only accessing values from the first vector. A whopping 82% of our OpVectorShuffle&rsquo;s were doing exactly this, so I added some new fake opcodes for OpVectorSwizzle, using 2 bits to encode each literal (in a swizzle at most 4 elements of a vec4 were being shuffled around, which can be encoded in 2 bits).</p>
<blockquote>
<p>1874.17 kilobytes 38.50%</p>
</blockquote>
<p>Shaving a cool 36 kilobytes off of our YARI-V encoded size.</p>
<h2 id="swapshop">Swapshop</h2>
<p>I noticed that OpBranchConditional and OpSelectionMerge were being used enough that requiring 2 bytes to encode their opcodes was silly, so I swapped these with the CL-specific OpTypeEvent and OpTypeDeviceEvent for a further 8 kilobyte reduction in our YARI-V encoded size:</p>
<blockquote>
<p>1868.01 kilobytes 38.37%</p>
</blockquote>
<h2 id="composing">Composing</h2>
<p>OpCompositeExtract and OpCompositeConstruct take a decent amount of space in the SPIR-V binary with 7% of the bytes dedicated to them.</p>
<p>I first split OpCompositeExtract into two encodings; one that has exactly one literal, and one for all other cases:</p>
<blockquote>
<p>1859.28 kilobytes 38.19%</p>
</blockquote>
<p>Then I split split OpCompositeConstruct into four encodings; one that has one constituent, one that has two constituents, one that has three constituents, and one for all other encodings:</p>
<blockquote>
<p>1855.46 kilobytes 38.11%</p>
</blockquote>
<p>Next, I noticed that OpCompositeExtract was being used mostly to lift a scalar from a vector for some scalar calculation. So I detected when OpCompositeExtract was being used with literals in the range [0..4), and added four encodings of OpCompositeExtract; one that assumes the literal is zero, one that assumes it is one, one that assumes it is two, and one that assumes it is three:</p>
<blockquote>
<p>1843.40 kilobytes 37.86%</p>
</blockquote>
<h2 id="relaxing-precisely-while-decorating">Relaxing Precisely While Decorating</h2>
<p>The most used decoration of OpDecorate was RelaxedPrecision - with 66% of the 23770 uses of the opcode encoding that. So I added a new fake opcode for OpDecorateRelaxedPrecision, allowing me to not actually encode the decoration for RelaxedPrecision and skip the unnecessary byte.</p>
<blockquote>
<p>1828.03 kilobytes 37.55%</p>
</blockquote>
<p>I then used the same logic on OpMemberDecorate. The most used decoration with OpMemberDecorate was for Offset - accounting for 90% of the 14332 uses of the opcode. I added a new fake opcode for OpMemberDecorateOffset, to skip outputting the decoration in this most used case.</p>
<blockquote>
<p>1816.17 kilobytes 37.30%</p>
</blockquote>
<p>And with this I was really excited because I&rsquo;d finally beaten <!-- raw HTML omitted -->@aras_p<!-- raw HTML omitted -->‘s SMOL-V (his was taking 1837.88 kilobytes for the shaders).</p>
<h2 id="the-big-plot-twist">The Big Plot Twist</h2>
<p>One thing I hadn&rsquo;t been keeping an eye on (showing my newbieness to all things compression) was the compression ratio when passing YARI-V into something like <!-- raw HTML omitted -->zstd<!-- raw HTML omitted -->. SMOL-V is primarily a data filtering algorithm - it runs on a SPIR-V shader to create SMOL-V such that the SMOL-V is much more easily compressible than the SPIR-V was. My mistake was I was thinking of YARI-V solely as a compression format, and not as a filtering algorithm.</p>
<p>When I tested running zstd at level 20 encoding on YARI-V versus SMOL-V, YARI-V was taking 440 kilobytes compressed to SMOL-V&rsquo;s 348 kilobytes! Even though the encoding of YARI-V was smaller than SMOL-V&rsquo;s, SMOL-V was clearly filtering the data such that it made the compressors life easier.</p>
<p>I had to now work out how to increase repetition in my YARI-V encoding to help out compressors.</p>
<h2 id="delta-encoding-more-things">Delta Encoding More Things</h2>
<p>I had previously only delta encoded the result <!-- raw HTML omitted --> of my opcodes - but <!-- raw HTML omitted -->&rsquo;s are used in the body of the opcodes to. I looked at our three most used opcodes and started there.</p>
<p>For OpLoad and OpStore, I delta encoded the <!-- raw HTML omitted --> that they were loading/storing from/to. This should result in a 1 byte encoding, as most OpLoad&rsquo;s and OpStore&rsquo;s are using the result <!-- raw HTML omitted --> from an OpAccessChain to work out where to load from, and the access chain is usually the instruction immediately before the load or store.</p>
<blockquote>
<p>1810.70 kilobytes 37.19%</p>
</blockquote>
<h2 id="unvarinting-things">Unvarinting Things</h2>
<p>By using the varint encoding everywhere I was being a little over zealous with the use of varints. For example, if we were declaring an OpConstant that was a floating point value, as long as the floating point constant was not denormal it would always take 5 bytes to encode instead of the 4 bytes it would have taken if we hadn&rsquo;t used varint encoding. So I added some logic to detect constants that had any bits set that would result in a 4 byte or larger varint encoding, and just memcpy&rsquo;d these into the YARI-V encoding.</p>
<p>It turns out that 47% of our constants fitted this pattern, which saved one byte per constant encoded.</p>
<blockquote>
<p>1805.71 kilobytes 37.09%</p>
</blockquote>
<h2 id="the-case-of-the-mistaken-delta-encoded-types">The Case of the Mistaken Delta Encoded Types</h2>
<p>I still wasn&rsquo;t anywhere near where I needed to be when compressed, and I was having trouble working out why I was still so far away. So I did some analysis of number of bytes taken up by delta encoding both our <!-- raw HTML omitted -->&rsquo;s and types. It turned out that our types were being delta encoded to 1 or 2 bytes which seemed reasonable at first glance. But then looking more closely, I realised that, since types are declared at the beginning of the SPIR-V shader modules, they mostly had low <!-- raw HTML omitted -->&rsquo;s assigned to them. In _most _cases the <!-- raw HTML omitted -->&rsquo;s were less than 127 for our types. This meant that instead of delta encoding them which was giving us roughly 50/50 for 1/2 byte encodings, if I just used varint encoding without delta encoding too, I&rsquo;m getting nearly 95% of types encoded in 1 byte.</p>
<blockquote>
<p>1675.96 kilobytes 34.42%</p>
</blockquote>
<p>Shaving a whopping 125 kilobytes off of our resultant YARI-V encoding!</p>
<p>I then noticed that SMOL-V had an option to strip the non-essential <!-- raw HTML omitted -->&rsquo;s from the SPIR-V shader modules. This involves removing debug instructions like OpName, OpMemberName, OpLine, etc. that aren&rsquo;t required to be present for the SPIR-V to function correctly.</p>
<p>I added in my own option on encoding to handle stripping of the debug instructions, which resulted in:</p>
<blockquote>
<p>1498.67 kilobytes 32.41%</p>
</blockquote>
<p>Which is a further 176 kilobytes smaller than our non-stripped YARI-V encoding, and 130 kilobytes smaller than SMOL-V&rsquo;s equivalent stripped encoding.</p>
<p>At this stage I thought I was golden, I&rsquo;d cracked the puzzle and <em>obviously</em> my YARI-V encoding would be smaller than SMOL-V? Oh how I was wrong!</p>
<h2 id="results">Results</h2>
<!-- raw HTML omitted -->
<pre><code>&lt;th style=&quot;text-align: right;&quot;&gt;
  Size (kilobytes)
&lt;/th&gt;

&lt;th style=&quot;text-align: right;&quot;&gt;
  Compression (%)
&lt;/th&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: right;&quot;&gt;
  4868.468750
&lt;/td&gt;

&lt;td style=&quot;text-align: right;&quot;&gt;
  100.000000%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: right;&quot;&gt;
  590.573242
&lt;/td&gt;

&lt;td style=&quot;text-align: right;&quot;&gt;
  12.130575%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: right;&quot;&gt;
  1837.881836
&lt;/td&gt;

&lt;td style=&quot;text-align: right;&quot;&gt;
  37.750717%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: right;&quot;&gt;
  386.879883
&lt;/td&gt;

&lt;td style=&quot;text-align: right;&quot;&gt;
  7.946644%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: right;&quot;&gt;
  1675.956055
&lt;/td&gt;

&lt;td style=&quot;text-align: right;&quot;&gt;
  34.424706%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: right;&quot;&gt;
  390.577148
&lt;/td&gt;

&lt;td style=&quot;text-align: right;&quot;&gt;
  8.022587%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: right;&quot;&gt;
  1629.115234
&lt;/td&gt;

&lt;td style=&quot;text-align: right;&quot;&gt;
  33.462580%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: right;&quot;&gt;
  348.073242
&lt;/td&gt;

&lt;td style=&quot;text-align: right;&quot;&gt;
  7.149542%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: right;&quot;&gt;
  1498.666016
&lt;/td&gt;

&lt;td style=&quot;text-align: right;&quot;&gt;
  30.783108%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: right;&quot;&gt;
  364.057617
&lt;/td&gt;

&lt;td style=&quot;text-align: right;&quot;&gt;
  7.477867%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<p>The brass tax is that SMOL-V, with stripping, and then fed through zstd at level 20, is 16 kilobytes <strong>smaller</strong> than the equivalent YARI-V, stripped and fed through zstd at level 20, even though YARI-V is 130 kilobytes <strong>smaller</strong> than SMOL-V when comparing the results of YARI-V against SMOL-V directly.</p>
<p>My main suspicion is that my approach of creating new fake opcodes, and thus allowing me to avoid outputting the word count, is probably wrong. Only 9.74% of my opcodes required a word count in the end - but across the 286932 opcodes used in the input SPIR-V shaders this means that 27956 opcodes were using the more expensive approach to encoding our word count.</p>
<p>My other main idea is that it would seem that SMOL-V is creating a binary stream that zstd can more easily work out how to compress - more sequences of bits must be the same in SMOL-V as compared to YARI-V. I think my approach of simply trying to compress the input SPIR-V into as concise a form as I could with YARI-V meant I lost a little of the big picture that this should have been more of a filtering step on the SPIR-V rather than a compression algorithm in its own right.</p>
<h2 id="future-work">Future Work</h2>
<p>One thing I&rsquo;d like to look at is if I could remap the <!-- raw HTML omitted -->&rsquo;s in the SPIR-V (guarded by an option) such that we could increase the delta encoding success rate. At present our delta encoded IDs take up:</p>
<!-- raw HTML omitted -->
<pre><code>&lt;th style=&quot;text-align: right;&quot;&gt;
  percentage of opcodes
&lt;/th&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: right;&quot;&gt;
  58.180900%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: right;&quot;&gt;
  27.674441%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: right;&quot;&gt;
  14.144659%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: right;&quot;&gt;
  0.000000%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<pre><code>&lt;td style=&quot;text-align: right;&quot;&gt;
  0.000000%
&lt;/td&gt;
</code></pre>
<!-- raw HTML omitted -->
<p>At present 58% of the times we delta encode we get a value that will fit within 1 byte of our zig-zagged varint encoding. 27% fits within 2 bytes, and then 14% in 3 bytes. I think the best place to start would be to try and decrease the number of times a 3 byte encoding was required, and try to map <!-- raw HTML omitted -->&rsquo;s for locality.</p>
<p>A great example of where this would be useful is with OpConstant&rsquo;s. OpConstant&rsquo;s are declared early in the SPIR-V shader module and are therefore generally given a low <!-- raw HTML omitted -->. But they tend to be used in the body of the functions, which occurs much later on. If an OpConstant was used by an OpFMul, it would be awesome if we could make the <!-- raw HTML omitted --> of the OpConstant close to the <!-- raw HTML omitted --> of OpFMul to increase our chances of a 1 byte delta encoding.</p>
<h2 id="getting-yari-v">Getting YARI-V</h2>
<p>YARI-V is <!-- raw HTML omitted -->available on GitHub<!-- raw HTML omitted --> licensed under the unlicense. I hope the code is useful to someone, even though I fell short of my aim I very much enjoyed the journey of trying.</p>
]]></description>
    </item>
    
    <item>
      <title>spirv-stats update - exposing more information</title>
      <link>https://www.neilhenning.dev/posts/spirv-stats-update-exposing-more-information/</link>
      <pubDate>Sun, 25 Sep 2016 19:42:23 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/spirv-stats-update-exposing-more-information/</guid>
      <description><![CDATA[<p>In a <!-- raw HTML omitted -->previous post<!-- raw HTML omitted --> I introduced a little command line tool spirv-stats I&rsquo;ve been working on. Since doing the initial version, I&rsquo;ve extended the information the tool will give you based on some queries I had on the SPIR-V binaries we were using - in <!-- raw HTML omitted -->the GitHub pull request here<!-- raw HTML omitted -->.</p>
<p>For the most commonly used opcodes, I&rsquo;ve tried to break them down to understand a little more about the shape of the opcodes.</p>
<h2 id="opload--opstore">OpLoad &amp; OpStore</h2>
<p>For OpLoad and OpStore - they have an optional additional parameter for a memory access. So I wondered, given the SPIR-V shaders we have as input, how many of the OpLoad&rsquo;s and OpStore&rsquo;s in the SPIR-V have the optional memory access literal? It turns out none of them do!</p>
<h2 id="opdecorate--opmemberdecorate">OpDecorate &amp; OpMemberDecorate</h2>
<p>For OpDecorate the first thing I wanted to know was how many of the decorations used had any additional literals. It turns out that 70% of OpDecorate&rsquo;s have no additional literal, and the remaining 30% has one additional literal. The next query I had was what kind of decorations were mostly used in the SPIR-V shaders? It turns out the most used decoration was the RelaxedPrecision decoration with 66% of the uses of OpDecorate just for this one. The next most used was the Location decoration with 11%. I then extended these checks over to OpMemberDecorate, and it turns out that 90% of decorations on OpMemberDecorate have one literal! The reason is because a cool 84% of the decorations used on OpMemberDecorate are for encoding the Offset of struct members.</p>
<h2 id="opaccesschain">OpAccessChain</h2>
<p>OpAccessChain can have an arbitrarily long set of IDs used to index into the pointer object. So I wondered how many of these were using a small number of indices? It turns out that 78% of the uses of OpAccessChain had only one index, 19% have two indices, and a mere 2% have three indices.</p>
<h2 id="opvariable">OpVariable</h2>
<p>I wondered how many variables as used in our SPIR-V shaders had initializers (they have an initial value). None of them do! Of all 19041 uses of OpVariable not one had an initializer.</p>
<h2 id="opconstant">OpConstant</h2>
<p>Of the constants used in the SPIR-V shaders, all of them use exactly one literal. This is unsurprising because int64/double types are not widely supported or used in shaders, but I wanted to be sure.</p>
<h2 id="opvectorshuffle">OpVectorShuffle</h2>
<p>The first thing I wanted to know about OpVectorShuffle was how many literals were being used when shuffling the vectors - remember that the number of literals corresponds to the width of the output vector. It turns out that 31% of shuffles have two literals (a common case when extracting from a vec4 the indices into an image sample), 45% of shuffles have three literals, and 23% have four literals. The next question I had was to do with the undef literal that can be used in shuffle. 0xFFFFFFFFu (-1 in signed) can be used to signify that that element of the resulting vector is undefined. I wondered if the SPIR-V shaders we had were using this? It turns out none of them are (currently at least). The next question I had was how many shuffles were using literals lower than 4, and lower than 8. These two numbers would be if you were shuffling an individual vec4, or shuffling two vec4. 82% of the shuffles are using literals lower than 4 - so this could either be shuffling two vec2&rsquo;s together, or one vec4. The next question then is how many OpShuffle&rsquo;s are using the same vector ID in both vector components. This pattern is used when you actually only want to shuffle elements from the one vector. Well it turns out exactly 82% of shuffles were using both vectors the same!</p>
<h2 id="opcompositeextract--opcompositeconstruct">OpCompositeExtract &amp; OpCompositeConstruct</h2>
<p>The last two opcodes that I have looked at currently were OpCompositeExtract and OpCompositeConstruct. For both I wondered how many what were the common number of literals being used? For extract, 97% were using exactly one literal. and 3% were using two literals. For construct, 17% used one literal, 41% used two literals, 41% used three literals. Also, for extract, I wondered how many of the extracts were being used to pull a single element out of a vector. So I checked how many times the literal was zero to three. Roughly 26% were accessing the zeroth, first or second, and 20% the third.</p>
<h2 id="sample-output">Sample Output</h2>
<p>Below is a sample output run over the shaders that <!-- raw HTML omitted -->smol-v<!-- raw HTML omitted --> uses for testing. The changes in the latest version from the previous are <!-- raw HTML omitted -->highlighted in red<!-- raw HTML omitted -->.</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></description>
    </item>
    
    <item>
      <title>spirv-stats - a tool to output statistics of your SPIR-V shader modules</title>
      <link>https://www.neilhenning.dev/posts/spirv-stats-a-tool-to-output-statistics-of-your-spir-v-shader-modules/</link>
      <pubDate>Wed, 21 Sep 2016 14:59:43 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/spirv-stats-a-tool-to-output-statistics-of-your-spir-v-shader-modules/</guid>
      <description><![CDATA[<p>I&rsquo;ve just released a small one C++ file tool called <!-- raw HTML omitted -->spirv-stats<!-- raw HTML omitted -->. It will take one or more SPIR-V input files, and calculate the composition of the SPIR-V shader modules like so:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>It firstly outputs the total number of hits in the SPIR-V shader module(s) - this is the total number of opcodes found within the module(s). Then it outputs the total byte size of the module(s), followed by a sorted breakdown of the module(s), with the most hit opcodes coming first.</p>
<p>I decided to run this across the various folders of SPIR-V that <!-- raw HTML omitted -->@aras_p<!-- raw HTML omitted --> is using in his <!-- raw HTML omitted -->smol-v<!-- raw HTML omitted --> tool, with the following results.</p>
<h2 id="dota2">dota2</h2>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>OpMemberDecorate dominates the dota2 shaders - nearly 20% of the module is decorating members of structs! Next we have OpLoad at 16% of the hits, but with 13% of the size of the files, followed by OpAccessChain at 10% of the hits and 12% of the size. Most of the shader module(s) are taken up with decorating struct members, and then loading and storing to various variables.</p>
<h2 id="shadertoy">shadertoy</h2>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>The shadertoy folder is dominated by loads and stores. Then curiously OpLabel - this indicates that there is a heavy amount of branching/looping occurring in the source shaders, as an OpLabel signifies a new basic block has been declared. OpBranch is the sixth most used opcode, which also backs up the view that these shaders make heavy use of branching/looping.</p>
<h2 id="talos">talos</h2>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>The talos folder is dominated once again by loads and stores. Next is OpCompositeExtract - which is extracting an element from a composite (aggregate, matrix or vector). I&rsquo;d take a guess that there is a lot of vector math going on in these shaders, as the sixth most used opcode is OpVectorShuffle.</p>
<h2 id="unity">unity</h2>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And lastly the unity folder. These shader modules are dominated by OpDecorate. The next three most used opcodes are OpLoad, OpStore and OpAccessChain - so loading and storing to variables is taking up a sizeable amount of the shader modules.</p>
<h2 id="all-together">All Together</h2>
<p>If we look at all the folders above as one output from  <!-- raw HTML omitted -->spirv-stats<!-- raw HTML omitted --> instead:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>We can see that loading and storing dominates our shader modules at 28% of the opcodes and 25% of the binary size.</p>
<h2 id="summary">Summary</h2>
<p>The tool showed us some interesting divergent trends across each of the providers of the SPIR-V shader modules. Thanks to Valve, Shadertoy, Croteam and Unity for allowing <!-- raw HTML omitted -->@aras_p<!-- raw HTML omitted --> to use their SPIR-V shaders when he wrote his <!-- raw HTML omitted -->smol-v<!-- raw HTML omitted --> tool. I wouldn&rsquo;t have had such interesting source material otherwise to run my tool against!</p>
<p>The  <!-- raw HTML omitted -->spirv-stats<!-- raw HTML omitted --> tool can be got via its <!-- raw HTML omitted -->GitHub repository<!-- raw HTML omitted --> - hope it is useful to someone!</p>
]]></description>
    </item>
    
    <item>
      <title>Adding type identifiers (MPC -&gt; LLVM for the Neil Language #3)</title>
      <link>https://www.neilhenning.dev/posts/adding-type-identifiers-mpc-llvm-for-the-neil-language-3/</link>
      <pubDate>Sun, 18 Sep 2016 13:36:28 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/adding-type-identifiers-mpc-llvm-for-the-neil-language-3/</guid>
      <description><![CDATA[<p>In my previous post <!-- raw HTML omitted -->cleaning up the parser<!-- raw HTML omitted -->, I had rationalised the parser for my custom language I&rsquo;m calling Neil - <strong>N</strong>ot <strong>E</strong>xactly an <strong>I</strong>ntermediate <strong>L</strong>anguage.</p>
<p>The next step in making my language more useful and expression is to add the ability to arbitrarily create variables within a function, store an initial value to the variable, and then be able to update the variable.</p>
<p>Previously, our language could handle:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Whereas now we want it to be able to handle:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>In <!-- raw HTML omitted -->GitHub Pull Request #1<!-- raw HTML omitted --> I&rsquo;ve submitted the patch of changes required to get this to work, but lets cover the steps that were required to do this!</p>
<h2 id="mpc-grammar-changes">MPC Grammar Changes</h2>
<p>We firstly need to modify our MPC grammar to accept type declarations within the body of a function. Our functions (procedure in the grammar) are made up of zero or more statements. We modify the stmt definition in the grammar to be:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>As shown in <!-- raw HTML omitted -->red<!-- raw HTML omitted -->, we&rsquo;ve added two new statement variants:</p>
<ul>
<li>a type identifier followed by an optional initializer</li>
<li>assigning into an existing identifier</li>
</ul>
<p>With these two changes, we can represent all the fun variable shenanigans we could imagine.</p>
<h2 id="ast-lowering">AST Lowering</h2>
<p>We need to handle two extra cases in our lower_statement method now - lowering type definitions within functions, and assignments into already defined identifiers.</p>
<p>To detect the type identifier case, we simply:</p>
<ul>
<li>add some logic to check if the first child of a statement AST node is a typeident</li>
<li>the first child of a type identifier is the type, which we lookup in the type table</li>
<li>the second child of a type identifier is the name of the variable, which we&rsquo;ll use to assign an entry in the symbol table</li>
<li>we then use LLVM&rsquo;s stack allocation instruction alloca to create memory for our variable to reside within</li>
<li>and lastly store into the symbol table, using the variable name we already parsed, that the name maps to the alloca&rsquo;ed variable</li>
</ul>
<p>We then need to check whether the variable had an initializer or not:</p>
<ul>
<li>if the statement began with a type identifier AST node, and had exactly two children, we know that there was no initializer (so can skip the following logic)</li>
<li>otherwise, the statement must have exactly four children (a type identifier, an ‘=&rsquo; character, an expression, and lastly a ‘;&rsquo; character)</li>
<li>we use the lower_ast_node method to lower the expression, passing in the type we deduced from the type identifier</li>
<li>and lastly use LLVM&rsquo;s store instruction to assign the value of the expression into the memory backing the variable</li>
</ul>
<p>To detect when we want to assign into an existing variable:</p>
<ul>
<li>we know a variable declaration is an identifier, followed by an ‘=&rsquo; character, followed by an expression, and lastly a ‘;&rsquo; character</li>
<li>we then lookup the variable in the symbol table</li>
<li>we use the lower_ast_node method to lower the expression on the right-hand-side of the ‘=&rsquo; character, passing in the type of the type identifier (we use LLVMTypeOf on the value to deduce the type)</li>
<li>and lastly we use LLVM&rsquo;s store instruction to assign the value of the expression into the memory backing the variable</li>
</ul>
<p>Easy!</p>
<h2 id="modifying-expression-lowering"><!-- raw HTML omitted --><!-- raw HTML omitted -->Modifying Expression Lowering</h2>
<p>We need to slightly modify expression lowering to. Previously all values in the symbol table were directly correlated to the type used to declare the value in the source language. For example, a function parameter with type i32 would have the LLVM type i32 to match it. Now that we have function local variables that have a stack allocation backing them, we need to deduce when we find an identifier, if it was an identifier that came from a function local variable, or an identifier that came from a function parameter. In lower_ident, we now have an extra check to see if the value in the symbol table is an alloca instruction, EG. it requires to be loaded before we can use it in a further expression. If we find that it is an alloca, we simply use LLVM&rsquo;s load instruction on it, and return this new LLVM value instead of the original value in the symbol table.</p>
<h2 id="remembering-the-symbols-to-murder">Remembering the Symbols to Murder</h2>
<p>When we close a function, we would loop through the named parameters of the function and remove them from the symbol table. These symbols were only usable within the body of the function so we had to ensure we didn&rsquo;t accidently extend their lifetime beyond the function close. This also now applies to variables declared within a function too! Now, to add a little complexity, since variables can be declared in any statement of a function, we need to keep a list of symbols that need to be destroyed when the function closes. We use a new NeilVector (at present just a wrapper around std::vector) to keep track of which symbols we need to destroy when we close the function. When calling lower_statement and having detected a new type identifier definition, we push back the name of the symbol that we need to cleanup onto our symbol cleanup vector, and then when the function closes we just loop through this vector, and erase the corresponding symbol in the symbol table.</p>
<h2 id="what-is-next">What is Next?</h2>
<p>So now we&rsquo;ve added function local variables to the language, it is about time that we tackled a big lacking feature - branching! In the next post we&rsquo;ll cover how we handle adding if statements to the language. Stay tuned!</p>
]]></description>
    </item>
    
    <item>
      <title>json.h update - fixing bugs found by nativejson-benchmark</title>
      <link>https://www.neilhenning.dev/posts/json-h-update-fixing-bugs-found-by-nativejson-benchmark/</link>
      <pubDate>Thu, 15 Sep 2016 14:41:02 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/json-h-update-fixing-bugs-found-by-nativejson-benchmark/</guid>
      <description><![CDATA[<p>I was recently made aware of the awesome JSON parser/writer benchmark suite <!-- raw HTML omitted -->nativejson-benchmark<!-- raw HTML omitted -->  (thanks to the awesome <!-- raw HTML omitted -->@chadaustin<!-- raw HTML omitted -->).</p>
<p>The suite takes over 40 different JSON libraries and compares how fast the can parse/write JSON, but also has a set of test cases that cover some really obtuse corner cases that a lot of parsers missed. One of the parsers that failed some of these tests was my own one <!-- raw HTML omitted -->json.h<!-- raw HTML omitted -->, so in <!-- raw HTML omitted -->pull request #42<!-- raw HTML omitted --> I&rsquo;ve merged in the fixes for the failures uncovered by the test suite.</p>
<p>The main difference when users of <!-- raw HTML omitted -->json.h<!-- raw HTML omitted --> migrate to the latest code is the deprecation of the <em>json_parse_flags_allow_string_simplification</em> option. My reading of the JSON specifications was wrong in that I thought I had to preserve control characters like ‘\n&rsquo; into the end result. The <em>json_parse_flags_allow_string_simplification</em> option was my ‘solution&rsquo; to what I thought would be non-conforming behaviour. Now, with the tip code, effectively <em>json_parse_flags_allow_string_simplification</em> is always on by default, with no option to turn it off.</p>
<p>Another change is that any malformed characters that occurred after a valid JSON sequence in source would have previously been ignored. Say you had provided the following JSON:</p>
<blockquote>
<p>{“a” : true, “b” : false} heyo this really shouldn&rsquo;t be here</p>
</blockquote>
<p>Previously, the parser would just parse the object and terminate when the object closed - EG. when the closing ‘}&rsquo; was detected. This was dangerous behaviour that <!-- raw HTML omitted -->nativejson-benchmark<!-- raw HTML omitted --> correctly failed my library on, so I&rsquo;ve changed it such that it will fail if:</p>
<ul>
<li>Any non-whitespace character is found after the close of the parent value</li>
<li>Or, if <em>json_parse_flags_allow_c_style_comments</em> is enabled, any non-whitespace character occurs outwith any comments that occur after the close of the parent value</li>
</ul>
<p><!-- raw HTML omitted -->json.h<!-- raw HTML omitted --> should now pass 100% of the tests provided in the <!-- raw HTML omitted -->nativejson-benchmark<!-- raw HTML omitted --> test suite, and be more useful to users going forward. Happy hunting folks!</p>
]]></description>
    </item>
    
    <item>
      <title>Cleaning up the parser (MPC -&gt; LLVM for the Neil Language #2)</title>
      <link>https://www.neilhenning.dev/posts/cleaning-up-the-parser-mpc-llvm-for-the-neil-language-2/</link>
      <pubDate>Fri, 09 Sep 2016 21:10:30 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/cleaning-up-the-parser-mpc-llvm-for-the-neil-language-2/</guid>
      <description><![CDATA[<p>In my previous post <a href="https://www.neilhenning.dev/hooking-up-mpc-llvm/">Hooking up MPC &amp; LLVM</a> I had started hooking up <!-- raw HTML omitted -->MPC<!-- raw HTML omitted --> to <!-- raw HTML omitted -->LLVM<!-- raw HTML omitted -->, to start developing a custom language I&rsquo;m calling Neil - <strong>N</strong>ot <strong>E</strong>xactly an <strong>I</strong>ntermediate <strong>L</strong>anguage.</p>
<p>Since then, I&rsquo;ve tried to rationalise the various hacks I had to do on the original version just to get <em>something</em> working, and actually try and have a clean codebase for generating LLVM from our MPC grammar. Check out the <a href="https://github.com/sheredom/neil">GitHub repository here</a> if you want to follow the progress.</p>
<p>I decided to wrap the logic into a C++ class called ASTLowering - this will encapsulate an entire invocation of MPC -&gt; LLVM, and hold some structures for the symbol table, type table, the LLVM IRBuilder we are using, and the current function we are generating a body for. I did this just to try and keep down the number of parameters I&rsquo;m passing down between the recursive function calls we&rsquo;ll need to use to walk the AST and output our LLVM IR.</p>
<p>So next up - let us cover a bunch of the core concepts we need to parse our language to LLVM IR.</p>
<h2 id="llvm-values--types">LLVM Values &amp; Types</h2>
<p>Everything (near enough) in LLVM IR derives from the LLVM Value base class - in the C API this becomes LLVMValueRef. Functions, function Arguments, Instructions, Constants - they all derive from the LLVM Value class. It&rsquo;s important to note that most of the things we&rsquo;ll be dealing with are these values.</p>
<p>And everything that is an LLVM Value has an corresponding LLVM Type - Function Types, Integer Types, Pointer Types, etc, etc - we can query any value in LLVM to get its corresponding type.</p>
<h2 id="symbol-table">Symbol Table</h2>
<p>First up is the symbol table, specifically what is a symbol table in the context of our parser?</p>
<p>The symbol table is just a map of an identifier (the name of the variable/function) to the LLVM Value that represents the variable/function in the IR. For instance, lets say we had this function:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>As we are parsing, when we encounter the function ‘foo&rsquo; in our AST, we add an entry in our symbol table to record that there is an LLVM Value (in this case, the LLVM Function) whose name is ‘foo&rsquo;. We also add in, only within the scope of the body of the function, that there is a symbol called ‘a&rsquo;, whose LLVM Value is the first LLVM Argument of the function ‘foo'.</p>
<p>And that is it!</p>
<h2 id="type-table">Type Table</h2>
<p>We keep a type table - a table of all known types that are being used and are valid in the program. At present, we just hardcode all the supported types we have - i1, i8, i16, i32, i64, u8, u16, u32, u64, f16, f32 and f64. The identifiers of each of these types in the Neil language (for example ‘u8&rsquo;) is mapped to the corresponding LLVM Type - in the C API called LLVMTypeRef. Then, when we are parsing a type identifier in the AST (for example, the return type of a function definition), we simply look up the string name of the type in the type table, and use the corresponding LLVM Type when creating the value.</p>
<h2 id="how-our-parsing-works">How our Parsing Works</h2>
<p>Let&rsquo;s take a simple example of our Neil language:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>We feed this to our mpc parser for the Neil language, which produces us the following AST:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Our parser starts at the root MPC node (always called ‘&gt;&rsquo;), and then looks for any functions defined in the source file. If we find a function, we&rsquo;ll have a corresponding ‘procedure&rsquo; node in the AST.</p>
<p>We find the first procedure, which has the declaration:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>The steps we follow to parse this are:</p>
<ul>
<li>A procedure always starts with a type. We lookup the contents of the first child of the procedure in our type table, which returns us the LLVM type for a 32 bit integer.</li>
<li>The function has a identifier - the name of the function. We remember the second child&rsquo;s contents is the name of the function.</li>
<li>The third child is the opening ‘(‘ for any arguments to the function.</li>
<li>While the next child is not the closing ‘)&rsquo; for the arguments to the function, we look for a type-identifier.
<ul>
<li>The first child of a type-identifier is the type, which we again lookup in our type table, and store this into a vector.</li>
<li>The second child of a type-identifier is the name for the argument of the type. We store this name into a vector.</li>
</ul>
</li>
<li>Once we reach the closing ‘)&rsquo; for the arguments, we can now create the LLVM Function to populate the symbol table with.</li>
</ul>
<p>To create an LLVM Function we first need the type of the function - we need the return type, and an array of the argument types. With these (which we just parsed above), we can create the function type. Once we have the function type, we combine this with the name of the function we discovered in the second child of our procedure, and create the new LLVM Function. The last thing we need to do to finalise the declaration of our function is name each of the arguments to the function. We run through the arguments of the function calling LLVMSetValueName() using the vector of names we remembered when parsing our type-identifiers earlier.</p>
<p>And huzzah! We have our function declaration.</p>
<p>Next up, we parse the body of the function:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>The function body consists of:</p>
<ul>
<li>The first child is the opening ‘{‘ for the body of the function.</li>
<li>While the next child is not the closing ‘}&rsquo; for the body of the function, we loop through all of the statement AST nodes for the body of the function.</li>
<li>Within the statement AST node, we support two kinds of statements at present - return statements, and function call statements. In the example showing we find that:
<ul>
<li>We have a ‘return&rsquo; as the first child to the statement (thus it is a return statement type).</li>
<li>If the second child is not ‘;&rsquo;, we are returning a value from the function, in the form of an lexp AST node.
<ul>
<li>The first child of an lexp AST node is always a term AST node.
<ul>
<li>The first child of a term AST node is always a factor. In the example above we can see we have a ‘factor|ident|regex&rsquo; named node - this highlights a cool feature of MPC I&rsquo;ll talk about later*.
<ul>
<li>We parse the factor-that-is-an-identifier, which is the identifier ‘x&rsquo;. We look this up in the symbol table, finding the argument to our function called ‘x&rsquo;, and use that LLVM Value as the value for the factor.</li>
</ul>
</li>
<li>If there is a second child of a term AST node, it is either multiply ‘*&rsquo;, divide ‘/&rsquo; or remainder ‘%&rsquo;, in our example it is a multiply.</li>
<li>We then parse the third child (if there was a second, there must be a third node according to the rules of our grammar), which is also a factor AST node.
<ul>
<li>We parse this factor-that-is-a-literal, which is the constant ‘5&rsquo;. Now, in our Neil language, constants don&rsquo;t inherently have a type - we <em>infer</em> the type from the closest typed expression. So in this instance, we know that the type of the left-hand-side of our multiplication operation is the type ‘i32&rsquo;, so our constant gets parsed into an LLVM Value that is the constant ‘5&rsquo; that is a 32 bit integer.</li>
</ul>
</li>
</ul>
</li>
<li>if there is a second child of a lexp AST node, it is either addition ‘+&rsquo; or subtraction ‘-‘, in our example it is an addition.</li>
<li>We then parse the third child of the lexp AST node (if there was a second child, there must be a third child), which is a term AST node:
<ul>
<li>The term in this case is a term-that-is-a-factor-that-is-a-literal, which is the constant &lsquo;42&rsquo;. Again, our constant is un-typed, so we infer that the result of the left-hand-side of our addition has the type ‘i32&rsquo;, and use that as the type for this constant.</li>
</ul>
</li>
</ul>
</li>
<li>The last child of the statement must be a ‘;&rsquo; to close the statement.</li>
</ul>
</li>
<li>And the last child of the procedure must be a ‘}&rsquo; to close the function.</li>
</ul>
<p>And that is it! We have parsed our function, and we get the result in LLVM IR of:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<h2 id="cool-mpc-feature">Cool MPC Feature*</h2>
<p>When going through how we parse, I eluded to a cool MPC feature that we&rsquo;d have to come back to - I like to call them ‘multi-type-AST-nodes&rsquo;. If a node in the AST has exactly one child, MPC will fold the nodes together. A great example in the above AST is:</p>
<!-- raw HTML omitted -->
<p>Which is a node that is a term -&gt; factor -&gt; literal -&gt; regex! This means that we have to do a little more complex parsing when we look at the ‘tag&rsquo; of each AST node (see ‘lower_ast_node&rsquo; in the GitHub for Neil) - we can&rsquo;t just say ‘this node is a term&rsquo;, we have to look at the entire tag, and work backwards to work out how we should be parsing the value. While it increases the complexity of the parsing marginally, you can see why this would be a huge win if we had a super large input source file being parsed by MPC - we are using one node in place of four, a 25% saving in memory usage for the MPC format!</p>
<h2 id="what-is-next">What is Next?</h2>
<p>So we&rsquo;ve got basic parsing support into our language, and we can make simple programs. But we don&rsquo;t have some really basic features that make languages actually usable yet. In the next post, we&rsquo;ll add type identifiers, so we can declare variables within our function bodies. Stay tuned!</p>
]]></description>
    </item>
    
    <item>
      <title>Hooking up MPC &amp;#038; LLVM</title>
      <link>https://www.neilhenning.dev/posts/hooking-up-mpc-llvm/</link>
      <pubDate>Sun, 28 Aug 2016 20:47:41 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/hooking-up-mpc-llvm/</guid>
      <description><![CDATA[<p>I&rsquo;ve been tinkering around with <!-- raw HTML omitted -->mpc<!-- raw HTML omitted --> and <!-- raw HTML omitted -->llvm<!-- raw HTML omitted --> recently - just to satisfy a few simple questions:</p>
<ul>
<li>How easy is it to use mpc?</li>
<li>How easy is the LLVM c api to use?</li>
<li>How easy is it to connect a parser generator to an LLVM Module?</li>
</ul>
<p>So given the above aims, I&rsquo;ve embarked on creating my own stupid little language, that I&rsquo;m calling ‘<em>neil</em>‘  - <strong>N</strong>ot <strong>E</strong>xactly an <strong>I</strong>ntermediate <strong>L</strong>anguage. It is utterly by chance that the name ‘<em>neil</em>‘ happens to be my own name, if you&rsquo;ve believe that gratuitous lie!</p>
<p>A ‘<em>neil</em>‘ program currently consists of one allowed type - a 32 bit integer named i32, function definitions, function calls, and being able to return the results of one function from another. In short, it is (currently, and most likely permanently) a really stupid language.</p>
<p>An example legal ‘neil&rsquo; program is:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>So lets get right into how we construct this grammar in mpc. The mpc grammar for our ‘<em>neil</em>‘ language is as follows:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>It&rsquo;s a very simple grammar, I looked at the <!-- raw HTML omitted -->mpc - smallc<!-- raw HTML omitted --> example to work out what to do. To parse using mpc, I have the following function:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>With this, we can then iterate through a successfully parsed ‘<em>neil</em>‘ input using the:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>type that mpc provides. The struct elements are as follows:</p>
<ul>
<li>tag - the string name of the ast node&rsquo;s type</li>
<li>contents - what the ast node is pointing at in the original source input</li>
<li>state - the line information for the ast node</li>
<li>children_num - the length of the children array</li>
<li>children - an array of AST node&rsquo;s that are children of the current node</li>
</ul>
<p>Next up, we need to create what we need from LLVM to produce a module for the current file. I&rsquo;m using the LLVM C API because I&rsquo;ve never used it before, having only ever used the C++ API in my day to day stuff at work, so I thought it would be useful to have a look at it.</p>
<p>First up we need an LLVM Module - this is an encapsulation of a ‘<em>neil</em>‘ input file for our uses. I use:</p>
<!-- raw HTML omitted -->
<p>To get a module to work with. Then, for each AST node that is a procedure, I create a corresponding LLVM function with:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>(Note I&rsquo;m cheating for now because I know my functions return i32, and take no params, don&rsquo;t do this in production code!).</p>
<p>Then, since I have no control flow within my functions, I can create one basic block to hold the body of the function, and an IR builder to help us make the instructions within the basic block, with:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And with this we can begin to parse the body of the functions!</p>
<p>I parse the return statement (the only allowed statement within our functions), and check if it returns a literal or the result of a call to a function:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And the result is:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>From the example ‘<em>neil</em>‘ file I gave above.</p>
<p>TL;DR mpc is pretty cool, the LLVM C API is very easy to use, and I&rsquo;ll be fleshing out my ‘<em>neil</em>‘ language in future blog posts once I try handling a more complicated input grammar.</p>
<p>PS the full source for the example is below:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></description>
    </item>
    
    <item>
      <title>A simple Vulkan Compute example</title>
      <link>https://www.neilhenning.dev/posts/a-simple-vulkan-compute-example/</link>
      <pubDate>Sun, 29 May 2016 19:51:43 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/a-simple-vulkan-compute-example/</guid>
      <description><![CDATA[<p>With all the buzz surrounding Vulkan and its ability to make graphics more shiny/pretty/fast, there is one key thing seems to have been lost in the ether of information - Vulkan isn&rsquo;t just a graphics API, it supports compute too! Quoting the specification (bold added for effect):</p>
<blockquote>
<p>Vulkan is an API (Application Programming Interface) for graphics and <strong>compute</strong> hardware</p>
</blockquote>
<p>And:</p>
<blockquote>
<p>This specification defines four types of functionality that queues may support: graphics, <strong>compute</strong>, transfer, and sparse memory management.</p>
</blockquote>
<p>We can see that, through how well crafted the language is, Vulkan is not only allowed to support compute, there are cases where a Vulkan driver could expose <strong><em>only compute</em></strong>.</p>
<p>In this vein, I&rsquo;ve put together a simple Vulkan compute sample - <!-- raw HTML omitted -->VkComputeSample<!-- raw HTML omitted -->. The sample:</p>
<ul>
<li>allocates two buffers</li>
<li>fills them with random data</li>
<li>creates a compute shader that will memcpy from one buffer to the other</li>
<li>then check that the data copied over successfully</li>
</ul>
<p>Key Vulkan principles covered:</p>
<ul>
<li>creating a device and queue for compute only</li>
<li>allocating memories and buffers from them</li>
<li>writing a simple compute shader</li>
<li>executing the compute shader</li>
<li>getting the results</li>
</ul>
<p>So without further ado, let us begin.</p>
<h3 id="creating-a-device-and-queue-for-compute-only">creating a device and queue for compute only</h3>
<p>Vulkan has a ton of boilerplate code you need to use to get ready for action.</p>
<p>First up we need a VkInstance. To get this, we need to look at two of Vulkan&rsquo;s structs - VkApplicationInfo and VkInstanceCreateInfo:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">struct</span> VkApplicationInfo {
</span></span><span style="display:flex;"><span>    VkStructureType    sType;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span>        pNext;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span><span style="color:#f92672">*</span>        pApplicationName;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span>           applicationVersion;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span><span style="color:#f92672">*</span>        pEngineName;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span>           engineVersion;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span>           apiVersion; <span style="color:#75715e">// care about this
</span></span></span><span style="display:flex;"><span>} VkApplicationInfo;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">struct</span> VkInstanceCreateInfo {
</span></span><span style="display:flex;"><span>    VkStructureType             sType;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span>                 pNext;
</span></span><span style="display:flex;"><span>    VkInstanceCreateFlags       flags;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> VkApplicationInfo<span style="color:#f92672">*</span>    pApplicationInfo; <span style="color:#75715e">// care about this
</span></span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span>                    enabledLayerCount;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span><span style="color:#f92672">*</span>          ppEnabledLayerNames;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span>                    enabledExtensionCount;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span><span style="color:#f92672">*</span>          ppEnabledExtensionNames;
</span></span><span style="display:flex;"><span>} VkInstanceCreateInfo;
</span></span></code></pre></div><p>I&rsquo;ve flagged the only two fields we really need to care about here - apiVersion and pApplicationInfo. The most important field here is apiVersion. apiVersion will allow us to write an application against the current Vulkan specification and specify exactly which version of Vulkan we wrote our application against within the code.</p>
<p>Why is this important you ask?</p>
<ol>
<li>It helps future you. You&rsquo;ll know which version of the specification to look at.</li>
<li>It allows the validation layer to understand which version of Vulkan you think you are interacting with, and potentially flag up any cross version issues between your application and the drivers you are interacting with.</li>
</ol>
<p>I recommend you always at least provide an apiVersion.</p>
<p>pApplicationInfo is the easier to justify - you need this to point to a valid VkApplicationInfo if you want to specify an apiVersion, which I again highly recommend you use.</p>
<p>Next, we need to get all the physical devices the instance can interact with:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">uint32_t</span> physicalDeviceCount <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">vkEnumeratePhysicalDevices</span>(instance, <span style="color:#f92672">&amp;</span>physicalDeviceCount, <span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>VkPhysicalDevice<span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> physicalDevices <span style="color:#f92672">=</span> (VkPhysicalDevice<span style="color:#f92672">*</span>)<span style="color:#a6e22e">malloc</span>(
</span></span><span style="display:flex;"><span>   <span style="color:#66d9ef">sizeof</span>(VkPhysicalDevice) <span style="color:#f92672">*</span> physicalDeviceCount);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">vkEnumeratePhysicalDevices</span>(
</span></span><span style="display:flex;"><span>  instance, <span style="color:#f92672">&amp;</span>physicalDeviceCount, physicalDevices);
</span></span></code></pre></div><p>We do this by using a pair of vkEnumeratePhysicalDevices calls - one to get the number of physical devices the instance knows about, and one to fill a newly created array with handles to these physical devices.</p>
<p>For the purposes of the sample, I iterate through these physical devices and run my sample on each of the physical devices present in the system - but for a ‘real-world application&rsquo; you&rsquo;d want to find which device best suits your workload by using vkGetPhysicalDeviceFeatures, vkGetPhysicalDeviceFormatProperties, vkGetPhysicalDeviceImageFormatProperties, vkGetPhysicalDeviceProperties, vkGetPhysicalDeviceQueueFamilyProperties and vkGetPhysicalDeviceMemoryProperties.</p>
<p>For each physical device we need to find a queue family for that physical device which can work for compute:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">uint32_t</span> queueFamilyPropertiesCount <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">vkGetPhysicalDeviceQueueFamilyProperties</span>(
</span></span><span style="display:flex;"><span>  physicalDevice, <span style="color:#f92672">&amp;</span>queueFamilyPropertiesCount, <span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>VkQueueFamilyProperties<span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span> queueFamilyProperties <span style="color:#f92672">=</span>
</span></span><span style="display:flex;"><span>  (VkQueueFamilyProperties<span style="color:#f92672">*</span>)<span style="color:#a6e22e">malloc</span>(
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">sizeof</span>(VkQueueFamilyProperties) <span style="color:#f92672">*</span> queueFamilyPropertiesCount);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">vkGetPhysicalDeviceQueueFamilyProperties</span>(physicalDevice,
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&amp;</span>queueFamilyPropertiesCount, queueFamilyProperties);
</span></span></code></pre></div><p>We do this by using a pair of calls to vkGetPhysicalDeviceQueueFamilyProperties, the first to get the number of queue families available, and the second to fill an array of information about our queue families. In each queue family:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">struct</span> VkQueueFamilyProperties {
</span></span><span style="display:flex;"><span>    VkQueueFlags    queueFlags; <span style="color:#75715e">// care about this
</span></span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span>        queueCount;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span>        timestampValidBits;
</span></span><span style="display:flex;"><span>    VkExtent3D      minImageTransferGranularity;
</span></span><span style="display:flex;"><span>} VkQueueFamilyProperties;
</span></span></code></pre></div><p>We care about the queueFlags member which specifies what workloads can execute on a particular queue. A naive way to do this would be to find any queue that could handle compute workloads. A better approach would be to find a queue that only handled compute workloads (but you need to ignore the transfer bit and for our purposes the sparse binding bit too).</p>
<p>Once we have a valid index into our queueFamilyProperties array we allocated, we need to keep this index around - it becomes our queue family index used in various other places of the API.</p>
<p>Next up, create the device:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">struct</span> VkDeviceQueueCreateInfo {
</span></span><span style="display:flex;"><span>    VkStructureType             sType;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span>                 pNext;
</span></span><span style="display:flex;"><span>    VkDeviceQueueCreateFlags    flags;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span>                    queueFamilyIndex; <span style="color:#75715e">// care about this
</span></span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span>                    queueCount;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">float</span><span style="color:#f92672">*</span>                pQueuePriorities;
</span></span><span style="display:flex;"><span>} VkDeviceQueueCreateInfo;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">struct</span> VkDeviceCreateInfo {
</span></span><span style="display:flex;"><span>    VkStructureType                    sType;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span>                        pNext;
</span></span><span style="display:flex;"><span>    VkDeviceCreateFlags                flags;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span>                           queueCreateInfoCount; <span style="color:#75715e">// care about this
</span></span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> VkDeviceQueueCreateInfo<span style="color:#f92672">*</span>     pQueueCreateInfos;    <span style="color:#75715e">// care about this
</span></span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span>                           enabledLayerCount;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span><span style="color:#f92672">*</span>                 ppEnabledLayerNames;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span>                           enabledExtensionCount;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">char</span><span style="color:#f92672">*</span> <span style="color:#66d9ef">const</span><span style="color:#f92672">*</span>                 ppEnabledExtensionNames;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> VkPhysicalDeviceFeatures<span style="color:#f92672">*</span>    pEnabledFeatures;
</span></span><span style="display:flex;"><span>} VkDeviceCreateInfo;
</span></span></code></pre></div><p>The queue family index we just worked out will be used in our VkDeviceQueueCreateInfo struct&rsquo;s queueFamilyIndex member, and our VkDeviceCreateInfo will contain one queueCreateInfoCount, with pQueueCreateInfos set to the address of our single VkDeviceQueueCreateInfo struct.</p>
<p>Lastly we get our device&rsquo;s queue using:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>VkQueue queue;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">vkGetDeviceQueue</span>(device, queueFamilyIndex, <span style="color:#ae81ff">0</span>, <span style="color:#f92672">&amp;</span>queue);
</span></span></code></pre></div><p>Et voilà, we have our device, we have our queue, and we are done (with getting our device and queue at least).</p>
<h3 id="allocating-memories-and-buffers-from-them">allocating memories and buffers from them</h3>
<p>To allocate buffers for use in our compute shader, we first have to allocate memory that backs the buffer - the physical location of the buffer for the device. Vulkan supports <a href="https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html#memory-device">many different memory types</a>, so we need to query for the buffer that matches our requirements. We do this by a call to vkGetPhysicalDeviceMemoryProperties, and we then find a memory that has the properties we require, and is big enough for our uses:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">const</span> VkDeviceSize memorySize; <span style="color:#75715e">// whatever size of memory we require
</span></span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">uint32_t</span> k <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; k <span style="color:#f92672">&amp;</span>lt; properties.memoryTypeCount; k<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> VkMemoryType memoryType <span style="color:#f92672">=</span> properties.memoryTypes[k];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">if</span> ((VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT <span style="color:#f92672">&amp;</span> memoryType.propertyFlags)
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&amp;&amp;</span> (VK_MEMORY_PROPERTY_HOST_COHERENT_BIT <span style="color:#f92672">&amp;</span> memoryType.propertyFlags)
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&amp;&amp;</span> (memorySize <span style="color:#f92672">&amp;</span>lt; properties.memoryHeaps[memoryType.heapIndex].size)) {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// found our memory type!
</span></span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>If we know how big a memory we require, we can find an index in our VkPhysicalDeviceMemoryProperties struct that has the properties we require set, and is big enough. For the sample I&rsquo;m using memory that can be host visible, and is coherent (for ease of sample writing).</p>
<p>With the memory type index we found above we can allocate a memory:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">struct</span> VkMemoryAllocateInfo {
</span></span><span style="display:flex;"><span>    VkStructureType    sType;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span>        pNext;
</span></span><span style="display:flex;"><span>    VkDeviceSize       allocationSize;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span>           memoryTypeIndex; <span style="color:#75715e">// care about this
</span></span></span><span style="display:flex;"><span>} VkMemoryAllocateInfo;
</span></span></code></pre></div><p>We need to care about the memoryTypeIndex - which we&rsquo;ll set to the index we worked out from VkPhysicalDeviceMemoryProperties before.</p>
<p>For the sample, I allocate one memory, and then subdivide it into two buffers. We create two storage buffers (using VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), and since we do not intend to use overlapping regions of memory for the buffers our sharing mode is VK_SHARING_MODE_EXCLUSIVE. Lastly we need to specify which queue families these buffers will be used with - in our case its the one queueFamilyIndex we discovered at the start.</p>
<p>The link between our memories and our buffers is vkBindBufferMemory:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#a6e22e">vkBindBufferMemory</span>(device, in_buffer, memory, <span style="color:#ae81ff">0</span>);
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">vkBindBufferMemory</span>(device, out_buffer, memory, bufferSize);
</span></span></code></pre></div><p>The crucial parameter for us to use the one memory for two buffers is the last one - memoryOffset. For our second buffer we set it to begin after the first buffer has ended. Since we are creating storage buffers, we need to be sure that our memoryOffset is a multiple of the minStorageBufferOffsetAlignment member of the VkPhysicalDeviceLimits struct. For the purposes of the sample, we choose a memory size that is a large power of two, satisfying the alignment requirements on our target platforms.</p>
<p>The last thing we can do is fill the memory with some initial random data. To do this we map the memory, write to it, and unmap, prior to using the memory in any queue:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>VkDeviceSize memorySize; <span style="color:#75715e">// whatever size of memory we require
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int32_t</span> <span style="color:#f92672">*</span>payload;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">vkMapMemory</span>(device, memory, <span style="color:#ae81ff">0</span>, memorySize, <span style="color:#ae81ff">0</span>, (<span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>)<span style="color:#f92672">&amp;</span>payload);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">uint32_t</span> k <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; k <span style="color:#f92672">&amp;</span>lt; memorySize <span style="color:#f92672">/</span> <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">int32_t</span>); k<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>  payload[k] <span style="color:#f92672">=</span> <span style="color:#a6e22e">rand</span>();
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">vkUnmapMemory</span>(device, memory);
</span></span></code></pre></div><p>And that is it, we have our memory and buffers ready to data up later.</p>
<h3 id="writing-a-simple-compute-shader">writing a simple compute shader</h3>
<p>My job with Codeplay is to work on the Vulkan specification with the Khronos group. My real passion within this is making compute awesome. I spend a good amount of my time working on Vulkan compute but also on SPIR-V for Vulkan. I&rsquo;ve never been a happy user of GLSL compute shaders - and luckily now I don&rsquo;t have to use them!</p>
<p>For the purposes of the sample, I&rsquo;ve hand written a little compute shader to copy from a storage buffer (set = 0, binding = 0) to another storage buffer (set = 0, binding = 1). As to the details of my approach, I&rsquo;ll leave that to a future blog post (it&rsquo;d be a lengthy sidetrack for this post I fear).</p>
<p>To create a compute pipeline that we can execute with, we first create a shader module with vkCreateShaderModule. Next we need a descriptor set layout using vkCreateDescriptorSetLayout, with the following structs:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>VkDescriptorSetLayoutBinding descriptorSetLayoutBindings[<span style="color:#ae81ff">2</span>] <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>  {<span style="color:#ae81ff">0</span>, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, <span style="color:#ae81ff">1</span>, VK_SHADER_STAGE_COMPUTE_BIT, <span style="color:#ae81ff">0</span>},
</span></span><span style="display:flex;"><span>  {<span style="color:#ae81ff">1</span>, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, <span style="color:#ae81ff">1</span>, VK_SHADER_STAGE_COMPUTE_BIT, <span style="color:#ae81ff">0</span>}
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>  VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">2</span>, descriptorSetLayoutBindings
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p>We are describing the bindings within the set we are using for our compute shader, namely we have two descriptors in the set, both of which are storage buffers being used in a compute shader.</p>
<p>We then use vkCreatePipelineLayout to create our pipeline layout:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">typedef</span> <span style="color:#66d9ef">struct</span> VkPipelineLayoutCreateInfo {
</span></span><span style="display:flex;"><span>    VkStructureType                 sType;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> <span style="color:#66d9ef">void</span><span style="color:#f92672">*</span>                     pNext;
</span></span><span style="display:flex;"><span>    VkPipelineLayoutCreateFlags     flags;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span>                        setLayoutCount; <span style="color:#75715e">// care about this
</span></span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> VkDescriptorSetLayout<span style="color:#f92672">*</span>    pSetLayouts;    <span style="color:#75715e">// care about this
</span></span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">uint32_t</span>                        pushConstantRangeCount;
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">const</span> VkPushConstantRange<span style="color:#f92672">*</span>      pPushConstantRanges;
</span></span><span style="display:flex;"><span>} VkPipelineLayoutCreateInfo;
</span></span></code></pre></div><p>Since we have only one descriptor set, we set setLayoutCount to 1, and pSetLayouts to the descriptor set layout we created for our two bindings-set created before.</p>
<p>And then lastly we use vkCreateComputePipelines to create our compute pipeline:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>VkComputePipelineCreateInfo computePipelineCreateInfo <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>  VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>,
</span></span><span style="display:flex;"><span>  {
</span></span><span style="display:flex;"><span>    VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>, VK_SHADER_STAGE_COMPUTE_BIT, shader_module, <span style="color:#e6db74">&#34;f&#34;</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>  },
</span></span><span style="display:flex;"><span>  pipelineLayout, <span style="color:#ae81ff">0</span>, <span style="color:#ae81ff">0</span>
</span></span><span style="display:flex;"><span>};
</span></span></code></pre></div><p>Our shader has one entry point called &ldquo;f&rdquo; for its shader, and it is a compute shader. We also need the pipeline layout we just created, and et voilà - we have our compute pipeline ready to execute with.</p>
<h3 id="executing-the-compute-shader">executing the compute shader</h3>
<p>To execute a compute shader we need to:</p>
<ol>
<li>Create a descriptor set that has two VkDescriptorBufferInfo&rsquo;s for each of our buffers (one for each binding in the compute shader).</li>
<li>Update the descriptor set to set the bindings of both of the VkBuffer&rsquo;s we created earlier.</li>
<li>Create a command pool with our queue family index.</li>
<li>Allocate a command buffer from the command pool (we&rsquo;re using VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT as we aren&rsquo;t resubmitting the buffer in our sample).</li>
<li>Begin the command buffer.</li>
<li>Bind our compute pipeline.</li>
<li>Bind our descriptor set at the VK_PIPELINE_BIND_POINT_COMPUTE.</li>
<li>Dispatch a compute shader for each element of our buffer.</li>
<li>End the command buffer.</li>
<li>And submit it to the queue!</li>
</ol>
<h3 id="getting-the-results">getting the results</h3>
<p>To get the results from a submitted command buffer, the coarse way to do this is to use vkQueueWaitIdle - wait for all command buffers submitted to a queue to complete. For our purposes, we are submitting one queue, and waiting for it to complete, so it is the perfect tool for our sample - but broadly speaking you are better chaining dependent submissions together with VkSemaphore&rsquo;s, and using a VkFence for only the queue at the end of the workload to ensure the execution has complete.</p>
<p>Once we&rsquo;ve waited on the queue, we simply map the memory and check that the first half of the buffer equals the second half - EG. the memcpy of the elements succeeded:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#66d9ef">int32_t</span> <span style="color:#f92672">*</span>payload;
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">vkMapMemory</span>(device, memory, <span style="color:#ae81ff">0</span>, memorySize, <span style="color:#ae81ff">0</span>, (<span style="color:#66d9ef">void</span> <span style="color:#f92672">*</span>)<span style="color:#f92672">&amp;</span>payload);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">uint32_t</span> k <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>, e <span style="color:#f92672">=</span> bufferSize <span style="color:#f92672">/</span> <span style="color:#66d9ef">sizeof</span>(<span style="color:#66d9ef">int32_t</span>); k <span style="color:#f92672">&amp;</span>lt; e; k<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#a6e22e">assert</span>(payload[k <span style="color:#f92672">+</span> e] <span style="color:#f92672">==</span> payload[k]);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>And we are done! We have written our first memcpy sample in Vulkan compute shaders.</p>
<h3 id="fin">fin</h3>
<p>The sample is dirty in <em>&lsquo;real-world application&rsquo;</em> terms - it doesn&rsquo;t free any of the Vulkan objects that need to be freed on completion. TL;DR one of the drivers I am testing on loves to segfault on perfectly valid code (and yes, for any IHV&rsquo;s reading this I have already flagged this up with the relevant vendor!).</p>
<p>But for the purposes of explaining an easy Vulkan compute sample to all the compute lovers among my readership I hope the above gives you a good overview of exactly how to do that - yes there are many hoops to jump through to get something executing, but the sheer level of control that can be achieved through the Vulkan API far outweighs a few extra lines of code we need.</p>
<p>The full sample is available at the <a href="https://gist.github.com/sheredom/523f02bbad2ae397d7ed255f3f3b5a7f">GitHub gist here</a>.</p>
<p>Stay tuned for more Vulkan compute examples to come in future posts!</p>
]]></description>
    </item>
    
    <item>
      <title>Allocators in json.h!</title>
      <link>https://www.neilhenning.dev/posts/allocators-in-json-h/</link>
      <pubDate>Sun, 27 Mar 2016 20:11:38 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/allocators-in-json-h/</guid>
      <description><![CDATA[<p>While at GDC I got a feature request from the awesome folks over at <!-- raw HTML omitted -->Blastbay Studios<!-- raw HTML omitted --> requesting that they could feed an allocator to <!-- raw HTML omitted -->json.h<!-- raw HTML omitted -->, my JSON parsing library. This has long been on my TODO list, so I took the opportunity of a plane ride back from San Francisco to the Isle of Skye to remedy the situation!</p>
<p>The latest master version of <!-- raw HTML omitted -->j<!-- raw HTML omitted -->son.h changes the signature of json_parse_ex to include two new fields:</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>alloc_func_ptr and user_data.</p>
<p>For recap, json.h uses 1 allocation to store the entire structure and contents of the JSON file (see <!-- raw HTML omitted -->my introductory post for json.h<!-- raw HTML omitted --> for details).</p>
<p>Instead of calling malloc, if alloc_func_ptr is not NULL, it will instead call the allocator and provide the user_data to the allocator as the first parameter, and the size of allocation requested as the second parameter.</p>
<p>I hope this added functionality proves useful to the many people who are already using json.h in their applications!</p>
]]></description>
    </item>
    
    <item>
      <title>git pre-commit clang-format hook</title>
      <link>https://www.neilhenning.dev/posts/git-pre-commit-clang-format-hook/</link>
      <pubDate>Mon, 11 Jan 2016 11:54:15 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/git-pre-commit-clang-format-hook/</guid>
      <description><![CDATA[<p>Most of my company projects have a requirement that we run clang-format on all commits to keep a consistent style. Unfortunately, I&rsquo;m as forgetful as the fabled goldfish (<a href="https://en.wikipedia.org/wiki/Goldfish#Cognitive_abilities">which actually isn&rsquo;t that forgetful it turns out</a>) so I often forget to run clang-format.</p>
<p>After the umpteenth time of forgetting and suffering some quite deepseated rage from my colleagues, I decided to investigate a way to automate the process.</p>
<p>It turns out git has a really cool feature introduced in 1.7.0 to specify a folder of hooks, such that when you run git clone or git init to create a new local copy of a repository, it will as part of the creation process take a copy of these ‘template&rsquo; git hooks and use them in the repository.</p>
<p>I&rsquo;ve created a GitHub repo <a href="https://github.com/sheredom/git-hooks">git-hooks</a> that contains my pre-commit hook for running clang-format on all .c, .cpp, .cc and .h files before committing them.</p>
<p>To use, simply clone the git repo to a folder <!-- raw HTML omitted -->, and then run;</p>
<pre><code>git config --global init.templatedir &quot;&lt;whatever folder name you choose&gt;&quot;
</code></pre>
<p>Then whenever you clone or init a git repository this hook will be copied and be used in your repositories. If you have existing repositories that you want to use the hook, simply re-run git init in the repository and it will copy the hook across.</p>
<p>One minor caveat, if you have any pre-existing git pre-commit hook in the repository then git will not overwrite it.</p>
<p>I&rsquo;ve tested this on Windows and Linux, and I hope it proves as useful to others as it has been to me!</p>
]]></description>
    </item>
    
    <item>
      <title>Full Simplified JSON support in json.h</title>
      <link>https://www.neilhenning.dev/posts/full-simplified-json-support-in-json-h/</link>
      <pubDate>Wed, 23 Dec 2015 17:28:07 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/full-simplified-json-support-in-json-h/</guid>
      <description><![CDATA[<p>In a previous post <!-- raw HTML omitted -->(Partial) Simplified JSON support in json.h<!-- raw HTML omitted --> I covered the partially added simplified JSON support I had added to <!-- raw HTML omitted -->json.h<!-- raw HTML omitted -->. One of the things I covered was my unwillingness to implement two of the features of simplified JSON, commas being optional and replacing : with =. I argued that both of these were unnecessary and stupid additions to the library.</p>
<p>I was wrong. The immediate feedback I received detailed good reasons why these were useful, but more importantly - why did I half-arse implementing a feature that was requested by a user!</p>
<p>So today, I&rsquo;ve implemented all of simplified JSON. You can now parse;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>by using the following code;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>A few caveats to remember when writing/using this code though:</p>
<ul>
<li>json_parse_flags_allow_simplified_json is a bitmask enabling many other json_parse_flags that you can enable separately. As such, the behaviour of each of them applies collectively when using this flag</li>
<li>commas aren&rsquo;t banned, they are just not required. You can mix commas/no-commas throughout your simplified JSON. You can also have trailing commas after the last element in an object/array now too</li>
<li>unquoted keys aren&rsquo;t banned, you can mix and match quoted/unquoted keys</li>
<li>you always have a global object. Even if your JSON string was ‘{}&rsquo;, you would have a global object that contained one empty object with simplified JSON enabled</li>
<li>colons aren&rsquo;t banned, you can mix ‘:&rsquo; and ‘=&rsquo; when separating your key/value pairs within objects</li>
</ul>
<p>I hope you find this option useful, and I intend to keep working on <!-- raw HTML omitted -->json.h<!-- raw HTML omitted --> over my Christmas holidays so stay tuned!</p>
]]></description>
    </item>
    
    <item>
      <title>Introducing utest.h!</title>
      <link>https://www.neilhenning.dev/posts/introducing-utest-h/</link>
      <pubDate>Fri, 11 Dec 2015 15:34:40 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/introducing-utest-h/</guid>
      <description><![CDATA[<p>So as you may (or may not) already know - I&rsquo;ve written two tiny C libraries - <!-- raw HTML omitted -->utf8.h<!-- raw HTML omitted --> and <!-- raw HTML omitted -->json.h<!-- raw HTML omitted -->. One of the questions that most plagued me when writing these libraries was ‘How should I write the tests for them?&rsquo; I could put them in a separate repository, I could put them within the repository, should I create a new testing framework every time? It would be useful to be able to have test cases spread across multiple files… and the thoughts went on and on.</p>
<p>Basically what I wanted was a single header variant of <!-- raw HTML omitted -->googletest<!-- raw HTML omitted --> - and for it to be able to work in C. I scoured the interwebs a bit, but I couldn&rsquo;t really find exactly what I wanted. When in doubt, write your own I say!</p>
<p>So I&rsquo;m introducing <!-- raw HTML omitted -->utest.h<!-- raw HTML omitted --> - a single header C/C++ unit tester. It&rsquo;s licensed under the public domain (via the <!-- raw HTML omitted -->unlicense<!-- raw HTML omitted -->), and it works and is tested on Mac OSX, Linux and Windows, with both C and C++ files in the same tested executable. I&rsquo;ve tried to mimic <!-- raw HTML omitted -->googletest<!-- raw HTML omitted -->‘s command line output as much as possible, even using the coloured text output where possible.</p>
<p>To start testing with <!-- raw HTML omitted -->utest.h<!-- raw HTML omitted -->, the absolute minimum you need is a TESTCASE(set, name) and UTEST_MAIN() to be in one of your source files. UTEST_MAIN() defines an int main(…) entry point function, so don&rsquo;t try and define your own! For example;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>I use the gcc/clang extension __attribute__((constructor)) to allow multiple files to register test cases pre-main, and an even uglier MSVC workaround to mimic __attribute__((constructor)) on Windows. The bottom line though - it works, and everyone can test across C/C++ to their heart&rsquo;s delight.</p>
<p>Future work will include having command line arguments to select what test cases to run, and being able to output an xunit/junit xml file so that continuous integrations can easily pick up the results of the test cases. Stay tuned!</p>
]]></description>
    </item>
    
    <item>
      <title>(Partial) Simplified JSON support in json.h</title>
      <link>https://www.neilhenning.dev/posts/partial-simplified-json-support-in-json-h/</link>
      <pubDate>Fri, 04 Dec 2015 09:51:02 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/partial-simplified-json-support-in-json-h/</guid>
      <description><![CDATA[<p>With the help of the rather awesome <!-- raw HTML omitted -->@ocornut<!-- raw HTML omitted --> - I&rsquo;ve managed to get a variant of <!-- raw HTML omitted -->simplified JSON<!-- raw HTML omitted --> support into <!-- raw HTML omitted -->json.h<!-- raw HTML omitted -->!</p>
<p>So first off - what is simplified JSON?  Taken straight from the Bitsquid blog;</p>
<ol>
<li>Assume an object definition at the root level (no need to surround entire file with { })</li>
<li>Commas are optional</li>
<li>Quotes around object keys are optional if the keys are valid identifiers</li>
<li>Replace : with =</li>
</ol>
<p>Of the four points above, I&rsquo;m going to argue that only 1. and 3. are actually useful.</p>
<hr>
<h4 id="1-assume-an-object-definition-at-the-root-level-no-need-to-surround-entire-file-with--">1. Assume an object definition at the root level (no need to surround entire file with { })</h4>
<p>If you are always going to start a JSON file with an object (which is the recommended behaviour when using JSON), it can be quite tedious to surround the parent object with { }&rsquo;s. Imagine we have the following;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Whereas with 1. this could read;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>As we can see, it reads that little bit nicer overall. It has a nice benefit of also meaning you don&rsquo;t have to indent the parent key/value elements of the main object - if you like me are rather over the top about indentation this is a nice space saver. The one downside for the JSON security purists is that someone could easily append onto the object with new elements - something that I know is a problem in certain domains.</p>
<h4 id="2-commas-are-optional">2. Commas are optional</h4>
<p>I really dislike this idea. Essentially the idea is that;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Would be entirely valid with simplified JSON. I dislike this because you can end up with some really disgusting code. The code above looks like the newlines are basically replacing the commas to denote new elements, but the above would be functionally equivalent to;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Which looks utterly hideous. This also adds some pretty funky parsing variants for <!-- raw HTML omitted -->json.h<!-- raw HTML omitted --> which I just wasn&rsquo;t keen to add.</p>
<h4 id="3-quotes-around-object-keys-are-optional-if-the-keys-are-valid-identifiers">3. Quotes around object keys are optional if the keys are valid identifiers</h4>
<p>It can be a real chore and also quite expensive in terms of file size to surround all the keys of objects with ” “‘s too! For the example;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>Given that “a”, “b” and “c” don&rsquo;t contain funky characters or whitespace, why not allow them to be specified like;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>It looks pretty nice, and saves some space, to be able to specify them without the ” “‘s.</p>
<h4 id="4-replace--with-">4. Replace : with =</h4>
<p>This rule I dislike simply because it is a stylistic choice. Even reading the Bitsquid blog that specified simplified JSON - it was done to make the code read more like Lua. This is something we could add, but I don&rsquo;t see the point as its not a functional change, its a stylistic change.</p>
<h4 id="solving-the-problem-with-2">Solving the problem with 2.</h4>
<p>So as I said in my comments on 2., I don&rsquo;t like the ‘commas are optional&rsquo; rule. To my rescue came <!-- raw HTML omitted -->@ocornut<!-- raw HTML omitted --> - who happened to suggest that allowing trailing commas on elements would be a useful helper for some work he was doing with my <!-- raw HTML omitted -->json.h<!-- raw HTML omitted --> library, and it got me thinking - this seems to solve at least part of the problem with 2.! Making it such that commas are a little easier to use makes them seem that little bit more innocuous for developers to use.</p>
<p>So I&rsquo;ve settled on a happy medium of the features from simplified JSON that I think are useful. In the next post I&rsquo;ll explain how I changed the API to allow both pure/original/unadulterated JSON to survive alongside my partial simplified JSON support!</p>
]]></description>
    </item>
    
    <item>
      <title>json.h performance (update!)</title>
      <link>https://www.neilhenning.dev/posts/json-h-performance-update/</link>
      <pubDate>Mon, 14 Sep 2015 14:41:51 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/json-h-performance-update/</guid>
      <description><![CDATA[<p>So previously I tested my json.h library&rsquo;s performance against other JSON libraries in the wild (<a href="https://www.neilhenning.dev/json-h-performance-vs-other-cc-json-parsers/">json.h performance (vs other C/C++ JSON parsers</a>). My JSON parser wasn&rsquo;t performing as I&rsquo;d expect in the tests, so I&rsquo;ve spent a good amount of time looking at why.</p>
<p>Before we begin, you can find the sources to my public domain, one .c/one .h file json.h library here - <a href="https://github.com/sheredom/json.h">https://github.com/sheredom/json.h</a></p>
<p>A little information on my initial approach. The idea was that we would try and keep the values that make up arrays and objects together in memory. Using the worked example;</p>
<blockquote>
<p>{<!-- raw HTML omitted -->“a”<!-- raw HTML omitted --> : [<!-- raw HTML omitted -->123<!-- raw HTML omitted -->, <!-- raw HTML omitted -->null<!-- raw HTML omitted -->, <!-- raw HTML omitted -->true<!-- raw HTML omitted -->, <!-- raw HTML omitted -->false<!-- raw HTML omitted -->, <!-- raw HTML omitted -->“alphabet”<!-- raw HTML omitted -->]}</p>
</blockquote>
<p>Would produce the following DOM structure for the above JSON;</p>

<img src="/wp-content/uploads/2015/08/chart2.png"  class="center"  style="border-radius: 8px;"    />


<p>In the above diagram, we can see that the one json_object_s contains an array to the names and values contained within the object, and the one json_array_s contains an array to the values.</p>
<p>In practice though, it was this design decision that caused the main performance bottleneck of the approach - effectively each time you came to a new object or array, you&rsquo;d have to first skip over all the contents of the object or array simply to first find out the number of values within! In big O notation, our worst case was O(n²) for parsing any given JSON file.</p>
<p>To fix this issue, we need to decouple the allocation of the memory to store the values contained within objects and arrays such that we can create a single value, fill out of the information about the contents of that value, and then allocate the next value. Effectively we need to sacrifice our array and instead have a linked-list of values.</p>
<p>To do this I&rsquo;ve introduced json_array_element_s and json_object_element_s structures which form the new linked-list to the json.h library, and it is through these that you&rsquo;ll have to iterate when traversing the DOM. Our worst case now becomes O(n) for parsing a JSON file.</p>
<p>Our new DOM for the above worked example is;</p>

<img src="/wp-content/uploads/2015/09/dom2.png"  class="center"  style="border-radius: 8px;"    />


<p>Our new DOM is admittedly not as concise or pretty, but performance wise - it is a winner.</p>
<p>I used three files, parsed and traversed them, and recorded the results in my previous post. I&rsquo;ve updated the graphs below but this time added in a new row &lsquo;json.h - old&rsquo; for the previous approach, and json.h is using the newer approach.</p>

<img src="/wp-content/uploads/2015/09/json-generator2.png"  class="center"  style="border-radius: 8px;"    />



<img src="/wp-content/uploads/2015/09/AllSets2.png"  class="center"  style="border-radius: 8px;"    />



<img src="/wp-content/uploads/2015/09/sf-city-lots-json2.png"  class="center"  style="border-radius: 8px;"    />


<p>As can be seen from the three charts, our performance is massively improved over the previous approach, an easy 3x+ faster overall. gason still performs the best of all the libraries benchmarked, but at least our parser is now in the region of the other parsers in terms of performance, non-withstanding the massive philosophical design difference that json.h decided on.</p>
<p>I hope you enjoyed this post, and I&rsquo;ll keep beavering away on my json.h library to improve it further!</p>
]]></description>
    </item>
    
    <item>
      <title>json.h performance (vs other C/C&#43;&#43; JSON parsers)</title>
      <link>https://www.neilhenning.dev/posts/json-h-performance-vs-other-cc-json-parsers/</link>
      <pubDate>Mon, 24 Aug 2015 13:10:34 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/json-h-performance-vs-other-cc-json-parsers/</guid>
      <description><![CDATA[<p>One of the first questions I had when I open sourced my <a href="https://www.neilhenning.dev/json-h/">json.h</a> library was how fast it can parse compared to other commonly used JSON libraries around. I&rsquo;ve gone through all of the JSON libraries in C/C++ that I find tolerable (and I&rsquo;ll document which ones I wouldn&rsquo;t touch with a barge pole and why too!) and performed a performance comparison on them.</p>
<p>First off, I tested the following JSON C/C++ libraries;</p>
<ul>
<li><a href="https://github.com/vivkin/gason">gason</a> - C++ library with MIT license.</li>
<li><a href="https://github.com/sheredom/json.h">json.h</a> - my own JSON library, written in C and licensed under the unlicense.</li>
<li><a href="https://github.com/giacomodrago/minijson_reader">minijson_reader</a> - C++11 library with BSD 3-Clause license.</li>
<li><a href="https://github.com/miloyip/rapidjson">rapidjson</a> - C++ library with MIT license.</li>
<li><a href="https://github.com/chadaustin/sajson">sajson</a> - C++ library with MIT license.</li>
<li><a href="https://github.com/esnme/ujson4c/">ujson4c</a> - C library with BSD license.</li>
</ul>
<p>And I rejected the following JSON C/C++ libraries (with some comments reasoning why I haven&rsquo;t used them);</p>
<ul>
<li><a href="https://bitbucket.org/zserge/jsmn">jsmn</a> - I initially did add this to the benchmark, but I found that when testing large input files, the time taken to parse was exponentially linked to the file size. Thus after around 1 minute trying to parse a 190MB file I made my benchmark timeout, and have removed this library from my benchmarking.</li>
<li><a href="http://fossil.wanderinghorse.net/wikis/cson/">cson</a> - Uses some bizarre SCM called <a href="http://fossil-scm.org/">Fossil SCM</a> which was enough of a roadblock to stop any further explorations.</li>
<li><a href="https://github.com/cesanta/frozen">frozen</a> - GPL license means it isn&rsquo;t worth considering any further.</li>
<li><a href="https://github.com/akheron/jansson">jansson</a> - absolutely crazy CMake files required to get it to build.</li>
<li><a href="https://github.com/quartzjer/js0n">js0n</a> - only allows for searching of arbitrary tokens in a JSON stream, does not do a full parse and exploration of the DOM.</li>
<li><a href="https://github.com/open-source-parsers/jsoncpp">jsoncpp</a> - another crazy CMake mess, not touching this library.</li>
<li><a href="https://github.com/tunnuz/json">json++</a> - requires Flex/Bison, stupid requirement for a simple library.</li>
<li><a href="https://github.com/json-c/json-c">json-c</a> - Absolutely no idea what is going on with this repository. Clusterfuck is too kind an explanation for what is going on.</li>
<li><a href="http://www.catb.org/~esr/microjson/">mjson</a> - Requires compile time knowledge of JSON structure (only allows parsing of ‘known&rsquo; JSON structures).</li>
<li><a href="https://bitbucket.org/yarosla/nxjson">nxjson</a> - Another GPL licensed library means it is a write-off.</li>
<li><a href="https://github.com/vivkin/vjson">vjson</a> - code did not have a license, too risky to explore it further.</li>
</ul>
<p>I ran two kinds of testing, the cost of parsing some JSON files and storing them in the intermediate form, and also the cost of parsing then traversing the JSON to count all the numbers in the JSON structure.</p>

<img src="/wp-content/uploads/2015/08/json-generator.png"  class="center"  style="border-radius: 8px;"    />


<p>The first JSON file I tested was a 9KB file. In this test my own json.h library is second worst of the six tested, a full 4x slower than the best performing gason library.</p>

<img src="/wp-content/uploads/2015/08/AllSets.png"  class="center"  style="border-radius: 8px;"    />


<p>Ouch, on the 12.9MB file we perform worst of all. The reason minijson_reader seems to beat us here is that the input file AllSets.json is simply one large JSON array containing identical JSON objects in each element. The bigger the depth of the JSON objects (EG. objects, within arrays, within objects, etc.) the worst minijson_reader performs.</p>

<img src="/wp-content/uploads/2015/08/sf-city-lots-json.png"  class="center"  style="border-radius: 8px;"    />


<p>On the largest of our inputs, the large 190MB file, we perform second worst again. This library has many levels of objects and arrays, which is why minijson_reader performs atrociously bad.</p>
<p>One thing to note among all the examples is the difference between the parsing, and parse + traversing. Our library has a much narrower gap between these two than the other libraries, which means once the parsing has completed, iterating through our in memory representation is much quicker than the alternatives, I just need to work out now how to improve the parsing speed!</p>
<p>So in conclusion, my library is slower than I&rsquo;d like - the only heartening thing is the speed of the library is a constant (at least I don&rsquo;t have exponentially bad parsing!). I&rsquo;ve already started to profile and re-write the offending part of the parsing, something I&rsquo;ll cover in a future blog post.</p>
<p>Please check out the library <a href="https://github.com/sheredom/json.h">here</a> - I am more than happy to accept merge requests and feedback (I&rsquo;ve already changed things based on user feedback!).</p>
]]></description>
    </item>
    
    <item>
      <title>json.h</title>
      <link>https://www.neilhenning.dev/posts/json-h/</link>
      <pubDate>Tue, 18 Aug 2015 09:05:41 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/json-h/</guid>
      <description><![CDATA[<p>Back in May, the rather awesome <a href="https://www.patreon.com/imgui">imgui</a> creator <a href="https://twitter.com/ocornut">@ocornut</a> asked the following;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And it got me thinking - why isn&rsquo;t there a simple JSON reader/writer lib in the same vein as the <a href="https://github.com/nothings/stb">stb_*</a> libraries that performs a single call to malloc to encode the state? I couldn&rsquo;t find one, so I decided to write my own.</p>
<p>I&rsquo;m introducing <a href="https://github.com/sheredom/json.h">json.h</a> - my one header/one source json library that will parse a JSON source into a single allocation buffer, and also has functions to write out the minified version of the JSON, and a pretty print function (for human readable JSON).</p>
<p>Lets go through a worked example, lets take the following trivial JSON;</p>
<blockquote>
<p>{<!-- raw HTML omitted -->“a”<!-- raw HTML omitted --> : [<!-- raw HTML omitted -->123<!-- raw HTML omitted -->, <!-- raw HTML omitted -->null<!-- raw HTML omitted -->, <!-- raw HTML omitted -->true<!-- raw HTML omitted -->, <!-- raw HTML omitted -->false<!-- raw HTML omitted -->, <!-- raw HTML omitted -->“alphabet”<!-- raw HTML omitted -->]}</p>
</blockquote>
<p>The above example covers all the core concepts inherent within JSON, so serves as a good coverage tool for our parsing. The above will be parsed (using json_parse) into a single-malloc&rsquo;ed buffer, with the start of that buffer being a json_value_s* - a pointer to the root value. The Document Object Model (DOM) for this JSON is;</p>

<img src="/wp-content/uploads/2015/08/chart2.png"  class="center"  style="border-radius: 8px;"    />


<p>And the single allocation in-memory view of the above is;</p>

<img src="/wp-content/uploads/2015/08/chart3.png"  class="center"  style="border-radius: 8px;"    />


<p>In terms of speed of the library I&rsquo;ve used these JSON files for reference;</p>
<ul>
<li><a href="https://github.com/zeMirco/sf-city-lots-json">sf-city-lots-json</a> - 181.4MB file</li>
<li><a href="http://mtgjson.com/json/AllSets.json">mtgjson.com&rsquo;s AllSets.json</a> - 12.9MB file</li>
<li><a href="http://www.mockaroo.com">http://www.mockaroo.com</a> - 134KB file</li>
<li><a href="http://www.json-generator.com/">http://www.json-generator.com</a> - 9 KB file</li>
</ul>
<p>Which produces the following chart;</p>

<img src="/wp-content/uploads/2015/08/chart.png"  class="center"  style="border-radius: 8px;"    />


<p>Currently, parsing is averaging around 55 MB/s, pretty writing around 300 MB/s and minified writing around 500 MB/s on my Intel Core i7-2700k 3.5GHz.</p>
<p>My next step will be to look into my parsing approach and see if anything can be done to speed up parsing of JSON!</p>
<p>I hope this library is useful, and I&rsquo;m happy to have any comments/critiques on my approach.</p>
]]></description>
    </item>
    
    <item>
      <title>utf8.h progress!</title>
      <link>https://www.neilhenning.dev/posts/utf8-h-progress/</link>
      <pubDate>Thu, 23 Jul 2015 15:14:15 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/utf8-h-progress/</guid>
      <description><![CDATA[<p>Since my <a href="https://www.neilhenning.dev/utf8-h/">last post introducing utf8.h</a> I&rsquo;ve been frantically working on fleshing out the core utf8* functions to match the str* ones, and also listening to developer feedback!</p>
<p>Firstly, you can check out the one header C/C++ library here - <a href="https://github.com/sheredom/utf8.h">utf8.h</a>.</p>
<ul>
<li><a href="https://twitter.com/daniel_collin">@daniel_collin</a> suggested adding an ASCII only utf8casecmp, which has been added. I&rsquo;m looking into extending this to support more of the characters in Unicode (the most obvious ones that I can understand are ASCII characters with accents).</li>
<li><a href="https://twitter.com/mcclure111">@mcclure111</a> suggested I actually document the code where appropriate, and I&rsquo;ve undertake efforts to remedy this.</li>
</ul>
<p>Next up I plan to tackle the utf8canon that <a href="https://twitter.com/KmBenzie">@KmBenzie</a> suggested, to canonicalize poorly formed utf8 codepoints into the correct form (for example, utf8 ascii values can be encoded erroneously in a 4-byte codepoint which is regarded as poor form).</p>
]]></description>
    </item>
    
    <item>
      <title>utf8.h</title>
      <link>https://www.neilhenning.dev/posts/utf8-h/</link>
      <pubDate>Tue, 07 Jul 2015 22:47:16 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/utf8-h/</guid>
      <description><![CDATA[<p>I&rsquo;ve been tinkering around with a new one header library (having been inspired by the awesome <a href="https://github.com/nothings/stb">stb</a> libraries that <a href="http://twitter.com/nothings">@nothings</a> created), a utf8 string library <a href="https://github.com/sheredom/utf8.h">https://github.com/sheredom/utf8.h</a>.</p>
<p>The <a href="https://github.com/sheredom/utf8.h/blob/master/utf8.h">utf8.h</a> header adds some new utf8* prefixed functions that match the str* functions you would find in string.h, except that they are all written for utf8 exclusively. For example, utf8len will return the number of utf8 codepoints found in the provided utf8 string.</p>
<p>The code works for gcc and clang currently (I haven&rsquo;t had the time to port it to Windows and MSVC), and I would love it if you would check it out!</p>
]]></description>
    </item>
    
    <item>
      <title>Length vs size for array dimensions</title>
      <link>https://www.neilhenning.dev/posts/length-vs-size-for-array-dimensions/</link>
      <pubDate>Mon, 01 Jun 2015 19:49:09 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/length-vs-size-for-array-dimensions/</guid>
      <description><![CDATA[<p>I&rsquo;m quite particular about how I word the variables that are exposed via my APIs. I always prefix pointers that I write to with out_*, my variables are always in C style this_is_my_variables_name and I try to be as descriptive as possible of what the type is actually going to be used for.</p>
<p>One thing that I tend to pay particular attention to is when I want to pass an array of items into a function. For example;</p>
<!-- raw HTML omitted -->
<p>Is a really awful entry point for an array to an API. First off, there is no correlation in the wording of a and b, even if there was b should be an unsigned type if it is going to point to valid allocated memory. A better approach would be;</p>
<!-- raw HTML omitted -->
<p>But there is something I don&rsquo;t like about this. I don&rsquo;t like the use of the word ‘size&rsquo; here.</p>
<p>Maybe this isn&rsquo;t the case for all, but for me ‘size&rsquo; equates directly to bytes, it is the size of memory allocated to contain a variable or array. If I see an API like the above, I immediately think that the code within that will loop over the array like;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>For me, I would use length in this context - length implies that the memory is allocated such that there is length N int&rsquo;s in the array. I only use size when I am dealing with void* array pointers - EG. some data that I can make no assumptions what its composition is.</p>
<p>One last quirk with this approach is that some people like to still use size when referring to char* data - EG. an array with a byte-width payload. I would still recommend you use length in this context, because you are still assuming that you will interface with that char* array by simply using the length as a bounding value, like;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
]]></description>
    </item>
    
    <item>
      <title>On the use and abuse of size_t</title>
      <link>https://www.neilhenning.dev/posts/on-the-use-and-abuse-of-size_t/</link>
      <pubDate>Mon, 25 May 2015 22:06:25 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/on-the-use-and-abuse-of-size_t/</guid>
      <description><![CDATA[<p>Just about everyone has used the size_t type - and everybody and their grandmothers know what the type means of course! The usual answers I get to ‘tell me what size_t is without Googling it&rsquo; is;</p>
<ol>
<li>It is the parameter type for malloc to allocate memory!</li>
<li>It is a platform dependent 32/64 bit unsigned integer type!</li>
<li>It is what size_type in all the C++ std template hell is! (ok I made this one up - but fuck me the size_type lark really annoys me in the std code.)</li>
</ol>
<p>In general though the main assumption is that the size_t type is a platform agnostic way to represent any potential size of memory you could allocate or use.</p>
<p>The definition from <a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf">ISO/IEC 9899:TC3</a>, section 7.17 is;</p>
<blockquote>
<p>size_t</p>
<p>which is the unsigned integer type of the result of the sizeof operator</p>
</blockquote>
<p>And also relevant  is section 7.18.3;</p>
<blockquote>
<p>limit of size_t</p>
<p>SIZE_MAX 65535</p>
</blockquote>
<p>So the minimum maximum value that size_t must be able to hold is 65535, which is 16 bits of precision, and size_t is only defined to be an unknown unsigned integer type. Let that sink in - size_t can, by the standard, be an uint16_t type on a platform with 32 or 64 bit addressing.</p>
<p>Now before the reader decides to flip their table like this fine gentleman;</p>

<img src="/wp-content/uploads/2015/05/tableflip.gif"  class="center"  style="border-radius: 8px;"    />


<p>I completely understand that on every platform the modern C/C++ developer uses and cares about size_t is either uint32_t on 32 bit platforms, or uint64_t on 64 bit platforms. What annoys me though is that I could take my perfectly portable (among standard MSVC/Clang/GCC compilers) C/C++ code and run it on some random compiler for a given platform, and it could fail in a non-obvious way! This in turn would probably lead me to say ‘this new platform must have shit tools!&rsquo; when in fact the platform is supporting the C standard to the letter in their approach.</p>
<p>This is why I don&rsquo;t use size_t in my interfaces or code, it irks me that some random compiler somewhere could legitimately fail on my code.</p>
<p>So what is the alternative? Really the type we should be using is uintptr_t - EG. the unsigned integer type that matches the width of the pointer type. That way if I decide to allocate all of my memory I will always have a type that can encompass that size value always. But of course, there is a problem there too, from section 7.18.1.4;</p>
<blockquote>
<p>The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:</p>
<p>intptr_t</p>
<p>The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:</p>
<p>uintptr_t</p>
<p>These types are optional.</p>
</blockquote>
<p>And just for emphasis  <em><strong>‘</strong></em><strong>These types are optional&rsquo;</strong>. So anyone thinking of using these types too? Please don&rsquo;t! An entirely conformant compiler and toolchain could give you a big;</p>

<img src="/wp-content/uploads/2015/05/fuckhugh.jpg"  class="center"  style="border-radius: 8px;"    />


<p>What I tend to do (and I understand the grievances in this) is either define my own size type in my interfaces (involves a ton of preprocessor checks for arm/x86/x86-64/ppc/mips/etc) or just use uint64_t for anything that could represent memory. So the next time you see a uint64_t representing an allocatable size in some of my code, you know why!</p>
]]></description>
    </item>
    
    <item>
      <title>Connecting a build node to Jenkins on Raspberry Pi 2</title>
      <link>https://www.neilhenning.dev/posts/connecting-a-build-node-to-jenkins-on-raspberry-pi-2/</link>
      <pubDate>Thu, 21 May 2015 22:13:30 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/connecting-a-build-node-to-jenkins-on-raspberry-pi-2/</guid>
      <description><![CDATA[<p>So I previously <a href="https://www.neilhenning.dev/installing-jenkins-on-raspberry-pi-2/">installed Jenkins on my Raspberry Pi 2</a>, and <a href="https://www.neilhenning.dev/running-your-first-job-on-the-raspberry-pi-2-jenkins/">ran my first job through Jenkins</a>. The final obvious step was to get another build node to connect to my Jenkins server so that workload can be offloaded from the Raspberry Pi 2 to another device.</p>
<p>The lovely folks over at <a href="https://twitter.com/ImaginationTech">Imagination Technologies</a> sent me a <a href="http://community.imgtec.com/platforms/creator-ci20/">MIPS Creator CI20</a> board a while back, and this seemed like the perfect node to add to my new Jenkins build farm!</p>
<p>So first step, you go to ‘Manage Jenkins&rsquo; -&gt; ‘Manage Nodes';</p>

<img src="/wp-content/uploads/2015/05/Capture.png"  class="center"  style="border-radius: 8px;"    />


<p>Next, you want to add a new Node (picking whatever name you choose), I went with ci20 for a rather obvious name. My only choice was a &lsquo;Dumb Slave&rsquo;, so I went with that.</p>

<img src="/wp-content/uploads/2015/05/Capture1.png"  class="center"  style="border-radius: 8px;"    />


<p>Next up, we need to configure how our Jenkins server running on the Raspberry Pi 2 will connect to the ci20!</p>

<img src="/wp-content/uploads/2015/05/Capture2.png"  class="center"  style="border-radius: 8px;"    />


<p>I use the stock settings and debian 7 that comes pre-installed on the ci20, so I used launch via ssh, stuck in the username password I use to ssh into the ci20 myself, and lastly I had to set the ‘Remote root directory&rsquo; to the ci20 username&rsquo;s home directory.</p>
<p>On the ci20 itself, I had to run;</p>
<!-- raw HTML omitted -->
<p>For the missing packages I needed on the device.</p>
<p>The last thing I did was edit my previous doboz job to only run on the ci20 label, forcing it to run on the new ci20 build node exclusively. And the results?</p>

<img src="/wp-content/uploads/2015/05/Capture3.png"  class="center"  style="border-radius: 8px;"    />


<p>That concludes my foray into the Jenkins on Raspberry Pi 2 world - in conclusion it is definitely possible now to run Jenkins on the Raspberry Pi with the beefier new model.</p>
]]></description>
    </item>
    
    <item>
      <title>Running your first job on the Raspberry Pi 2 / Jenkins</title>
      <link>https://www.neilhenning.dev/posts/running-your-first-job-on-the-raspberry-pi-2-jenkins/</link>
      <pubDate>Tue, 19 May 2015 21:53:42 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/running-your-first-job-on-the-raspberry-pi-2-jenkins/</guid>
      <description><![CDATA[<p>So in my last post <a href="https://www.neilhenning.dev/installing-jenkins-on-raspberry-pi-2/">Installing Jenkins on Raspberry Pi 2</a> I took us through the steps it took me to get a Jenkins server running on my Raspberry Pi 2 - but I didn&rsquo;t actually run any jobs on the Raspberry Pi 2! Time to rectify.</p>
<p>So I decided to build <a href="http://voxelium.wordpress.com/2011/03/19/doboz-compression-library-with-very-fast-decompression/">doboz</a> - a really awesome little compression/decompression library written by <a href="https://twitter.com/attila_afra">Attila Áfra</a>. I first forked it from HG -&gt; Git, and fired it up onto my GitHub <a href="https://github.com/sheredom/doboz">here</a>.</p>
<p>I did some minor cleaning up (removed the VC10 folder, moved COPYING.txt to LICENSE as is the GitHub norm) but all in all the remainder of the code was the same.</p>
<p>I then tried to add my first Jenkins job to pull this repo - but oh wait! Jenkins by default only has the CVS and SVN version control plugins installed, so I had to first at the Git SCM Plugin. After installing that, I created a simple job called doboz that pulled the repository, and huzzah! It worked!</p>
<p>Next up, to actually build the thing. Now I primarily use CMake for all my builds (it is awful in many ways, but it is cross platform and the LLVM project uses it so that is good enough for me) - so I added a CMakeLists.txt that would build a libdoboz.so for me. I then added a build step/execute shell that simply did;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>And ran it… and it failed.</p>

<img src="/wp-content/uploads/2015/05/Screenshot-from-2015-05-19-215625.png"  class="center"  style="border-radius: 8px;"    />


<p>Basically CMake wasn&rsquo;t installed by default on the Pi! So I ssh onto the Pi, run;</p>
<!-- raw HTML omitted -->
<p>And then once it completes, I re-ran the Jenkins job, and it failed again.</p>

<img src="/wp-content/uploads/2015/05/Screenshot-from-2015-05-19-224739.png"  class="center"  style="border-radius: 8px;"    />


<p>Luckily I recognized this error from a previous customer project, basically before including stdint.h on some wacky platforms you need to;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>To actually get UINT64_MAX and all the other *_MIN and *_MAX defines.</p>
<p>I then ran the job again, and it passed.</p>

<img src="/wp-content/uploads/2015/05/Screenshot-from-2015-05-19-223307.png"  class="center"  style="border-radius: 8px;"    />


<p>So there you have it! Our first job to run on our Jenkins / Raspberry Pi 2. In a follow-up post I&rsquo;ll show you how to connect another build node to the Raspberry Pi 2, so that the job is actually being built on another machine entirely (which is entirely the point of Jenkins!).</p>
]]></description>
    </item>
    
    <item>
      <title>Installing Jenkins on Raspberry Pi 2</title>
      <link>https://www.neilhenning.dev/posts/installing-jenkins-on-raspberry-pi-2/</link>
      <pubDate>Fri, 15 May 2015 22:11:14 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/installing-jenkins-on-raspberry-pi-2/</guid>
      <description><![CDATA[<p>So I&rsquo;ve always wanted to roll my own home continuous integration (CI) server - I use Jenkins as my main CI at work (having used Atlassian&rsquo;s Bamboo and the hideousness that is buildbot in the past), so I thought I may as well start there.</p>
<p>I previously tried to get Jenkins running on my Raspberry Pi B+ - but the single core and general slowness of the device just meant it wasn&rsquo;t feasible. Then, I got a Raspberry Pi 2 (naturally) so I wondered if it was any more capable?</p>
<p>For reference - I&rsquo;m running stock Raspbian on the device.</p>
<p>First up, lets install Jenkins! I run sudo apt-get install Jenkins, and voilà, Jenkins is installed! I navigate to the default Jenkins port 8080 in a web browser, and it is indeed the Jenkins I know and <!-- raw HTML omitted -->love<!-- raw HTML omitted --> have developed Stockholm Syndrome for. But wait - it is a rather old version! It turns out that the default package included in Debian is a much older Jenkins installation. Jenkins has a built in mechanism in the web interface to allow you to update Jenkins from the webpage, I tried this and it spectacularly failed. The crux of the matter is that since I installed Jenkins via sudo apt-get, it has placed the jenkins.war file in a sudo location, such that the web updating method can&rsquo;t replace the original file.</p>
<p>After reading on the Jenkins website, I noticed they had an alternative solution for <a href="https://wiki.jenkins-ci.org/display/JENKINS/Installing&#43;Jenkins&#43;on&#43;Ubuntu">installing on ubuntu</a> - since Ubuntu and Raspbian share the same .deb, dpkg and apt-get infrastructure at this point, I just followed the instructions;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>This worked, kinda. Basically because Raspbian already has a method for acquiring the jenkins.war, it didn&rsquo;t like me installing Jenkins via the new method (said there was a .deb file that conflicted). After some Googling, I found <a href="http://www.webupd8.org/2011/02/fix-dpkg-error-trying-to-overwrite-x.html">this article</a> which had the command;</p>
<!-- raw HTML omitted -->
<p>Which I used but replaced the .deb file with the offending jenkins .deb, and it installed ok.</p>
<p>For some reason Jenkins wouldn&rsquo;t start though, so I manually ran the init service that is installed to /etc/init.d/jenkins and ran it as follows;</p>
<!-- raw HTML omitted -->
<p>And it complained that I was using Java 6 instead of the minimum required Java 7. If you use the Linux command update-alternatives, you can do;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>You can then use;</p>
<!-- raw HTML omitted -->
<p> </p>
<p>Which will ask you to select which java version to by default use - I selected the jdk 8 one.</p>
<p>I then in my browser went to the 8080 port for my Raspberry Pi 2 - and I got the shiny latest version of Jenkins, huzzah!</p>
<p>I&rsquo;ve not had time to add any actual build jobs yet - but from first impressions, immediately on reboot loading each page takes a good 10 seconds. I ran top on the Pi at the same time and the Java process spikes to 130% of CPU. Once you have loaded the page once, it loads quickly the second time, and this is not being client-side cached, it seems that on the Pi the Jenkins process is doing some form of caching of content which is welcome!</p>
<p>Once I add some actual build jobs that generate output I&rsquo;ll do a follow up post on how responsive it gets under load.</p>
<hr>
<p> </p>
]]></description>
    </item>
    
    <item>
      <title>Khronos/EuroLLVM talk - Why SPIR-V?</title>
      <link>https://www.neilhenning.dev/posts/khronoseurollvm-talk-why-spir-v/</link>
      <pubDate>Fri, 17 Apr 2015 08:32:30 +0000</pubDate>
      <guid>https://www.neilhenning.dev/posts/khronoseurollvm-talk-why-spir-v/</guid>
      <description><![CDATA[<p>I&rsquo;ve uploaded my slides with speaker notes for the Khronos/EuroLLVM talk I gave this week. Please check them out!</p>
<p><a href="https://www.neilhenning.dev/wp-content/uploads/2015/04/WhySPIR-V-Notes.pdf">WhySPIR-V</a></p>
]]></description>
    </item>
    
    <item>
      <title>Raspberry Pi 2 Dot Product Test</title>
      <link>https://www.neilhenning.dev/raspberry-pi-2-dot-product-test/</link>
      <pubDate>Fri, 03 Apr 2015 21:44:35 +0000</pubDate>
      <guid>https://www.neilhenning.dev/raspberry-pi-2-dot-product-test/</guid>
      <description><![CDATA[<p>After reading <a href="https://deplinenoise.wordpress.com/2015/03/06/slides-simd-at-insomniac-games-gdc-2015/">“SIMD at Insomniac Games – How we do the shuffle”</a>  I realised I hadn&rsquo;t done anything with my new Raspberry Pi 2 yet. First thing I decided was to try and figure out whether the NEON unit in it was any good, and so I choose a really simple example, calculating a ton of dot products on 4 element vectors, and wrote a bunch of different implementations to try and solve this.</p>

<img src="/wp-content/uploads/2015/04/asm1.png"  class="center"  style="border-radius: 8px;"    />


<p>The results are surprising - right enough I did manage (via using inline asm) to get a NEON version going faster than everything else - but what shocked me is that I couldn&rsquo;t get clang to output faster vector code than the scalar version. I tried a ton of different methods (pragma unroll, manual unroll, inlining on and off) and yet the scalar implementation was always faster.</p>
<p>It seems that at least part of the slowdown is that all the vector versions use the vldn load instructions, whereas the scalar ones (and my fastest hand written version) use vldmia to do the calculation.</p>
<p>My best attempt was;</p>
<!-- raw HTML omitted -->
<!-- raw HTML omitted -->
<p>I do wonder if I could hide more of the cost of the loads/stores by double buffering the workload - only other thing I can think to try!</p>
<p>If you want to check out the rest of the code yourself, or run the examples here is the test file.</p>
<p><a href="https://www.neilhenning.dev/wp-content/uploads/2015/04/test.c">test.c</a></p>
]]></description>
    </item>
    
    <item>
      <title>life log</title>
      <link>https://www.neilhenning.dev/lifelog/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.neilhenning.dev/lifelog/</guid>
      <description><![CDATA[<p>Heyo, I&rsquo;m Neil Henning and this is the log of my adventures with gaia to date!</p>
<h3 id="2026---unreal-engine-6-announced">2026 - Unreal Engine 6 Announced</h3>
<p>Unreal Engine 6 was <a href="https://www.unrealengine.com/news/the-road-to-ue-6">announced</a>
to the world, and my work on AutoRTFM and Verse is the building block for
everything we are going to ship.</p>
<h3 id="2026---sped-up-verse-compilation-by-over-2x-in-fortnite-4100">2026 - Sped up Verse Compilation by over 2x in Fortnite 41.00</h3>
<p>In Fortnite 41.00 I sped up Verse compilation speed for our UEFN developers by
over 2x (as measured across a range of popular islands). This involved a lot of
deep technical analysis (thanks Superluminal!) and some significant refactors of
the code.</p>
<h3 id="2025---deployed-transactional-memory-system-for-entire-uefn-server-fleet">2025 - Deployed Transactional Memory system for entire UEFN Server Fleet</h3>
<p>In Fortnite 36.20 we deployed the entire UEFN server fleet with the
transactional memory system I initially implemented, optimized, and deployed.
Beyond the very deep and complex optimization work involved in getting this
transactional memory system to have as little additional overhead over raw C++
as possible (while adding the safety it provides), I had to invent novel
approaches to interfacing existing legacy threaded code that was
<strong>not partaking</strong> in transactions, with the transactional code.</p>
<h3 id="2024---software-transactional-memory-for-verse">2024 - Software Transactional Memory for Verse</h3>
<p>The <a href="https://www.neilhenning.dev/posts/verse-transactional-memory/">Software Transactional Memory system</a> I worked on for the Verse language was publicly announced. My main contribution was making the LLVM pass fast, optimizing the runtime, and integration and bugfixing in Unreal Engine, Fortnite, and UEFN.</p>
<h3 id="2023---released-unreal-engine-for-fortnite-and-verse">2023 - Released Unreal Engine for Fortnite and Verse</h3>
<p>I worked on the <a href="https://store.epicgames.com/en-US/p/fortnite--uefn">Unreal Engine for Fortnite</a>,
specifically on the Verse programming language. Verse is the cornerstone of how
developers write safe, scaleable, and performant code that can scale for the
half a billion players that love Fortnite, and its beyond exciting that users
will now be able to use Verse to create experiences that could never be realised
in Fortnite before.</p>
<h3 id="2022---joined-epic">2022 - Joined Epic</h3>
<p>I joined Epic to work on the Verse language, bringing my years of experience in
compilers to the team.</p>
<h3 id="2022---released-burst-17">2022 - Released <a href="https://docs.unity3d.com/Packages/com.unity.burst@1.7/changelog/CHANGELOG.html">Burst 1.7</a></h3>
<p>In Burst 1.7 my main contributions were:</p>
<ul>
<li>Added an <em>object cache</em> to Burst, making compilation times <strong>3.5x</strong> faster.</li>
<li>Made <em>Direct Call</em> Burst&rsquo;ed methods <strong>33x</strong> faster to process during domain reload.</li>
<li>Made <em>Shared Statics</em> usage <strong>13.3x</strong> faster when entering playmode.</li>
<li>Improved the compile time of Unity NetCode by <strong>39x</strong> through improvements to the Burst compiler.</li>
</ul>
<h3 id="2021---released-burst-16">2021 - Released <a href="https://docs.unity3d.com/Packages/com.unity.burst@1.6/changelog/CHANGELOG.html">Burst 1.6</a></h3>
<p>In Burst 1.6 my main contributions were:</p>
<ul>
<li>Improved the compile time of Burst by <strong>4x</strong>.</li>
<li>Made Burst load <strong>20x</strong> faster during startup.</li>
<li>Made code changes in the editor <strong>2x</strong> faster.</li>
</ul>
<h3 id="2021---released-burst-15">2021 - Released <a href="https://docs.unity3d.com/Packages/com.unity.burst@1.5/changelog/CHANGELOG.html">Burst 1.5</a></h3>
<p>In Burst 1.5 my main contributions were:</p>
<ul>
<li>Reduced the executable size of Burst&rsquo;ed code by <strong>43%</strong>.</li>
<li>Improved the compile time of Burst by <strong>45%</strong>.</li>
<li>Added <code>Assume</code>, <code>Likely</code>, <code>Unlikely</code> intrinsics to Burst to let users hint to the compiler about optimizations opportunities.</li>
<li>Added an opt-for-size mode to Burst to reduce executable size by a further <strong>11%</strong>.</li>
</ul>
<h3 id="2020---open-sourced-ubenchh">2020 - Open Sourced <a href="https://github.com/sheredom/ubench.h">ubench.h</a></h3>
<p>I open sourced a single header benchmarking library for C/C++. Check out the library on my GitHub - <a href="https://github.com/sheredom/ubench.h">https://github.com/sheredom/ubench.h</a>.</p>
<h3 id="2020---open-sourced-hashmaph">2020 - Open Sourced <a href="https://github.com/sheredom/hashmap.h">hashmap.h</a></h3>
<p>I open sourced a single header hashmap library for C/C++. Check out the library on my GitHub - <a href="https://github.com/sheredom/hashmap.h">https://github.com/sheredom/hashmap.h</a>.</p>
<h3 id="2020---released-burst-14">2020 - Released <a href="https://docs.unity3d.com/Packages/com.unity.burst@1.4/changelog/CHANGELOG.html">Burst 1.4</a></h3>
<p>In Burst 1.4 my main contributions were:</p>
<ul>
<li>Added support for <code>F16C</code>, and <code>FMA</code> intrinsics to Burst.</li>
<li>Improved Burst compile time by <strong>30%</strong> by using a sizable internal Unity production as a test bed.</li>
<li>Added support for <code>AssumeRange</code> across Unity Collections code to enable significant optimization opportunities in Burst.</li>
<li>Changed how we vectorize to significantly improve vectorization (in collaboration with our partnership with Arm).</li>
<li>Added support for cross platform native hardware exception handling in Burst&rsquo;ed code. This meant that the three desktop platforms (Windows, macOS, Linux) could, in the editor, catch exceptions caused by Burst code (dereferencing <code>null</code> or things of that nature). This was a hugely complex feature.</li>
</ul>
<h3 id="2020---published-in-parameters-in-burst-blog-post-on-unitys-blog">2020 - Published <a href="https://blog.unity.com/technology/in-parameters-in-burst">In parameters in Burst</a> blog post on Unity&rsquo;s blog</h3>
<p>Our users were getting conflicting advice on whether <code>in</code> parameters were safe to use, so I wrote a hugely popular blog post summarizing what happens with <code>in</code> parameters in Burst, and where you should think about using them.</p>
<h3 id="2020---published-enhanced-aliasing-with-burst-blog-post-on-unitys-blog">2020 - Published <a href="https://blog.unity.com/technology/enhanced-aliasing-with-burst">Enhanced Aliasing with Burst</a> blog post on Unity&rsquo;s blog</h3>
<p>To explain how aliasing works and how to take advantage of the new aliasing support in Burst 1.3, I wrote a popular blog post explaining what aliasing is, how you can avoid it, and the new compiler intrinsics I added to let users ask the compiler <em>&lsquo;Hey do these things alias?&rsquo;</em>.</p>
<h3 id="2020---released-burst-13">2020 - Released <a href="https://docs.unity3d.com/Packages/com.unity.burst@1.3/changelog/CHANGELOG.html">Burst 1.3</a></h3>
<p>In Burst 1.3 my main contributions were:</p>
<ul>
<li>Added an advanced aliasing solution for Burst, supercharging Burst&rsquo;ed code by enabling much better aliasing deductions, improving optimizations, and enabling vectorization in more cases.</li>
<li>I also improved the startup performance of the Burst compiler by 3x.</li>
<li>Spent a lot of time improving the performance of Unity Physics&rsquo; Burst&rsquo;ed code.</li>
<li>Added an <code>AssumeRange</code> attribute to let us provide assumptions on return values and parameters.</li>
</ul>
<h3 id="2020---released-vulkan-12--spir-v-15">2020 - Released <a href="https://www.khronos.org/registry/vulkan/specs/1.2/html/vkspec.html">Vulkan 1.2</a> &amp; <a href="https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html">SPIR-V 1.5</a></h3>
<p>When I was at AMD I was working furiously on Vulkan 1.2 features that&rsquo;d make developers lives happier. I mostly worked on things related to bindless and subgroup support, and my hands are very much in the creation of these specifications - even though they came out 6 months after I left AMD! Super stoked that these are now in developers hands.</p>
<h3 id="2019---joined-unity">2019 - Joined Unity</h3>
<p>I joined Unity to work on the Burst compiler - an optimizing compiler that takes a subset of C# and uses LLVM to turn this into highly performant and vectorized code. The opportunity to make such a huge impact to develpers lives (Burst is changing the game for Unity users) was too appealing to turn down.</p>
<h3 id="2019---released-vk_khr_uniform_buffer_standard_layout">2019 - Released VK_KHR_uniform_buffer_standard_layout</h3>
<p>I was an author of the GLSL extension <a href="https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VK_KHR_uniform_buffer_standard_layout">VK_KHR_uniform_buffer_standard_layout</a>, which lets developers use the <code>std430</code> layout on uniform buffer objects (UBOs).</p>
<h3 id="2019---released-vk_ext_subgroup_size_control">2019 - Released VK_EXT_subgroup_size_control</h3>
<p>I was an author of the GLSL extension <a href="https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VK_EXT_subgroup_size_control">VK_EXT_subgroup_size_control</a>, which lets developers get access to the variable subgroup size support in AMD Navi GPUs and Intel GPUs.</p>
<h3 id="2019---released-vk_ext_pipeline_creation_feedback">2019 - Released VK_EXT_pipeline_creation_feedback</h3>
<p>I was an author of the GLSL extension <a href="https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VK_EXT_pipeline_creation_feedback">VK_EXT_pipeline_creation_feedback</a>, which lets developers get feedback from what actually took place during pipeline creation - to be used for effectively creating pipeline caches.</p>
<h3 id="2019---released-vk_ext_buffer_device_address">2019 - Released VK_EXT_buffer_device_address</h3>
<p>I was an author of the GLSL extension <a href="https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VK_EXT_buffer_device_address">VK_EXT_buffer_device_address</a>, which lets developers use explicit 64-bit pointers in their shaders.</p>
<h3 id="2019---released-gl_ext_shader_explicit_arithmetic_types">2019 - Released GL_EXT_shader_explicit_arithmetic_types</h3>
<p>I was an author of the GLSL extension <a href="https://github.com/KhronosGroup/GLSL/blob/master/extensions/ext/GL_EXT_shader_explicit_arithmetic_types.txt">GL_EXT_shader_explicit_arithmetic_types</a>, which lets developers use a ton of new types in GLSL, using much saner explicit names too!</p>
<h3 id="2018---released-spv_khr_no_integer_wrap_decoration">2018 - Released SPV_KHR_no_integer_wrap_decoration</h3>
<p>I was an author of the SPIR-V extension <a href="http://htmlpreview.github.io/?https://github.com/KhronosGroup/SPIRV-Registry/blob/master/extensions/KHR/SPV_KHR_no_integer_wrap_decoration.html">SPV_KHR_no_integer_wrap_decoration</a>, which lets developers add hints that integer operations do not wrap (which can be more performant on certain vendor hardware).</p>
<h3 id="2018---released-spv_khr_float_controls">2018 - Released SPV_KHR_float_controls</h3>
<p>I was an author of the SPIR-V extension <a href="http://htmlpreview.github.io/?https://github.com/KhronosGroup/SPIRV-Registry/blob/master/extensions/KHR/SPV_KHR_float_controls.html">SPV_KHR_float_controls</a> , which lets developers control the floating-point rounding and flushing behaviour of their shaders.</p>
<h3 id="2018---released-vk_khr_shader_atomic_int64">2018 - Released VK_KHR_shader_atomic_int64</h3>
<p>I was an author of the Vulkan extension <a href="https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VK_KHR_shader_atomic_int64">VK_KHR_shader_atomic_int64</a>, which lets developers use 64-bit integer in atomic operations in their shaders.</p>
<h3 id="2018---released-vk_ext_inline_uniform_block">2018 - Released VK_EXT_inline_uniform_block</h3>
<p>I was an author of the Vulkan extension <a href="https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VK_EXT_inline_uniform_block">VK_EXT_inline_uniform_block</a>, which lets developers put small constants within descriptor sets that gives them an additional method to load data onto AMD GPUs more efficiently.</p>
<h3 id="2018---joined-amd">2018 - Joined AMD</h3>
<p>I joined AMD to work in the Game Engineering division, bringing my skills in compilers, drivers, and optimisations.</p>
<p>My background with heterogeneous hardware, coupled with my experience with LLVM and a general love of making things as fast and maintainable as possible, make me an ideally placed to thrive at AMD.</p>
<h3 id="2018---released-spv_ext_descriptor_indexing">2018 - Released SPV_EXT_descriptor_indexing</h3>
<p>I contributed to the SPIR-V extension <a href="http://htmlpreview.github.io/?https://github.com/KhronosGroup/SPIRV-Registry/blob/master/extensions/EXT/SPV_EXT_descriptor_indexing.html">SPV_EXT_descriptor_indexing</a>, which lets developers make use of bindless buffers and images in the Vulkan API.</p>
<h3 id="2018---published-a-vulkan-subgroup-tutorial-on-khronosorg">2018 - Published a <a href="https://www.khronos.org/blog/vulkan-subgroup-tutorial">Vulkan Subgroup Tutorial</a> on khronos.org</h3>
<p>I published a <a href="https://www.khronos.org/blog/vulkan-subgroup-tutorial">Vulkan Subgroup Tutorial</a> on khronos.org, covering how to make use of the subgroup functionality I added to Vulkan 1.1.</p>
<h3 id="2018---released-vulkan-11--spir-v-13">2018 - Released <a href="https://www.khronos.org/registry/vulkan/specs/1.1/html/vkspec.html">Vulkan 1.1</a> &amp; <a href="https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html">SPIR-V 1.3</a></h3>
<p>As the primary author of Vulkan&rsquo;s subgroup functionality I am proud to have spent 2 years of my life ensuring that Vulkan 1.1 is what developers need. The work I undertook included writing the <a href="https://github.com/KhronosGroup/GLSL/blob/master/extensions/khr/GL_KHR_shader_subgroup.txt">GL_KHR_shader_subgroup</a> GLSL extension, <a href="https://github.com/KhronosGroup/glslang/pull/1277">adding glslang support for GL_KHR_shader_subgroup and HLSL&rsquo;s Shader Model 6.0 wave operations</a>, adding the <a href="https://www.khronos.org/registry/spir-v/specs/unified1/SPIRV.html">GroupNonUniform SPIR-V 1.3 opcodes</a>, and also <a href="https://github.com/KhronosGroup/VK-GL-CTS/commit/69593fca6204550740739cc03ec9a51d29f5d8c5#diff-cd737ccdee53c4f32e08991010bc9ebc">writing the conformance tests</a>.</p>
<h3 id="2017---open-sourced-subprocessh">2017 - Open Sourced <a href="https://github.com/sheredom/subprocess.h">subprocess.h</a></h3>
<p>I open sourced a single header process spawning and interaction library for C/C++. Check out the library on my GitHub - <a href="https://github.com/sheredom/subprocess.h">https://github.com/sheredom/subprocess.h</a>.</p>
<h3 id="2017---speaker-at-khronos-munich-chapter">2017 - Speaker at <a href="https://www.meetup.com/Khronos-Munchen-Chapter/events/242664238/">Khronos Munich Chapter</a></h3>
<p>I gave a talk at the Khronos Munich Chapter titled &lsquo;OpenCL to Vulkan: A Porting Guide&rsquo;. I covered how to port from the OpenCL API to the Vulkan API, some common problems our customers have faced, and how to fix them. <a href="https://www.neilhenning.dev/wp-content/uploads/2015/03/OpenCL-to-Vulkan-A-Porting-Guide.pdf">Slides</a></p>
<h3 id="2017---released-vk_khr_image_format_list">2017 - Released VK_KHR_image_format_list</h3>
<p>I contributed to the Vulkan extension <a href="https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VK_KHR_image_format_list">VK_KHR_image_format_list</a>, which lets developers list what image formats will be used with <em>VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT</em> allowing implementations to use more optimal paths where possible.</p>
<h3 id="2017---released-vk_khr_maintenance2">2017 - Released VK_KHR_maintenance2</h3>
<p>I contributed to the Vulkan extension <a href="https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VK_KHR_maintenance2">VK_KHR_maintenance2</a>, which is a bumper pack of extensions on Vulkan 1.0 to enable a bunch of functionality developers had been requesting.</p>
<h3 id="2017---released-clspv">2017 - Released <a href="https://github.com/google/clspv">clspv</a></h3>
<p>I was the project lead and main developer on a Google/Codeplay collaboration project <a href="https://github.com/google/clspv">clspv</a>, which allows OpenCL C sources to be compiled to Vulkan SPIR-V. The codebase is being actively used by developers to port 1 million+ line codebases of OpenCL C to Vulkan with minimal source changes.</p>
<h3 id="2017---released-vk_khr_variable_pointers">2017 - Released VK_KHR_variable_pointers</h3>
<p>I contributed to the Vulkan extension <a href="https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VK_KHR_variable_pointers">VK_KHR_variable_pointers</a>, which allows for more expressive pointer operations to be used by SPIR-V in Vulkan 1.0.</p>
<h3 id="2017---released-vk_khr_16bit_storage">2017 - Released VK_KHR_16bit_storage</h3>
<p>I contributed to the Vulkan extension <a href="https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VK_KHR_16bit_storage">VK_KHR_16bit_storage</a>, which allows 16 bit buffers to be loaded and stored from, while performing operations in a higher bit-width type, in the SPIR-V used in Vulkan 1.0.</p>
<h3 id="2017---released-spir-v-12">2017 - Released <a href="https://www.khronos.org/registry/spir-v/specs/1.2/SPIRV.html">SPIR-V 1.2</a></h3>
<p>I contributed to SPIR-V version 1.2, primarily targeted at OpenCL.</p>
<h3 id="2017---released-spv_khr_variable_pointers">2017 - Released SPV_KHR_variable_pointers</h3>
<p>I contributed to the SPIR-V extension <a href="https://www.khronos.org/registry/spir-v/extensions/KHR/SPV_KHR_variable_pointers.html">SPV_KHR_variable_pointers</a>, which enables more expressive pointer operations in SPIR-V.</p>
<h3 id="2017---released-spv_khr_16bit_storage">2017 - Released SPV_KHR_16bit_storage</h3>
<p>I contributed to the SPIR-V extension <a href="https://www.khronos.org/registry/spir-v/extensions/KHR/SPV_KHR_16bit_storage.html">SPV_KHR_16bit_storage</a>, which enables 16 bit load/store operations in SPIR-V.</p>
<h3 id="2017---released-vk_khr_maintenance1">2017 - Released VK_KHR_maintenance1</h3>
<p>I contributed to the Vulkan extension <a href="https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VK_KHR_maintenance1">VK_KHR_maintenance1</a>, which is a bumper pack of extensions on Vulkan 1.0 to enable a bunch of functionality developers had been requesting.</p>
<h3 id="2017---released-vk_ext_shader_subgroup_ballot">2017 - Released VK_EXT_shader_subgroup_ballot</h3>
<p>I contributed to the Vulkan extension <a href="https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VK_EXT_shader_subgroup_ballot">VK_EXT_shader_subgroup_ballot</a>, which enables a limited form of subgroup ballot operations via a Vulkan 1.0 extension.</p>
<h3 id="2017---released-vk_ext_shader_subgroup_vote">2017 - Released VK_EXT_shader_subgroup_vote</h3>
<p>I contributed to the Vulkan extension <a href="https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VK_EXT_shader_subgroup_vote">VK_EXT_shader_subgroup_vote</a>, which enables a limited form of subgroup vote operations via a Vulkan 1.0 extension.</p>
<h3 id="2016---released-spv_khr_shader_ballot">2016 - Released SPV_KHR_shader_ballot</h3>
<p>I contributed to the SPIR-V extension <a href="https://www.khronos.org/registry/spir-v/extensions/KHR/SPV_KHR_shader_ballot.html">SPV_KHR_shader_ballot</a>, which enables a limited form of subgroup ballot operations via a SPIR-V 1.0 extension.</p>
<h3 id="2016---open-sourced-yari-v">2016 - Open Sourced <a href="https://github.com/sheredom/yari-v">YARI-V</a></h3>
<p>I open sourced a SPIR-V compressor I&rsquo;m calling <a href="https://www.neilhenning.dev/introducing-yari-v-an-experiment-on-spir-v-compression/">YARI-V</a> - it is a single C/C++ header, and you check out the library on my GitHub - <a href="https://github.com/sheredom/yari-v">https://github.com/sheredom/yari-v</a></p>
<h3 id="2016---released-spir-v-11">2016 - Released <a href="https://www.khronos.org/registry/spir-v/specs/1.1/SPIRV.html">SPIR-V 1.1</a></h3>
<p>I contributed to SPIR-V version 1.1, primarily targeted at OpenCL.</p>
<h3 id="2016---speaker-at-gdc">2016 - Speaker at <a href="http://schedule.gdconf.com/session/working-with-vulkan-on-android-an-introduction-to-spir-v-presented-by-imagination-technologies">GDC</a></h3>
<p>I gave a talk at GDC titled &lsquo;An Introduction to SPIR-V&rsquo;. I covered the basics of SPIR-V, how and why Vulkan uses it, how to hand-write SPIR-V shaders, and how to optimize and find bugs in SPIR-V. <a href="https://www.neilhenning.dev/wp-content/uploads/2015/03/AnIntroductionToSPIR-V.pdf">Slides</a></p>
<h3 id="2016---released-vulkan-10">2016 - Released <a href="https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html">Vulkan 1.0</a></h3>
<p>Two years of my life was sunk into making Vulkan a good platform for compute workloads, and in 2016 it was finally released to the community.</p>
<h3 id="2016---released-spir-v-10">2016 - Released <a href="https://www.khronos.org/registry/spir-v/specs/1.0/SPIRV.html">SPIR-V 1.0</a></h3>
<p>Two years of my life was sunk into making SPIR-V great for Vulkan. My focus was to ensure that Vulkan and SPIR-V would make a good target for compute workloads, something that the community can now utelize.</p>
<h3 id="2016---released-gl_">2016 - Released <a href="https://www.khronos.org/registry/vulkan/specs/misc/GL_KHR_vulkan_glsl.txt">GL_KHR_vulkan_glsl</a></h3>
<p>I was a named contributor to the GLSL variant for Vulkan - this specification modifies the GLSL shading language to enable the features of Vulkan, something I was very proud to have worked on!</p>
<h3 id="2015---open-sourced-utesth">2015 - Open Sourced <a href="https://github.com/sheredom/utest.h">utest.h</a></h3>
<p>I open sourced a single header unit testing framework for C/C++. Check out the library on my GitHub - <a href="https://github.com/sheredom/utest.h">https://github.com/sheredom/utest.h</a>.</p>
<h3 id="2015---open-sourced-jsonh">2015 - Open Sourced <a href="https://github.com/sheredom/json.h">json.h</a></h3>
<p>I open sourced a JSON parser/writer for C/C++. The library supports JSON, but also simplified JSON too. Check out the library on my GitHub - <a href="https://github.com/sheredom/json.h">https://github.com/sheredom/json.h</a></p>
<h3 id="2015---open-sourced-utf8h">2015 - Open Sourced <a href="https://github.com/sheredom/utf8.h">utf8.h</a></h3>
<p>I open sourced a utf8 string processing library, to provide c string.h like functions but specifically for processing utf8 strings. Check out the library on my GitHub - <a href="https://github.com/sheredom/utf8.h">https://github.com/sheredom/utf8.h</a></p>
<h3 id="2015---speaker-at-khronos-uk-chaptereurollvm">2015 - Speaker at <a href="http://www.meetup.com/khronos-uk-chapter/events/221391028/">Khronos UK Chapter</a>/<a href="http://llvm.org/devmtg/2015-04/">EuroLLVM</a></h3>
<p>I gave a talk at the Khronos UK Chapter&rsquo;s side event attached to the main EuroLLVM conference. My talk was on SPIR-V, the motivation and some of the required features, and how both OpenCL and Vulkan will use it. I got to announce a small part of the specification here, specialization constants! <a href="https://www.neilhenning.dev/khronoseurollvm-talk-why-spir-v/">Slides + speaker notes</a>.</p>
<h3 id="2015---promoted-to-principal-software-engineer-vulkan--spir-v-at-codeplay">2015 - Promoted to Principal Software Engineer, Vulkan &amp; SPIR-V at <a href="http://www.codeplay.com/">Codeplay</a></h3>
<p>To coincide with my new focus on Vulkan and SPIR-V, I got a promotion within the company. My years of experience with Khronos and open standards put me in a great position to contribute back to the specifications of both Vulkan and SPIR-V.</p>
<h3 id="2014---began-contributing-to-vulkan">2014 - Began contributing to <a href="https://www.khronos.org/vulkan">Vulkan</a></h3>
<p>Since its inception, I&rsquo;ve been involved in the working group at Khronos to help define the new generation, and open standard API. My focus has primarily been;</p>
<ul>
<li>Compute as a first-class citizen in the API (including non-GPU compute support).</li>
<li>Binary shader format evangelist.</li>
<li>Smoothing the interaction between the API and the binary shaders.</li>
</ul>
<h3 id="2014---began-contributing-to-spir-v">2014 - Began contributing to <a href="https://www.khronos.org/spir">SPIR-V</a></h3>
<p>SPIR-V is a truly revolutionary addition to the graphics and compute eco-system - now we have a single representation that allows us to define the many shader and kernel types that GLSL and OpenCL Kernel Language support (and of course - much, much, more). My involvement in SPIR-V allowed me to bring my years of experience in writing drivers for OpenGL ES and OpenCL, coupled with my lengthy time of using LLVM, to the working group.</p>
<h3 id="2014---began-working-remotely-at-codeplay">2014 - Began working remotely at <a href="http://www.codeplay.com/">Codeplay</a></h3>
<p>I always knew I was going to end up working remotely - specifically on the Isle of Skye. My better half is from there, and in 2013 when she got a job in the local high school, I requested the right to work remotely, and it was granted. Six months later (I gave the company a grace period to ease the transition) I had bought a house, and am now reaping the rewards a remote life can bring (just look at the view I get every day!).</p>
<h3 id="2014---speaker-at-iwocl">2014 - Speaker at <a href="http://www.iwocl.org/iwocl-2014/abstracts/spir-me-the-details-building-custom-language-support-on-opencl/">IWOCL</a></h3>
<p>I was a speaker at the International Workshop on OpenCL - giving a talk entitled &lsquo;SPIR me the details: building custom language support on OpenCL&rsquo;. The talk gave a run through of the <a href="https://www.khronos.org/registry/spir/specs/spir_spec-1.2.pdf">SPIR 1.2 specification</a>, and by using the example of targeting custom languages at GPUs explained the pro&rsquo;s and con&rsquo;s of using SPIR with OpenCL.</p>
<h3 id="2014---shipped-opencl-12-driver-for-customer">2014 - Shipped OpenCL 1.2 driver for customer</h3>
<p>Shipped a conformant OpenCL 1.2 driver in the mobile space for a client. Details of which are unfortunately under NDA.</p>
<h3 id="2013---speaker-at-amd-developer-summit">2013 - Speaker at <a href="http://developer.amd.com/apu/">AMD Developer Summit</a></h3>
<p>I was a speaker at AMD&rsquo;s Developer Summit for 2013 - presenting a talk on how to target custom languages at heterogeneous systems. The talk focused mostly on the (at the time) recently announced <a href="https://www.khronos.org/registry/spir/specs/spir_spec-1.2.pdf">SPIR 1.2 specification</a>, and how to target that from your own languages.</p>
<h3 id="2013---shipped-opencl-12-driver-for-customer">2013 - Shipped OpenCL 1.2 driver for customer</h3>
<p>Shipped a conformant OpenCL 1.2 driver in the mobile space for a client. Details of which are unfortunately under NDA.</p>
<h3 id="2012---shipped-opencl-11-driver-for-customer">2012 - Shipped OpenCL 1.1 driver for customer</h3>
<p>Shipped a conformant OpenCL 1.1 driver in the mobile space for a client. Details of which are unfortunately under NDA.</p>
<h3 id="2011---speaker-at-gameai-conference">2011 - Speaker at <a href="http://archives.nucl.ai/recording/high-performance-racing-ai-in-nascar-2011/">Game/AI Conference</a></h3>
<p>After our experience shipping NASCAR The Game 2011, notably the awesome/insane process I went through to get the AI system ported to the SPU on the PlayStation®3, I gave a talk at the Game/AI Conference going through the techniques I used to take very obtuse and linear code and have it run in parallel across the SPUs.</p>
<h3 id="2011---promoted-to-technology-lead-at-codeplay">2011 - Promoted to Technology Lead at <a href="http://www.codeplay.com/">Codeplay</a></h3>
<p>After gaining the relevant experience in the company, in 2011 I was promoted to Technology Lead. This changed my responsibilities in the company - involving me in the decision making process, leading a team, lots of client interaction and contract negotiations too.</p>
<h3 id="2011---fire-fighting-on-an-activision-title">2011 - Fire-fighting on an Activision title</h3>
<p>I was flown to the US for onsite fire-fighting for a title. The work was entirely porting code to the SPUs on the PlayStation®3, and I achieved a 10% (~4ms drop in frame time) improvement in just two weeks of on-site development.</p>
<h3 id="2011---shipped-nascar-the-game-2011">2011 - Shipped <a href="http://en.wikipedia.org/wiki/NASCAR_The_Game:_2011">NASCAR The Game: 2011</a></h3>
<p>After working for 15 months on this title, we finally shipped in 2011. My work was mostly in optimizations to hit a playable framerate, I partially ported PhysX to the SPUs, I ported the AI system to the SPUs, ported the metal damage system that we created for Eutechnyx to the SPUs, and general CPU optimizations for the Xbox 360 and PlayStation®3.</p>
<h3 id="2009---joined-codeplay-as-a-software-engineer">2009 - Joined <a href="http://www.codeplay.com/">Codeplay</a> as a Software Engineer</h3>
<p>After graduating from University, I joined Codeplay - mostly because I knew they had PlayStation®3&rsquo;s and I loved the <a href="http://cell.scei.co.jp/pdf/SPU_ISA_v12.pdf">SPU ISA</a>.</p>
<h3 id="2009---graduated-from-university-of-glasgow-with-a-bsc-hons-in-software-engineering">2009 - Graduated from <a href="http://www.gla.ac.uk/">University of Glasgow</a> with a BSc (Hons.) in Software Engineering</h3>
<p>During my four years at the University of Glasgow, I studied a wide range of courses, all of my electives being anything to do with Operating Systems and low level programming.</p>
<p>In my fourth year, I won the best project prize for my implementation of Software Transactional Memory on Cell - basically my first taste of using a PlayStation®3, and first time using the SPUs!</p>
]]></description>
    </item>
    
  </channel>
</rss>

