# rss_item

title: Configuration and plugin hell and why I don't use Vim and Tmux anymore
feedurl: https://mitjafelicijan.com/feed.xml
content_mime_type: text/html
guid:
https://mitjafelicijan.com/configuration-and-plugin-hell-and-why-i-dont-use-vim-and-tmux-anymore.html

url:
https://mitjafelicijan.com/configuration-and-plugin-hell-and-why-i-dont-use-vim-and-tmux-anymore.html

content:
<p>There are three tiers of CLI software as far as I am concerned:</p>
<ul>
<li>tools like <code>ls</code>, <code>cat</code>, <code>ps</code> (you use flags to customize, and you pipe
results through them),</li>
<li>tools like <code>htop</code>, <code>nvtop</code>, <code>midnight commander</code>
(you can change the theme and maybe small things),</li>
<li>editors like <code>vim</code>,
<code>helix</code>, <code>emacs</code> and multiplexers like <code>tmux</code>, <code>zellij</code>, <code>screen</code>
(usually very customizable).</li>
</ul>
<p>I understand that something like <a href="https://www.gnu.org/software/coreutils/">GNU
utils</a> need to be small and
concise and minimal. No unnecessary fat or configuration options. I am a
massive proponent of <a href="https://en.wikipedia.org/wiki/POSIX">POSIX</a>
style of utilities. I still think the <a href="https://www.geeksforgeeks.org/piping-in-unix-or-linux/"><code>pipe operator</code></a> is
one of the most amazing things ever invented. I am still in awe when I
use it today.</p>
<p>But when it comes to applications like text editors or terminal
multiplexers, I have a bit of a different opinion. I think they need to
have some basic batteries included. And I agree that basic batteries
included is a loaded term and means different things to different
people. I will try to make a case that takes in account things that
matter to me and, by extension, also may matter to others. Otherwise,
they would not have configuration files for these applications that are
bigger than some of their own projects.</p>
<p>It is very naive to think that bare-bones <a href="https://www.vim.org/">Vim</a>
is enough for working on a larger codebase. For some it may
be so, but the majority of people would prefer some minimal
<a href="https://en.wikipedia.org/wiki/Language_Server_Protocol">LSP</a> integration
to quickly jump to definitions, fuzzy finding of files, things like
that. And in <a href="https://www.vim.org/">Vim</a>, I need a plugin to do this. The
same goes for <a href="https://neovim.io/">Neovim</a>.</p>
<p>People bash on others when they say: I would rather not deal with
configurations, or I just want to use my system without the time
investment of learning everything into details and then configuring it.</p>
<p>Most people don't derive their pleasure from ricing their setup. How is
this so impossible to understand for some people?</p>
<p>There is also the argument that you should learn your tools. That is
correct and true. But again, it's a matter of perspective. Not everything
needs to be conquered and dominated. I am perfectly fine with knowing only
30% of some tool if 30% is what I need from it to do the job I need to do.</p>
<p>For me, the argument, &quot;But what if you end up being on a
server?&quot; is ridiculous. Firstly, you shouldn't be developing on
a server. If you need to SSH to debug something, there is probably
<a href="https://en.wikipedia.org/wiki/Vi_%28text_editor%29">Vi</a> there already and
<code>:w</code> and searching config files will work. And if nothing else, you most
likely have <code>nano</code>. Not pretty, but gets the job done. I don't think
people making these arguments take their <a href="https://neovim.io/">Neovim</a>
setup (with all their custom shortcuts and plugins, which makes this
a <a href="https://www.guidefari.com/pde/">PDE</a> actually) with them on the
server. If they do this, they should be fired. :)</p>
<p>You should learn <a href="https://vim.rtorr.com/">Vim motions</a> is another
one. They will change your life. I did learn a lot of them. I think
they are amazing. But my life wasn't changed at all. I can still
hop into a normal notepad and do some coding there and be very
productive. Nothing really changed for me. I suspect these are the
things that people who have very addictive personalities say because
<a href="https://www.vim.org/">Vim</a> motions bring joy to them. I can imagine
they get a massive dopamine hit using it. For me, it does nothing. It
is a convenient way to edit text. If I don't have them, I also don't
miss them. <a href="https://vim.rtorr.com/">Vim motions</a> I mean. I adapt
quickly. Doesn't bother me at all.</p>
<p>The next argument I hear a lot is, &quot;I only check my setup once a year, and
then I am set. I don't tinker with my setup at all&quot;. This is an argument
of a seasoned user who went through all the stages of Vimtopia. If you
were to put a vanilla Vim in front of them, they would feel almost as lost
as a first-time user. You get a completely warped sense of reality when
you rice your setup to ungodly levels. Which you tend to do anyway. It's
the nature of the beast. Sure, you would know some basic motions, but
all those custom shortcuts you are so used to would not be there. You
would feel lost. No question about it.</p>
<p>Did I have a massive <code>.vimrc</code>? Yes, I did. I was transitioning
from <a href="https://www.gnu.org/software/emacs/">Emacs</a> to
<a href="https://www.vim.org/">Vim</a> and I wanted some basic things to navigate
code and not waste time finding stuff in projects I work on. And
to reproduce something usable required multiple plugins to make
<a href="https://en.wikipedia.org/wiki/Language_Server_Protocol">LSP</a> work,
fuzzy searching was a bit easier, just two plugins, I think. But
it required a ton of reading and Googling for information. Also,
let's not pretend these plugins are frozen in time. Making
<a href="https://en.wikipedia.org/wiki/Language_Server_Protocol">LSP</a> work with
<a href="https://neovim.io/">Neovim</a> became much easier, and you now use different
plugins than you did two years ago. So, you also have to keep track of
these things. This adds a big overhead. Let's be honest about it.</p>
<p>The same goes for <a href="https://github.com/tmux/tmux">Tmux</a>. Tmux also supports
plugins. And here we go again. And saying you can just use the native
functionalities is a dishonest thing to say. Because if that were true,
nobody would use these plugins, and they would not be popular at all.</p>
<p>Now, if you like ricing your setup. Configuring things. And playing
around with your environment, you go for it. I can understand. I was
the same in my youth. It was fun and I loved every minute of it.</p>
<p>The problematic thing that occurs is that Vim evangelists then go and
preach the Vim gospel, making everybody not using it feel like shit and
incompetent fools who do not care about &quot;real&quot; programming.</p>
<p>I have friends who use <a href="https://code.visualstudio.com/">VS Code</a> and
are amazing programmers. They don't care about terminals or plugins or
config files. They open their editor of choice and smash at writing the
code they need to write. And my respect for them has nothing to do with
the complexity of their setup. I respect them because the code they write
is of high quality. How they come up with it is of no importance to me.</p>
<p>Most of the software we use daily or runs our world was written by
people who barely knew how to use a keyboard. Just watch <a href="https://www.youtube.com/watch?v=tc4ROCJYbm0">Brian Kernighan
type</a> and you will see what
I mean. And then look at his accomplishments. Slow typing doesn't mean
shit. It's the quality of the work that matters.</p>
<p>The reason why I switched to
<a href="https://helix-editor.com/">Helix</a> is simple. It has
<a href="https://en.wikipedia.org/wiki/Language_Server_Protocol">LSP</a> and fuzzy
finding built-in. There is no plugin system in place, so they needed to
include common things programmers need these days. For commenting a line,
you don't need a plugin. Just press <code>ctrl+c</code> over the line and that's
it. I don't remap anything. I use the defaults. The only thing I did
was change a default theme. And I choose one that was bundled with the
editor. That was it!</p>
<p>The same goes for <a href="https://github.com/tmux/tmux">Tmux</a>. I
don't use it anymore, but I need a multiplexer. I am used to
it. Old dog, new tricks kind of a thing. I've used it for years
and years. And <a href="https://zellij.dev/">Zellij</a> is a modern take on
<a href="https://github.com/tmux/tmux">Tmux</a>. Batteries included and with sane
defaults. No config file or plugins on my system to make it usable.</p>
<p>This elitism about personal setups is so exhausting. You should use your
computer the way you want to use it, and I will use mine the way I see
fit. This herd mentality I see so often is so cringe. I'm so over taking
people seriously when it comes to these topics.</p>


guid: https://mitjafelicijan.com/calling-assembly-functions-from-c.html
title: Calling assembly functions from C
url: https://mitjafelicijan.com/calling-assembly-functions-from-c.html
feedurl: https://mitjafelicijan.com/feed.xml
content_mime_type: text/html
content:
<p>This is using the portable GNU assembler and TinyCC compiler but GCC or Clang
can be used as well.</p>
<p>First lets define a simple function in assembly.</p>
<pre tabindex="0" style="background-color:#fff;"><code><span style="display:flex;"><span><span style="color:#008000"># sum.s
</span></span></span><span style="display:flex;"><span><span style="color:#008000"></span>.intel_syntax noprefix
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>.global sum
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>.text
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>sum:
</span></span><span style="display:flex;"><span>    add rdi, rsi
</span></span><span style="display:flex;"><span>    mov rax, rdi
</span></span><span style="display:flex;"><span>    ret
</span></span></code></pre><p>Lets compile this with GNU assembler <code>as sum.s -o sum.o</code>.</p>
<p>Now we need a C program that calls this function.</p>
<pre tabindex="0" style="background-color:#fff;"><code><span style="display:flex;"><span><span style="color:#008000">// main.c
</span></span></span><span style="display:flex;"><span><span style="color:#008000"></span><span style="color:#00f">#include</span> <span style="color:#00f">&lt;stdio.h&gt;</span><span style="color:#00f">
</span></span></span><span style="display:flex;"><span><span style="color:#00f"></span>
</span></span><span style="display:flex;"><span><span style="color:#008000">// We need to define the signature of the function.
</span></span></span><span style="display:flex;"><span><span style="color:#008000"></span><span style="color:#2b91af">int</span> sum(<span style="color:#2b91af">int</span> a, <span style="color:#2b91af">int</span> b);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#2b91af">int</span> main() {
</span></span><span style="display:flex;"><span>    <span style="color:#00f">for</span>(<span style="color:#2b91af">int</span> i=0; i&lt;10; ++i) {
</span></span><span style="display:flex;"><span>        printf(<span style="color:#a31515">&#34;SUM of 5+%d is %d</span><span style="color:#a31515">\n</span><span style="color:#a31515">&#34;</span>, i, sum(5, i));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#00f">return</span> 0;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre><p>Now lets compile and link into final program with <code>tcc main.c sum.o -o main</code>.</p>
<p>Use this table to see what each register is being used for.</p>
<table>
<thead>
<tr>
<th>Register</th>
<th>Conventional use</th>
<th>Low 32-bits</th>
<th>Low 16-bits</th>
<th>Low 8-bits</th>
</tr>
</thead>
<tbody>
<tr>
<td>%rax</td>
<td>Return value, caller-saved</td>
<td>%eax</td>
<td>%ax</td>
<td>%al</td>
</tr>
<tr>
<td>%rdi</td>
<td>1st argument, caller-saved</td>
<td>%edi</td>
<td>%di</td>
<td>%dil</td>
</tr>
<tr>
<td>%rsi</td>
<td>2nd argument, caller-saved</td>
<td>%esi</td>
<td>%si</td>
<td>%sil</td>
</tr>
<tr>
<td>%rdx</td>
<td>3rd argument, caller-saved</td>
<td>%edx</td>
<td>%dx</td>
<td>%dl</td>
</tr>
<tr>
<td>%rcx</td>
<td>4th argument, caller-saved</td>
<td>%ecx</td>
<td>%cx</td>
<td>%cl</td>
</tr>
<tr>
<td>%r8</td>
<td>5th argument, caller-saved</td>
<td>%r8d</td>
<td>%r8w</td>
<td>%r8b</td>
</tr>
<tr>
<td>%r9</td>
<td>6th argument, caller-saved</td>
<td>%r9d</td>
<td>%r9w</td>
<td>%r9b</td>
</tr>
<tr>
<td>%r10</td>
<td>Scratch/temporary, caller-saved</td>
<td>%r10d</td>
<td>%r10w</td>
<td>%r10b</td>
</tr>
<tr>
<td>%r11</td>
<td>Scratch/temporary, caller-saved</td>
<td>%r11d</td>
<td>%r11w</td>
<td>%r11b</td>
</tr>
<tr>
<td>%rsp</td>
<td>Stack pointer, callee-saved</td>
<td>%esp</td>
<td>%sp</td>
<td>%spl</td>
</tr>
<tr>
<td>%rbx</td>
<td>Local variable, callee-saved</td>
<td>%ebx</td>
<td>%bx</td>
<td>%bl</td>
</tr>
<tr>
<td>%rbp</td>
<td>Local variable, callee-saved</td>
<td>%ebp</td>
<td>%bp</td>
<td>%bpl</td>
</tr>
<tr>
<td>%r12</td>
<td>Local variable, callee-saved</td>
<td>%r12d</td>
<td>%r12w</td>
<td>%r12b</td>
</tr>
<tr>
<td>%r13</td>
<td>Local variable, callee-saved</td>
<td>%r13d</td>
<td>%r13w</td>
<td>%r13b</td>
</tr>
<tr>
<td>%r14</td>
<td>Local variable, callee-saved</td>
<td>%r14d</td>
<td>%r14w</td>
<td>%r14b</td>
</tr>
<tr>
<td>%r15</td>
<td>Local variable, callee-saved</td>
<td>%r15d</td>
<td>%r15w</td>
<td>%r15b</td>
</tr>
<tr>
<td>%rip</td>
<td>Instruction pointer</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>%rflags</td>
<td>Status/condition code bits</td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p>You can read more about <a href="/assets/notes/asm64-handout.pdf">x86-64 Machine-Level Programming</a>.</p>


guid: https://mitjafelicijan.com/sending-signals-to-c-program.html
title: Sending signals to C programs
url: https://mitjafelicijan.com/sending-signals-to-c-program.html
feedurl: https://mitjafelicijan.com/feed.xml
content_mime_type: text/html
content:
<p>For simple and easy IPC to the C program we can use signals.
<a href="https://www.man7.org/linux/man-pages/man7/signal.7.html">https://www.man7.org/linux/man-pages/man7/signal.7.html</a></p>
<p>Only two user defined signals are available (<code>SIGUSR1</code> and <code>SIGUSR2</code>) but you
can hijack other ones even though this is really not advisable.</p>
<pre tabindex="0" style="background-color:#fff;"><code><span style="display:flex;"><span><span style="color:#008000">// signal.c
</span></span></span><span style="display:flex;"><span><span style="color:#008000"></span><span style="color:#00f">#include</span> <span style="color:#00f">&lt;stdio.h&gt;</span><span style="color:#00f">
</span></span></span><span style="display:flex;"><span><span style="color:#00f">#include</span> <span style="color:#00f">&lt;stdlib.h&gt;</span><span style="color:#00f">
</span></span></span><span style="display:flex;"><span><span style="color:#00f">#include</span> <span style="color:#00f">&lt;signal.h&gt;</span><span style="color:#00f">
</span></span></span><span style="display:flex;"><span><span style="color:#00f">#include</span> <span style="color:#00f">&lt;unistd.h&gt;</span><span style="color:#00f">
</span></span></span><span style="display:flex;"><span><span style="color:#00f"></span>
</span></span><span style="display:flex;"><span><span style="color:#2b91af">void</span> handle_signal(<span style="color:#2b91af">int</span> signal) {
</span></span><span style="display:flex;"><span>    printf(<span style="color:#a31515">&#34;Signal received: %d</span><span style="color:#a31515">\n</span><span style="color:#a31515">&#34;</span>, signal);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#2b91af">int</span> main() {
</span></span><span style="display:flex;"><span>    signal(SIGUSR1, handle_signal); <span style="color:#008000">// is equal to 10
</span></span></span><span style="display:flex;"><span><span style="color:#008000"></span>    signal(SIGUSR2, handle_signal); <span style="color:#008000">// is equal to 12
</span></span></span><span style="display:flex;"><span><span style="color:#008000"></span>
</span></span><span style="display:flex;"><span>    <span style="color:#00f">while</span>(1) {
</span></span><span style="display:flex;"><span>        sleep(1);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#00f">return</span> 0;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre><p>Compile with <code>gcc -o signal signal.c</code> and run the program with <code>./signal</code> and
then from another terminal send the signal to the program with <code>kill -10 $(pidof signal)</code> which should print out <code>Signal received: 10</code>.</p>
<table>
<thead>
<tr>
<th>Signal</th>
<th>x86/ARM</th>
<th>Alpha/</th>
<th>MIPS</th>
<th>PARISC</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>SIGHUP</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td></td>
</tr>
<tr>
<td>SIGINT</td>
<td>2</td>
<td>2</td>
<td>2</td>
<td>2</td>
<td></td>
</tr>
<tr>
<td>SIGQUIT</td>
<td>3</td>
<td>3</td>
<td>3</td>
<td>3</td>
<td></td>
</tr>
<tr>
<td>SIGILL</td>
<td>4</td>
<td>4</td>
<td>4</td>
<td>4</td>
<td></td>
</tr>
<tr>
<td>SIGTRAP</td>
<td>5</td>
<td>5</td>
<td>5</td>
<td>5</td>
<td></td>
</tr>
<tr>
<td>SIGABRT</td>
<td>6</td>
<td>6</td>
<td>6</td>
<td>6</td>
<td></td>
</tr>
<tr>
<td>SIGIOT</td>
<td>6</td>
<td>6</td>
<td>6</td>
<td>6</td>
<td></td>
</tr>
<tr>
<td>SIGBUS</td>
<td>7</td>
<td>10</td>
<td>10</td>
<td>10</td>
<td></td>
</tr>
<tr>
<td>SIGEMT</td>
<td>-</td>
<td>7</td>
<td>7</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>SIGFPE</td>
<td>8</td>
<td>8</td>
<td>8</td>
<td>8</td>
<td></td>
</tr>
<tr>
<td>SIGKILL</td>
<td>9</td>
<td>9</td>
<td>9</td>
<td>9</td>
<td></td>
</tr>
<tr>
<td><strong>SIGUSR1</strong></td>
<td><strong>10</strong></td>
<td><strong>30</strong></td>
<td><strong>16</strong></td>
<td><strong>16</strong></td>
<td></td>
</tr>
<tr>
<td>SIGSEGV</td>
<td>11</td>
<td>11</td>
<td>11</td>
<td>11</td>
<td></td>
</tr>
<tr>
<td><strong>SIGUSR2</strong></td>
<td><strong>12</strong></td>
<td><strong>31</strong></td>
<td><strong>17</strong></td>
<td><strong>17</strong></td>
<td></td>
</tr>
<tr>
<td>SIGPIPE</td>
<td>13</td>
<td>13</td>
<td>13</td>
<td>13</td>
<td></td>
</tr>
<tr>
<td>SIGALRM</td>
<td>14</td>
<td>14</td>
<td>14</td>
<td>14</td>
<td></td>
</tr>
<tr>
<td>SIGTERM</td>
<td>15</td>
<td>15</td>
<td>15</td>
<td>15</td>
<td></td>
</tr>
<tr>
<td>SIGSTKFLT</td>
<td>16</td>
<td>-</td>
<td>-</td>
<td>7</td>
<td></td>
</tr>
<tr>
<td>SIGCHLD</td>
<td>17</td>
<td>20</td>
<td>18</td>
<td>18</td>
<td></td>
</tr>
<tr>
<td>SIGCLD</td>
<td>-</td>
<td>-</td>
<td>18</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>SIGCONT</td>
<td>18</td>
<td>19</td>
<td>25</td>
<td>26</td>
<td></td>
</tr>
<tr>
<td>SIGSTOP</td>
<td>19</td>
<td>17</td>
<td>23</td>
<td>24</td>
<td></td>
</tr>
<tr>
<td>SIGTSTP</td>
<td>20</td>
<td>18</td>
<td>24</td>
<td>25</td>
<td></td>
</tr>
<tr>
<td>SIGTTIN</td>
<td>21</td>
<td>21</td>
<td>26</td>
<td>27</td>
<td></td>
</tr>
<tr>
<td>SIGTTOU</td>
<td>22</td>
<td>22</td>
<td>27</td>
<td>28</td>
<td></td>
</tr>
<tr>
<td>SIGURG</td>
<td>23</td>
<td>16</td>
<td>21</td>
<td>29</td>
<td></td>
</tr>
<tr>
<td>SIGXCPU</td>
<td>24</td>
<td>24</td>
<td>30</td>
<td>12</td>
<td></td>
</tr>
<tr>
<td>SIGXFSZ</td>
<td>25</td>
<td>25</td>
<td>31</td>
<td>30</td>
<td></td>
</tr>
<tr>
<td>SIGVTALRM</td>
<td>26</td>
<td>26</td>
<td>28</td>
<td>20</td>
<td></td>
</tr>
<tr>
<td>SIGPROF</td>
<td>27</td>
<td>27</td>
<td>29</td>
<td>21</td>
<td></td>
</tr>
<tr>
<td>SIGWINCH</td>
<td>28</td>
<td>28</td>
<td>20</td>
<td>23</td>
<td></td>
</tr>
<tr>
<td>SIGIO</td>
<td>29</td>
<td>23</td>
<td>22</td>
<td>22</td>
<td></td>
</tr>
<tr>
<td>SIGPOLL</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>Same as SIGIO</td>
</tr>
<tr>
<td>SIGPWR</td>
<td>30</td>
<td>29/-</td>
<td>19</td>
<td>19</td>
<td></td>
</tr>
<tr>
<td>SIGINFO</td>
<td>-</td>
<td>29/-</td>
<td>-</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>SIGLOST</td>
<td>-</td>
<td>-/29</td>
<td>-</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>SIGSYS</td>
<td>31</td>
<td>12</td>
<td>12</td>
<td>31</td>
<td></td>
</tr>
<tr>
<td>SIGUNUSED</td>
<td>31</td>
<td>-</td>
<td>-</td>
<td>31</td>
<td></td>
</tr>
</tbody>
</table>


guid: https://mitjafelicijan.com/embedding-resources-into-binary-with-c.html
title: Embedding resources into binary with C
url: https://mitjafelicijan.com/embedding-resources-into-binary-with-c.html
feedurl: https://mitjafelicijan.com/feed.xml
content_mime_type: text/html
content:
<p><a href="https://en.cppreference.com/w/c/preprocessor/embed">Binary resource inclusion</a>
preprocessor has been put into the C23 standard but has not yet been
implemented by the compilers.</p>
<p>Until then a workaround with <a href="https://linux.die.net/man/1/xxd"><code>xxd</code></a> is
possible without spending time on rolling out your own.</p>
<p><code>xxd</code> has an option to export to C header file which makes this much easier.
This works for all files be that text files or binary ones such as images, etc.</p>
<p>Convert <code>text.txt</code> into a C header file with <code>xxd -i test.txt &gt; test.h</code>. This
creates the following file and uses the filename for variable names.</p>
<pre tabindex="0" style="background-color:#fff;"><code><span style="display:flex;"><span><span style="color:#008000">// test.h
</span></span></span><span style="display:flex;"><span><span style="color:#008000"></span><span style="color:#2b91af">unsigned</span> <span style="color:#2b91af">char</span> test_txt[] = {
</span></span><span style="display:flex;"><span>  0x54, 0x68, 0x65, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x72, 0x75,
</span></span><span style="display:flex;"><span>  0x6c, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x79, 0x70, 0x69, 0x63, 0x61,
</span></span><span style="display:flex;"><span>  0x6c, 0x20, 0x6f, 0x66, 0x20, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x75, 0x6d,
</span></span><span style="display:flex;"><span>  ...
</span></span><span style="display:flex;"><span>  };
</span></span><span style="display:flex;"><span><span style="color:#2b91af">unsigned</span> <span style="color:#2b91af">int</span> test_txt_len = 547;
</span></span></code></pre><p>Then use it in C in this manner.</p>
<pre tabindex="0" style="background-color:#fff;"><code><span style="display:flex;"><span><span style="color:#008000">// main.c
</span></span></span><span style="display:flex;"><span><span style="color:#008000"></span><span style="color:#00f">#include</span> <span style="color:#00f">&lt;stdio.h&gt;</span><span style="color:#00f">
</span></span></span><span style="display:flex;"><span><span style="color:#00f">#include</span> <span style="color:#00f">&#34;test.h&#34;</span><span style="color:#00f">
</span></span></span><span style="display:flex;"><span><span style="color:#00f"></span>
</span></span><span style="display:flex;"><span><span style="color:#2b91af">int</span> main(<span style="color:#2b91af">void</span>) {
</span></span><span style="display:flex;"><span>  printf(<span style="color:#a31515">&#34;Testing embedding of files into binary.</span><span style="color:#a31515">\n</span><span style="color:#a31515">&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#00f">for</span> (<span style="color:#2b91af">unsigned</span> <span style="color:#2b91af">int</span> i = 0; i &lt; test_txt_len; i++) {
</span></span><span style="display:flex;"><span>    printf(<span style="color:#a31515">&#34;%02x &#34;</span>, test_txt[i]);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  printf(<span style="color:#a31515">&#34;</span><span style="color:#a31515">\n\n</span><span style="color:#a31515">&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#00f">for</span> (<span style="color:#2b91af">unsigned</span> <span style="color:#2b91af">int</span> i = 0; i &lt; test_txt_len; i++) {
</span></span><span style="display:flex;"><span>    printf(<span style="color:#a31515">&#34;%c&#34;</span>, test_txt[i]);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>  printf(<span style="color:#a31515">&#34;</span><span style="color:#a31515">\n\n</span><span style="color:#a31515">&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#00f">return</span> 0;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre>


guid: https://mitjafelicijan.com/write-and-read-structs-to-files-in-c.html
title: Write and read structs to/from files in C
url: https://mitjafelicijan.com/write-and-read-structs-to-files-in-c.html
feedurl: https://mitjafelicijan.com/feed.xml
content_mime_type: text/html
content:
<p>First let's define a shared header file for the struct definition.</p>
<pre tabindex="0" style="background-color:#fff;"><code><span style="display:flex;"><span><span style="color:#008000">// struct.h
</span></span></span><span style="display:flex;"><span><span style="color:#008000"></span><span style="color:#00f">typedef</span> <span style="color:#00f">struct</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#2b91af">char</span> name[50];
</span></span><span style="display:flex;"><span>    <span style="color:#2b91af">int</span> health;
</span></span><span style="display:flex;"><span>    <span style="color:#2b91af">float</span> damage;
</span></span><span style="display:flex;"><span>} Character;
</span></span></code></pre><p>Now lets write it to a <code>character.dat</code> file.</p>
<pre tabindex="0" style="background-color:#fff;"><code><span style="display:flex;"><span><span style="color:#008000">// write.c
</span></span></span><span style="display:flex;"><span><span style="color:#008000"></span><span style="color:#00f">#include</span> <span style="color:#00f">&lt;stdio.h&gt;</span><span style="color:#00f">
</span></span></span><span style="display:flex;"><span><span style="color:#00f">#include</span> <span style="color:#00f">&lt;string.h&gt;</span><span style="color:#00f">
</span></span></span><span style="display:flex;"><span><span style="color:#00f"></span>
</span></span><span style="display:flex;"><span><span style="color:#00f">#include</span> <span style="color:#00f">&#34;struct.h&#34;</span><span style="color:#00f">
</span></span></span><span style="display:flex;"><span><span style="color:#00f"></span>
</span></span><span style="display:flex;"><span><span style="color:#2b91af">int</span> main(<span style="color:#2b91af">void</span>) {
</span></span><span style="display:flex;"><span>    printf(<span style="color:#a31515">&#34;Write struct</span><span style="color:#a31515">\n</span><span style="color:#a31515">&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Character ch;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    strcpy(ch.name, <span style="color:#a31515">&#34;John Doe&#34;</span>);
</span></span><span style="display:flex;"><span>    ch.health = 30;
</span></span><span style="display:flex;"><span>    ch.damage = 5.9;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    FILE* file = fopen(<span style="color:#a31515">&#34;character.dat&#34;</span>, <span style="color:#a31515">&#34;wb&#34;</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#00f">if</span> (file == NULL) {
</span></span><span style="display:flex;"><span>        perror(<span style="color:#a31515">&#34;Error opening file&#34;</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#00f">return</span> 1;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    fwrite(&amp;ch, <span style="color:#00f">sizeof</span>(Character), 1, file);
</span></span><span style="display:flex;"><span>    fclose(file);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#00f">return</span> 0;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre><p>If we check the contents of the <code>character.dat</code> file it should look like this.</p>
<pre tabindex="0" style="background-color:#fff;"><code><span style="display:flex;"><span>$ xxd character.dat
</span></span><span style="display:flex;"><span>00000000: 4a6f 686e 2044 6f65 0000 0000 0000 0000  John Doe........
</span></span><span style="display:flex;"><span>00000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
</span></span><span style="display:flex;"><span>00000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
</span></span><span style="display:flex;"><span>00000030: 0000 0000 1e00 0000 cdcc bc40            ...........@
</span></span></code></pre><p>Reading and serializing back to a struct.</p>
<pre tabindex="0" style="background-color:#fff;"><code><span style="display:flex;"><span><span style="color:#008000">// read.c
</span></span></span><span style="display:flex;"><span><span style="color:#008000"></span><span style="color:#00f">#include</span> <span style="color:#00f">&lt;stdio.h&gt;</span><span style="color:#00f">
</span></span></span><span style="display:flex;"><span><span style="color:#00f"></span>
</span></span><span style="display:flex;"><span><span style="color:#00f">#include</span> <span style="color:#00f">&#34;struct.h&#34;</span><span style="color:#00f">
</span></span></span><span style="display:flex;"><span><span style="color:#00f"></span>
</span></span><span style="display:flex;"><span><span style="color:#2b91af">int</span> main(<span style="color:#2b91af">void</span>) {
</span></span><span style="display:flex;"><span>    printf(<span style="color:#a31515">&#34;Read struct</span><span style="color:#a31515">\n</span><span style="color:#a31515">&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    Character ch;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    FILE* file = fopen(<span style="color:#a31515">&#34;character.dat&#34;</span>, <span style="color:#a31515">&#34;rb&#34;</span>);
</span></span><span style="display:flex;"><span>    <span style="color:#00f">if</span> (file == NULL) {
</span></span><span style="display:flex;"><span>        perror(<span style="color:#a31515">&#34;Error opening file&#34;</span>);
</span></span><span style="display:flex;"><span>        <span style="color:#00f">return</span> 1;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    fread(&amp;ch, <span style="color:#00f">sizeof</span>(Character), 1, file);
</span></span><span style="display:flex;"><span>    fclose(file);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    printf(<span style="color:#a31515">&#34;Name: %s</span><span style="color:#a31515">\n</span><span style="color:#a31515">&#34;</span>, ch.name);
</span></span><span style="display:flex;"><span>    printf(<span style="color:#a31515">&#34;Health: %d</span><span style="color:#a31515">\n</span><span style="color:#a31515">&#34;</span>, ch.health);
</span></span><span style="display:flex;"><span>    printf(<span style="color:#a31515">&#34;Damage: %.1f</span><span style="color:#a31515">\n</span><span style="color:#a31515">&#34;</span>, ch.damage);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#00f">return</span> 0;
</span></span><span style="display:flex;"><span>}
</span></span></code></pre>


guid: https://mitjafelicijan.com/use-option-key-as-meta-macos-alactritty.html
title: Use option key as meta in Alacritty under macOS
url: https://mitjafelicijan.com/use-option-key-as-meta-macos-alactritty.html
feedurl: https://mitjafelicijan.com/feed.xml
content_mime_type: text/html
content:
<p>To use option key under macOS as Meta key use the option
<code>option_as_alt</code> and set it to <code>&quot;Both&quot;</code>.</p>
<p>This is the example for the newer Toml file format.</p>
<pre tabindex="0" style="background-color:#fff;"><code><span style="display:flex;"><span><span style="color:#008000"># ~/.alacritty.toml</span>
</span></span><span style="display:flex;"><span>[window]
</span></span><span style="display:flex;"><span>option_as_alt = <span style="color:#a31515">&#34;Both&#34;</span>
</span></span></code></pre><p>And this is the older YAML format.</p>
<pre tabindex="0" style="background-color:#fff;"><code><span style="display:flex;"><span><span style="color:#008000"># ~/.alacritty.yml</span>
</span></span><span style="display:flex;"><span>window:
</span></span><span style="display:flex;"><span>  option_as_alt: Both
</span></span></code></pre><p>Check more at <a href="https://alacritty.org/config-alacritty.html#s20">https://alacritty.org/config-alacritty.html#s20</a>.</p>


guid: https://www.neilhenning.dev/lifelog/
title: life log
url: https://www.neilhenning.dev/lifelog/
feedurl: https://www.duskborn.com/index.xml
content:
<p>Heyo, I&rsquo;m Neil Henning and this is the log of my adventures with gaia to date!</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-17httpsdocsunity3dcompackagescomunityburst17changelogchangeloghtml">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-16httpsdocsunity3dcompackagescomunityburst16changelogchangeloghtml">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-15httpsdocsunity3dcompackagescomunityburst15changelogchangeloghtml">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-ubenchhhttpsgithubcomsheredomubenchh">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-hashmaphhttpsgithubcomsheredomhashmaph">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-14httpsdocsunity3dcompackagescomunityburst14changelogchangeloghtml">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-bursthttpsblogunitycomtechnologyin-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-bursthttpsblogunitycomtechnologyenhanced-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-13httpsdocsunity3dcompackagescomunityburst13changelogchangeloghtml">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-12httpswwwkhronosorgregistryvulkanspecs12htmlvkspechtml--spir-v-15httpswwwkhronosorgregistryspir-vspecsunified1spirvhtml">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-tutorialhttpswwwkhronosorgblogvulkan-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-11httpswwwkhronosorgregistryvulkanspecs11htmlvkspechtml--spir-v-13httpswwwkhronosorgregistryspir-vspecsunified1spirvhtml">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-subprocesshhttpsgithubcomsheredomsubprocessh">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-chapterhttpswwwmeetupcomkhronos-munchen-chapterevents242664238">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-clspvhttpsgithubcomgoogleclspv">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-12httpswwwkhronosorgregistryspir-vspecs12spirvhtml">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-vhttpsgithubcomsheredomyari-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-11httpswwwkhronosorgregistryspir-vspecs11spirvhtml">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-gdchttpschedulegdconfcomsessionworking-with-vulkan-on-android-an-introduction-to-spir-v-presented-by-imagination-technologies">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-10httpswwwkhronosorgregistryvulkanspecs10htmlvkspechtml">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-10httpswwwkhronosorgregistryspir-vspecs10spirvhtml">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_khr_vulkan_glslhttpswwwkhronosorgregistryvulkanspecsmiscgl_khr_vulkan_glsltxt">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-utesthhttpsgithubcomsheredomutesth">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-jsonhhttpsgithubcomsheredomjsonh">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-utf8hhttpsgithubcomsheredomutf8h">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-chapterhttpwwwmeetupcomkhronos-uk-chapterevents221391028eurollvmhttpllvmorgdevmtg2015-04">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-codeplayhttpwwwcodeplaycom">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-vulkanhttpswwwkhronosorgvulkan">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-vhttpswwwkhronosorgspir">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-codeplayhttpwwwcodeplaycom">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-iwoclhttpwwwiwoclorgiwocl-2014abstractsspir-me-the-details-building-custom-language-support-on-opencl">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-summithttpdeveloperamdcomapu">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-conferencehttparchivesnuclairecordinghigh-performance-racing-ai-in-nascar-2011">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-codeplayhttpwwwcodeplaycom">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-2011httpenwikipediaorgwikinascar_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-codeplayhttpwwwcodeplaycom-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-glasgowhttpwwwglaacuk-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>


guid: https://www.neilhenning.dev/raspberry-pi-2-dot-product-test/
title: Raspberry Pi 2 Dot Product Test
url: https://www.neilhenning.dev/raspberry-pi-2-dot-product-test/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/khronoseurollvm-talk-why-spir-v/
title: Khronos/EuroLLVM talk - Why SPIR-V?
url: https://www.neilhenning.dev/posts/khronoseurollvm-talk-why-spir-v/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/installing-jenkins-on-raspberry-pi-2/
title: Installing Jenkins on Raspberry Pi 2
url: https://www.neilhenning.dev/posts/installing-jenkins-on-raspberry-pi-2/
feedurl: https://www.duskborn.com/index.xml
content:
<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+Jenkins+on+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>


guid: https://www.neilhenning.dev/posts/running-your-first-job-on-the-raspberry-pi-2-jenkins/
title: Running your first job on the Raspberry Pi 2 / Jenkins
url: https://www.neilhenning.dev/posts/running-your-first-job-on-the-raspberry-pi-2-jenkins/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/connecting-a-build-node-to-jenkins-on-raspberry-pi-2/
title: Connecting a build node to Jenkins on Raspberry Pi 2
url: https://www.neilhenning.dev/posts/connecting-a-build-node-to-jenkins-on-raspberry-pi-2/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/on-the-use-and-abuse-of-size_t/
title: On the use and abuse of size_t
url: https://www.neilhenning.dev/posts/on-the-use-and-abuse-of-size_t/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/length-vs-size-for-array-dimensions/
title: Length vs size for array dimensions
url: https://www.neilhenning.dev/posts/length-vs-size-for-array-dimensions/
feedurl: https://www.duskborn.com/index.xml
content:
<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 -->


guid: https://www.neilhenning.dev/posts/utf8-h/
title: utf8.h
url: https://www.neilhenning.dev/posts/utf8-h/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/utf8-h-progress/
title: utf8.h progress!
url: https://www.neilhenning.dev/posts/utf8-h-progress/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/json-h/
title: json.h
url: https://www.neilhenning.dev/posts/json-h/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/json-h-performance-vs-other-cc-json-parsers/
title: json.h performance (vs other C/C++ JSON parsers)
url: https://www.neilhenning.dev/posts/json-h-performance-vs-other-cc-json-parsers/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/json-h-performance-update/
title: json.h performance (update!)
url: https://www.neilhenning.dev/posts/json-h-performance-update/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/partial-simplified-json-support-in-json-h/
title: (Partial) Simplified JSON support in json.h
url: https://www.neilhenning.dev/posts/partial-simplified-json-support-in-json-h/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/introducing-utest-h/
title: Introducing utest.h!
url: https://www.neilhenning.dev/posts/introducing-utest-h/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/full-simplified-json-support-in-json-h/
title: Full Simplified JSON support in json.h
url: https://www.neilhenning.dev/posts/full-simplified-json-support-in-json-h/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/git-pre-commit-clang-format-hook/
title: git pre-commit clang-format hook
url: https://www.neilhenning.dev/posts/git-pre-commit-clang-format-hook/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/allocators-in-json-h/
title: Allocators in json.h!
url: https://www.neilhenning.dev/posts/allocators-in-json-h/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/a-simple-vulkan-compute-example/
title: A simple Vulkan Compute example
url: https://www.neilhenning.dev/posts/a-simple-vulkan-compute-example/
feedurl: https://www.duskborn.com/index.xml
content:
<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;"><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><span style="color:#75715e"></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:#75715e"></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;"><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;"><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;"><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:#75715e"></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;"><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:#75715e"></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:#75715e"></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:#75715e"></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;"><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;"><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:#75715e"></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 style="color:#75715e"></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;"><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><span style="color:#75715e"></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;"><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;"><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 style="color:#75715e"></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;"><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;"><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:#75715e"></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:#75715e"></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;"><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;"><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>


guid: https://www.neilhenning.dev/posts/hooking-up-mpc-llvm/
title: Hooking up MPC &#038; LLVM
url: https://www.neilhenning.dev/posts/hooking-up-mpc-llvm/
feedurl: https://www.duskborn.com/index.xml
content:
<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 -->


guid: https://www.neilhenning.dev/posts/cleaning-up-the-parser-mpc-llvm-for-the-neil-language-2/
title: Cleaning up the parser (MPC -> LLVM for the Neil Language #2)
url: https://www.neilhenning.dev/posts/cleaning-up-the-parser-mpc-llvm-for-the-neil-language-2/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/json-h-update-fixing-bugs-found-by-nativejson-benchmark/
title: json.h update - fixing bugs found by nativejson-benchmark
url: https://www.neilhenning.dev/posts/json-h-update-fixing-bugs-found-by-nativejson-benchmark/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/adding-type-identifiers-mpc-llvm-for-the-neil-language-3/
title: Adding type identifiers (MPC -> LLVM for the Neil Language #3)
url: https://www.neilhenning.dev/posts/adding-type-identifiers-mpc-llvm-for-the-neil-language-3/
feedurl: https://www.duskborn.com/index.xml
content:
<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="deldelmodifying-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>


title: spirv-stats - a tool to output statistics of your SPIR-V shader modules
feedurl: https://www.duskborn.com/index.xml
guid:
https://www.neilhenning.dev/posts/spirv-stats-a-tool-to-output-statistics-of-your-spir-v-shader-modules/

url:
https://www.neilhenning.dev/posts/spirv-stats-a-tool-to-output-statistics-of-your-spir-v-shader-modules/

content:
<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>


guid: https://www.neilhenning.dev/posts/spirv-stats-update-exposing-more-information/
title: spirv-stats update - exposing more information
url: https://www.neilhenning.dev/posts/spirv-stats-update-exposing-more-information/
feedurl: https://www.duskborn.com/index.xml
content:
<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 -->


guid: https://www.neilhenning.dev/posts/introducing-yari-v-an-experiment-on-spir-v-compression/
title: Introducing YARI-V - an experiment on SPIR-V compression
url: https://www.neilhenning.dev/posts/introducing-yari-v-an-experiment-on-spir-v-compression/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/adding-branching-mpc-llvm-for-the-neil-language-4/
title: Adding branching (MPC -> LLVM for the Neil Language #4)
url: https://www.neilhenning.dev/posts/adding-branching-mpc-llvm-for-the-neil-language-4/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/adding-loops-mpc-llvm-for-the-neil-language-5/
title: Adding loops (MPC -> LLVM for the Neil Language #5)
url: https://www.neilhenning.dev/posts/adding-loops-mpc-llvm-for-the-neil-language-5/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/adding-json-5-to-json-h/
title: Adding JSON 5 to json.h
url: https://www.neilhenning.dev/posts/adding-json-5-to-json-h/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/opencl-vulkan-a-porting-guide-1/
title: OpenCL -> Vulkan: A Porting Guide (#1)
url: https://www.neilhenning.dev/posts/opencl-vulkan-a-porting-guide-1/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/opencl-vulkan-a-porting-guide-2/
title: OpenCL -> Vulkan: A Porting Guide (#2)
url: https://www.neilhenning.dev/posts/opencl-vulkan-a-porting-guide-2/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/opencl-vulkan-a-porting-guide-3/
title: OpenCL -> Vulkan: A Porting Guide (#3)
url: https://www.neilhenning.dev/posts/opencl-vulkan-a-porting-guide-3/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


title: I'm speaking at the Munich Khronos Chapter Meeting 13th October 2017
feedurl: https://www.duskborn.com/index.xml
guid:
https://www.neilhenning.dev/posts/im-speaking-at-the-munich-khronos-chapter-meeting-13th-october-2017/

url:
https://www.neilhenning.dev/posts/im-speaking-at-the-munich-khronos-chapter-meeting-13th-october-2017/

content:
<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>


guid: https://www.neilhenning.dev/posts/slides-from-my-khronos-munich-chapter-talk/
title: Slides from my Khronos Munich Chapter talk
url: https://www.neilhenning.dev/posts/slides-from-my-khronos-munich-chapter-talk/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/llvm-crt-auto-magically-selecting-the-correct-crt/
title: LLVM &#038; CRT - auto-magically selecting the correct CRT
url: https://www.neilhenning.dev/posts/llvm-crt-auto-magically-selecting-the-correct-crt/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/cross-compiling-sollya-to-windows-with-emscripten/
title: Cross compiling Sollya to Windows with Emscripten
url: https://www.neilhenning.dev/posts/cross-compiling-sollya-to-windows-with-emscripten/
feedurl: https://www.duskborn.com/index.xml
content:
<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 -->


guid: https://www.neilhenning.dev/posts/introducing-process-h/
title: Introducing process.h!
url: https://www.neilhenning.dev/posts/introducing-process-h/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/adding-latin-and-greek-support-to-utf8-h/
title: Adding Latin and Greek support to utf8.h!
url: https://www.neilhenning.dev/posts/adding-latin-and-greek-support-to-utf8-h/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/how-to-read-write-llvm-bitcode/
title: How to read &#038; write LLVM bitcode
url: https://www.neilhenning.dev/posts/how-to-read-write-llvm-bitcode/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/optimizing-llvm-ir-from-the-c-api/
title: Optimizing LLVM IR from the C API
url: https://www.neilhenning.dev/posts/optimizing-llvm-ir-from-the-c-api/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/1-22x-performance-improvements-in-json-h/
title: 1.22x Performance Improvements in json.h!
url: https://www.neilhenning.dev/posts/1-22x-performance-improvements-in-json-h/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/so-long-codeplay-thanks-for-all-the-fish/
title: So long Codeplay, thanks for all the fish!
url: https://www.neilhenning.dev/posts/so-long-codeplay-thanks-for-all-the-fish/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/babys-first-crate-cpp_new/
title: Baby's First Crate: cpp_new
url: https://www.neilhenning.dev/posts/babys-first-crate-cpp_new/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/2018-review/
title: 2018 Review
url: https://www.neilhenning.dev/posts/2018-review/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/introducing-bump_alloc-my-new-rust-crate/
title: Introducing bump_alloc - my new Rust crate
url: https://www.neilhenning.dev/posts/introducing-bump_alloc-my-new-rust-crate/
feedurl: https://www.duskborn.com/index.xml
content:
<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>


guid: https://www.neilhenning.dev/posts/switching-to-hugo/
title: Switching my blog to Hugo
url: https://www.neilhenning.dev/posts/switching-to-hugo/
feedurl: https://www.duskborn.com/index.xml
content:
<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;"><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;"><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;"><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;"><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;"><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;"><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>


guid: https://www.neilhenning.dev/posts/utest-h-performance/
title: Comparing utest.h against googletest and jctest
url: https://www.neilhenning.dev/posts/utest-h-performance/
feedurl: https://www.duskborn.com/index.xml
content:
<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;"><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 style="color:#75715e"></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;"><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>


guid: https://www.neilhenning.dev/posts/fpscev/
title: An Experimental Floating-Point Scalar Evolution
url: https://www.neilhenning.dev/posts/fpscev/
feedurl: https://www.duskborn.com/index.xml
content:
<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;"><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 style="color:#75715e"></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;"><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><span style="color:#75715e"></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 style="color:#75715e"></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 style="color:#75715e"></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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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>


guid: https://www.neilhenning.dev/posts/fpscev-fast-math-propagation/
title: Using Floating-Point Scalar Evolution to Propagate Fast-Math Flags
url: https://www.neilhenning.dev/posts/fpscev-fast-math-propagation/
feedurl: https://www.duskborn.com/index.xml
content:
<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;"><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;"><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><span style="color:#75715e"></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><span style="color:#75715e"></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><span style="color:#75715e"></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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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;"><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>


