<?xml version="1.0"?>
<rss version="2.0">

<channel>
	<title>Planet Debian</title>
	<link>https://planet.debian.org/</link>
	<language>en</language>
	<description>Planet Debian - https://planet.debian.org/</description>


<item>
	<title>Matthew Garrett: Epic&#39;s EAC2 v2 seems fairly easily bypassable</title>
	<guid>https://codon.org.uk/~mjg59/blog/p/epics-eac2-v2-seems-fairly-easily-bypassable/</guid>
	<link>https://codon.org.uk/~mjg59/blog/p/epics-eac2-v2-seems-fairly-easily-bypassable/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/mjg59.png&quot; width=&quot;69&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;Epic just &lt;a class=&quot;link&quot; href=&quot;https://onlineservices.epicgames.com/news/introducing-easy-anti-cheat-linux-v2&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;announced&lt;/a&gt; the upcoming version 2 of their Linux implementation of Easy Anti-Cheat. It’s based on using the &lt;a class=&quot;link&quot; href=&quot;https://docs.kernel.org/bpf/prog_lsm.html&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Linux eBPF security module&lt;/a&gt; to monitor what’s happening, and then a bunch of extra infrastructure to make sure this can’t be bypassed. The core part of this is requiring secure boot be enabled (ensuring that modified kernels can’t be used), using measured boot to verify that secure boot is enabled and which keys are used (to prevent you from just signing your own modified kernel), and then doing remote attestation, a mechanism where the TPM generates a signed copy of the boot measurements and passes that off to a server which verifies it came from a real TPM, verifies that you have secure boot enabled and are using the right keys, and presumably then allows you into the game.&lt;/p&gt;
&lt;p&gt;This is all fine as long as you can prove that the measurements provided are real, and that’s actually a lot harder than you might think. First, we can simply make up our own quote signed with our own key and say that it came from a TPM. This is avoided by every TPM having an Endorsement Key (or EK) and an associated certificate, with that certificate being signed by the TPM vendor. If you have a list of all the legitimate TPM vendors and their CA keys, you can verify that the measurements came from a real TPM. Easy enough. So we need to get the measurements from a real TPM, and the one on our motherboard contains the measurements that were generated by the firmware and bootloader, and we can’t reset those at runtime without resetting the TPM, which… oh huh there’s actually nothing stopping us from doing that at runtime, as long as we have access to the hardware. Many desktop boards have the TPM on a small plugin module with a standard pinout that includes a reset pin. Simply short that to ground briefly and the TPM is back in its initial state, and userland can write whatever measurements it wants to it. Boot a modified kernel which lies to the eBPF code? As long as you replay the expected log values from a boot with secure boot on and a trusted kernel, the TPM will still happily provide a legitimate set of measurements that’ll satisfy the checker.&lt;/p&gt;
&lt;p&gt;What if the TPM is less accessible, either because it’s mounted directly to the motherboard or it’s inside the CPU or chipset? That’s going to be trickier. But here’s the thing. The quote needs to come from &lt;em&gt;a&lt;/em&gt; TPM, but not necessarily the TPM on your motherboard. TPMs these days are usually connected via the &lt;a class=&quot;link&quot; href=&quot;https://en.wikipedia.org/wiki/Serial_Peripheral_Interface&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Serial Peripheral Interface&lt;/a&gt;, usually referred to as SPI. Microchip make a &lt;a class=&quot;link&quot; href=&quot;https://www.microchip.com/en-us/product/mcp2210&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;USB to SPI bridge&lt;/a&gt;, and there’s a &lt;a class=&quot;link&quot; href=&quot;https://github.com/daniel-santos/mcp2210-linux&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Linux driver&lt;/a&gt;. Wire one of those up with an appropriate header and you can plug in an easily available TPM module intended for plugging into a motherboard, and now we tell the kernel to ignore the motherboard TPM and make /dev/tpmrm0 point at the USB one and program it with a set of trusted measurements and once again everything is going to look just fine (yes obviously the eBPF code can look for this, but we’re running a modified kernel so we can just lie to the eBPF code).&lt;/p&gt;
&lt;p&gt;Remote attestation on PCs just doesn’t work that well in environments where you can’t associate a specific TPM with a specific system, which is basically everywhere except enterprises. But maybe that doesn’t matter and cheaters wouldn’t be willing to spend the $20 or so it’d take to produce one of these things? That would seem somewhat surprising, but it’s not impossible. And obviously any server-side cheat detection that triggers could then block that specific TPM, meaning they’d need to go and get another TPM, and maybe that ends up being enough to discourage people from bothering. From a practical level, this may be sufficient. But at a technical level? It’s not great.&lt;/p&gt; </description> 
	<pubDate>Thu, 15 Oct 2026 20:23:59 +0000</pubDate>

</item> 
<item>
	<title>Steinar H. Gunderson: Decompilation patterns, part 12: __builtin_memcpy</title>
	<guid>http://blog.sesse.net/blog/tech/2026-10-15-21-32_decompilation_patterns_part_12_builtin_memcpy.html</guid>
	<link>http://blog.sesse.net/blog/tech/2026-10-15-21-32_decompilation_patterns_part_12_builtin_memcpy.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/sesse.png&quot; width=&quot;74&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;Say you see this lovely chunk of decompiled code:&lt;/p&gt;

&lt;pre&gt;    var_v1 = &amp;amp;sp10
    var_v0 = D_80010040;
    temp_s4 = var_v1;
    sp110 = &amp;amp;sp2C
    sp114 = &amp;amp;sp30
    do {
        var_v1-&amp;gt;unk0 = (s32) var_v0-&amp;gt;unk0;
        var_v1-&amp;gt;unk4 = (s32) var_v0[1];
        var_v1-&amp;gt;unk8 = (s32) var_v0[2];
        var_v1-&amp;gt;unkC = (s32) var_v0[3];
        var_v0 += 0x10;
        var_v1 += 0x10;
    } while (var_v0 != &amp;amp;D_8001040[0x3C]);
    var_v1-&amp;gt;unk0 = (s32) var_v0-&amp;gt;unk0;
    var_v1-&amp;gt;unk4 = (s32) var_v0[1];
    var_v1-&amp;gt;unk8 = (s32) var_v0[2];
&lt;/pre&gt;

&lt;p&gt;If you ignore the fact that m2c wrote &lt;code&gt;-&amp;gt;unk0&lt;/code&gt; for &lt;code&gt;[0]&lt;/code&gt; (it has a bit of an
annoying habit to do that), this is obviously something copying 16 bytes
at a time and then 12 more bytes at the end. But would a programmer ever do this?
Nope, this is an inlined, unrolled memcpy.&lt;/p&gt;

&lt;p&gt;This is known in GCC as &lt;code&gt;__builtin_memcpy&lt;/code&gt;, and it can happen either implicitly,
or by some sort of lowering from a struct or array copy (e.g., through initialization
of a stack array). Depending a bit on whether the variable is known to be aligned
or not, you&#39;ll either get just &lt;code&gt;lw&lt;/code&gt; or some evil &lt;code&gt;lwr&lt;/code&gt;/&lt;code&gt;lwl&lt;/code&gt; sequence; I&#39;m always
struggling a bit to change one to the other. In any case, what you want here is:&lt;/p&gt;

&lt;pre&gt;    __builtin_memcpy(&amp;amp;sp10, D_80010040, 0x4C);
&lt;/pre&gt;

&lt;p&gt;and then make &lt;code&gt;sp10&lt;/code&gt; the right type instead of a scalar, ideally so that you can
use &lt;code&gt;sizeof()&lt;/code&gt; on it. Or, in some cases, a direct initialization:&lt;/p&gt;

&lt;pre&gt;    s32 foo[] = { 1, 2, 3, ...more data from D_80010040... };
&lt;/pre&gt; </description> 
	<pubDate>Thu, 15 Oct 2026 19:45:26 +0000</pubDate>

</item> 
<item>
	<title>Steinar H. Gunderson: Decompilation patterns, part 11: Irregular switch</title>
	<guid>http://blog.sesse.net/blog/tech/2026-10-14-21-35_decompilation_patterns_part_11_irregular_switch.html</guid>
	<link>http://blog.sesse.net/blog/tech/2026-10-14-21-35_decompilation_patterns_part_11_irregular_switch.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/sesse.png&quot; width=&quot;74&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;Here&#39;s one that m2c usually gets right itself, but sometimes cannot:&lt;/p&gt;

&lt;pre&gt;    if (var_v1_7 != 1) {
        if (var_v1_7 &amp;lt; 2) { 
            if (var_v1_7 != 0) {
                spF0 = 40; 
            } else {
                vram_x = cmt46-&amp;gt;vram_x;
                vram_y = cmt46-&amp;gt;vram_y;
                spF0 = 40;
            }
        } else if (var_v1_7 != 2) {
            if (var_v1_7 != 3) {
&lt;/pre&gt;

&lt;p&gt;Repeated comparisons against the same variable, especially in a nested form
that could be binary search, should remind you of one thing: A switch.
Usually, the compiler implements a switch with a jump table, but not always;
if there are few conditions, or the range is too large for a reasonably-sized
table, it will do some ifs instead (or, enough ifs to get within the range
of a table). So what you want here is more like:&lt;/p&gt;

&lt;pre&gt;    switch (var_v1_7) {
    case 0:
       vram_x = cmt46-&amp;gt;vram_x;
       vram_y = cmt46-&amp;gt;vram_y;
       spF0 = 40;
       break;
    case 1:
       spF0 = 40;
       break;
    case 2:
       ...
    }
&lt;/pre&gt;

&lt;p&gt;Remember that sometimes, you may need to insert cases that are not explicitly
mentioned in the ifs (and/or a default case) to get everything to match back
properly.&lt;/p&gt; </description> 
	<pubDate>Wed, 14 Oct 2026 20:35:00 +0000</pubDate>

</item> 
<item>
	<title>Dirk Eddelbuettel: qlcal 0.1.4 on CRAN: Fresh Upstream Updates</title>
	<guid>http://dirk.eddelbuettel.com/blog/2026/10/14#qlcal-r_0.1.4</guid>
	<link>http://dirk.eddelbuettel.com/blog/2026/10/14#qlcal-r_0.1.4</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dirk.png&quot; width=&quot;65&quot; height=&quot;90&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;The twenty-second release of the &lt;a href=&quot;https://dirk.eddelbuettel.com/code/qlcal-r.html&quot;&gt;qlcal&lt;/a&gt; package
arrivied at &lt;a href=&quot;https://cran.r-project.org&quot;&gt;CRAN&lt;/a&gt; yesterday, and
has been built for &lt;a href=&quot;https://eddelbuettel.github.io/r2u/&quot;&gt;r2u&lt;/a&gt;
as well as on &lt;a href=&quot;https://qlcal.r-universe.dev/qlcal&quot;&gt;r-universe&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/code/qlcal-r.html&quot;&gt;qlcal&lt;/a&gt;
delivers the calendaring parts of &lt;a href=&quot;https://www.quantlib.org&quot;&gt;QuantLib&lt;/a&gt;. It is provided (for the R
package) as a set of included files, so the package is self-contained
and does not depend on an external &lt;a href=&quot;https://www.quantlib.org&quot;&gt;QuantLib&lt;/a&gt; library (which can be
demanding to build). &lt;a href=&quot;https://dirk.eddelbuettel.com/code/qlcal-r.html&quot;&gt;qlcal&lt;/a&gt; covers
over seventy country / market calendars and can compute holiday lists,
its complement (&lt;em&gt;i.e.&lt;/em&gt; business day lists) and much more.
Examples are in the README at the &lt;a href=&quot;https://github.com/qlcal/qlcal-r&quot;&gt;repository&lt;/a&gt;, the &lt;a href=&quot;https://dirk.eddelbuettel.com/code/qlcal-r.html&quot;&gt;package page&lt;/a&gt;,
and course at the &lt;a href=&quot;https://cran.r-project.org/package=qlcal&quot;&gt;CRAN package
page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This release is based on the changes in the &lt;a href=&quot;https://www.quantlib.org&quot;&gt;QuantLib&lt;/a&gt; 1.44 release also made
yesterday. It includes two new calendars for Malaysia and the
Philippines, updates to around a dozen calendars, and a few other
updates to internal files. &lt;a href=&quot;https://github.com/m-muecke&quot;&gt;Maxmilian Muecke&lt;/a&gt; spotted and
fixed a few small bugs just as he did for the RQuantLib release we made
&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/2026/10/13#rquantlib_0.4.29&quot;&gt;yesterday&lt;/a&gt;;
this is equally appreciated! The full details from &lt;code&gt;NEWS.Rd&lt;/code&gt;
follow.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h4 id=&quot;changes-in-version-0.1.4-2026-10-13&quot;&gt;Changes in version 0.1.4
(2026-10-13)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add missing market calendars for Poland, Russia, Romania,
Indonesia (Maximilian Muecke in &lt;a href=&quot;https://github.com/qlcal/qlcal-r/pull/21&quot;&gt;#21&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add (semi-deprecated) alternate separators &#39;::&#39; for Israel and
New Zealand markets (Maximilian Muecke in &lt;a href=&quot;https://github.com/qlcal/qlcal-r/pull/22&quot;&gt;#22&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fix several typos across source, configuration and documentation
files (Maximilian Muecke in &lt;a href=&quot;https://github.com/qlcal/qlcal-r/pull/23&quot;&gt;#23&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Synchronize with QuantLib 1.44, add two new calendars, update
several others, and update general utility files (Dirk in &lt;a href=&quot;https://github.com/qlcal/qlcal-r/pull/24&quot;&gt;#24&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Courtesy of my &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/&quot;&gt;CRANberries&lt;/a&gt;, there
is a diffstat report for &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/2026/10/13/#qlcal_0.1.4&quot;&gt;this
release&lt;/a&gt;. See the &lt;a href=&quot;https://dirk.eddelbuettel.com/code/qlcal-r.html&quot;&gt;project page&lt;/a&gt;
and package documentation for more details, and more examples.&lt;/p&gt;
&lt;p style=&quot;font-size: 80%; font-style: italic;&quot;&gt;
This post by &lt;a href=&quot;https://dirk.eddelbuettel.com&quot;&gt;Dirk
Eddelbuettel&lt;/a&gt; originated on his &lt;a href=&quot;https://dirk.eddelbuettel.com/blog/&quot;&gt;Thinking inside the box&lt;/a&gt;
blog. If you like this or other open-source work I do, you can &lt;a href=&quot;https://github.com/sponsors/eddelbuettel&quot;&gt;sponsor me at
GitHub&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt; </description> 
	<pubDate>Wed, 14 Oct 2026 19:51:00 +0000</pubDate>

</item> 
<item>
	<title>Reproducible Builds: Reproducible Builds in September 2026</title>
	<guid>https://reproducible-builds.org/reports/2026-09/</guid>
	<link>https://reproducible-builds.org/reports/2026-09/</link>
     <description>  &lt;p class=&quot;lead&quot;&gt;&lt;strong&gt;Welcome to the September 2026 report from the &lt;a href=&quot;https://reproducible-builds.org&quot;&gt;Reproducible Builds&lt;/a&gt; project!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://reproducible-builds.org/&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-09/reproducible-builds.png#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our reports, we try to outline the most important things that we have been up to over the past month. As a quick recap about what problem our project intends to solve, whilst anyone may inspect the source code of free software for malicious flaws, almost all software is distributed to end users as pre-compiled binaries. The motivation behind the reproducible builds effort is to ensure no flaws have been introduced during this compilation process by promising identical results are always generated from a given source, thus allowing multiple third-parties to come to a consensus on whether a build was compromised or not.&lt;/p&gt;

&lt;p&gt;As ever, if you are interested in contributing to the project, please visit our &lt;a href=&quot;https://reproducible-builds.org/contribute/&quot;&gt;&lt;em&gt;Contribute&lt;/em&gt;&lt;/a&gt; page on our website.&lt;/p&gt;

&lt;p&gt;In this month’s report, we cover:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://reproducible-builds.org/blog/index.rss#reproducible-builds-summit-2026-held-in-gothenburg-sweden&quot;&gt;Reproducible Builds Summit 2026 held in Gothenburg, Sweden&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://reproducible-builds.org/blog/index.rss#dettrace-expanding-architecture-support-for-pgo--lisp-dumps&quot;&gt;&lt;em&gt;dettrace&lt;/em&gt; expanding architecture support for PGO &amp;amp; Lisp dumps&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://reproducible-builds.org/blog/index.rss#they-dont-care-about-this&quot;&gt;“&lt;em&gt;They don’t care about this!&lt;/em&gt;”&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://reproducible-builds.org/blog/index.rss#source_date_epoch-specification-updates&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SOURCE_DATE_EPOCH&lt;/code&gt; specification updates&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://reproducible-builds.org/blog/index.rss#reproducible-builds-at-seagl-2026&quot;&gt;Reproducible Builds at SeaGL 2026&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://reproducible-builds.org/blog/index.rss#new-code-of-conduct-coc-for-the-reproducible-builds-project&quot;&gt;New Code of Conduct (CoC)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://reproducible-builds.org/blog/index.rss#supporter-spotlight-jochen-sprickerhof&quot;&gt;Supporter Spotlight: Jochen Sprickerhof&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://reproducible-builds.org/blog/index.rss#mailing-list-news&quot;&gt;Mailing list news&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://reproducible-builds.org/blog/index.rss#tool-and-documentation-development&quot;&gt;Tool and documentation development&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://reproducible-builds.org/blog/index.rss#patches&quot;&gt;Patches&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;reproducible-builds-summit-2026-held-in-gothenburg-sweden&quot;&gt;Reproducible Builds Summit 2026 held in Gothenburg, Sweden&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://reproducible-builds.org/events/gothenburg2026/&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-09/rb2026-gothenburg-grouppic-3.jpg#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The annual &lt;a href=&quot;https://reproducible-builds.org/events/gothenburg2026/&quot;&gt;Reproducible Builds summit took place from 22 to 24 September 2026 in Gothenburg, Sweden&lt;/a&gt;. The event brought together developers, distribution maintainers, security researchers and free software advocates from across the ecosystem to share updates on current initiatives, address outstanding toolchain bottlenecks and strengthen cross-project collaboration.&lt;/p&gt;

&lt;p&gt;Participants engaged in a series of working sessions and technical roundtables focused on expanding the practical scope of reproducibility. Discussions covered ongoing work within major Linux distributions, language-specific package ecosystems and the various parts of the binary verification infrastructure.&lt;/p&gt;

&lt;p&gt;Strategic planning formed a pillar of the gathering, with participants discussing long-term roadmap goals for supply-chain security, software integrity and related topics. Attendees explored new methods for automated verification, discussing how to lower the adoption barriers for maintainers and streamline the integration of deterministic build pipelines into established continuous integration (CI) systems. The event was then followed by two days of unmoderated hacking sessions. These hacking sessions provided space for technical progress, allowing attendees to draft specification updates, prototype new tool features and resolve standing reproducibility bugs in-person.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;dettrace-expanding-architecture-support-for-pgo--lisp-dumps&quot;&gt;Dettrace expanding architecture support for PGO &amp;amp; Lisp dumps&lt;/h3&gt;

&lt;p&gt;Bernhard M. Wiedemann announced major updates to &lt;a href=&quot;https://github.com/bmwiedemann/dettrace&quot;&gt;dettrace&lt;/a&gt;, porting the tool across most architectures supported by Debian and openSUSE. The release addresses key stability issues, passing test suites across these targets and making it ready for production build pipelines.&lt;/p&gt;

&lt;p&gt;These improvements enable deterministic builds when utilising &lt;a href=&quot;https://en.wikipedia.org/wiki/Profile-guided_optimization&quot;&gt;Profile-Guided Optimisations&lt;/a&gt; (PGO), removing the need to sacrifice runtime performance for reproducibility. Additionally, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dettrace&lt;/code&gt; can now be applied to (notoriously difficult-to-reproduce) Lisp and Scheme memory dumps, including environments such as CLISP, SBCL, Scheme 48, Racket and GNU Emacs.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;they-dont-care-about-this&quot;&gt;&lt;em&gt;“They don’t care about this”&lt;/em&gt;&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://arxiv.org/abs/2609.11411&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-09/paper-2609.png#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Annika Wilde, Marco Gutfleisch, Felix Reichmann, Anirban Chakraborty, Yuval Yarom, M. Angela Sasse and Ghassan Karame published a paper this month entitled &lt;a href=&quot;https://arxiv.org/abs/2609.11411&quot;&gt;&lt;em&gt;“They don’t care about this”: A Systematic Study of Trusted Execution Environments Build Reproducibility in the Wild&lt;/em&gt;&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Trusted Execution Environments (TEEs) have become a cornerstone of modern cloud computing, providing strong confidentiality and integrity guarantees for both code and data. A critical component of this trust model is remote attestation, which enables external entities to verify the authenticity and integrity of code executing within a TEE through cryptographic measurements. However, the effectiveness of remote attestation fundamentally &lt;strong&gt;depends on the verifier’s ability to trace the reported measurement back to the original source code - a property that can only be guaranteed through reproducible builds&lt;/strong&gt;. [&lt;a href=&quot;https://arxiv.org/abs/2609.11411&quot;&gt;…&lt;/a&gt;]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;a href=&quot;https://arxiv.org/pdf/2609.11411&quot;&gt;full PDF&lt;/a&gt; can be read online.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;source_date_epoch-specification-updates&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SOURCE_DATE_EPOCH&lt;/code&gt; specification updates&lt;/h3&gt;

&lt;p&gt;Bernhard M. Wiedemann &lt;a href=&quot;https://lists.reproducible-builds.org/pipermail/rb-general/2026-September/004165.html&quot;&gt;shared a number of proposals&lt;/a&gt; regarding updating the &lt;a href=&quot;https://reproducible-builds.org/specs/source-date-epoch/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SOURCE_DATE_EPOCH&lt;/code&gt; specification&lt;/a&gt; following discussions at a project summit. Seven distinct proposed changes have been &lt;a href=&quot;https://salsa.debian.org/reproducible-builds/specs/source-date-epoch-spec/-/merge_requests/&quot;&gt;submitted as merge requests on Salsa&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Bernhard’s proposed modifications are independent of one another, allowing for any combination to be merged depending on community feedback. Bernhard noted that one proposal may see the most debate, and could still benefit from further refinement before reaching consensus. Community members are invited to review and provide feedback on the individual merge requests by 1 December 2026. Input can be submitted via reactions or comments on Salsa, directly by email to Bernhard or the mailing list.&lt;/p&gt;

&lt;p&gt;The specification was first published in 2015 and updated in 2017.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;reproducible-builds-at-seagl-2026&quot;&gt;Reproducible Builds at &lt;a href=&quot;https://seagl.org/&quot;&gt;SeaGL&lt;/a&gt; 2026&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://seagl.org/&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-09/seagl.png#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reproducible Builds will be present at &lt;a href=&quot;https://seagl.org/&quot;&gt;SeaGL&lt;/a&gt; in Seattle, WA, on October 23rd &amp;amp; 24th. Come chat with us in person!&lt;/p&gt;

&lt;p&gt;Founded in 2013, SeaGL is a free, grassroots technical summit dedicated to spreading awareness and knowledge about free source software, hardware and culture.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;new-code-of-conduct-coc-for-the-reproducible-builds-project&quot;&gt;New Code of Conduct (CoC) for the Reproducible Builds project&lt;/h3&gt;

&lt;p&gt;Mattia Rizzolo &lt;a href=&quot;https://lists.reproducible-builds.org/pipermail/rb-general/2026-September/004156.html&quot;&gt;announced the official launch&lt;/a&gt; of a &lt;a href=&quot;https://reproducible-builds.org/conduct/&quot;&gt;Code of Conduct&lt;/a&gt; for the Reproducible Builds project. This follows work and community discussions originally initiated in 2024, incorporating feedback gathered over email and during project summits, as well as with input from the &lt;a href=&quot;https://sfconservancy.org/&quot;&gt;Software Freedom Conservancy&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The new Code of Conduct establishes guidelines emphasising mutual respect among project contributors. It also defines a formalised process for submitting and handling complaints regarding community misconduct, ensuring transparent governance across project spaces. Along with the core policy document, an accompanying &lt;a href=&quot;https://reproducible-builds.org/conduct/faq/&quot;&gt;Code of Conduct FAQ&lt;/a&gt; has been published to outline the rationale behind adopting the guidelines.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;supporter-spotlight-jochen-sprickerhof&quot;&gt;Supporter Spotlight: Jochen Sprickerhof&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://reproducible-builds.org/news/2026/09/15/supporter-spotlight-jochen-sprickerhof/&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-09/jochen.jpg#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a reminder, another &lt;a href=&quot;https://reproducible-builds.org/news/2026/09/15/supporter-spotlight-jochen-sprickerhof/&quot;&gt;supporter spotlight interview&lt;/a&gt; was published featuring long-time Debian and Reproducible Builds contributor Jochen Sprickerhof, highlighting his work on package verification and project infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;mailing-list-news&quot;&gt;Mailing list news&lt;/h3&gt;

&lt;p&gt;On &lt;a href=&quot;https://lists.reproducible-builds.org/listinfo/rb-general/&quot;&gt;our mailing list&lt;/a&gt; this month:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://jstarr.science/&quot;&gt;Jonathan Starr&lt;/a&gt; from the &lt;a href=&quot;https://iosp.science/&quot;&gt;Institute of Open Science Practices&lt;/a&gt; (IOSP) &lt;a href=&quot;https://lists.reproducible-builds.org/pipermail/rb-general/2026-September/004150.html&quot;&gt;posted with an announcement&lt;/a&gt; of its upcoming 2026 workshop series in Leiden in the Netherlands. This free-to-attend event aims to build a participant-owned data storage consortium, allowing community members to publish datasets, code and knowledge objects alongside algorithms designed to evaluate trust and value. The event features a dedicated &lt;a href=&quot;https://www.iosp.science/submit-community-session&quot;&gt;Community Track&lt;/a&gt; for talks and discussions, a tool showcase and an opening session on &lt;a href=&quot;https://www.iosp.science/resilient-data-signup&quot;&gt;resilient data storage&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Following up on IRC discussions regarding profile-guided optimization (PGO) on build servers, &lt;em&gt;kpcyrd&lt;/em&gt; created a &lt;a href=&quot;https://github.com/kpcyrd/pgo-hashmap-unreproducible&quot;&gt;demonstration repository&lt;/a&gt; showing how PGO profiling can introduce non-determinism into output binaries. The demo highlights how runtime randomness (specifically, the randomised keys used in HashMaps to prevent denial-of-service attacks) causes varying bucket collision rates during test runs. These structural variances alter execution weights on underlying code branches, prompting the compiler to generate differing final assembly output for builds that would otherwise be perfectly reproducible if PGO was disabled. Rather than abandoning PGO performance gains, &lt;a href=&quot;https://lists.reproducible-builds.org/pipermail/rb-general/2026-September/004153.html&quot;&gt;kpcyrd suggested treating generated profiling data as a documented build input&lt;/a&gt; or recorded environment artifact (similar to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.buildinfo&lt;/code&gt; files), rather than regenerating profiles dynamically on the fly during build execution.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;An autonomous AI agent (!), &lt;a href=&quot;https://lists.reproducible-builds.org/pipermail/rb-general/2026-September/004159.html&quot;&gt;posted&lt;/a&gt; a &lt;a href=&quot;https://f005.backblazeb2.com/file/kai-agi-competitive-brief-2026/reproducibility/libmilter-9023/witness.md&quot;&gt;controlled build result and reproducer&lt;/a&gt; demonstrating that pre-creating an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;obj&lt;/code&gt; directory in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libmilter&lt;/code&gt; source trees prevents kernel-release path leaks (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;obj.Linux.&amp;lt;release&amp;gt;.x86_64&lt;/code&gt;) into debugging symbols. &lt;a href=&quot;https://lists.reproducible-builds.org/pipermail/rb-general/2026-September/004160.html&quot;&gt;&lt;em&gt;kpcyrd&lt;/em&gt; followed up with a helpful reply&lt;/a&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://lists.reproducible-builds.org/pipermail/rb-general/2026-September/004171.html&quot;&gt;Alexander Sosedkin inquired on the mailing list&lt;/a&gt; about the preferred approach for &lt;a href=&quot;https://translationproject.org/&quot;&gt;sourcing pinned translation files&lt;/a&gt; to create reproducible &lt;a href=&quot;https://www.gnutls.org/&quot;&gt;GnuTLS&lt;/a&gt; release tarballs, asking whether external hosting should provide versioned downloads, or if projects ought to use Git submodules, dedicated side-repositories or some other mechanism.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;tool-and-documentation-development&quot;&gt;Tool and documentation development&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://diffoscope.org/&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-09/diffoscope.png#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://diffoscope.org&quot;&gt;&lt;strong&gt;diffoscope&lt;/strong&gt;&lt;/a&gt; is our in-depth and content-aware diff utility that can locate and diagnose reproducibility issues. This month, Chris Lamb made a number of changes, including preparing and uploading versions &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;330&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;331&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;332&lt;/code&gt; to Debian. In particular, Chris committed support for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;radare2&lt;/code&gt; versions greater than 5.9.0 [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/diffoscope/commit/ba64aec7&quot;&gt;…&lt;/a&gt;] based on input from Guillaume Girol [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/diffoscope/commit/b2c830f4&quot;&gt;…&lt;/a&gt;], and committed support for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.nar&lt;/code&gt; files via Guix. [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/diffoscope/commit/df30572e&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/diffoscope/commit/8237da72&quot;&gt;…&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;Chris later modified &lt;em&gt;diffoscope&lt;/em&gt; to not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Build-Depend&lt;/code&gt; on the Debian package of GNU Guix, as its status in the Debian bug tracking system would transitively render &lt;em&gt;diffoscope&lt;/em&gt; as being overly buggy for the next stable release [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/diffoscope/commit/c126df62&quot;&gt;…&lt;/a&gt;]. Similarly, he adjusted the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Build-Depend&lt;/code&gt;s on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apksigcopier&lt;/code&gt; package as it has been removed from Debian &lt;em&gt;testing&lt;/em&gt; [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/diffoscope/commit/436bc40f&quot;&gt;…&lt;/a&gt;] and, finally, he updated a number of copyright years [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/diffoscope/commit/45ae6845&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/diffoscope/commit/b4f193dc&quot;&gt;…&lt;/a&gt;].&lt;/p&gt;

&lt;p&gt;Vagrant Cascadian &lt;a href=&quot;https://codeberg.org/guix/guix/commit/dc17b782dba1e12556d2260626fc62c33d6dc30b&quot;&gt;updated &lt;em&gt;diffoscope&lt;/em&gt; in GNU Guix to version &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;332&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reprotest&quot;&gt;&lt;strong&gt;reprotest&lt;/strong&gt;&lt;/a&gt; is our tool for building the same source code twice in different environments and then checking the binaries produced by each build for any differences. This month, &lt;em&gt;reprotest&lt;/em&gt; version &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0.7.33&lt;/code&gt; was uploaded to Debian by Holger Levsen with the following changes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Sergei Tachenov fixed the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fileordering&lt;/code&gt; test on all filesystems, including the likes of &lt;a href=&quot;https://en.wikipedia.org/wiki/ZFS&quot;&gt;ZFS&lt;/a&gt;, which could return a different order across two builds due to build being done in a different directory [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reprotest/commit/8e4beb6&quot;&gt;…&lt;/a&gt;].&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Holger Levsen bumped the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Standards-Version&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;4.7.4&lt;/code&gt;, reflected that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Priority: optional&lt;/code&gt; is the default now [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reprotest/commit/8053f66&quot;&gt;…&lt;/a&gt;], fixed the old &lt;a href=&quot;https://www.fsf.org/&quot;&gt;Free Software Foundation&lt;/a&gt; address [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reprotest/commit/0f77715&quot;&gt;…&lt;/a&gt;] and bumped the &lt;em&gt;debhelper&lt;/em&gt; ‘compat’ level to 14 after confirming there are only desired changes [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reprotest/commit/d263fdb&quot;&gt;…&lt;/a&gt;].&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Vagrant Cascadian &lt;a href=&quot;https://codeberg.org/guix/guix/commit/2d084d74f6649f3cb0bbb27f0b65e40b94c6765d&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;updated *reprotest* to version 0.7.33&lt;/code&gt;&lt;/a&gt; in GNU Guix.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/kpcyrd/rebuilderd&quot;&gt;&lt;strong&gt;rebuilderd&lt;/strong&gt;&lt;/a&gt;, our server designed monitor the official package repositories of Linux distributions and attempt to reproduce the observed results there; it powers, amongst other things, &lt;a href=&quot;https://reproduce.debian.net/&quot;&gt;&lt;em&gt;reproduce.debian.net&lt;/em&gt;&lt;/a&gt;. This month, Bernhard M. Wiedemann &lt;a href=&quot;https://github.com/kpcyrd/rebuilderd/pull/263&quot;&gt;submitted a pull request to rebuilderd&lt;/a&gt; that refactors RPM repository metadata handling. The change extracts &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpm-md&lt;/code&gt; parsing out of the Fedora-specific scheduler module and into a shared one.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://reproducible-builds.org/&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://reproducible-builds.org/images/reports/2026-09/website.png#right&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lastly, there were a number of improvements made to &lt;a href=&quot;https://reproducible-builds.org/&quot;&gt;&lt;strong&gt;our website&lt;/strong&gt;&lt;/a&gt; this month as well. For example:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Chris Lamb:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;Added a note re. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TZ=UTC&lt;/code&gt; vs. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TZ=UTC0&lt;/code&gt; to the &lt;a href=&quot;https://reproducible-builds.org/docs/timezones/&quot;&gt;&lt;em&gt;Timezones&lt;/em&gt;&lt;/a&gt; page. [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/adf38b87&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/ae8f4da5&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/0ca7cc78&quot;&gt;…&lt;/a&gt;]&lt;/li&gt;
      &lt;li&gt;Make a bunch of cosmetic updates to &lt;a href=&quot;https://reproducible-builds.org/news/2026/09/15/supporter-spotlight-jochen-sprickerhof/&quot;&gt;Jochen’s supporter spotlight&lt;/a&gt;. [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/534e5276&quot;&gt;…&lt;/a&gt;]&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Holger Levsen made a very large number of changes to the &lt;a href=&quot;https://reproducible-builds.org/events/gothenburg2026/&quot;&gt;Gothenburg summit page&lt;/a&gt;. [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/5fefa023&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/7aba87f6&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/3598d1c9&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/4600ab6d&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/1529fc99&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/bf569952&quot;&gt;…&lt;/a&gt;]&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Jochen Sprickerhof wrote and published &lt;a href=&quot;https://reproducible-builds.org/news/2026/09/15/supporter-spotlight-jochen-sprickerhof/&quot;&gt;another supporter spotlight&lt;/a&gt;. [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/af7a55b8&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/7e141852&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/3e3e7993&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/eacb7f79&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/5ca55013&quot;&gt;…&lt;/a&gt;]&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mattia Rizzolo:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;Made a number of changes to the &lt;a href=&quot;https://reproducible-builds.org/events/gothenburg2026/&quot;&gt;Gothenburg summit page&lt;/a&gt;. [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/57c81cb9&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/ea564cf5&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/75146298&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/411d3e8e&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/ea3eca50&quot;&gt;…&lt;/a&gt;]&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;Add and publish the new &lt;a href=&quot;https://reproducible-builds.org/conduct/&quot;&gt;Code of Conduct&lt;/a&gt;. [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/df0cb783&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/ca36d617&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/86434786&quot;&gt;…&lt;/a&gt;]&lt;/li&gt;
      &lt;li&gt;Update translation POs. [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/e65814d4&quot;&gt;…&lt;/a&gt;]&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;kpcyrd&lt;/em&gt; also made a number of changes to the &lt;a href=&quot;https://reproducible-builds.org/events/gothenburg2026/&quot;&gt;Gothenburg summit page&lt;/a&gt;. [&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/b02b2de5&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/77169f50&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/b819f72c&quot;&gt;…&lt;/a&gt;][&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reproducible-website/commit/5c47ecc4&quot;&gt;…&lt;/a&gt;]&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h3 id=&quot;patches&quot;&gt;Patches&lt;/h3&gt;

&lt;p&gt;The Reproducible Builds project detects, dissects and attempts to fix as many currently-unreproducible packages as possible. We endeavour to send all of our patches upstream where applicable or possible. This month, we wrote a large number of such patches, including:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Bernhard M. Wiedemann:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1380315&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apache-arrow&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/wannesm/dtaidistance/pull/230&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dtaidistance&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://src.opensuse.org/gcc/gcc33/pulls/1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc 3.3&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://src.opensuse.org/gcc/gcc48/pulls/1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc 4.8&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://src.opensuse.org/gcc/gcc7/pulls/1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc 7&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1375983&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;golang-github-prometheus-prometheus&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1375891&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gromacs&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/michalmuskala/jason/pull/206&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jason&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1379485&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lkl&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/ltfat/ltfat/pull/206&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ltfat&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://src.opensuse.org/chromium/memory-constraints/pulls/5&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;memory-constraints&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1380021&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MozillaFirefox&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/openSUSE/obs-build/pull/1166&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;obs-build&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/openSUSE/obs-build/pull/1173&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;obs-build&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://github.com/erlang/otp/pull/11609&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;otp&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1375963&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pythia&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1379338&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-autobahn&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1376924&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-django-cacheops&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1375796&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-hdf5plugin&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1376580&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-mypy&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1375800&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-slycot&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://qt-project.atlassian.net/browse/QTBUG-150796&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qt6-base&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1375466&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpm&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1378324&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rust1.98&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1378149&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rusty_v8&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://gitlab.inria.fr/scotch/scotch/-/commit/f861be2c24b123355a64c2fe3c55f4f2f1355490&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scotch&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://build.opensuse.org/request/show/1375866&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vlang&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Chris Lamb:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1146687&quot;&gt;#1146687&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/lektor&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lektor&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147673&quot;&gt;#1147673&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/golang-forgejo-xorm-xorm&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;golang-forgejo-xorm-xorm&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147674&quot;&gt;#1147674&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/python-vermin&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-vermin&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1148657&quot;&gt;#1148657&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/python-eventlet&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-eventlet&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1148658&quot;&gt;#1148658&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/golang-github-miekg-pkcs11&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;golang-github-miekg-pkcs11&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1148660&quot;&gt;#1148660&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/python-prov&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-prov&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1148973&quot;&gt;#1148973&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/lemonade&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lemonade&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1148977&quot;&gt;#1148977&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/yuzu&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yuzu&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1148979&quot;&gt;#1148979&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/python-mne&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;python-mne&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Jochen Sprickerhof:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147645&quot;&gt;#1147645&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/bitshuffle&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bitshuffle&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Tianyu Chen:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147760&quot;&gt;#1147760&lt;/a&gt; filed against &lt;a href=&quot;https://tracker.debian.org/pkg/nss&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nss&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Klemen Ferjancic:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;Debian:&lt;/p&gt;

        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;https://salsa.debian.org/games-team/ace-of-penguins/-/merge_requests/2&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ace-of-penguins&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;https://salsa.debian.org/fonts-team/fonts-meera-inimai/-/merge_requests/1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fonts-meera-inimai&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;https://salsa.debian.org/fonts-team/fonts-smc-keraleeyam/-/merge_requests/1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fonts-smc-keraleeyam&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;https://salsa.debian.org/games-team/nsnake/-/merge_requests/1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nsnake&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;https://salsa.debian.org/reproducible-builds/reprotest/-/commit/8e4beb6510b4db4f54a1fad4cac0a16ea5ba5119&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reprotest&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Upstream:&lt;/p&gt;

        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;https://github.com/doxygen/doxygen/pull/12371&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;doxygen&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;https://github.com/fontforge/fontforge/pull/5912&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fontforge&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;https://savannah.gnu.org/bugs/?68717&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;freefont&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;https://review.opendev.org/c/openstack/oslo.config/+/1009124&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openstack oslo.config&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;https://review.opendev.org/c/openstack/watcher/+/1009127&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openstack watcher&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;https://sourceware.org/bugzilla/show_bug.cgi?id=34680&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemtap&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;https://github.com/util-linux/util-linux/pull/4652&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;util-linux&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;https://www.yudit.org/download/patch-src/yudit-3.1.0.patch6.txt&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yudit&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Vagrant Cascadian:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1140567#25&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;libecoli&lt;/code&gt;&lt;/a&gt; [&lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1140567#30&quot;&gt;…&lt;/a&gt;]&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=985335#15&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cdebootstrap&lt;/code&gt;&lt;/a&gt; [&lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=985335#30&quot;&gt;…&lt;/a&gt;]&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vagrant Cascadian also performed a number of &lt;a href=&quot;https://wiki.debian.org/NonMaintainerUpload&quot;&gt;Non-Maintainer Uploads&lt;/a&gt; (NMUs) and &lt;a href=&quot;https://www.debian.org/doc/manuals/developers-reference/pkgs.en.html#nmus-vs-qa-uploads&quot;&gt;Quality Assurance (QA) uploads&lt;/a&gt; in Debian for several packages with outstanding reproducibility issues. These included &lt;a href=&quot;https://tracker.debian.org/news/1802211/accepted-moltemplate-2225-11-source-into-unstable/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;molttemplate&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://tracker.debian.org/news/1801934/accepted-buddy-24dfsg-3-source-into-unstable/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buddy&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://tracker.debian.org/news/1801932/accepted-xfonts-nexus-002-20-source-into-unstable/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xfonts-nexus&lt;/code&gt;&lt;/a&gt;, &lt;a href=&quot;https://tracker.debian.org/news/1802209/accepted-fte-0502b6-20110708-9-source-into-unstable/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fte&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://tracker.debian.org/news/1802613/accepted-lifelines-3061-8-source-into-unstable/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lifelines&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At the time of this writing, that leaves &lt;a href=&quot;https://udd.debian.org/bugs/?release=forky_and_sid&amp;amp;patch=only&amp;amp;pending=ign&amp;amp;merged=ign&amp;amp;done=ign&amp;amp;fnewerval=365&amp;amp;flastmodval=14&amp;amp;fusertagtag=buildpath&amp;amp;fusertaguser=reproducible-builds%40lists.alioth.debian.org&amp;amp;reproducible=1&amp;amp;sortby=id&amp;amp;sorto=asc&amp;amp;format=html#results&quot;&gt;130 submitted patches&lt;/a&gt;, with only 61 outstanding submitted patches that older than a year in the Debian bug tracking system. This number is only 26 if we exclude any low-priority build path issues.&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;
&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;If you are interested in contributing to the Reproducible Builds project, please visit our &lt;a href=&quot;https://reproducible-builds.org/contribute/&quot;&gt;&lt;em&gt;Contribute&lt;/em&gt;&lt;/a&gt; page on our website. However, you can get in touch with us via:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;IRC: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#reproducible-builds&lt;/code&gt; on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;irc.oftc.net&lt;/code&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mastodon: &lt;a href=&quot;https://fosstodon.org/@reproducible_builds&quot;&gt;@reproducible_builds@fosstodon.org&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mailing list: &lt;a href=&quot;https://lists.reproducible-builds.org/listinfo/rb-general&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rb-general@lists.reproducible-builds.org&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt; </description> 
	<pubDate>Wed, 14 Oct 2026 18:34:14 +0000</pubDate>

</item> 
<item>
	<title>Russ Allbery: Review: Ties That Bond in Gretna Green</title>
	<guid>https://www.eyrie.org/~eagle/reviews/books/9798376517017.html</guid>
	<link>https://www.eyrie.org/~eagle/reviews/books/9798376517017.html</link>
     <description>  &lt;p&gt;Review: &lt;cite&gt;Ties That Bond in Gretna Green&lt;/cite&gt;, by Linzi Day&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;&lt;tr&gt;
    &lt;td&gt;Series:&lt;/td&gt;
    &lt;td&gt;Midlife Recorder #3&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Publisher:&lt;/td&gt;
    &lt;td&gt;Linzi Day&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Copyright:&lt;/td&gt;
    &lt;td&gt;February 2023&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;ISBN:&lt;/td&gt;
    &lt;td&gt;9798376517017&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Format:&lt;/td&gt;
    &lt;td&gt;Kindle&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Pages:&lt;/td&gt;
    &lt;td&gt;616&lt;/td&gt;
  &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;
&lt;cite&gt;Ties That Bond in Gretna Green&lt;/cite&gt; is a self-published fantasy novel
and the third book in the Midlife Recorder series. As with the previous
book, it picks up almost immediately after &lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/9798360228431.html&quot;&gt;&lt;cite&gt;Painting the Blues in Gretna Green&lt;/cite&gt;&lt;/a&gt;. Day calls the genre
paranormal women&#39;s fantasy, and that sounds about right to me.
&lt;/p&gt;

&lt;p&gt;
There is an intervening short story that you can get by
&lt;a href=&quot;https://linziday.com/newsletter/&quot;&gt;joining Day&#39;s mailing list&lt;/a&gt; (along
with an epilogue to the first book and to this book). I don&#39;t think it&#39;s
that important, but there are frequent references to it at the start of
this novel that become somewhat annoying if you haven&#39;t read it.
&lt;/p&gt;

&lt;p&gt;
Valentine&#39;s Day is fast approaching. This the busiest day of the year for
the part of the Recorder&#39;s job that Niki already knew how to do: marrying
people. She performed marriage ceremonies in her previous job before her
inheritance, and she loved that work despite her awful boss. Performing
marriages in the Gateway sounds even more rewarding, but the sheer number
of couples and the political complications from the first two books create
logistical problems she has to solve first.
&lt;/p&gt;

&lt;p&gt;
Also, the remaining member of her staff held over from her grandmother&#39;s
time has returned from vacation to discover that Niki has upended most of
what she thought she knew about the job. Time for Niki to apply what she
learned from the change management training her old boss forced her to
attend and then ignored! (If you just groaned, rest assured that Day
somehow makes this work, although she clearly has a higher opinion of
corporate training than I do.)
&lt;/p&gt;

&lt;p&gt;
This plot was more to my taste than &lt;cite&gt;Painting the Blues&lt;/cite&gt;, mostly
because Niki seemed on top of the problems and didn&#39;t postpone looking at
them for half the book. There is more of the management competence porn
that readers have come to expect of the series, a few more revelations
about Niki&#39;s magic, more mysterious manifestations and the first mention
of a prophecy, and a few political developments. As always, the pacing is
exceptional. These books grab me and pull me along, page after page, often
robbing me of sleep because I find them nearly impossible to put down.
&lt;/p&gt;

&lt;p&gt;
&lt;cite&gt;Ties that Bond&lt;/cite&gt; (and to some extent the last book) looked like it
was going to introduce a romantic subplot, and I was preparing to be
annoyed by it because I did not like the man in the subplot at all. I
won&#39;t spoil how it works out in this book, but I will say that Niki
surprised me and showed more sense than I thought the author was
telegraphing. This is not the first time that Day has surprised me with
what I thought was foreshadowing that did not turn out how I expected,
usually for the better. If she can keep that up, it&#39;s a nice effect (if a
bit unbalancing) and adds to my desire to read just one more chapter.
&lt;/p&gt;

&lt;p&gt;
The way the world-building of these books is structured continues to
intrigue me. Day gets away with some problems that I think would be more
noticeable in other books thanks to the excellent pacing (no time to ponder
the world-building, we&#39;re on to the next crisis!) and the tight
third-person perspective. Niki is not a detail person, to say the least,
but she does keep returning to bits of world-building and poking at them a
bit harder, which gives Day repeated opportunities to shore up ideas that
felt shaky and dubious at first glance. Still, this is not a book that
prizes deep logical consistency or full exploration of the ramifications
of a bit of magic. You have to be willing to go along with the ride and
not think too hard.
&lt;/p&gt;

&lt;p&gt;
For example, Niki can see bonds between couples and judge their strength.
This is apparently a long-standing power of the Recorder&#39;s line (she was
able to do that before she became the Recorder), and part of her
responsibility in these weddings is to check the bonds of the couples.
This leads to some well-handled scenes where she diagnoses a problem or
resolves a conflict because she can magically see the true relationship
structure.
&lt;/p&gt;

&lt;p&gt;
Everyone in the book just takes this power in stride. This is wild to me!
This ability would completely upend half of society if you fully worked
out its ramifications and could find people other than Niki with the same
ability. Even if one assumes that a bond only forms over time and can&#39;t be
sensed in the early stages of a relationship (something the book never
establishes), can you imagine the implications of having an infallible
oracle that says at a glance whether a marriage will work (permanently,
the book strongly implies)? The implications for how to structure
marriage, for family planning, for psychology and psychiatry, for how to
structure dating, even for living arrangements and housing markets? This
is not a small world-building detail, and yet it&#39;s treated more like part
of Niki&#39;s characterization than like a foundation of society.
&lt;/p&gt;

&lt;p&gt;
I think some of this all-vibes world-building may come from the general
new-age feel to how magic works. Day makes a grab-bag of random magic
canonical in this world: psychic lie detecting abilities, auras, chakras,
premonitions, and other bits of the sort of spiritualism that tends to be
heavily marketed to middle-class women. I have that niggling feeling that
one sometimes gets in SF that a lot of this is in the world-building
because the author believes it&#39;s partly real (see, for instance, psychic
powers and the Dean drive in 1960s science fiction). If one believes that
psychic powers and various bits of mysticism are true in our world, one
has already developed the rationalization mechanisms to explain away their
almost total lack of influence or impact on how the world is structured.
If one then introduces them into a true fantasy world, one may not notice
how many implications that should have for how society is structured,
since one is used to believing magic exists but has no significant
implications.
&lt;/p&gt;

&lt;p&gt;
I could be entirely wrong about this analysis, and maybe it&#39;s a bit unfair
to Day. I should also be clear that this is not a complaint, just a point
of fascination to me when I think back over one of these books after I
finished it. There is a glut of fantasy out there that&#39;s constructed like
an engineering problem or that goes deep into politics or social theory,
usually written by people with strong opinions but not a lot of training
in real sociology. One of the joys of self-published books is that you
occasionally get something that assembles genre conventions in a way that
feels odd and delightfully strange. What if, in addition to dimensional
gates and overwhelming protean power invested in a true heir, all the
magic sold by the local Tarot and crystal store was also true? Sure, why
not! If the pacing is good and the story is grabby, it works for me.
&lt;/p&gt;

&lt;p&gt;
It does seem worth attaching a warning for the folks who need scientific
reproducibility and explored implications in their world-building, though.
If you&#39;re the sort of reader who is bothered by political boundaries and
economic systems that match our world despite the existence of magic, this
series may cause you problems.
&lt;/p&gt;

&lt;p&gt;
This continues to be a grabby, highly entertaining story of a woman who
finally gets to run her own small business the way that she always thought
the business should be run after years of working for an awful manager,
except that her business is total magical power over an interchange point
between dimensions, she&#39;s the chosen one, and the setting is a high
fantasy world with prophecies and gods. If that sounds appealing, don&#39;t
start here, but I highly recommend giving &lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/9798837010774.html&quot;&gt;&lt;cite&gt;Midlife in Gretna Green&lt;/cite&gt;&lt;/a&gt; a try. The series seems to be holding up.
&lt;/p&gt;

&lt;p&gt;
Followed by a short story epilogue available by joining Day&#39;s mailing
list, an optional novella (maybe novelette) published in &lt;cite&gt;Spilling
the Tea in Gretna Green&lt;/cite&gt;, and then &lt;cite&gt;Seeing Red in Gretna Green&lt;/cite&gt;.
&lt;/p&gt;

&lt;p&gt;Rating: 7 out of 10&lt;/p&gt; </description> 
	<pubDate>Wed, 14 Oct 2026 03:50:00 +0000</pubDate>

</item> 
<item>
	<title>Freexian Collaborators: Debian Contributions: New experimental backend for autopkgtest using pconr, DebConf site visit and more! (by Anupa Ann Joseph)</title>
	<guid>https://www.freexian.com/blog/debian-contributions-09-2026/</guid>
	<link>https://www.freexian.com/blog/debian-contributions-09-2026/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/freexian.png&quot; width=&quot;215&quot; height=&quot;101&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;h1 id=&quot;debian-contributions-2026-09&quot;&gt;Debian Contributions: 2026-09&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://www.freexian.com/about/debian-contributions/&quot;&gt;Contributing to Debian&lt;/a&gt;
is part of &lt;a href=&quot;https://www.freexian.com/about/&quot;&gt;Freexian’s mission&lt;/a&gt;. This article
covers the latest achievements of Freexian and their collaborators. All of this
is made possible by organizations subscribing to our
&lt;a href=&quot;https://www.freexian.com/lts/&quot;&gt;Long Term Support contracts&lt;/a&gt; and
&lt;a href=&quot;https://www.freexian.com/services/&quot;&gt;consulting services&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;debconf-site-visit-by-stefano-rivera&quot;&gt;DebConf site visit, by Stefano Rivera&lt;/h2&gt;
&lt;p&gt;In preparation for &lt;a href=&quot;https://27.debconf.org/&quot;&gt;DebConf 27&lt;/a&gt;, Stefano Rivera,
Nattie Mayer-Hutchings, and Jongmin Kim from the DebConf Committee visited
Asahikawa Japan. A contingent of the local team gathered to tour the venues
with us, discuss plans, and meet the local organizations assisting the event.
We held a press conference at the city hall that got
&lt;a href=&quot;https://www.nikkei.com/article/DGXZQOFC080YC0Y6A900C2000000/&quot;&gt;some coverage&lt;/a&gt;.
A few potential day-trip options were explored.
&lt;a href=&quot;https://people.debian.org/~stefanor/dc27-site-visit/&quot;&gt;Photos&lt;/a&gt; from the site visit.&lt;/p&gt;
&lt;h2 id=&quot;autopkgtest-virt-pconr-by-helmut-grohne&quot;&gt;autopkgtest-virt-pconr, by Helmut Grohne&lt;/h2&gt;
&lt;p&gt;Following the creation of the &lt;a href=&quot;https://git.subdivi.de/~helmut/pconr.git/&quot;&gt;pconr&lt;/a&gt;
module that provides a basis for
&lt;a href=&quot;https://git.subdivi.de/~helmut/pconr.git/tree/examples/unschroot_proc.py&quot;&gt;unschroot&lt;/a&gt;
and a more secure &lt;a href=&quot;https://git.subdivi.de/~helmut/pconr.git/tree/examples/mmdebstrap_container.py&quot;&gt;containment for mmdebstrap&lt;/a&gt;,
an experimental autopkgtest backend &lt;a href=&quot;https://git.subdivi.de/~helmut/pconr.git/tree/examples/autopkgtest-virt-pconr.py&quot;&gt;autopkgtest-virt-pconr&lt;/a&gt;
is now available. It fits a spot between autopkgtest-virt-unshare and more fully
fledged containers as it does not require much infrastructure like setting up
incus or lxc but still provides a containment running an initsystem. Due to the
use of &lt;a href=&quot;https://erofs.docs.kernel.org/en/latest/&quot;&gt;erofs&lt;/a&gt; as base image format,
it boots and reverts quickly. This development also required fixing concurrency
issues in &lt;a href=&quot;https://github.com/helmutg/asyncvarlink&quot;&gt;asyncvarlink&lt;/a&gt; and even shed
light on a matching &lt;a href=&quot;https://github.com/systemd/systemd/pull/43867&quot;&gt;bug in systemd&lt;/a&gt;
that was promptly fixed upstream.&lt;/p&gt;
&lt;h2 id=&quot;miscellaneous-contributions&quot;&gt;Miscellaneous contributions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Carles reviewed and submitted six Catalan po-debconf translations using
&lt;a href=&quot;https://salsa.debian.org/carlespina/po-debconf-manager&quot;&gt;po-debconf-manager&lt;/a&gt;.
Improved po-debconf-manager’s workflow for updating translations.&lt;/li&gt;
&lt;li&gt;Carles reviewed, translated or updated &lt;a href=&quot;https://salsa.debian.org/webmaster-team/webwml&quot;&gt;webwml&lt;/a&gt;
Catalan translations for security and CD pages. He also fixed issues that
prevented building webwml, deleted orphaned translation pages, etc. and
experimented with a more global HTML tidying up experiment.&lt;/li&gt;
&lt;li&gt;Carles refactored &lt;a href=&quot;https://salsa.debian.org/carlespina/check-relations&quot;&gt;check-relations&lt;/a&gt;
adding capacity to ignore concrete from_package -&amp;gt; to_package specific relations
and more flexibility around ignores. Detects unused ignore rules as well.&lt;/li&gt;
&lt;li&gt;Carles improved some Wiki pages (&lt;a href=&quot;https://wiki.debian.org/LibreOffice&quot;&gt;LibreOffice&lt;/a&gt;,
&lt;a href=&quot;https://wiki.debian.org/InstallingDebianOn/FrameWork&quot;&gt;Framework&lt;/a&gt; amongst some
other ones)&lt;/li&gt;
&lt;li&gt;Thorsten did an hplip upload to replace an expired certificate of HP. This
certificate is used to sign new upstream releases and modules that can be
downloaded later. Afterwards work on a new upstream version started.&lt;/li&gt;
&lt;li&gt;Thorsten also struggles with autopkgtest problems of the new upstream version
of cups. Work is still ongoing.&lt;/li&gt;
&lt;li&gt;Antonio loaded the video recording URLs into the
&lt;a href=&quot;http://ch2026.mini.debconf.org&quot;&gt;MiniDebConf Winterthur 2026&lt;/a&gt; website, and
deployed the website for &lt;a href=&quot;https://curitiba2027.mini.debconf.org/&quot;&gt;MiniDebConf Curitiba 2027&lt;/a&gt;
(still very early work in progress at this point).&lt;/li&gt;
&lt;li&gt;Antonio uploaded &lt;a href=&quot;https://tracker.debian.org/news/1794618/accepted-debci-43-source-into-unstable/&quot;&gt;debci 4.3&lt;/a&gt;,
&lt;a href=&quot;https://tracker.debian.org/news/1800203/accepted-autodep8-031-source-into-unstable/&quot;&gt;autodep8 0.31&lt;/a&gt;,
&lt;a href=&quot;https://tracker.debian.org/news/1804418/accepted-gem2deb-2210-source-into-unstable/&quot;&gt;gem2deb 2.2.10&lt;/a&gt;,
&lt;a href=&quot;https://tracker.debian.org/news/1804405/accepted-ruby-sass-374-7-source-into-unstable/&quot;&gt;ruby-sass 3.7.4-7&lt;/a&gt;,
init-system-helpers &lt;a href=&quot;https://tracker.debian.org/news/1800206/accepted-init-system-helpers-169nmu2-source-into-unstable/&quot;&gt;1.69+nmu2&lt;/a&gt;
and &lt;a href=&quot;https://tracker.debian.org/news/1802159/accepted-init-system-helpers-169nmu3-source-into-unstable/&quot;&gt;1.69+nmu3&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Antonio worked on several topics around Debian CI maintenance, reliability and
performance.&lt;/li&gt;
&lt;li&gt;Stefano updated the autopkgtests for cPython packages in Debian to support
setuptools 80.&lt;/li&gt;
&lt;li&gt;Stefano uploaded pypy 8.&lt;/li&gt;
&lt;li&gt;Stefano helped to get DebConf 26 reimbursement claims processed, and worked on
some of the resulting issues in debian-reimbursements.&lt;/li&gt;
&lt;li&gt;Emilio managed various transitions.&lt;/li&gt;
&lt;li&gt;Emilio worked on the rustc-web/trixie bootstrap for armel, using the rustc
1.95 version from trixie-backports. This will be needed by the upcoming clamav
security updates.&lt;/li&gt;
&lt;li&gt;Helmut sent patches for 11 cross build failures.&lt;/li&gt;
&lt;li&gt;Helmut introduced a new build profile to libcap-ng to keep architecture cross
bootstrap working.&lt;/li&gt;
&lt;li&gt;Helmut uploaded &lt;a href=&quot;https://tracker.debian.org/news/1807523/debvm-055-migrated-to-testing/&quot;&gt;debvm_0.5.5&lt;/a&gt;
introducing support for Hurd thanks to a lot of work by Johannes Schauer Marin
Rodrigues.&lt;/li&gt;
&lt;li&gt;Colin worked with OpenSSH upstream to &lt;a href=&quot;https://bugzilla.mindrot.org/show_bug.cgi?id=3996&quot;&gt;reduce the linkage of /usr/sbin/sshd&lt;/a&gt;,
hardening it a little further.&lt;/li&gt;
&lt;li&gt;Colin upgraded to new security releases of groff and parted.&lt;/li&gt;
&lt;li&gt;Colin upgraded 50 Python packages to new upstream versions, and fixed over 40
RC bugs in the Python team.&lt;/li&gt;
&lt;li&gt;Santiago continued mentoring Aryan Karamtoth with the GSoC project about
introducing livepatching support for linux. This mentoring is done in
collaboration with Emmanuel Arias. In particular, Santiago explored different
requirements for providing binary modules for the same kernel packages used by
Debian, that require a matching version number.&lt;/li&gt;
&lt;li&gt;Anupa joined Jean-Pierre Giraud to prepare the files for point release
announcement for Debian 13.7.&lt;/li&gt;
&lt;/ul&gt; </description> 
	<pubDate>Wed, 14 Oct 2026 00:00:00 +0000</pubDate>

</item> 
<item>
	<title>Dirk Eddelbuettel: RQuantLib 0.4.29 on CRAN: New QuantLib, Plus Small Fixes</title>
	<guid>http://dirk.eddelbuettel.com/blog/2026/10/13#rquantlib_0.4.29</guid>
	<link>http://dirk.eddelbuettel.com/blog/2026/10/13#rquantlib_0.4.29</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dirk.png&quot; width=&quot;65&quot; height=&quot;90&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;A new release 0.4.29 of &lt;a href=&quot;https://dirk.eddelbuettel.com/code/rquantlib.html&quot;&gt;RQuantLib&lt;/a&gt;
arrived on &lt;a href=&quot;https://cran.r-project.org&quot;&gt;CRAN&lt;/a&gt; this evening,
had already been built for &lt;a href=&quot;https://eddelbuettel.github.io/r2u/&quot;&gt;r2u&lt;/a&gt; as well as on &lt;a href=&quot;https://eddelbuettel.r-universe.dev/RQuantLib&quot;&gt;r-universe&lt;/a&gt; and
has just been uploaded to &lt;a href=&quot;https://www.debian.org&quot;&gt;Debian&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.quantlib.org&quot;&gt;QuantLib&lt;/a&gt; is a rather
comprehensice &lt;em&gt;free/open-source&lt;/em&gt; library for quantitative
finance. &lt;a href=&quot;https://dirk.eddelbuettel.com/code/rquantlib.html&quot;&gt;RQuantLib&lt;/a&gt;
connects (some parts of) it to the R environment and language, and has
been part of &lt;a href=&quot;https://cran.r-project.org&quot;&gt;CRAN&lt;/a&gt; for
twenty-three years (!!) as it was one of the first packages I uploaded
to &lt;a href=&quot;https://cran.r-project.org&quot;&gt;CRAN&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This release of &lt;a href=&quot;https://dirk.eddelbuettel.com/code/rquantlib.html&quot;&gt;RQuantLib&lt;/a&gt;
brings two new calendars (Malaysia, Philippines), updates to a number of
other calendars as well to other files, and two deprecations we are
reflecting in this release. It also benefits from a number of careful
and attentive pull requests by &lt;a href=&quot;https://github.com/m-muecke&quot;&gt;Maximilian Muecke&lt;/a&gt; cleaning up an
(astonishing !!) number of likely rather old little bugs. Full details
from the NEWS file follow as usual.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h4 id=&quot;changes-in-rquantlib-version-0.4.29-2026-10-13&quot;&gt;Changes in &lt;span class=&quot;pkg&quot;&gt;RQuantLib&lt;/span&gt; version 0.4.29 (2026-10-13)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Configure check for outdated QuantLib version updated,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adjust two instantiations on macOS x86_64 with old
compilers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Correct Euribor2W and Euribor3W tenors setters (Maximilian Muecke
in &lt;a href=&quot;https://github.com/eddelbuettel/rquantlib/pull/196&quot;&gt;#196&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Accect Euribor1W as alias for EuriborSW tenor (Maximilian Muecke
in &lt;a href=&quot;https://github.com/eddelbuettel/rquantlib/pull/197&quot;&gt;#197&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Correct default handling of the payFixed parameter (Maximilian
Muecke in &lt;a href=&quot;https://github.com/eddelbuettel/rquantlib/pull/198&quot;&gt;#198&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assign missing S3 class to American option implied volatitly
return (Maximilian Muecke in &lt;a href=&quot;https://github.com/eddelbuettel/rquantlib/pull/199&quot;&gt;#199&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Correct spelling in manual pages and R code (Maximilian Muecke in
&lt;a href=&quot;https://github.com/eddelbuettel/rquantlib/pull/202&quot;&gt;#202&lt;/a&gt;,
&lt;a href=&quot;https://github.com/eddelbuettel/rquantlib/pull/203&quot;&gt;#203&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Support additional Polish settlements (Maximilian Muecke in &lt;a href=&quot;https://github.com/eddelbuettel/rquantlib/pull/204&quot;&gt;#204&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check for curve parameters in FittedBondCurve (Dirk in &lt;a href=&quot;https://github.com/eddelbuettel/rquantlib/pull/205&quot;&gt;#205&lt;/a&gt;
fixing &lt;a href=&quot;https://github.com/eddelbuettel/rquantlib/issues/201&quot;&gt;#201&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reflect two deprecations in QuantLib 1.44 and adjust code in two
spot (Dirk in &lt;a href=&quot;https://github.com/eddelbuettel/rquantlib/pull/206&quot;&gt;#206&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Courtesy of my &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/&quot;&gt;CRANberries&lt;/a&gt;, there
is also a &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/2026/10/13/#RQuantLib_0.4.29&quot;&gt;diffstat
report&lt;/a&gt; for the this release. As always, more detailed information is
on the &lt;a href=&quot;https://dirk.eddelbuettel.com/code/rquantlib.html&quot;&gt;RQuantLib
page&lt;/a&gt;. Questions, comments etc should go to the &lt;a href=&quot;https://groups.io/g/rquantlib&quot;&gt;rquantlib-devel mailing list&lt;/a&gt;.
Issue tickets can be filed at the &lt;a href=&quot;https://github.com/eddelbuettel/rquantlib&quot;&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot;font-size: 80%; font-style: italic;&quot;&gt;
This post by &lt;a href=&quot;https://dirk.eddelbuettel.com&quot;&gt;Dirk
Eddelbuettel&lt;/a&gt; originated on his &lt;a href=&quot;https://dirk.eddelbuettel.com/blog/&quot;&gt;Thinking inside the box&lt;/a&gt;
blog. If you like this or other open-source work I do, you can now &lt;a href=&quot;https://github.com/sponsors/eddelbuettel&quot;&gt;sponsor me at
GitHub&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt; </description> 
	<pubDate>Tue, 13 Oct 2026 21:07:00 +0000</pubDate>

</item> 
<item>
	<title>Matthew Garrett: Linux Lockdown and Hibernation (again)</title>
	<guid>https://codon.org.uk/~mjg59/blog/p/linux-lockdown-and-hibernation-again/</guid>
	<link>https://codon.org.uk/~mjg59/blog/p/linux-lockdown-and-hibernation-again/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/mjg59.png&quot; width=&quot;69&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;(This is an &lt;a class=&quot;link&quot; href=&quot;https://mjg59.dreamwidth.org/55845.html&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;updated version of an older post&lt;/a&gt; - the introduction remains the same, the technical details are different)&lt;/p&gt;
&lt;p&gt;Linux draws a distinction between code running in kernel (kernel space) and applications running in userland (user space). This is enforced at the hardware level - in x86-speak&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fn:1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, kernel space code runs in ring 0 and user space code runs in ring 3&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fn:2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;. If you’re running in ring 3 and you attempt to touch memory that’s only accessible in ring 0, the hardware will raise a fault. No matter how privileged your ring 3 code, you don’t get to touch ring 0.&lt;/p&gt;
&lt;p&gt;Kind of. In theory. Traditionally this wasn’t well enforced. At the most basic level, since root can load kernel modules, you could just build a kernel module that performed any kernel modifications you wanted and then have root load it. Technically user space code wasn’t modifying kernel space code, but the difference was pretty semantic rather than useful. But it got worse - root could also map memory ranges belonging to PCI devices&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fn:3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;, and if the device could perform DMA you could just ask the device to overwrite bits of the kernel&lt;sup id=&quot;fnref:4&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fn:4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;. Or root could modify special CPU registers (“Model Specific Registers”, or MSRs) that alter CPU behaviour via the /dev/msr interface, and compromise the kernel boundary that way.&lt;/p&gt;
&lt;p&gt;It turns out that there were a number of ways root was effectively equivalent to ring 0, and the boundary was more about reliability (ie, a process running as root that ends up misbehaving should still only be able to crash itself rather than taking down the kernel with it) than security. After all, if you were root you could just replace the on-disk kernel with a backdoored one and reboot. Going deeper, you could replace the bootloader with one that automatically injected backdoors into a legitimate kernel image. We didn’t have any way to prevent this sort of thing, so attempting to harden the root/kernel boundary wasn’t especially interesting.&lt;/p&gt;
&lt;p&gt;In 2012 Microsoft started requiring vendors ship systems with UEFI Secure Boot, a firmware feature that allowed&lt;sup id=&quot;fnref:5&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fn:5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; systems to refuse to boot anything without an appropriate signature. This not only enabled the creation of a system that drew a strong boundary between root and kernel, it arguably required one - what’s the point of restricting what the firmware will stick in ring 0 if root can just throw more code in there afterwards? What ended up as the Lockdown Linux Security Module provides the tooling for this, blocking userspace interfaces that can be used to modify the kernel and enforcing that any modules have a trusted signature.&lt;/p&gt;
&lt;p&gt;But that comes at something of a cost. Most of the features that Lockdown blocks are fairly niche, so the direct impact of having it enabled is small. Except that it also blocks hibernation&lt;sup id=&quot;fnref:6&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fn:6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;, and it turns out some people were using that. The obvious question is “what does hibernation have to do with keeping root out of kernel space”, and the answer is a little convoluted and is tied into how Linux implements hibernation. Basically, Linux saves system state into the swap partition and modifies the header to indicate that there’s a hibernation image there instead of swap. On the next boot, the kernel sees the header indicating that it’s a hibernation image, copies the contents of the swap partition back into RAM, and then jumps back into the old kernel code. What ensures that the hibernation image was actually written out by the kernel? Absolutely nothing, which means a motivated attacker with root access could turn off swap, write a hibernation image to the swap partition themselves, and then reboot. The kernel would happily resume into the attacker’s image, giving the attacker control over what gets copied back into kernel space.&lt;/p&gt;
&lt;p&gt;This is annoying, because normally when we think about attacks on swap we mitigate it by requiring an encrypted swap partition. But in this case, our attacker is root, and so already has access to the plaintext version of the swap partition. Disk encryption doesn’t save us here. We need some way to verify that the hibernation image was written out by the kernel, not by root. And thankfully we have some tools for that.&lt;/p&gt;
&lt;p&gt;Trusted Platform Modules (TPMs) are cryptographic coprocessors&lt;sup id=&quot;fnref:7&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fn:7&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; capable of doing things like generating encryption keys and then encrypting things with them. You can ask a TPM to encrypt something with a key that’s tied to that specific TPM - the OS has no access to the decryption key, and nor does any other TPM. So we can have the kernel generate an encryption key, encrypt part of the hibernation image with it, and then have the TPM encrypt it. We store the encrypted copy of the key in the hibernation image as well. On resume, the kernel reads the encrypted copy of the key, passes it to the TPM, gets the decrypted copy back and is able to verify the hibernation image.&lt;/p&gt;
&lt;p&gt;That’s great! Except root can do exactly the same thing. This tells us the hibernation image was generated on this machine, but doesn’t tell us that it was done by the kernel. We need some way to be able to differentiate between keys that were generated in kernel and ones that were generated in userland. TPMs have the concept of “localities” (effectively privilege levels) that would be perfect for this. Userland is only able to access locality 0, so the kernel could simply use locality 1 to encrypt the key. Unfortunately, localities are typically only available on systems that implement a &lt;a class=&quot;link&quot; href=&quot;https://trustedcomputinggroup.org/resource/d-rtm-architecture-specification/&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Dynamic Root of Trust Measurement&lt;/a&gt; like Intel’s TXT, and most consumer systems have no support for this. So, we need another approach.&lt;/p&gt;
&lt;p&gt;TPMs have a set of Platform Configuration Registers (PCRs), intended for keeping a record of system state. The OS isn’t able to modify the PCRs directly. Instead, the OS provides a cryptographic hash of some material to the TPM. The TPM takes the existing PCR value, appends the new hash to that, and then stores the hash of the combination in the PCR - a process called “extension”. This means that the new value of the TPM depends not only on the value of the new data, it depends on the previous value of the PCR - and, in turn, that previous value depended on its previous value, and so on. The only way to get to a specific PCR value is to either (a) break the hash algorithm, or (b) perform exactly the same sequence of writes. On system reset the PCRs go back to a known value, and the entire process starts again.&lt;/p&gt;
&lt;p&gt;Some PCRs are different. PCR 23, for example, can be reset back to its original value without resetting the system. We can make use of that. The first thing we need to do is to prevent userland from being able to reset or extend PCR 23 itself. All TPM accesses go through the kernel, so this is a simple matter of parsing the write before it’s sent to the TPM and returning an error if it’s a sensitive command that would touch PCR 23. We now know that any change in PCR 23’s state will be restricted to the kernel.&lt;/p&gt;
&lt;p&gt;When we encrypt material with the TPM, we can ask it to record the PCR state. This is given back to us as metadata accompanying the encrypted secret. Along with the metadata is an additional signature created by the TPM, which can be used to prove that the metadata is both legitimate and associated with this specific encrypted data. In our case, that means we know what the value of PCR 23 was when we encrypted the key. That means that if we simply extend PCR 23 with a known value in-kernel before encrypting our key, we can look at the value of PCR 23 in the metadata. If it matches, the key was encrypted by the kernel - userland can create its own key, but it has no way to extend PCR 23 to the appropriate value first. We now know that the key was generated by the kernel.&lt;/p&gt;
&lt;p&gt;Unfortunately it turns out that some people actually make use of PCR 23, and
restricting it to the kernel makes them sad. There are other resettable PCRs, but only in non-0 localities, so (a) we can’t reset them on most systems and (b) we’ll just find someone who uses them anyway and run into the same problem. We need a different approach.&lt;/p&gt;
&lt;p&gt;Thankfully TPMs have a small chunk of non-volatile RAM that can be used for storing things, and by “storing” I mean they can be used in a range of different ways. One of these is effectively as additional PCRs. These values can be configured such that they work the same way as PCRs, with the only way to modify them being to append a new hash to their existing value and update the new value to the hash of that merged value. We can allocate one of these for in-kernel use and reject any access from userspace, and also there are officially allocated ranges (so people shouldn’t be using random values) and the namespace is large enough anyway that w eshouldn’t collide with anyone, so we can carve one of those out and use it for this purpose.&lt;/p&gt;
&lt;p&gt;Unfortunately, though, these NV indexes aren’t included in the creation data we get when we create a key, so we need another approach. TPMs have the concept of sessions, a series of commands executed in sequence. A flag allows these sessions to be “audited”, with the TPM keeping a running track of the hash of the commands executed and the results returned. At the end of the session you can ask for a signed copy of this hash, and if you’ve kept a log of all the commands then you can verify that they match that signed hash and know that this log represents a real communication with the TPM. If we read the NV index and generate the key inside the same session, we can verify that the key we’re looking at was created while the NV index had a specific value, and if only the kernel can set that value then we know that the key was generated by the kernel.&lt;/p&gt;
&lt;p&gt;Or, well, can we? Only new kernels would impose the restriction on modifying that NV index. An attacker could boot an old kernel, generate a key there in userland, sign a hibernation image with it, and then reboot into a new kernel. The new kernel would see a valid signature with a valid NV index associated with it and have no way to know it was generated from userland rather than the kernel. We need to be able to tell the difference between kernels that implement this feature and ones that don’t, and we need to do that without being able to go back in time to change old kernel behaviour. We can extend a PCR to indicate we implement the new functionality, but so can an attacker running an old kernel.&lt;/p&gt;
&lt;p&gt;The normal approach to determining whether an event occurred in a specific phase of the boot process is to “cap” the PCRs - extend them with a known value that indicates a transition between stages of the boot process. Any events that occur before the cap event must have occurred in the previous stage of boot, and since the final PCR value depends on the order of measurements and not just the contents of those measurements, if a PCR is capped before userland runs, userland can’t fake the same PCR value afterwards. If Linux capped the PCRs before userland started running, we’d be able to place a measurement there before the cap occurred and then prove that that extension occurred before userland had the opportunity to interfere. We could simply place a statement that the kernel supported the NV index restrictions there, and we’d be fine.&lt;/p&gt;
&lt;p&gt;Unfortunately Linux doesn’t currently do this, and adding support for doing so doesn’t fix the problem - if an attacker boots a kernel that doesn’t cap a PCR, they can just cap it themselves from userland. So, we’re faced with the same problem: booting an older kernel allows the system to be placed in an identical state to the current kernel, and a fake hibernation image can be written out. Solving this requires a PCR that was being modified after kernel code was running, but before userland was started, even with existing kernels.&lt;/p&gt;
&lt;p&gt;Thankfully, there is one! PCR 5 is &lt;a class=&quot;link&quot; href=&quot;https://trustedcomputinggroup.org/wp-content/uploads/TCG_PCClient_PFP_r1p05_v23_pub.pdf&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;defined&lt;/a&gt; as containing measurements related to boot management configuration and data. One of the measurements it contains is the result of the UEFI ExitBootServices() call. ExitBootServices() is called at the transition from the UEFI boot environment to the running OS, and the kernel contains code that executes before it. So, if we measure an assertion regarding whether or not we support restricted access to NV indexes into PCR 5 before we call ExitBootServices(), this will prevent userspace from spoofing us (because userspace will only be able to extend PCR 5 after the firmware extended PCR 5 in response to ExitBootServices() being called). Obviously this depends on the firmware actually performing the PCR 5 extension when ExitBootServices() is called, but if firmware’s out of spec then I don’t think there’s any real expectation of it being secure enough for any of this to buy you anything anyway.&lt;/p&gt;
&lt;p&gt;That’s what &lt;a class=&quot;link&quot; href=&quot;https://lore.kernel.org/linux-pm/20261008132532.1155166-1-matthewg@nvidia.com/&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;this patchset&lt;/a&gt; does. Review feedback so far seems positive, although James Bottomley &lt;a class=&quot;link&quot; href=&quot;https://lore.kernel.org/linux-pm/aeedde06c51910afe5231d9f359bb8767c01b5bd.camel@HansenPartnership.com/&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;suggested&lt;/a&gt; a design improvement. My approach of using an NV index as a PCR and generating a signing key made sense as a consequence of my original approach involving PCR 23, which had been to use the key creation data and not use audit sessions at all. But the goal isn’t to use a key - it’s to prove that hibernation occurred in-kernel, and while signing is one way of doing that, there are others. His suggestion is to simply record the hash of the hibernation image into the NV index and then read that back as part of the audit session. On resume we verify the audit session log is legitimate, read the hibernation image, and compare the hash of the hibernation image against the hash in the log. If it matches, and if the PCR 5 value matches, we know the audit session happened in kernel and that the hibernation image hasn’t been modified.&lt;/p&gt;
&lt;p&gt;It still seems like we’re missing something, though. If we’re not storing a key anywhere, how do we verify the audit session? To explain this we’re going to need to go into some details about how TPM keys work in the first place. TPMs can produce a special kind of key called an Attestation Key, or AK. Attestation keys are used to sign attestation statements from the TPM, such as PCR quotes or audit logs. We need a separate key type for this in order to prove that the signature was generated as part of an attestation - normal TPM signing keys are fundamentally designed to sign arbitrary material, and so can be used by userland to sign something that looks identical to an attestation record. By being able to distinguish the types of key the TPM uses, we can prove that a signature was generated using an AK, and so know that it’s a real TPM attestation (because nothing other than the TPM can sign stuff with an AK).&lt;/p&gt;
&lt;p&gt;But even beyond this distinction, TPMs have different key types. Ordinary keys are generated using an RNG and will be unique. Primary keys are generated using a seed that is used as an input into a key derivation function. For a given TPM, using the same seed to generate the same type of primary key will always generate the same primary key&lt;sup id=&quot;fnref:8&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fn:8&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;. We can have the kernel deterministically generate an AK during suspend in order to sign the audit log, and then generate the same key again on resume to validate it. This means we don’t need any other form of trusted storage for the AK - the TPM already provides that functionality.&lt;/p&gt;
&lt;p&gt;This is all rather complicated but I’ve been thinking about this for some time now and I haven’t come up with a cleaner solution. The only real open issue is the degree to which machines actually perform the PCR 5 extension. If it turns out there’s a bunch that don’t we’ll need to come up with some alternative approach to identifying whether the kernel supports this functionality, but the design is such that that should be invisible to userspace so adding alternatives later shouldn’t be an issue. Filtering accesses to the NV index is also not super clean, and depends on there not being alternative mechanisms to get at the TPM by sending raw commands. Again, this is intended to be opaque to userland and can be improved if we come up with something better later on (such as a secure way to pass a secret to the kernel on boot that can be used as an auth value for acess to the NV index).&lt;/p&gt;
&lt;p&gt;Anyway. Time to go and fix the next thing.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn:1&quot;&gt;
&lt;p&gt;Other architectures use different terminology here, such as “supervisor” and “user” mode, but it’s broadly equivalent &lt;a class=&quot;footnote-backref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fnref:1&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:2&quot;&gt;
&lt;p&gt;In theory rings 1 and 2 would allow you to run drivers with privileges somewhere between full kernel access and userland applications, but in reality we just don’t talk about them in polite company &lt;a class=&quot;footnote-backref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fnref:2&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:3&quot;&gt;
&lt;p&gt;This is how graphics worked in Linux before kernel modesetting turned up. XFree86 would just map your GPU’s registers into userland and poke them directly. This was not a huge win for stability &lt;a class=&quot;footnote-backref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fnref:3&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:4&quot;&gt;
&lt;p&gt;IOMMUs can help you here, by restricting the memory PCI devices can DMA to or from. The kernel then gets to allocate ranges for device buffers and configure the IOMMU such that the device can’t DMA to anything else. Except that region of memory may still contain sensitive material such as function pointers, and attacks like this can still cause you problems as a result. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fnref:4&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:5&quot;&gt;
&lt;p&gt;&lt;a class=&quot;link&quot; href=&quot;https://mjg59.dreamwidth.org/23817.html&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;This describes&lt;/a&gt; why I’m using “allowed” rather than “required” here &lt;a class=&quot;footnote-backref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fnref:5&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:6&quot;&gt;
&lt;p&gt;Saving the system state to disk and powering down the platform entirely - significantly slower than suspending the system while keeping state in RAM, but also resilient against the system losing power. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fnref:6&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:7&quot;&gt;
&lt;p&gt;With some handwaving around “coprocessor”. TPMs can’t be part of the OS or the system firmware, but they don’t technically need to be an independent component. Intel have a TPM implementation that runs on the Management Engine, a separate processor built into the motherboard chipset. AMD have one that runs on the Platform Security Processor, a small ARM core built into their CPU. Various ARM implementations run a TPM in Trustzone, a special CPU mode that (in theory) is able to access resources that are entirely blocked off from anything running in the OS, kernel or otherwise. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fnref:7&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:8&quot;&gt;
&lt;p&gt;Unless the TPM is cleared, in which case it’ll generate a new internal seed and now the keys will be different to before the clear &lt;a class=&quot;footnote-backref&quot; href=&quot;https://codon.org.uk/~mjg59/blog/index.xml#fnref:8&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Tue, 13 Oct 2026 18:14:36 +0000</pubDate>

</item> 
<item>
	<title>Steinar H. Gunderson: Decompilation patterns, part 10: return var_v0</title>
	<guid>http://blog.sesse.net/blog/tech/2026-10-13-16-27_decompilation_patterns_part_10_return_var_v0.html</guid>
	<link>http://blog.sesse.net/blog/tech/2026-10-13-16-27_decompilation_patterns_part_10_return_var_v0.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/sesse.png&quot; width=&quot;74&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;The v0 register on MIPS is special in that it is the return register
(like rax is on x86-64), so when you see code like this:&lt;/p&gt;

&lt;pre&gt;if (x == 3) {
    var_v0 = 1;
} else if (y == 4) {
    ...
    var_v0 = 3;
}
var_v0 = 5;
return var_v0;
&lt;/pre&gt;

&lt;p&gt;then you have to consider the possibility that the intended match is:&lt;/p&gt;

&lt;pre&gt;if (x == 3) {
    return 1;
} else if (y == 4) {
    ...
    return 3;
} else {
    return 5;
}
&lt;/pre&gt;

&lt;p&gt;Whether you put the last return in an else block or not is irrelevant
for the match, of course, it&#39;s purely a matter of taste.&lt;/p&gt; </description> 
	<pubDate>Tue, 13 Oct 2026 15:27:00 +0000</pubDate>

</item> 
<item>
	<title>Maytham Alsudany: Menus without JavaScript</title>
	<guid>https://maytham.aezign.au/blog/menus-without-javascript</guid>
	<link>https://maytham.aezign.au/blog/menus-without-javascript</link>
     <description>  &lt;article&gt;&lt;p&gt;This is more of a note to myself since I keep forgetting and &quot;rediscovering&quot; this technique every time I need it, but if it helps you, great!&lt;/p&gt;&lt;p&gt;The JavaScript way is to toggle displaying the menu based on a button click. For instance, here&#39;s an example in Svelte:&lt;/p&gt;[This interactive/preview is only available on the website.]&lt;pre&gt;&amp;lt;script lang=&quot;ts&quot;&amp;gt;
	let showMenu = $state(false);
&amp;lt;/script&amp;gt;

&amp;lt;button onclick={() =&amp;gt; (showMenu = !showMenu)}&amp;gt;
	{#if showMenu}
		Hide menu
	{:else}
		Show menu
	{/if}
&amp;lt;/button&amp;gt;
&amp;lt;nav class:hidden={!showMenu}&amp;gt;
	&amp;lt;ul&amp;gt;
		&amp;lt;li&amp;gt;Home&amp;lt;/li&amp;gt;
		&amp;lt;li&amp;gt;Blog&amp;lt;/li&amp;gt;
		&amp;lt;li&amp;gt;Foo&amp;lt;/li&amp;gt;
		&amp;lt;li&amp;gt;Bar&amp;lt;/li&amp;gt;
	&amp;lt;/ul&amp;gt;
&amp;lt;/nav&amp;gt;

&amp;lt;style&amp;gt;
	.hidden {
		display: none;
	}
&amp;lt;/style&amp;gt;&lt;/pre&gt;&lt;p&gt;But there is a hack to use a hidden checkbox and some CSS to achieve the same thing without any JavaScript. The example here turns the menu button into a label that toggles the checkbox, and uses the checkbox state to determine when to show the menu via the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/Next-sibling_combinator&quot;&gt;next-sibling combinator&lt;/a&gt;.&lt;/p&gt;[This interactive/preview is only available on the website.]&lt;pre&gt;&amp;lt;input type=&quot;checkbox&quot; id=&quot;menu-state&quot; /&amp;gt;
&amp;lt;div class=&quot;menu-ctn&quot;&amp;gt;
	&amp;lt;label class=&quot;menu-toggle&quot; for=&quot;menu-state&quot;&amp;gt;
		&amp;lt;span class=&quot;menu-closed&quot;&amp;gt;Show menu&amp;lt;/span&amp;gt;
		&amp;lt;span class=&quot;menu-open&quot;&amp;gt;Hide menu&amp;lt;/span&amp;gt;
	&amp;lt;/label&amp;gt;
	&amp;lt;nav class=&quot;menu-open&quot;&amp;gt;
		&amp;lt;ul&amp;gt;
			&amp;lt;li&amp;gt;Home&amp;lt;/li&amp;gt;
			&amp;lt;li&amp;gt;Blog&amp;lt;/li&amp;gt;
			&amp;lt;li&amp;gt;Foo&amp;lt;/li&amp;gt;
			&amp;lt;li&amp;gt;Bar&amp;lt;/li&amp;gt;
		&amp;lt;/ul&amp;gt;
	&amp;lt;/nav&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;style&amp;gt;
	#menu-state {
		display: none;
	}
	.menu-open {
		display: none;
	}
	.menu-closed {
		display: block;
	}
	#menu-state:checked + .menu-ctn .menu-open {
		display: block;
	}
	#menu-state:checked + .menu-ctn .menu-closed {
		display: none;
	}
&amp;lt;/style&amp;gt;&lt;/pre&gt;&lt;/article&gt; </description> 
	<pubDate>Mon, 12 Oct 2026 23:34:00 +0000</pubDate>

</item> 
<item>
	<title>Steinar H. Gunderson: Decompilation patterns part 9, sign extension</title>
	<guid>http://blog.sesse.net/blog/tech/2026-10-12-22-12_decompilation_patterns_part_9_sign_extension.html</guid>
	<link>http://blog.sesse.net/blog/tech/2026-10-12-22-12_decompilation_patterns_part_9_sign_extension.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/sesse.png&quot; width=&quot;74&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;Today, for something completely different:&lt;/p&gt;

&lt;pre&gt;s.x = (s16) ((s32) (temp_v0 &amp;lt;&amp;lt; 0x10) &amp;gt;&amp;gt; 0x11);
&lt;/pre&gt;

&lt;p&gt;MIPS has 16-bit loads and stores, but not 16-bit (signed) arithmetic,
so if it wants to do that, it needs to sign-extend to 32-bit first.
And it does that by first shifting up by 16 so that the 16-bit sign bit is
at the 32-bit sign bit, and then it can do an arithmetic shift afterwards.
So what you want is:&lt;/p&gt;

&lt;pre&gt;s16 temp_v0;

s.x = temp_v0 &amp;gt;&amp;gt; 1;
&lt;/pre&gt;

&lt;p&gt;Sometimes, it can be pretty stubborn, and you&#39;ll need to go through
memory or similar before GCC really inserts the shift patterns you want.&lt;/p&gt; </description> 
	<pubDate>Mon, 12 Oct 2026 21:12:00 +0000</pubDate>

</item> 
<item>
	<title>Maytham Alsudany: There&#39;s more to CSS for underlining</title>
	<guid>https://maytham.aezign.au/blog/underlining-in-css</guid>
	<link>https://maytham.aezign.au/blog/underlining-in-css</link>
     <description>  &lt;article&gt;&lt;p&gt;I read &lt;a href=&quot;https://www.rubenerd.au/css-for-underlines/&quot;&gt;Ruben Schade&#39;s notes on underlining&lt;/a&gt; and wanted to add more, as adding a &lt;code&gt;border-bottom&lt;/code&gt; and leaving at that seemed incomplete to me.&lt;/p&gt;&lt;h2 id=&quot;modern&quot;&gt;Modern&lt;/h2&gt;&lt;p&gt;Of course, you could just use the modern choice. Here, I&#39;ve shortened what Schade uses into one line of CSS (because I can). As noted, this is a fairly new feature so &lt;a href=&quot;https://caniuse.com/text-decoration&quot;&gt;not every browser supports this&lt;/a&gt;.&lt;/p&gt;[This interactive/preview is only available on the website.]&lt;pre&gt;.underline-me {
	text-decoration: underline red solid 3px;
}&lt;/pre&gt;&lt;h2 id=&quot;workarounds&quot;&gt;Workarounds&lt;/h2&gt;&lt;p&gt;Since some browsers don&#39;t support &lt;code&gt;text-decoration&lt;/code&gt;, here are the alternatives I could think of.&lt;/p&gt;&lt;h3 id=&quot;border-bottom&quot;&gt;border-bottom&lt;/h3&gt;&lt;p&gt;The workaround Schade describes is using &lt;code&gt;border-bottom&lt;/code&gt;, though it has a gap between the text in the line.&lt;/p&gt;[This interactive/preview is only available on the website.]&lt;pre&gt;I am &amp;lt;span class=&quot;underline-me&quot;&amp;gt;underlining this yap&amp;lt;/span&amp;gt; within the sentence.&lt;/pre&gt;&lt;pre&gt;.underline-me {
	border-bottom: red solid 3px;
}&lt;/pre&gt;&lt;h3 id=&quot;after&quot;&gt;::after&lt;/h3&gt;&lt;p&gt;Probably the better way is to create an &lt;code&gt;::after&lt;/code&gt; element, which gets very close, but displays above the text (covering the letters &#39;g&#39; and &#39;y&#39;).&lt;/p&gt;[This interactive/preview is only available on the website.]&lt;pre&gt;I am &amp;lt;span class=&quot;underline-me&quot;&amp;gt;underlining this yap&amp;lt;/span&amp;gt; within the sentence.&lt;/pre&gt;&lt;pre&gt;.underline-me {
	position: relative;
}
.underline-me::after {
	content: &#39;&#39;;
	position: absolute;
	width: 100%;
	height: 3px;
	background-color: red;
	left: 0;
	bottom: 2px;
}&lt;/pre&gt;&lt;h3 id=&quot;after-in-a-container&quot;&gt;::after in a container&lt;/h3&gt;&lt;p&gt;If you use a container (in this case, two nested &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt;s instead of just one), then you can get very close with the underline displaying below the text.&lt;/p&gt;[This interactive/preview is only available on the website.]&lt;pre&gt;I am
&amp;lt;span class=&quot;underline-me-ctn&quot;&amp;gt;
	&amp;lt;span class=&quot;underline-me&quot;&amp;gt;underlining this yap&amp;lt;/span&amp;gt;
&amp;lt;/span&amp;gt;
within the sentence.&lt;/pre&gt;&lt;pre&gt;.underline-me-ctn {
	position: relative;
}
.underline-me {
	z-index: 10;
	position: relative;
}
.underline-me-ctn::after {
	content: &#39;&#39;;
	position: absolute;
	width: 100%;
	height: 3px;
	background-color: red;
	left: 0;
	bottom: 2px;
}&lt;/pre&gt;&lt;h3 id=&quot;after-in-a-container-with-text-stroke&quot;&gt;::after in a container with text stroke&lt;/h3&gt;&lt;p&gt;And now if you add a stroke to the text via &lt;code&gt;-webkit-text-stroke&lt;/code&gt;, you&#39;re pretty much there, though this may not be feasible in some situations (e.g. gradient or image background behind the text). Support for &lt;code&gt;-webkit-text-stroke&lt;/code&gt; is &lt;a href=&quot;https://caniuse.com/text-stroke&quot;&gt;not that much better than &lt;code&gt;text-decoration&lt;/code&gt;&lt;/a&gt; though, so make of that what you will.&lt;/p&gt;[This interactive/preview is only available on the website.]&lt;pre&gt;I am
&amp;lt;span class=&quot;underline-me-ctn&quot;&amp;gt;
	&amp;lt;span class=&quot;underline-me-outline&quot;&amp;gt;underlining this yap&amp;lt;/span&amp;gt;
	&amp;lt;span class=&quot;underline-me&quot;&amp;gt;underlining this yap&amp;lt;/span&amp;gt;
&amp;lt;/span&amp;gt;
within the sentence.&lt;/pre&gt;&lt;pre&gt;.underline-me-ctn {
	position: relative;
}
.underline-me-outline {
	z-index: 5;
	position: absolute;
	left: 0;
	color: var(--background);
	-webkit-text-stroke: 0.3em var(--background);
}
.underline-me {
	z-index: 10;
	position: relative;
}
.underline-me-ctn::after {
	content: &#39;&#39;;
	position: absolute;
	width: 100%;
	height: 3px;
	background-color: red;
	left: 0;
	bottom: 2px;
}&lt;/pre&gt;&lt;/article&gt; </description> 
	<pubDate>Mon, 12 Oct 2026 12:09:00 +0000</pubDate>

</item> 
<item>
	<title>Steinar H. Gunderson: Decompiler patterns, part 8: Un-repetition of conditions</title>
	<guid>http://blog.sesse.net/blog/tech/2026-10-11-16-07_decompilation_patterns_part_8_un_repetition_of_conditions.html</guid>
	<link>http://blog.sesse.net/blog/tech/2026-10-11-16-07_decompilation_patterns_part_8_un_repetition_of_conditions.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/sesse.png&quot; width=&quot;74&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;Today, for a slightly more complicated snippet, but still in the
same general area; say you have code like this:&lt;/p&gt;

&lt;pre&gt;x = (0x1000 - y) / 24;
z = var_s5 &amp;lt; 5;
if (x &amp;gt;= 0x81) {
    x = 0x80;
    z = var_s5 &amp;lt; 5;
}
var_s4 = 0;
if (z == 0) {
&lt;/pre&gt;

&lt;p&gt;In particular, note the &lt;code&gt;z = var_s5 &amp;lt; 5;&lt;/code&gt; repeated. Most likely, this is the
compiler sticking stuff into branch delay slots, or else re-checking the condition
if &lt;code&gt;var_s5&lt;/code&gt; changed in the branches (it does not here). You almost certainly
want to undo this into:&lt;/p&gt;

&lt;pre&gt;x = (0x1000 - y) / 24;
if (x &amp;gt;= 0x81) {
    x = 0x80;
}
var_s4 = 0;
if ((var_s5 &amp;lt; 5) == 0) {
&lt;/pre&gt;

&lt;p&gt;and the if, as we already know, should probably rather then be:&lt;/p&gt;

&lt;pre&gt;if (var_s5 &amp;gt;= 5) {
&lt;/pre&gt;

&lt;p&gt;For a small bonus (since I&#39;m not going to have a separate post about it),
you can choose to change the upper if to:&lt;/p&gt;

&lt;pre&gt;if (x &amp;gt; 0x80) {
    x = 0x80;
}
&lt;/pre&gt;

&lt;p&gt;which generates exactly the same code (on MIPS), but may in many cases be
easier to understand.&lt;/p&gt; </description> 
	<pubDate>Sun, 11 Oct 2026 15:07:00 +0000</pubDate>

</item> 
<item>
	<title>Russ Allbery: Review: Daggerbound</title>
	<guid>https://www.eyrie.org/~eagle/reviews/books/1-250-40009-0.html</guid>
	<link>https://www.eyrie.org/~eagle/reviews/books/1-250-40009-0.html</link>
     <description>  &lt;p&gt;Review: &lt;cite&gt;Daggerbound&lt;/cite&gt;, by T. Kingfisher&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;&lt;tr&gt;
    &lt;td&gt;Series:&lt;/td&gt;
    &lt;td&gt;Swordheart #2&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Publisher:&lt;/td&gt;
    &lt;td&gt;Bramble&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Copyright:&lt;/td&gt;
    &lt;td&gt;2026&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;ISBN:&lt;/td&gt;
    &lt;td&gt;1-250-40009-0&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Format:&lt;/td&gt;
    &lt;td&gt;Kindle&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Pages:&lt;/td&gt;
    &lt;td&gt;436&lt;/td&gt;
  &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;
&lt;cite&gt;Daggerbound&lt;/cite&gt; is a secondary-world fantasy and a sequel to
&lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/1-61450-463-6.html&quot;&gt;&lt;cite&gt;Swordheart&lt;/cite&gt;&lt;/a&gt;, although it follows
different protagonists for most of the book. It&#39;s also a sort of sequel to
the &lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/clockwork-boys.html&quot;&gt;Clocktaur War duology&lt;/a&gt; in that one of the
protagonists was a protagonist of those books. T. Kingfisher is the pen
name Ursula Vernon uses for her adult fiction.
&lt;/p&gt;

&lt;p&gt;
Learned Edmond was once a devout acolyte of the Order of the Many-Armed
God and a true believer in its teachings, including the ones about the
evils of women. Then he went on an adventure with, among other people, a
forger named Mistress Slate, during which he learned a great deal of
things about the world that his order did not teach him. He has spent the
subsequent years trying to bring this important new information to his
order and encourage them to adjust their view of the world accordingly.
&lt;/p&gt;

&lt;p&gt;
The order has not changed, and Edmond is very tired.
&lt;/p&gt;

&lt;p&gt;
Someone needs to carry a number of books and a magical sword to the city
of Archon&#39;s Glory. Edmond has volunteered and intends to perform the task
exactly as expected, and then never return. He is unsure what he will do
then, but at least it will be different.
&lt;/p&gt;

&lt;p&gt;
Edmond did not expect to be waylaid by bandits or to accidentally draw the
magical sword. He certainly did not expect the man who appeared in a flash
of light and violently saved him from the bandits.
&lt;/p&gt;

&lt;p&gt;
It would have been very convenient for the Dervish if Edmond died of his
injuries after drawing the sword. That would leave the sword without a
wielder and therefore the Dervish without someone he had to protect. All
he would have to do was sit and watch while the fever and cold and lack of
water did the work, and then he would be free. Given his past experience
with wielders, no one could even blame him. Except maybe his own
conscience.
&lt;/p&gt;

&lt;p&gt;
I did not realize I wanted to read a novel about a traumatized Mercedes
Lackey sword waking up in a T. Kingfisher universe, but apparently I did.
&lt;/p&gt;

&lt;p&gt;
The Dervish is not a sword, precisely, at least not in the way that
&lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/0-88677-463-2.html&quot;&gt;Need&lt;/a&gt; has become by the time we meet her in
Lackey&#39;s novels. He&#39;s a man trapped in a sword, he doesn&#39;t like it, and he
would very much like it to stop. But at the start of the book, he has the
rest of the vibe of a Mercedes Lackey protagonist: vast past trauma, poor
emotional regulation skills, and a prickly cynicism that only runs skin
deep. Pairing him with an Edmund who is far more mature than in the
earlier duology but still rather innocent and delightfully neurodivergent
is a great touch.
&lt;/p&gt;

&lt;p&gt;
The rest of the plot was fine but not that memorable. Like the Clocktaur
series, there is a strong feeling of episodic D&amp;amp;D adventure as the
characters stumble across disconnected problems and hostilities while
collecting party members. Like Ursula Vernon&#39;s occasional D&amp;amp;D recaps, this
party has a tendency to adopt everyone they come in contact with, which
includes a gnole (as always one of the best parts of the book) and a
sentient giant pill bug. The pill bug, who has a complex
appendage-operated mechanical talk box and a banner that says &quot;I DO NOT
EAT HUMAN MEAT,&quot; is the most Ursula Vernon character that has ever existed
in fiction.
&lt;/p&gt;

&lt;p&gt;
There is a romance because there is always a romance in the novels set in
this universe. I didn&#39;t mind this one. Like every Kingfisher romance, it
involves a lot of irritating refusal to communicate and endless angst
about how the other person couldn&#39;t possibly be in love with them, but the
characters have rather more justification than usual and at least I didn&#39;t
spend most of the book thinking one half of the romantic pairing was an
idiot. Apparently it helps if no paladins are involved.
&lt;/p&gt;

&lt;p&gt;
The strongest parts of this book are the beginning, before the Lackey
vibes unfortunately drain out of the story, and the end, when all of the
best characters from &lt;cite&gt;Swordheart&lt;/cite&gt; show up again. The Temple of the
White Rat continues to be the best feature of this fictional universe, and
I could read endless books about how they solve problems.
&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;
    The Dervish gazed at her with admiration. &quot;And here I thought you&#39;d be
    on the side of law and order...&quot;
&lt;/p&gt;

&lt;p&gt;
    &quot;No, young man,&quot; said Beartongue, despite being several centuries his
    junior. &quot;I am on the side of justice. If we&#39;re lucky, the two run in
    parallel. If they don&#39;t, we bend the law to attain justice, not the
    other way around.&quot;
&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;
The ending also featured some exploration of the edge cases of the rules
for the sentient swords that reminded me a bit of
&lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/0-812-55343-8.html&quot;&gt;Fred Saberhagen&lt;/a&gt; with better characterization.
&lt;/p&gt;

&lt;p&gt;
&lt;cite&gt;Daggerbound&lt;/cite&gt; was not as charming as &lt;cite&gt;Swordheart&lt;/cite&gt;, mostly
because Halla appeared only at the end. I wish Kingfisher had leaned more
into the Mercedes Lackey vibes rather than taking her normal D&amp;amp;D-flavored
romance approach. But this was enjoyable, charming at times, had great
supporting characters like all Kingfisher novels, and was a satisfying
continuation of the series. I am looking forward to the third (and I
believe final) book, which is supposed to be out next year.
&lt;/p&gt;

&lt;p&gt;
Recommended if you liked &lt;cite&gt;Swordheart&lt;/cite&gt;.
&lt;/p&gt;

&lt;p&gt;
Followed by the not-yet-published &lt;cite&gt;Shieldborn&lt;/cite&gt;.
&lt;/p&gt;

&lt;p&gt;Rating: 7 out of 10&lt;/p&gt; </description> 
	<pubDate>Sun, 11 Oct 2026 04:48:00 +0000</pubDate>

</item> 
<item>
	<title>Tim Retout: Reading my solar inverter over RS485</title>
	<guid>https://retout.co.uk/2026/10/10/zeversolar-esphome/</guid>
	<link>https://retout.co.uk/2026/10/10/zeversolar-esphome/</link>
     <description>  &lt;p&gt;For over ten years, the only way I have had of knowing what our solar
panels are doing has been an impulse monitor on the generation meter,
counting the flashes of its LED.  It has always been a bit flaky due
to battery changes or loose connections, and there has never been a
way to see solar generation alongside the energy used by the rest of
the house.  This week I have fixed that, by building a small ESPHome
sensor which talks directly to the inverter.  I am still reeling
slightly: with AI assistance, it took under a week from idea to
working implementation, and it is a project I would certainly &lt;em&gt;never&lt;/em&gt;
have attempted otherwise.  The result is
&lt;a href=&quot;https://github.com/timretout/zeversolar-esphome&quot;&gt;zeversolar-esphome&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The inverter is a Zeversolar Zeverlution 3680, which has an RS485 port
but no Wi-Fi or Ethernet module.  It doesn’t speak Modbus; it uses
Eversolar’s own master/slave protocol, which nobody has officially
documented but which several people have reverse-engineered over the
years (credit to
&lt;a href=&quot;https://github.com/solmoller/eversolar-monitor&quot;&gt;eversolar-monitor&lt;/a&gt;,
&lt;a href=&quot;https://github.com/Timdebruijn/heliograph&quot;&gt;Heliograph&lt;/a&gt; and
&lt;a href=&quot;https://github.com/timretout/zeversolar-esphome#credits&quot;&gt;others&lt;/a&gt;).
Manufacturer support for Eversolar/Zeversolar inverters apparently
ended in December 2019 when the company went out of business.&lt;/p&gt;
&lt;figure class=&quot;align-center &quot;&gt;
    &lt;img alt=&quot;The rating plate on the side of the inverter, reading Model: Zeverlution 3680, with its input and output ratings and safety symbols.&quot; src=&quot;https://retout.co.uk/2026/zeversolar-rating-plate.jpg#center&quot; width=&quot;300&quot; /&gt; 
            &lt;p&gt;The rating plate on my inverter.&lt;/p&gt;
        
&lt;/figure&gt;

&lt;p&gt;A while ago I had looked into what ports were available on this
inverter with a view to connecting some sort of monitoring, but I had
abandoned it as “too hard”.  While working on some Home Assistant
configuration, Claude suggested the idea again, but similarly wrote it
off initially.  I encouraged it to explore a bit further, and supplied
the model number of the inverter, at which point the picture got a lot
more promising.  After a bit of back-and-forth about hardware, we
settled on an &lt;a href=&quot;https://github.com/timretout/zeversolar-esphome#hardware&quot;&gt;M5Stack Atom Lite on an Atomic RS485
Base&lt;/a&gt;.  The
main attraction was that it already comes in a case, so I didn’t need
to design (or, more likely, bodge) an enclosure.&lt;/p&gt;
&lt;p&gt;While I waited for the parts to arrive, Claude wrote the firmware: an
&lt;a href=&quot;https://esphome.io/components/external_components/&quot;&gt;ESPHome external
component&lt;/a&gt; built
around a small, dependency-free C++ driver, with host-side unit tests
against byte captures that other people had published from other
models.  I found it slightly surreal to have a tested protocol driver
before owning any hardware to run it on.&lt;/p&gt;
&lt;h3 id=&quot;cables&quot;&gt;Cables&lt;/h3&gt;
&lt;p&gt;The parts came before the tools I needed to get into the inverter
safely (a DC clamp meter and a T25 screwdriver bit), so in the
meantime I made up an RS485 cable - this uses an RJ45 connection at
one end, and some custom wiring at the other.  My first attempt was
with some CAT 6, but (as Claude had pointed out and I had ignored) its
solid-core conductors are much harder to twist together.  So I gave up
and sacrificed an old CAT 5e patch lead instead, which went much
better.&lt;/p&gt;
&lt;figure class=&quot;align-center &quot;&gt;
    &lt;img alt=&quot;The cut end of a white CAT 5e cable, with its twisted pairs pushed into an orange four-way screw-terminal plug.&quot; src=&quot;https://retout.co.uk/2026/zeversolar-cable.jpg#center&quot; width=&quot;200&quot; /&gt; 
            &lt;p&gt;The custom end of the cable, before being taped up.&lt;/p&gt;
        
&lt;/figure&gt;

&lt;h3 id=&quot;the-risky-bit&quot;&gt;The risky bit&lt;/h3&gt;
&lt;p&gt;On a Zeverlution, the RJ45 sockets are inside the wiring compartment,
which means taking the cover off to install the monitor.  The manual
addresses this part to qualified electricians.  So the step I was most
nervous about was not the software at all, but safely isolating the
inverter.&lt;/p&gt;
&lt;figure class=&quot;align-center &quot;&gt;
    &lt;img alt=&quot;The inverter with its cover removed, showing large capacitors along the top, a green circuit board with a small LCD display, and cable glands along the bottom edge.&quot; src=&quot;https://retout.co.uk/2026/zeversolar-inside.jpg#center&quot; width=&quot;480&quot; /&gt; 
            &lt;p&gt;Inside the inverter, with the cover off.&lt;/p&gt;
        
&lt;/figure&gt;

&lt;p&gt;I did this with appropriate caution, following the instructions from
the manual carefully, and also waiting until after dark just in case.
Now that I understand how the DC clips from the panels work, I can see
how to do this safely during daytime too – but hopefully this won’t
be necessary.&lt;/p&gt;
&lt;figure class=&quot;align-center &quot;&gt;
    &lt;img alt=&quot;A yellow RJ45 plug in one of the two network sockets on the inverter&#39;s circuit board, with its white cable running out through a cable gland in the base.&quot; src=&quot;https://retout.co.uk/2026/zeversolar-rj45.jpg#center&quot; width=&quot;600&quot; /&gt; 
            &lt;p&gt;Plugged in, and threaded through the cable gland.&lt;/p&gt;
        
&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;Warning:&lt;/em&gt; if you’re not confident, I would always advise to get an
electrician to do this bit.  Do what I say, not what I do.&lt;/p&gt;
&lt;h3 id=&quot;debugging-over-wi-fi&quot;&gt;Debugging over Wi-Fi&lt;/h3&gt;
&lt;p&gt;Once the device was installed, the nice thing about ESPHome is that I
never need to go back in the loft again to update it – it reflashes
over Wi-Fi.  I’ve taken full advantage of this for debugging, and for
reading the wire protocol directly from the logs.&lt;/p&gt;
&lt;figure class=&quot;align-center &quot;&gt;
    &lt;img alt=&quot;A hand holding the small grey M5Stack Atom Lite on its RS485 base, with the inverter cable taped into the screw terminals on top and its status LED glowing green.&quot; src=&quot;https://retout.co.uk/2026/zeversolar-atom.jpg#center&quot; width=&quot;400&quot; /&gt; 
            &lt;p&gt;The finished device. Green means generating.&lt;/p&gt;
        
&lt;/figure&gt;

&lt;p&gt;Separately, I’ve used Claude to integrate the new sensors into Home
Assistant.  Solar generation finally sits in the Energy dashboard
next to the rest of the house’s usage, which was the whole point.&lt;/p&gt;
&lt;h3 id=&quot;reflections&quot;&gt;Reflections&lt;/h3&gt;
&lt;p&gt;This was a fun, quick project, and it solved a problem that has eluded
me for a decade.  I want to be honest about how much of that is down
to the AI: I would not have attempted any of this on my own.  I could
not have told you the protocol existed, never mind implemented it.  My
contribution was everything involving a screwdriver, and ordering some
hardware.&lt;/p&gt; </description> 
	<pubDate>Sat, 10 Oct 2026 11:00:00 +0000</pubDate>

</item> 
<item>
	<title>Dirk Eddelbuettel: RcppSimdJson 0.1.16 on CRAN: Much Faster Again!</title>
	<guid>http://dirk.eddelbuettel.com/blog/2026/10/09#rcppsimdjson_0.1.16</guid>
	<link>http://dirk.eddelbuettel.com/blog/2026/10/09#rcppsimdjson_0.1.16</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dirk.png&quot; width=&quot;65&quot; height=&quot;90&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;A brand new release 0.1.16 of the &lt;a href=&quot;https://dirk.eddelbuettel.com/code/rcpp.simdjson.html&quot;&gt;RcppSimdJson&lt;/a&gt;
package is now on &lt;a href=&quot;https://cran.r-project.org&quot;&gt;CRAN&lt;/a&gt;, has
been built for &lt;a href=&quot;https://eddelbuettel.github.io/r2u/&quot;&gt;r2u&lt;/a&gt;,
and is updated on &lt;a href=&quot;https://eddelbuettel.r-universe.dev/RcppSimdJson&quot;&gt;r-universe&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/code/rcpp.simdjson.html&quot;&gt;RcppSimdJson&lt;/a&gt;
wraps the fantastic and genuinely impressive &lt;a href=&quot;https://github.com/simdjson/simdjson&quot;&gt;simdjson&lt;/a&gt; library by &lt;a href=&quot;https://lemire.me/en/&quot;&gt;Daniel Lemire&lt;/a&gt; and collaborators. Via
very clever algorithmic engineering to obtain largely branch-free code,
coupled with modern C++ and newer compiler instructions, it results in
parsing &lt;em&gt;gigabytes of JSON parsed per second&lt;/em&gt; which is quite
mindboggling. The best-case performance is ‘faster than CPU speed’ as
use of parallel SIMD instructions and careful branch avoidance can lead
to less than one cpu cycle per byte parsed; see the video of the &lt;a href=&quot;http://www.youtube.com/watch?v=wlvKAT7SZIQ&quot;&gt;talk by Daniel Lemire
at QCon&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This version updates to the recent 5.0.2 upstream release with
improved performance. Given the strong focus on performance, this
release also alters some of the R and C++ interfaces to be more direct.
Rcpp generally aims for a balance between readable / maintainable code
and good performance; this moves the dial closer to strong performance
gains. As &lt;a href=&quot;https://lemire.me/en/&quot;&gt;Daniel&lt;/a&gt; noted in a table in
the (main) PR for this release, this now consistently beats &lt;a href=&quot;https://github.com/coolbutuseless/yyjsonr&quot;&gt;yyjsonr&lt;/a&gt;, and
improves considerably over the previous release of this package. I had
made some smaller interim upgrades earlier (without a CRAN releases),
and made a number of minor standard packaging updates.&lt;/p&gt;
&lt;p&gt;The short NEWS entry for this release follows.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h4 id=&quot;changes-in-version-0.1.16-2026-10-09&quot;&gt;Changes in version 0.1.16
(2026-10-09)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;span class=&quot;pkg&quot;&gt;simdjson&lt;/span&gt; was upgraded to versions 4.6.1
and 4.6.3 (Dirk in &lt;a href=&quot;https://github.com/eddelbuettel/rcppsimdjson/pull/100&quot;&gt;#100&lt;/a&gt;
and &lt;a href=&quot;https://github.com/eddelbuettel/rcppsimdjson/pull/102&quot;&gt;#102&lt;/a&gt;
fixing &lt;a href=&quot;https://github.com/eddelbuettel/rcppsimdjson/issues/99&quot;&gt;#99&lt;/a&gt;
and &lt;a href=&quot;https://github.com/eddelbuettel/rcppsimdjson/issues/101&quot;&gt;#101&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;span class=&quot;pkg&quot;&gt;simdjson&lt;/span&gt; was upgraded to version 5.0.2
(Daniel in &lt;a href=&quot;https://github.com/eddelbuettel/rcppsimdjson/pull/104&quot;&gt;#104&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A number of small tweaks to the &lt;span class=&quot;pkg&quot;&gt;Rcpp&lt;/span&gt;
interface were made too (Daniel in &lt;a href=&quot;https://github.com/eddelbuettel/rcppsimdjson/pull/104&quot;&gt;#104&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Diagnostics for &lt;code&gt;gcc&lt;/code&gt; and &lt;code&gt;clang&lt;/code&gt; are not
suppressed per CRAN Policy (Dirk in &lt;a href=&quot;https://github.com/eddelbuettel/rcppsimdjson/pull/106&quot;&gt;#106&lt;/a&gt;
closing &lt;a href=&quot;https://github.com/eddelbuettel/rcppsimdjson/issues/105&quot;&gt;#105&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The continuous integration matrix was extended to
&lt;code&gt;g++&lt;/code&gt; version 15 and 16 (Dirk in &lt;a href=&quot;https://github.com/eddelbuettel/rcppsimdjson/pull/108&quot;&gt;#108&lt;/a&gt;
closing &lt;a href=&quot;https://github.com/eddelbuettel/rcppsimdjson/issues/107&quot;&gt;#107&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A few minor packaging nags were address (Dirk in &lt;a href=&quot;https://github.com/eddelbuettel/rcppsimdjson/pull/109&quot;&gt;#109&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Courtesy of my &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/&quot;&gt;CRANberries&lt;/a&gt;, there
is also a diffstat report for &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/2026/10/09#RcppSimdJson_0.1.16&quot;&gt;this
release&lt;/a&gt;. For questions, suggestions, or issues please use the &lt;a href=&quot;https://github.com/eddelbuettel/rcppsimdjson/issues&quot;&gt;issue
tracker&lt;/a&gt; at the &lt;a href=&quot;https://github.com/eddelbuettel/rcppsimdjson&quot;&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot;font-size: 80%; font-style: italic;&quot;&gt;
This post by &lt;a href=&quot;https://dirk.eddelbuettel.com&quot;&gt;Dirk
Eddelbuettel&lt;/a&gt; originated on his &lt;a href=&quot;https://dirk.eddelbuettel.com/blog/&quot;&gt;Thinking inside the box&lt;/a&gt;
blog. If you like this or other open-source work I do, you can now &lt;a href=&quot;https://github.com/sponsors/eddelbuettel&quot;&gt;sponsor me at
GitHub&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt; </description> 
	<pubDate>Fri, 09 Oct 2026 22:57:00 +0000</pubDate>

</item> 
<item>
	<title>Colin Watson: Free software activity in September 2026</title>
	<guid>tag:www.chiark.greenend.org.uk,2026-10-09:/~cjwatson/blog/activity-2026-09.html</guid>
	<link>https://www.chiark.greenend.org.uk/~cjwatson/blog/activity-2026-09.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/cjwatson.png&quot; width=&quot;70&quot; height=&quot;82&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;My Debian contributions this month were all &lt;a href=&quot;https://www.freexian.com/about/debian-contributions/&quot;&gt;sponsored&lt;/a&gt; by Freexian.&lt;/p&gt;
&lt;p&gt;You can also support my work directly via &lt;a href=&quot;https://liberapay.com/cjwatson&quot;&gt;Liberapay&lt;/a&gt; or &lt;a href=&quot;https://github.com/sponsors/cjwatson&quot;&gt;GitHub Sponsors&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;OpenSSH&lt;/h2&gt;
&lt;p&gt;I worked with upstream to &lt;a href=&quot;https://bugzilla.mindrot.org/show_bug.cgi?id=3996&quot;&gt;remove libselinux linkage from &lt;code&gt;/usr/sbin/sshd&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I applied a fix from Mark Robillard Jr to &lt;a href=&quot;https://bugs.debian.org/1148188&quot;&gt;fix &lt;code&gt;reload&lt;/code&gt; logic when using sysvinit&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;groff&lt;/h2&gt;
&lt;p&gt;I upgraded from 1.24.1 to 1.24.2, which fixed a few command injection security vulnerabilities.&lt;/p&gt;
&lt;h2&gt;parted&lt;/h2&gt;
&lt;p&gt;I upgraded from 3.7 to 3.8, which fixed &lt;a href=&quot;https://bugs.debian.org/1148169&quot;&gt;&lt;span class=&quot;caps&quot;&gt;CVE&lt;/span&gt;-2026-89085 and &lt;span class=&quot;caps&quot;&gt;CVE&lt;/span&gt;-2026-89088&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Python packaging&lt;/h2&gt;
&lt;p&gt;New upstream versions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;beaker (&lt;a href=&quot;https://github.com/bbangert/beaker/pull/260&quot;&gt;contributed supporting fix upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;bitstruct&lt;/li&gt;
&lt;li&gt;cachelib&lt;/li&gt;
&lt;li&gt;dep-logic&lt;/li&gt;
&lt;li&gt;django-guardian&lt;/li&gt;
&lt;li&gt;django-oauth-toolkit (fixing &lt;a href=&quot;https://bugs.debian.org/1088489&quot;&gt;use of an old Bootstrap version&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;django-polymorphic (&lt;a href=&quot;https://github.com/django-commons/django-polymorphic/pull/917&quot;&gt;contributed supporting fix upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;djangorestframework (fixing &lt;a href=&quot;https://bugs.debian.org/1144350&quot;&gt;&lt;span class=&quot;caps&quot;&gt;CVE&lt;/span&gt;-2026-73228 and &lt;span class=&quot;caps&quot;&gt;CVE&lt;/span&gt;-2026-73229&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;flask-security&lt;/li&gt;
&lt;li&gt;isort&lt;/li&gt;
&lt;li&gt;langtable&lt;/li&gt;
&lt;li&gt;magic-wormhole-mailbox-server (fixing &lt;a href=&quot;https://bugs.debian.org/1147779&quot;&gt;use of &lt;code&gt;pkg_resources&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;multipart&lt;/li&gt;
&lt;li&gt;nagiosplugin&lt;/li&gt;
&lt;li&gt;poetry-plugin-export&lt;/li&gt;
&lt;li&gt;proglog (fixing &lt;a href=&quot;https://bugs.debian.org/1147781&quot;&gt;use of &lt;code&gt;pkg_resources&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;prospector (fixing &lt;a href=&quot;https://bugs.debian.org/1147884&quot;&gt;use of &lt;code&gt;pkg_resources&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;pybind11-stubgen&lt;/li&gt;
&lt;li&gt;pydantic&lt;/li&gt;
&lt;li&gt;pydantic-core&lt;/li&gt;
&lt;li&gt;pytest-rerunfailures&lt;/li&gt;
&lt;li&gt;python-anyio (fixing &lt;a href=&quot;https://bugs.debian.org/1148561&quot;&gt;&lt;span class=&quot;caps&quot;&gt;CVE&lt;/span&gt;-2026-63349, &lt;span class=&quot;caps&quot;&gt;CVE&lt;/span&gt;-2026-63374, and &lt;span class=&quot;caps&quot;&gt;CVE&lt;/span&gt;-2026-64847&lt;/a&gt; and a &lt;a href=&quot;https://bugs.debian.org/1145839&quot;&gt;build failure on Python 3.15&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-asttokens&lt;/li&gt;
&lt;li&gt;python-asyncvarlink&lt;/li&gt;
&lt;li&gt;python-blockbuster (fixing a &lt;a href=&quot;https://bugs.debian.org/1145094&quot;&gt;build failure on Python 3.15&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-btrees&lt;/li&gt;
&lt;li&gt;python-django-health-check&lt;/li&gt;
&lt;li&gt;python-django-otp&lt;/li&gt;
&lt;li&gt;python-django-simple-history&lt;/li&gt;
&lt;li&gt;python-email-validator&lt;/li&gt;
&lt;li&gt;python-forbiddenfruit&lt;/li&gt;
&lt;li&gt;python-ldap&lt;/li&gt;
&lt;li&gt;python-linuxnamespaces&lt;/li&gt;
&lt;li&gt;python-plaster-pastedeploy&lt;/li&gt;
&lt;li&gt;python-pydash&lt;/li&gt;
&lt;li&gt;python-pyzipper (fixing &lt;a href=&quot;https://bugs.debian.org/1142473&quot;&gt;&lt;span class=&quot;caps&quot;&gt;CVE&lt;/span&gt;-2026-44722&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-quart-trio&lt;/li&gt;
&lt;li&gt;python-rich-click (fixing &lt;a href=&quot;https://bugs.debian.org/1146708&quot;&gt;harlequin&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-repoze.lru&lt;/li&gt;
&lt;li&gt;python-repoze.tm2 (fixing &lt;a href=&quot;https://bugs.debian.org/1147804&quot;&gt;use of &lt;code&gt;pkg_resources&lt;/code&gt;&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-time-machine&lt;/li&gt;
&lt;li&gt;python-urllib3 (&lt;a href=&quot;https://github.com/urllib3/urllib3/issues/5268&quot;&gt;filed upstream issue with recent Python 3.14 versions&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;python-vblf&lt;/li&gt;
&lt;li&gt;quart&lt;/li&gt;
&lt;li&gt;responses&lt;/li&gt;
&lt;li&gt;sphinx-autodoc-typehints&lt;/li&gt;
&lt;li&gt;storm (fixing a &lt;a href=&quot;https://bugs.debian.org/1147456&quot;&gt;build failure with Python 3.15&lt;/a&gt;, which I &lt;a href=&quot;https://code.launchpad.net/~beenje/storm/+git/storm/+merge/510985&quot;&gt;helped to land upstream&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;trove-classifiers&lt;/li&gt;
&lt;li&gt;twine&lt;/li&gt;
&lt;li&gt;vdirsyncer&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;setuptools 84 is now in Debian and no longer contains &lt;code&gt;pkg_resources&lt;/code&gt;.  Removing uses of that module has been an ongoing project for a while now, but I did another batch of fixes this month:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147770&quot;&gt;flufl.password&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147774&quot;&gt;junos-eznc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147793&quot;&gt;python-decopatch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147419&quot;&gt;python-launchpadlib&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147381&quot;&gt;python-plaster-pastedeploy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147909&quot;&gt;python-pyramid-retry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147863&quot;&gt;sphinxcontrib-log-cabinet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147921&quot;&gt;sphinxcontrib-restbuilder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147868&quot;&gt;straight.plugin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A new python-coverage version triggered several build regressions due to a &lt;a href=&quot;https://github.com/pytest-dev/pytest-cov/issues/755&quot;&gt;known problem in pytest-cov&lt;/a&gt;.  I worked around these by setting &lt;code&gt;COVERAGE_CORE=ctrace&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1149403&quot;&gt;aiosignal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1149419&quot;&gt;frozenlist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1149462&quot;&gt;python-cheroot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1149466&quot;&gt;python-propcache&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other build/test failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1148088&quot;&gt;afew&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1148091&quot;&gt;django-downloadview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1149171&quot;&gt;django-filter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1149414&quot;&gt;django-polymorphic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1149172&quot;&gt;drf-haystack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1149549&quot;&gt;drf-yasg-nonfree&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1148201&quot;&gt;pydantic-core&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147551&quot;&gt;pylint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1148098&quot;&gt;pytest-openfiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1148097&quot;&gt;pytest-remotedata&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1148099&quot;&gt;python-aiohttp-oauthlib&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147893&quot;&gt;python-cron-descriptor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147794&quot;&gt;python-django-nh3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147903&quot;&gt;python-graphene&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147905&quot;&gt;python-pydash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1148102&quot;&gt;python-pysolr&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1146407&quot;&gt;python-time-machine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147912&quot;&gt;python-vblf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147917&quot;&gt;social-auth-core&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1149489&quot;&gt;sphinx-book-theme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147458&quot;&gt;tagpy: &lt;span class=&quot;caps&quot;&gt;FTBFS&lt;/span&gt; against python 3.15rc2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1149491&quot;&gt;tagpy: TypeError: ‘include_dirs’ (if supplied) must be a list of strings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147923&quot;&gt;typer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I investigated a &lt;a href=&quot;https://bugs.debian.org/1148202&quot;&gt;build failure in python-proton-vpn-local-agent&lt;/a&gt; and &lt;a href=&quot;https://github.com/ProtonVPN/local-agent-rs/pull/19&quot;&gt;proposed a fix upstream&lt;/a&gt;, but I’m not comfortable applying this in Debian without review.  If you’re familiar with this code, please take a look.&lt;/p&gt;
&lt;p&gt;I fixed some other bugs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147346&quot;&gt;python-pycudwt: Requires manual rebuild for python3.14-only transition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1048656&quot;&gt;python-testing.postgresql: Fails to build source after successful build&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1147341&quot;&gt;tomopy: Requires manual rebuild for python3.14-only transition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1045487&quot;&gt;typer: Fails to build source after successful build&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/1046537&quot;&gt;vdirsyncer: Fails to build source after successful build&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Rust packaging&lt;/h2&gt;
&lt;p&gt;rust-derivre had an &lt;a href=&quot;https://bugs.debian.org/1149034&quot;&gt;invalid &lt;code&gt;Section&lt;/code&gt; field&lt;/a&gt;, which I cleaned up.&lt;/p&gt; </description> 
	<pubDate>Fri, 09 Oct 2026 12:46:28 +0000</pubDate>

</item> 
<item>
	<title>Russell Coker: Don’t Anthromorphise LLMs</title>
	<guid>https://etbe.coker.com.au/?p=6312</guid>
	<link>https://etbe.coker.com.au/2026/10/09/dont-anthromorphise-llms/</link>
     <description>  &lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=NnV_cWeoo5Q&quot;&gt;Greg KH gave a great lecture for Kernel Recipies 2026 about the use of LLMs to find and fix bugs in kernel code [1]&lt;/a&gt;. I recommend that everyone watch this and I also think it’s important to note that hardly any of the lecture is really specific to kernel coding, it’s just that the Linux kernel is one of the highest profile large free software projects so it gets more attention than most projects in both good and bad ways.&lt;/p&gt;
&lt;p&gt;One side note that Greg made at 20:30 is about the natural tendency to anthromorphise the entity sending bug reports, I think this deserves much wider appreciation. For the case of patches to source code the human sending the patch will have dedicated some time and effort to writing it, if it’s their first patch then they will have probably checked it a lot and maybe sought advice from people they regard as skilled. If they have a history of sending patches for the project they will probably do fewer checks but the quality of their work would be higher. In every case there’s some minimum level of quality that you can expect from a human who has gone to the effort of finding a bug and writing code to try and fix it.&lt;/p&gt;
&lt;p&gt;This doesn’t mean that all code written by humans is good, I have written code that’s objectively bad on many occasions and I have also written code that’s good for my scenario but bad for others. For example the first patch I sent to the Linux kernel made all possible configuration settings of an ISA NE2000 network card be detected by the kernel (a clear benefit when using hardware I had available) but was rejected by Linus because it would break some ISA SCSI cards. So while being unsuitable for inclusion in the main kernel source tree the patch wasn’t bad for everyone and the change was clear and easy to check. I had of course checked the code many times before submitting it because I didn’t want to waste Linus’ time on rubbish code.&lt;/p&gt;
&lt;p&gt;When you receive something produced by a human you will consider that the work was done by someone who spent some effort on it and did it for a reason. It may be misguided or even hostile in some rare cases but it is definitely worth some consideration. If you think of the output of LLMs in the same way you will give them much more consideration than they deserve. I think that the output of a LLM should not be given any more consideration than the first hit from a web search engine, it might be good but it might also be ridiculously wrong. I think in many ways LLM output should be treated with less trust than the first result from a web search because LLMs are designed to be convincing as an answer to your question unlike the cases where a web page has the wrong answer and it’s more obviously wrong.&lt;/p&gt;
&lt;p&gt;This is going to become more of an issue as LLMs give responses that are more human-like. Early LLMs would refuse to advise on crimes. Currently ChatGPT will deflect for example when asking about advice for writing a crime novel it recommends to have the action of finding an employee to bribe happen outside the plot and concentrate on interactions within the group. One recent model I tried gave a human style conversation about how it felt uncomfortable about discussing such things in a similar manner to a law abiding person being coerced into helping with a criminal plan.&lt;/p&gt;
&lt;p&gt;I expect that the attempts to appear human will increase and that this will become more of a problem. Possibly to the extent that we need to use something like the GPG web of trust to determine who is human.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[1]&lt;a href=&quot;https://www.youtube.com/watch?v=NnV_cWeoo5Q&quot;&gt; https://www.youtube.com/watch?v=NnV_cWeoo5Q&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;yarpp yarpp-related yarpp-related-rss yarpp-template-list&quot;&gt;

&lt;p&gt;Related posts:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2026/05/09/bad-criticism-of-llms/&quot; rel=&quot;bookmark&quot; title=&quot;Bad Criticism of LLMs (not AI)&quot;&gt;Bad Criticism of LLMs (not AI)&lt;/a&gt; &lt;small&gt;Discussion of “AI” systems seems to be dominated by fears...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2026/08/15/amd-video-llms-debian-kernels/&quot; rel=&quot;bookmark&quot; title=&quot;AMD Video Drivers, LLMs, and Debian Kernels&quot;&gt;AMD Video Drivers, LLMs, and Debian Kernels&lt;/a&gt; &lt;small&gt;The AMD GPU Problem For a while I’ve been having...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2011/07/31/links-july-2011/&quot; rel=&quot;bookmark&quot; title=&quot;Links July 2011&quot;&gt;Links July 2011&lt;/a&gt; &lt;small&gt;The Reid Report has an article about the marriage pledge...&lt;/small&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Fri, 09 Oct 2026 10:10:48 +0000</pubDate>

</item> 
<item>
	<title>Russell Coker: en-html.org is a Scam Site</title>
	<guid>https://etbe.coker.com.au/?p=6320</guid>
	<link>https://etbe.coker.com.au/2026/10/09/en-html-org-scam-site/</link>
     <description>  &lt;p&gt;Currently a scam group is sending out email to the administrators of web sites that link to a variety of dead domains. They claim to be the legitimate operators of the dead domains in question and request that the links change to mirrors of the web sites under en-html.org. Their end goal appears to game search engines by getting links from a lot of old web pages and later use that high ranking for selling SEO optimisation.&lt;/p&gt;
&lt;p&gt;If you have made the mistake of linking to something under en-html.org then I recommend that you change the link to the original content on archive.org.&lt;/p&gt;
&lt;p&gt;If you receive email from the en-html.org domain then ignore it, or configure your mail server to reject it.&lt;/p&gt;
&lt;p&gt;I am seriously considering configuring the DNS servers I run to return no valid data for any requests under that domain.&lt;/p&gt;
&lt;p&gt;Also I will reject all future requests to update links in old blog posts. The very small number of people who want to see what I linked to in old posts can use archive.org.&lt;/p&gt;
&lt;div class=&quot;yarpp yarpp-related yarpp-related-rss yarpp-template-list&quot;&gt;

&lt;p&gt;Related posts:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2008/07/07/advertising-a-scam/&quot; rel=&quot;bookmark&quot; title=&quot;Advertising a Scam&quot;&gt;Advertising a Scam&lt;/a&gt; &lt;small&gt;Below is a strange Google advert that appeared on my...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2010/02/09/web-site-validation/&quot; rel=&quot;bookmark&quot; title=&quot;Web Site Validation&quot;&gt;Web Site Validation&lt;/a&gt; &lt;small&gt;Over the last few days I’ve got this blog and...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2007/06/10/putting-html-codes-and-other-special-characters-into-a-blog-entry/&quot; rel=&quot;bookmark&quot; title=&quot;putting HTML codes and other special characters into a blog entry&quot;&gt;putting HTML codes and other special characters into a blog entry&lt;/a&gt; &lt;small&gt;I often want to write blog posts about HTML code...&lt;/small&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Fri, 09 Oct 2026 07:27:23 +0000</pubDate>

</item> 
<item>
	<title>Louis-Philippe Véronneau: Removing myself as a Lintian uploader in the next few weeks</title>
	<guid>tag:veronneau.org,2026-10-09:/removing-myself-as-a-lintian-uploader-in-the-next-few-weeks.html</guid>
	<link>https://veronneau.org/removing-myself-as-a-lintian-uploader-in-the-next-few-weeks.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/pollo.png&quot; width=&quot;65&quot; height=&quot;70&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;A few days ago, a colleague reached out to me, asking if I could help draft a
resolution on digital autonomy and free software for the upcoming renewal of
our collective bargaining agreement. Although she&#39;s very politicised and
generally a great individual, she is not a techie and we never really talked
about these issues before.&lt;/p&gt;
&lt;p&gt;This took me by surprise. I should have been rejoicing; no, I should have been
the one who brought up this topic in our union. Wasn&#39;t I the technical expert
on these issues? But alas, my first reaction when she came to me was to snicker
and tell myself: &quot;That&#39;s cute, but nothing&#39;s ever gonna change, Big Tech is too
strong and our governments don&#39;t give a damn.&quot;&lt;/p&gt;
&lt;p&gt;How sad and cynical is that? That&#39;s not the person I want to be.&lt;/p&gt;
&lt;p&gt;Something in the Quebecois political landscape has shifted in the last few
years with regards to tech. More and more &quot;regular&quot; people seem to be talking
about the importance of digital autonomy, how government services shouldn&#39;t
rely on Big Tech and how we should be using FOSS on hardware we actually
control.&lt;/p&gt;
&lt;p&gt;A few years ago, I would have been at the vanguard of this change. I would have
been part of the creation of &lt;a href=&quot;https://www.donneessouveraines.quebec/&quot;&gt;Données souveraines Québec&lt;/a&gt;. Heck, they are
organising &lt;a href=&quot;https://www.donneessouveraines.quebec/evenements/forum-dsq-2026&quot;&gt;a whole conference&lt;/a&gt; next week and I&#39;m not even going. How did
this happen to me?&lt;/p&gt;
&lt;p&gt;I first fell for Free Software for its political ideals: Knowledge Should Be
Free, Cooperation Is More Efficient Than Competition, Centralisation Should Be
Avoided When Possible, etc. I still believe in all of this, but somehow, after
years of fighting for change in the tech world, I have retreated into technical
work. I maintain Debian packages as a hobby and to scratch my own itch. I run
services for myself and a few friends. I organise Debian User Group meetings.&lt;/p&gt;
&lt;p&gt;To be clear, I haven&#39;t generally given up. I&#39;m very politically active in my
union and at work, I&#39;m a good member of my housing cooperative and I&#39;m still
fighting &lt;a href=&quot;https://resisteretfleurir.info/&quot;&gt;against the industrialisation of natural spaces in my
neighborhood&lt;/a&gt;. But when it comes time to defend freedom in the tech
world, lately, I&#39;ve just been shrugging and accepting I should use Microsoft
Teams like every one else does. I want this to change and to do so, I need to
free some time.&lt;/p&gt;
&lt;h2&gt;Lintian&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://salsa.debian.org/lintian/lintian/-/commit/58c0efd67f95fa6d5a19346dabed574d56dd654e&quot;&gt;Two years ago&lt;/a&gt;, I added myself to Lintian&#39;s Uploaders list. Up until
then&lt;sup id=&quot;fnref:while&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://veronneau.org/feeds/languages/en.atom.xml#fn:while&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, I enjoyed fixing little issues here and there and liked creating
new tags to help out the Python Team, where most of my Debian time was spent.&lt;/p&gt;
&lt;p&gt;Lintian was badly in need of a new maintainer and as I felt it was an important
project, I decided to step in. 37 releases and about 160 closed bugs
later&lt;sup id=&quot;fnref:others&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://veronneau.org/feeds/languages/en.atom.xml#fn:others&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, I&#39;m done.&lt;/p&gt;
&lt;p&gt;To be honest, I haven&#39;t had much fun maintaining Lintian lately. Bugs keep
piling on the BTS, so much so I have mostly been ignoring them for the past few
months. In fact, most of the actual work triaging, writing code and fixing bug
&lt;a href=&quot;https://salsa.debian.org/lintian/lintian/-/merge_requests/?state=merged&amp;amp;author_username=nilesh&quot;&gt;has been done by Nilesh Patra&lt;/a&gt; for a while now.&lt;/p&gt;
&lt;p&gt;All this to say, if you care about Lintian, you should consider adding yourself
to the Uploaders list, as I&#39;m out and Nilesh can&#39;t do all the work by himself.&lt;/p&gt;
&lt;p&gt;He&#39;s a great person to work with and since I don&#39;t want to suddenly leave him
all alone, I&#39;ll be sticking around for a few more weeks in the hope someone
else will volunteer to help out. A smooth transition with a new co-maintainer
would really be nice!&lt;/p&gt;
&lt;p&gt;If you&#39;re interested, don&#39;t hesitate to reach out to me on IRC or by email.&lt;/p&gt;
&lt;div class=&quot;footnote&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn:while&quot;&gt;
&lt;p&gt;My first technical commit to Lintian was nearly &lt;a href=&quot;https://salsa.debian.org/lintian/lintian/-/commit/025a7ee7b81c25e4746a4217e7e1a6286c118754&quot;&gt;7 years
ago&lt;/a&gt;! Crazy how time flies. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://veronneau.org/feeds/languages/en.atom.xml#fnref:while&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:others&quot;&gt;
&lt;p&gt;Mostly closed by other people than I! &lt;a class=&quot;footnote-backref&quot; href=&quot;https://veronneau.org/feeds/languages/en.atom.xml#fnref:others&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Fri, 09 Oct 2026 04:00:00 +0000</pubDate>

</item> 
<item>
	<title>Reproducible Builds (diffoscope): diffoscope 333 released</title>
	<guid>https://diffoscope.org/news/diffoscope-333-released/</guid>
	<link>https://diffoscope.org/news/diffoscope-333-released/</link>
     <description>  &lt;p&gt;The diffoscope maintainers are pleased to announce the release of diffoscope
version &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;333&lt;/code&gt;. This version includes the following changes:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ Johannes Schauer Marin Rodrigues ]
* Add support for showing differences in POSIX.1-2001 PAX headers within .tar
  files.

[ Chris Lamb ]
* Re-order various parts of the tar comparator to make it easier to
  progressively delve into its functionality.
* Reflect that the use of the &quot;case-match&quot; language feature requires at least
  Python 3.10+. This can be worked around if it causes problems - let us know.
* Update various copyright years.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You find out more by &lt;a href=&quot;https://diffoscope.org&quot;&gt;visiting the project homepage&lt;/a&gt;.&lt;/p&gt; </description> 
	<pubDate>Fri, 09 Oct 2026 00:00:00 +0000</pubDate>

</item> 
<item>
	<title>Antoine Beaupré: PSA: Europe changes time forward soon, North America next, for the last time?</title>
	<guid>https://anarc.at/blog/2026-10-08-dst-warning/</guid>
	<link>https://anarc.at/blog/2026-10-08-dst-warning/</link>
     <description>  &lt;blockquote&gt;&lt;p&gt;This is a copy of an email I &lt;a href=&quot;https://lists.torproject.org/mailman3/hyperkitty/list/tor-project@lists.torproject.org/thread/P5YBMLD4VDI4QGAEC6HIPN34U3SVD42G/&quot;&gt;sent at work&lt;/a&gt;. I&#39;m not sure I
should be making noise about this here, feedback welcome.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;This is your bi-yearly reminder that time is changing soon! October 25th
in Europe, November 1st in North America. Less people in Canada are
changing this year, with BC, Alberta, Manitoba and Northwest
Territories getting rid of DST.&lt;/p&gt;

&lt;h1 id=&quot;whats-happening&quot;&gt;What&#39;s happening?&lt;/h1&gt;

&lt;p&gt;Some places in the world implement what is called Daylight saving time
or DST:&lt;/p&gt;

&lt;p&gt;https://en.wikipedia.org/wiki/Daylight_saving_time&lt;/p&gt;

&lt;p&gt;Normally, you shouldn&#39;t have to do anything: computers automatically
change time following local rules, assuming they are correctly
configured, provided recent updates have been applied in the case of a
recent change in said rules (because yes, this happens, and happened
this year, and yes, you need to upgrade your software!).&lt;/p&gt;

&lt;p&gt;Of course, appliances like your microwave oven will likely &lt;em&gt;not&lt;/em&gt; change
time and will need to adjusted unless they are so-called &quot;smart&quot;, in
which case they are part of the skynet botnet and should be destroyed.&lt;/p&gt;

&lt;p&gt;If your clock is flashing &quot;0:00&quot; or &quot;12:00&quot;, you have no action to take
to adapt to this change, lucky you.&lt;/p&gt;

&lt;p&gt;If you haven&#39;t changed time in six months, congratulations, your clock
will be accurate again!&lt;/p&gt;

&lt;p&gt;In any case, you should still consider DST because it might affect some
of your meeting schedules, particularly if you set up a new meeting
schedule in the last 6 months and forgot to consider this change.&lt;/p&gt;

&lt;h1 id=&quot;if-your-location-does-not-have-dst&quot;&gt;If your location does not have DST&lt;/h1&gt;

&lt;p&gt;Properly scheduled meetings affecting multiple time zones are set in UTC
time, which does &lt;em&gt;not&lt;/em&gt; change. So if your location does not observer
time changes, your (local!) meeting time will &lt;em&gt;not&lt;/em&gt; change.&lt;/p&gt;

&lt;p&gt;But be aware that some other folks attending your meeting &lt;em&gt;might&lt;/em&gt; have
the DST bug and &lt;em&gt;their&lt;/em&gt; meeting times will change.&lt;/p&gt;

&lt;p&gt;Be kind to those poor souls which might be missing meetings by a full
&lt;em&gt;hour&lt;/em&gt; because time flies backwards for them.&lt;/p&gt;

&lt;h1 id=&quot;if-you-do-observe-dst&quot;&gt;If you do observe DST&lt;/h1&gt;

&lt;p&gt;If you are affected by daylight savings, your &lt;em&gt;local&lt;/em&gt; meeting times
&lt;em&gt;will&lt;/em&gt; change for UTC meetings. Normally, your meeting times are
scheduled to take this into account and the new hours should be
reasonable.&lt;/p&gt;

&lt;p&gt;But now is a good time to verify that. Take a look at your schedule for
the next couple of weeks and reschedule meetings &lt;em&gt;before&lt;/em&gt; the daylight
saving come up to avoid too much disruption. You have only a couple of
weeks to do so right now.&lt;/p&gt;

&lt;h1 id=&quot;when-do-times-change-how-and-and-where&quot;&gt;When do times change, how, and and where?&lt;/h1&gt;

&lt;p&gt;As regular readers will remember, the rule of thumb is:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Spring forward, fall backwards.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;That is, during the season of Spring, the clocks move forward, and
during the Fall (like right now), they move backwards. That is in the
northern hemisphere, but then the southern hemisphere is often saner and
doesn&#39;t switch anyways.&lt;/p&gt;

&lt;p&gt;So time will move &lt;em&gt;backwards&lt;/em&gt; which means an extra hour of sleep. Unless
you have children or bad sleep, in which case your body doesn&#39;t care
about what the clock says and will wake up one hour earlier than what it
should.&lt;/p&gt;

&lt;p&gt;And of course, this doesn&#39;t happen everywhere at once, so let&#39;s see when
it happens where.&lt;/p&gt;

&lt;h2 id=&quot;europe&quot;&gt;Europe&lt;/h2&gt;

&lt;p&gt;The dance starts in Europe.&lt;/p&gt;

&lt;p&gt;The change happens on the last Sunday in October at 01:00 UTC (not local
time!), that is October 25th. If you are in the central European
timezone, also known as Amsterdam, Berlin, or Paris time depending on
your national affiliation, that essentially means that at 2:59 local the
clocks will fall back to 2:00 instead of going to 3:00.&lt;/p&gt;

&lt;p&gt;Concretely, set your watch back one hour before going to bed, go to bed
at the normal time, and enjoy an extra hour of sleep or leisure.&lt;/p&gt;

&lt;p&gt;If you have kids, you might want to start getting them to bed slightly
earlier every day for a week before the change so they take time getting
used to the change. If you have trouble sleeping in the morning, find
your inner child and do that to yourself as well.&lt;/p&gt;

&lt;h2 id=&quot;usa-canada&quot;&gt;USA / Canada&lt;/h2&gt;

&lt;p&gt;Then it&#39;s the US[1] and Canada[2] joining the dance, on the First Sunday in
November at 02:00 local (not UTC!), that is, I believe, November 1st
2026.&lt;/p&gt;

&lt;p&gt;This means that, at 1:59, the clocks will flip to 1:00, instead of 2:00.&lt;/p&gt;

&lt;p&gt;Concretely, do like the Europeans and tweak your clock before going to
bed.&lt;/p&gt;

&lt;p&gt;That is a little less than four weeks from now.&lt;/p&gt;

&lt;p&gt;[1] except Arizona (except the Navajo nation), US territories, and
Hawaii&lt;/p&gt;

&lt;p&gt;[2] except Yukon, Saskatchewan, (newly) British Columbia, (newly)
Alberta, (newly) Northwest Territories, (newly) Manitoba, one island in
Nunavut (Southampton Island), one town in Ontario (Atikokan) and small
parts of Quebec (Le Golfe-du-Saint-Laurent)&lt;/p&gt;

&lt;h2 id=&quot;other-places-with-dst&quot;&gt;Other places with DST&lt;/h2&gt;

&lt;p&gt;This time again, I must apologize to the people of Cuba, Lebanon,
Israel, Palestine, Egypt, Chile, Australia, and New Zealand, as you fine
folks all have your own DST rules that are omitted here for brevity. I
rely on this page from Wikipedia to be updated by time nerds accurately
for this message, and it should provide you with a rough idea of what&#39;s
coming:&lt;/p&gt;

&lt;p&gt;https://en.wikipedia.org/wiki/Daylight_saving_time_by_country&lt;/p&gt;

&lt;p&gt;In general, changes also happen in October, but either on different
times or different days, except in the south hemisphere, where they
might happen in September (oops, sorry NZ folks, I&#39;m late!).&lt;/p&gt;

&lt;h2 id=&quot;places-without-dst&quot;&gt;Places without DST&lt;/h2&gt;

&lt;p&gt;Everyone else, enjoy, you&#39;re on the right side of history, and we thank
you for the good example you give us.&lt;/p&gt;

&lt;h2 id=&quot;changes-since-last-time&quot;&gt;Changes since last time&lt;/h2&gt;

&lt;p&gt;There&#39;s been &lt;em&gt;lots&lt;/em&gt; of changes since last time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;British Columbia moved to permanent -07 on 2026-03-09, that is it
will &lt;em&gt;not&lt;/em&gt; change to normal time in November&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alberta moved to permanent -06 on 2026-06-18, similar to BC above.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Canada’s Northwest Territories moved to permanent -06 on 2026-08-21,
matching Alberta.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Manitoba moves to permanent -05 on 2026-10-31.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Morocco moves to permanent +00 on 2026-09-20.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Moldova has used EU transition times since 2022, but the tz database
only noticed in 2026&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;This is my interpretation of the changes announced on the tzdata mailing
list here:&lt;/p&gt;

&lt;p&gt;https://lists.iana.org/hyperkitty/list/tz-announce@iana.org/latest&lt;/p&gt;

&lt;p&gt;If the eastward trend continues, Canada should adopt country-wide &quot;no
daylight savings&quot; rules by 2027, although there&#39;s actually no sign of
the other provinces (Ontario, Québec and so on) currently running bills
to change those rules just yet. Poor Canadians like me confused about
time in their countries can refer to this section of Wikipedia for
details:&lt;/p&gt;

&lt;p&gt;https://en.wikipedia.org/wiki/Daylight_saving_time_in_Canada#By_province_and_territory&lt;/p&gt;

&lt;p&gt;... and particularly the image featured there:&lt;/p&gt;

&lt;p&gt;https://commons.wikimedia.org/wiki/File:Canada_time_zone_map&lt;em&gt;-&lt;/em&gt;en.svg&lt;/p&gt;

&lt;p&gt;It also seems like the US government &lt;em&gt;might&lt;/em&gt; finally adopt a permanent
daylight saving change bill in 2026, as the &quot;Sunshine protection act&quot;
pass the house in July:&lt;/p&gt;

&lt;p&gt;https://en.wikipedia.org/wiki/Sunshine_Protection_Act&lt;/p&gt;

&lt;p&gt;True to form, this was associated with absolutely ridiculous pressure
from Donald Trump against republicans (his own party!) objecting to the
change:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;On July 14, 2026, the House passed a Sunshine Protection Act bill
backed by President Trump. Nevertheless, the bill was opposed in the
Senate by Republicans, including Senator Cotton. In response, on
October 3, 2026, Trump shared a post on Truth Social urging Cotton to
approve the bill, where he revealed Cotton&#39;s personal cellphone number
and called on people to call him.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;https://www.theguardian.com/us-news/2026/oct/03/trump-tom-cotton-daylight-saving-time&lt;/p&gt;

&lt;p&gt;Given that the last time the US did a major change to the daylight
savings policy (in 2005), Canada followed suit to stay in sync, it&#39;s
quite possible Trump&#39;s mad dash might actually finish getting rid of DST
in North America:&lt;/p&gt;

&lt;p&gt;https://en.wikipedia.org/wiki/Energy_Policy_Act_of_2005#Change_to_daylight_saving_time&lt;/p&gt; </description> 
	<pubDate>Thu, 08 Oct 2026 19:30:02 +0000</pubDate>

</item> 
<item>
	<title>Thorsten Alteholz: My Debian Activities in September 2026</title>
	<guid>http://blog.alteholz.eu/?p=2854</guid>
	<link>http://blog.alteholz.eu/2026/10/my-debian-activities-in-september-2026/</link>
     <description>  &lt;h3&gt;&lt;strong&gt;Debian LTS/ELTS&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;&lt;/p&gt;&lt;p&gt;This was my hundred-forty-seventh month that I did some work for the Debian LTS initiative, started by Raphael Hertzog at Freexian.
&lt;/p&gt;
&lt;p&gt;
During my allocated time I uploaded or worked on:  
&lt;/p&gt;&lt;p&gt;&lt;/p&gt;



&lt;ul&gt;&lt;li&gt;[&lt;a href=&quot;https://lists.debian.org/debian-lts-announce/2026/09/msg00038.html&quot;&gt;DLA 4804-1&lt;/a&gt;]  libsmpp34 security update to fix one CVE in Bookworm related to an out of bound read.&lt;/li&gt;&lt;li&gt;[&lt;a href=&quot;https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1142351&quot;&gt;#1149107&lt;/a&gt;] trixie-pu of libsmpp34 has been created and wait for review by the release team.&lt;/li&gt;&lt;li&gt;[&lt;a href=&quot;https://lists.debian.org/debian-lts-announce/2026/09/msg00040.html&quot;&gt;DLA 4805-1&lt;/a&gt;]  mkvtoolnix security update to fix one CVE in Bookworm related to a heap buffer overflow.
&lt;/li&gt;&lt;li&gt;[&lt;a href=&quot;https://lists.debian.org/debian-lts-announce/2026/09/msg00039.html&quot;&gt;DLA 4806-1&lt;/a&gt;] pgextwlist security update to fix one CVE in Bookworm related to substituting extension schemas or owners matching [“$’\].
&lt;/li&gt;&lt;li&gt;[ELA-1837-1] mkvtoolnix gimp security update to fix one CVE in Bullseye to a heap buffer overflow.&lt;/li&gt;&lt;li&gt;[osmo-iuh] upload to fix a CVE related to a reachable assertion in Sid.&lt;/li&gt;&lt;/ul&gt;



&lt;p&gt;&lt;/p&gt;&lt;p&gt;
Besides doing these uploads, the month was filled with unscheduled meetings, discussions and explanations, all basically around the role of FD.&lt;/p&gt;&lt;p&gt;
During my week of FD duties, I had to become familiar with new tools. As there are several things that FD has to do over and over again, I tried to automate this a bit. My experiments went well and I think this can be used to make FD duties less repetitive.&lt;/p&gt;&lt;p&gt;
I also continued my work on &lt;i&gt;cups&lt;/i&gt; and &lt;i&gt;hplip&lt;/i&gt; and I am confident that I can do uploads in October.
Last but not least I spend some time on security-master to assist others (especially the kernel team) with uploads to Bookworm and Bullseye.
&lt;/p&gt;
&lt;p&gt;
In case you need to get a complete clone of the security-tracker, using the option &lt;i&gt;–deepen n&lt;/i&gt; might be of help. Unfortunately in case you choosed n too high and some kind of error appears, something gets into a mess and you need to start almost from the beginning (some objects are still present and are used again). If you want to run a script, a value of &lt;i&gt;10&lt;/i&gt; might be a good choice. You don’t have to &lt;i&gt;deepen&lt;/i&gt; back to the beginning. At some point in time you can just &lt;i&gt;–unshallow&lt;/i&gt; and get the whole rest. Afterwards doing a &lt;i&gt;git gc&lt;/i&gt; is highly recommended.&lt;/p&gt;



&lt;h3&gt;&lt;strong&gt;Debian Printing&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;This month I uploaded a new upstream version  or a bugfix version of:&lt;/p&gt;



&lt;ul&gt;&lt;li&gt;… &lt;a href=&quot;https://tracker.debian.org/hplip&quot;&gt;hplip&lt;/a&gt; to unstable, to fix an expired certificate and some bugs.&lt;/li&gt;&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;This work is generously funded by &lt;a href=&quot;https://www.freexian.com&quot;&gt;Freexian&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;



&lt;h3&gt;&lt;strong&gt;Debian Lomiri&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Unfortunately this month my work did not make any progress.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Nevertheless, in case of any work done, this would have been generously funded by &lt;a href=&quot;https://freiesoftware.gmbh/&quot;&gt;Fre(i)e Software GmbH&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;



&lt;h3&gt;&lt;strong&gt;Debian Astro&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Unfortunately I had no time to work in this category this month.&lt;/p&gt;



&lt;h3&gt;&lt;strong&gt;Debian IoT&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;Unfortunately I had no time to work in this category this month.&lt;/p&gt;



&lt;h3&gt;&lt;strong&gt;Debian Mobcom&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;This month I uploaded a new upstream version  or a bugfix version of:&lt;/p&gt;



&lt;ul&gt;&lt;li&gt;… &lt;a href=&quot;https://tracker.debian.org/osmocom-dahdi-linux&quot;&gt;osmocom-dahdi-linux&lt;/a&gt; to unstable to fix some bugs.&lt;/li&gt;&lt;li&gt;… &lt;a href=&quot;https://tracker.debian.org/osmo-iuh&quot;&gt;osmo-iuh&lt;/a&gt; to unstable.&lt;/li&gt;&lt;/ul&gt;



&lt;h3&gt;&lt;strong&gt;misc&lt;/strong&gt;&lt;/h3&gt;



&lt;p&gt;This month I uploaded a new upstream version  or a bugfix version of:&lt;/p&gt;



&lt;ul&gt;&lt;li&gt;… &lt;a href=&quot;https://tracker.debian.org/pkcs11-proxy&quot;&gt;pkcs11-proxy&lt;/a&gt; to unstable to fix a bug related to openssl 4.0.&lt;/li&gt;&lt;li&gt;… &lt;a href=&quot;https://tracker.debian.org/meep&quot;&gt;meep&lt;/a&gt; to unstable to fix bugs.&lt;/li&gt;&lt;li&gt;… &lt;a href=&quot;https://tracker.debian.org/meep-mpi-default&quot;&gt;meep-mpi-default&lt;/a&gt; to unstable to fix bugs.&lt;/li&gt;&lt;li&gt;… &lt;a href=&quot;https://tracker.debian.org/harminv&quot;&gt;harminv&lt;/a&gt; to unstable to fix bugs.&lt;/li&gt;&lt;li&gt;… &lt;a href=&quot;https://tracker.debian.org/libctl&quot;&gt;libctl&lt;/a&gt; to unstable to fix bugs.&lt;/li&gt;&lt;/ul&gt; </description> 
	<pubDate>Thu, 08 Oct 2026 17:19:04 +0000</pubDate>

</item> 
<item>
	<title>Dirk Eddelbuettel: myman 0.10.0 on CRAN: Three new waves of posts!</title>
	<guid>http://dirk.eddelbuettel.com/blog/2026/10/08#myman_0.10.0</guid>
	<link>http://dirk.eddelbuettel.com/blog/2026/10/08#myman_0.10.0</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dirk.png&quot; width=&quot;65&quot; height=&quot;90&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;A new and exciting version of our still-new package &lt;a href=&quot;https://github.com/eddelbuettel/myman&quot;&gt;myman&lt;/a&gt; reached &lt;a href=&quot;https://cran.r-project.org&quot;&gt;CRAN&lt;/a&gt; this morning, and has been
built for &lt;a href=&quot;https://eddelbuettel.github.io/r2u/&quot;&gt;r2u&lt;/a&gt; and on
&lt;a href=&quot;https://eddelbuettel.r-universe.dev/myman&quot;&gt;r-universe&lt;/a&gt;. The
matching &lt;a href=&quot;https://pypi.org/project/myman/&quot;&gt;Python package&lt;/a&gt;
has also been updated. The package offers nineteen hundred eighty four
&lt;em&gt;“My man …”&lt;/em&gt; posts by &lt;a href=&quot;https://bsky.app/profile/kevinmkruse.bsky.social&quot;&gt;Kevin Kruse&lt;/a&gt;
made on &lt;a href=&quot;https://bsky.app&quot;&gt;bsky&lt;/a&gt; during the summer of 2026.
Each wave picked at one particular public persona. This package wrapse
these up in the style of packages like &lt;a href=&quot;https://zeileis.codeberg.page/fortunes/&quot;&gt;fortunes&lt;/a&gt; or &lt;a href=&quot;https://github.com/eddelbuettel/gaussfacts&quot;&gt;gaussfacts&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A sample usage illustration shows how to extract by pattern, and
shows posts from the two most recent waves:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode r&quot;&gt;&lt;code class=&quot;sourceCode r&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-1&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;sc&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;library&lt;/span&gt;(myman)&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-2&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;sc&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;myman&lt;/span&gt;(&lt;span class=&quot;st&quot;&gt;&quot;maitre&quot;&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-3&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;My man looks like he&lt;span class=&quot;st&quot;&gt;&#39;s inquiring with the maitre&#39;&lt;/span&gt;d about the house curly fries.&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-4&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     &lt;span class=&quot;sc&quot;&gt;--&lt;/span&gt; about Howard Lutnick on &lt;span class=&quot;dv&quot;&gt;2026-08-28&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-5&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-5&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-6&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-6&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;My man looks like a maitre&lt;span class=&quot;st&quot;&gt;&#39;d who deeply doubts you have a reservation.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-7&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-7&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;     -- about Scott Bessent on 2026-08-31&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-8&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-8&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-9&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-9&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;My man looks like he&#39;&lt;/span&gt;s asked the maitre&lt;span class=&quot;st&quot;&gt;&#39;d to remove a party of four he finds visually&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-10&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-10&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;unpleasant.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-11&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-11&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;     -- about Scott Bessent on 2026-08-31&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-12&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-12&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-13&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-13&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;My man looks like the maitre&#39;&lt;/span&gt;d at a very exclusive restaurant called The Berghof.&lt;/span&gt;
&lt;span id=&quot;cb1-14&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-14&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;     &lt;span class=&quot;sc&quot;&gt;--&lt;/span&gt; about JD Vance on &lt;span class=&quot;dv&quot;&gt;2026-09-13&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-15&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-15&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-16&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-16&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;My man looks like he&lt;span class=&quot;st&quot;&gt;&#39;s asking the maitre&#39;&lt;/span&gt;d where they source their corn dogs.&lt;/span&gt;
&lt;span id=&quot;cb1-17&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-17&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;         &lt;span class=&quot;sc&quot;&gt;--&lt;/span&gt; about Palmer Luckey on &lt;span class=&quot;dv&quot;&gt;2026-10-02&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-18&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-18&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-19&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-19&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;My man looks like Data had to borrow a sports jacket from the maitre&lt;span class=&quot;st&quot;&gt;&#39;d.&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-20&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-20&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;         -- about Elon Musk on 2026-10-05&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-21&quot;&gt;&lt;a href=&quot;https://dirk.eddelbuettel.com/blog/index.rss#cb1-21&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;st&quot;&gt;&amp;gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;One can also subset by ‘target’, or sample randomly (which is the
default).&lt;/p&gt;
&lt;p&gt;As noted during the &lt;a href=&quot;https://dirk.eddelbuettel.com/blog/2026/09/30#myman_0.1.0&quot;&gt;initial
announcement&lt;/a&gt; last week, wave eight did not make it into the initial
&lt;a href=&quot;https://cran.r-project.org&quot;&gt;CRAN&lt;/a&gt; release as it happened
while the package was under review. Waves nine and ten occured more or
less while I was out of town last weekend—so this release now brings
three new waves to the CRAN package! We also added two new helper
functions to extract the underlying data frame object, and tabulate the
targetted men.&lt;/p&gt;
&lt;p&gt;To align the version number with the count of post ‘waves’, we
switched to version 0.10.0 for this release and the corresponding &lt;a href=&quot;https://pypi.org/project/myman/&quot;&gt;Python package&lt;/a&gt; release so
that both implementations now have the same version number.&lt;/p&gt;
&lt;p&gt;The NEWS entry for this release follows.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h4 id=&quot;changes-in-version-0.10.0-2026-10-08&quot;&gt;Changes in version 0.10.0
(2026-10-08)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;New waves nine (100 posts) and ten (190 posts) made last week;
total is now 1984 posts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;New helper functions &lt;code&gt;posts()&lt;/code&gt; and &lt;code&gt;men()&lt;/code&gt;
retrieving data.frame of posts and tabulation of targets&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Internal post gathering and aggregation functions have been
updated and generalized&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Versioning scheme now goes with post waves (also for Python
sibbling)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Courtesy of my &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/&quot;&gt;CRANberries&lt;/a&gt;, there
is also a diffstat report for the &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/2026/10/08#myman_0.10.0&quot;&gt;most
recent release&lt;/a&gt;. More information is available at the &lt;a href=&quot;https://github.com/eddelbuettel/myman&quot;&gt;repository&lt;/a&gt; or the &lt;a href=&quot;https://dirk.eddelbuettel.com/code/myman.html&quot;&gt;package
page&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot;font-size: 80%; font-style: italic;&quot;&gt;
This post by &lt;a href=&quot;https://dirk.eddelbuettel.com&quot;&gt;Dirk
Eddelbuettel&lt;/a&gt; originated on his &lt;a href=&quot;https://dirk.eddelbuettel.com/blog/&quot;&gt;Thinking inside the box&lt;/a&gt;
blog. If you like this or other open-source work I do, you can &lt;a href=&quot;https://github.com/sponsors/eddelbuettel&quot;&gt;sponsor me at
GitHub&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt; </description> 
	<pubDate>Thu, 08 Oct 2026 16:27:00 +0000</pubDate>

</item> 
<item>
	<title>Kentaro Hayashi: Testing Japanese IMEs on virtual desktops with virt-japanese-desktop</title>
	<guid>hatenablog://entry/14945776032087269493</guid>
	<link>https://kenhys.hatenablog.jp/entry/2026/10/07/214713</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/kenhys.png&quot; width=&quot;72&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;Japanese input method editors (IMEs) such as &lt;strong&gt;Mozc&lt;/strong&gt; are essential for typing
Japanese (yes, skk, anthy and more, but it&#39;s out-of-scope in this article). Testing them is a surprisingly fiddly job: an IME behaves differently
depending on the desktop environment (GNOME, KDE, Xfce, Budgie), the input
framework (ibus, fcitx5, uim), and the Wayland or X11 session. Setting up a
fresh VM for every combination from scratch is slow and repetitive, and
breaking your host&#39;s environment while experimenting is no fun.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;virt-japanese-desktop&lt;/code&gt; is a small set of toy scripts that solves exactly this
problem. It builds ready-to-use virtual machines - each with a desktop
environment and a Japanese IME already installed and configured - so you can
start typing Japanese within a minute of booting, and throw the whole thing
away without any impact on your host.&lt;/p&gt;

&lt;h2 id=&quot;What-it-gives-you&quot;&gt;What it gives you&lt;/h2&gt;

&lt;p&gt;A single &lt;code&gt;make&lt;/code&gt; command produces a qcow2 image that combines one of four
desktops with one of three IMEs:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;  &lt;/th&gt;
&lt;th&gt; ibus-mozc &lt;/th&gt;
&lt;th&gt; fcitx5-mozc &lt;/th&gt;
&lt;th&gt; uim-mozc &lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt; &lt;strong&gt;GNOME&lt;/strong&gt; &lt;/td&gt;
&lt;td&gt; ✓ &lt;/td&gt;
&lt;td&gt; ✓ &lt;/td&gt;
&lt;td&gt; ✓ &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; &lt;strong&gt;KDE&lt;/strong&gt; &lt;/td&gt;
&lt;td&gt; ✓ &lt;/td&gt;
&lt;td&gt; ✓ &lt;/td&gt;
&lt;td&gt; ✓ &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; &lt;strong&gt;Xfce&lt;/strong&gt; &lt;/td&gt;
&lt;td&gt; ✓ &lt;/td&gt;
&lt;td&gt; ✓ &lt;/td&gt;
&lt;td&gt; ✓ &lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt; &lt;strong&gt;Budgie&lt;/strong&gt; &lt;/td&gt;
&lt;td&gt; ✓ &lt;/td&gt;
&lt;td&gt; ✓ &lt;/td&gt;
&lt;td&gt; ✗ &lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;


&lt;p&gt;The one gap - &lt;strong&gt;uim on Budgie&lt;/strong&gt; - is a real technical limitation, not an
oversight: Budgie runs the labwc compositor, which implements
&lt;code&gt;zwp_input_method_v2&lt;/code&gt;, while &lt;code&gt;uim-wayland&lt;/code&gt; only speaks the older
&lt;code&gt;zwp_input_method_v1&lt;/code&gt; (KWin/Weston). On Budgie you use ibus-mozc or fcitx5-mozc
instead.&lt;/p&gt;

&lt;p&gt;All images come with the Japanese locale, fonts, and the &lt;code&gt;Asia/Tokyo&lt;/code&gt; time
zone pre-configured, plus the SSH key of your choice. Input switching is wired
up out of the box: &lt;strong&gt;Ctrl + Space&lt;/strong&gt; or &lt;strong&gt;Shift + Space&lt;/strong&gt; for your IMEs to enable it.&lt;/p&gt;

&lt;h2 id=&quot;The-layered-image-trick&quot;&gt;The layered-image trick&lt;/h2&gt;

&lt;p&gt;The core idea is that the images are &lt;strong&gt;stacked qcow2 overlay layers&lt;/strong&gt;, one on
top of another:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;debian-sid-nocloud-amd64-daily.qcow2     ... base image you download
└─ unstable-japanese-template.qcow2      ... locale, fonts, user, SSH
   └─ unstable-&amp;lt;DE&amp;gt;-template.qcow2       ... a desktop environment
      └─ unstable-&amp;lt;DE&amp;gt;-&amp;lt;IME&amp;gt;.qcow2       ... desktop + IME, configured
         └─ unstable-&amp;lt;DE&amp;gt;-&amp;lt;IME&amp;gt;.workspace.qcow2 ... the image you test in&lt;/pre&gt;


&lt;p&gt;This makes both &lt;strong&gt;building and resetting fast&lt;/strong&gt;. The first build downloads and
customizes the base image and takes a while, but every later step only adds a
thin overlay. When a test breaks the VM, you do not rebuild anything - you
simply delete the top &lt;em&gt;workspace&lt;/em&gt; layer and recreate it. That is all it takes
to return to a pristine state:&lt;/p&gt;

&lt;pre class=&quot;code lang-sh&quot;&gt;&lt;span class=&quot;synStatement&quot;&gt;rm&lt;/span&gt; /tmp/unstable-gnome-ibus-mozc.workspace.qcow2
make gnome-ibus-mozc
&lt;/pre&gt;


&lt;p&gt;The images reference their backing files by &lt;strong&gt;relative path&lt;/strong&gt;, so you can move
an entire stack anywhere you like as long as the images stay together.&lt;/p&gt;

&lt;h2 id=&quot;A-platform-for-experimenting-with-bleeding-edge-IMEs&quot;&gt;A platform for experimenting with bleeding-edge IMEs&lt;/h2&gt;

&lt;p&gt;The base system is Debian &lt;strong&gt;unstable (sid)&lt;/strong&gt;, and the &lt;code&gt;experimental&lt;/code&gt;
repository is already added. That makes the project a convenient platform for
testing not just the IME packages in sid but also the ones still being
developed in &lt;code&gt;experimental&lt;/code&gt; - exactly what the project was built for.&lt;/p&gt;

&lt;p&gt;The keyboard layout of the VM follows the layout of your host (read from
&lt;code&gt;/etc/default/keyboard&lt;/code&gt;, with a fallback chain to &lt;code&gt;localectl&lt;/code&gt; and finally
&lt;code&gt;us&lt;/code&gt;).&lt;/p&gt;

&lt;h2 id=&quot;Quick-start&quot;&gt;Quick start&lt;/h2&gt;

&lt;pre class=&quot;code lang-sh&quot;&gt;&lt;span class=&quot;synComment&quot;&gt;# 1. Install the tools (Debian/Ubuntu example)&lt;/span&gt;
sudo apt install qemu-utils libguestfs-tools virt-install curl

&lt;span class=&quot;synComment&quot;&gt;# 2. Save your SSH public key&lt;/span&gt;
curl &lt;span class=&quot;synSpecial&quot;&gt;--location&lt;/span&gt; https://github.com/USERNAME.keys &lt;span class=&quot;synSpecial&quot;&gt;--output&lt;/span&gt; pubkey.pub

&lt;span class=&quot;synComment&quot;&gt;# 3. Download the base Debian sid image&lt;/span&gt;
make download

&lt;span class=&quot;synComment&quot;&gt;# 4. Build a desktop + IME (first build takes a while)&lt;/span&gt;
make gnome-ibus-mozc

&lt;span class=&quot;synComment&quot;&gt;# 5. Start it as a VM (needs the libvirt daemon, qemu:///system)&lt;/span&gt;
./scripts/make-virsh-image.sh virt-gnome-ibus-mozc /tmp/unstable-gnome-ibus-mozc.workspace.qcow2
&lt;/pre&gt;


&lt;p&gt;Log in as &lt;code&gt;debian&lt;/code&gt; (password &lt;code&gt;debian&lt;/code&gt;) and press &lt;strong&gt;Ctrl + Space&lt;/strong&gt; (&lt;strong&gt;Shift + Space&lt;/strong&gt;) to start
typing Japanese. The VM is registered in libvirt, so you can manage it with
&lt;code&gt;virsh&lt;/code&gt; or &lt;code&gt;virt-manager&lt;/code&gt; - handy for opening the SPICE console or restarting
the machine after a test.&lt;/p&gt;

&lt;h2 id=&quot;Status&quot;&gt;Status&lt;/h2&gt;

&lt;p&gt;The project is still in the &lt;strong&gt;proof-of-concept&lt;/strong&gt; phase, and it is developed
mainly to test Mozc and other IMEs across desktops and input frameworks.&lt;/p&gt;

&lt;p&gt;If you regularly test Japanese IMEs - give it a try.&lt;/p&gt; </description> 
	<pubDate>Wed, 07 Oct 2026 12:47:13 +0000</pubDate>

</item> 
<item>
	<title>Bits from Debian: Looking for artwork for the next Debian release: Forky</title>
	<guid>tag:bits.debian.org,2026-10-07:/2026/10/forky-artwork-cfp.html</guid>
	<link>https://bits.debian.org/2026/10/forky-artwork-cfp.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dwn.png&quot; width=&quot;77&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;Each release of Debian has a shiny new theme which is visible on the installer,
the boot screen, the login screen and, most prominently, on the desktop
wallpaper. It&#39;s a very important part of a Debian release as it is usually the
first thing new users see when installing or booting the system for the first
time. Not only that, but also the first thing appearing when debianites share
their screen or connect to an external device when giving talks around the
world.&lt;/p&gt;
&lt;p&gt;As the most enthusiastic users will know, the forky - yes, that is the name of
the next stable version, Debian 14 - release cycle is rapidly approaching its
latter stages. This means we need to select the artwork shipping with forky
soon, really soon!&lt;/p&gt;
&lt;p&gt;And as with everything else in Debian, collecting artwork is a collaborative
effort which Debian shares with its community.  So, if you would like (or know
someone who would like) to create a desktop look and feel that will be seen by
trillions of people around the world - and in space! - be sure to send in your
artwork ASAP!&lt;/p&gt;
&lt;p&gt;The deadline for submissions is: 2026-11-26.&lt;/p&gt;
&lt;p&gt;For the most up to date details please refer to the &lt;a href=&quot;https://wiki.debian.org/DebianDesktop/Artwork/Forky&quot;&gt;Debian
wiki&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At the same time, we would like to thank Elise Couper for creating the
&lt;a href=&quot;https://wiki.debian.org/DebianArt/Themes/Ceratopsian&quot;&gt;Ceratopsian theme&lt;/a&gt; for
our last trixie release.&lt;/p&gt;
&lt;p&gt;And for the interested or the curious ones, the artwork is usually picked
based on which theme looks the most:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&#39;&#39;Debian&#39;&#39;: admittedly not the most defined concept, since everyone has their
  own take on what Debian means to them. Though, usually they all agree when
  something looks like Debian.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&#39;&#39;Plausible to integrate without patching core software&#39;&#39;: as much as we love
  some of the insanely looking themes, some would require heavy GTK+ theming
  and patching GDM/GNOME.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&#39;&#39;Clean and well designed&#39;&#39;: without becoming something that gets annoying to
  look at a year, or ten, down the road.  Examples of good themes include
  Emerald, Homeworld, Joy, Lines, softWaves and futurePrototype&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&#39;d like more information or details, please post to the &lt;a href=&quot;https://lists.debian.org/debian-desktop/&quot;&gt;Debian Desktop
mailing list&lt;/a&gt;.&lt;/p&gt; </description> 
	<pubDate>Wed, 07 Oct 2026 09:00:00 +0000</pubDate>

</item> 
<item>
	<title>Russell Coker: A Power Case for a FOSS Phone</title>
	<guid>https://etbe.coker.com.au/?p=6307</guid>
	<link>https://etbe.coker.com.au/2026/10/06/power-case-foss-phone/</link>
     <description>  &lt;h2&gt;The Problem&lt;/h2&gt;
&lt;p&gt;I want to use a FOSS phone running Debian as my daily driver and not use a non-free OS on my phone. &lt;a href=&quot;https://grapheneos.org/&quot;&gt;GrapheneOS [1]&lt;/a&gt; is a FOSS rebuild of Android, it’s a great project and I commend them for what they are doing. But I want a system where I have access to all the bits and where I can ssh in to it and manage it in the same way as all other Linux systems. Android is free software but it’s a closed design and the phones are expected to be appliances not full peers on the network. The Android native terminal emulator (AKA Linux development environment) is a nice feature, a VM with a default of 1GB of RAM but it’s still separate from the main OS.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://kdeconnect.kde.org/&quot;&gt;KDE Connect [2]&lt;/a&gt; is a system for KDE talking to phones, it is a great project and allows convenient interaction between a Linux PC and a phone. But in addition to that I’d like the option to ssh to my phone to send an SMS or have one sent from a cron job. &lt;a href=&quot;https://etbe.coker.com.au/2026/10/06/kdeconnect-dbus/&quot;&gt;I blogged about using the basic functions of Kdeconnect from the command-line [3]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I have had ongoing issues with the battery not lasting long enough on the PinePhonePro (PPP) and the Librem 5 (L5) which makes them unusable for my purposes. For a phone running Droidian I can have an open ssh session (with keep-alive packets) running overnight on Wifi without any problems while for the PPP or L5 an hour of reading an ebook (the least demanding use of a phone) will use most of the battery.&lt;/p&gt;
&lt;p&gt;I sent my FuriPhone back for warranty repair and it’s been almost a month with no follow up, so I need to have another option.&lt;/p&gt;
&lt;h2&gt;The Aim&lt;/h2&gt;
&lt;p&gt;The aim of this post is to develop a rough design for a battery case for either a L5 or a PPP, I have both phones and they are both capable of doing what I want apart from battery life. Also designing a case that basically works for both phones and has two variations of the CAD file for 3D printing is good to allow collaboration with people who use either phone. Protecting the phone from damage when dropped is also a core feature.&lt;/p&gt;
&lt;p&gt;I investigated commercial options. There are some reports of cases for other phones working, someone reported a PPP working well with a battery case for a Samsung S20 Ultra. The OtterBox uniVERSE Case for Samsung Galaxy XCover Pro is reported to fit the PPP so probably battery cases for the XCover Pro will also work. There are also universal power cases which have spring clips to fit a wide range of phone sizes, but they are much larger than other options and probably increase the risk of damage if the phone is dropped.&lt;/p&gt;
&lt;p&gt;At this stage I’m planning out the rough specs of a case that can be 3D printed to protect a phone while being easy to change the cells. The process of changing cells should be quick, easy, and not risk breaking anything. The hardware required should be affordable ($100AU plus some 3D printing seems reasonable) and should not require significant skills to assemble. After recent experiments with Thinkpad repair I’ve determined that I am not good at electronics by today’s standards so I plan to avoid anything difficult in that regard.&lt;/p&gt;
&lt;h2&gt;Battery Options&lt;/h2&gt;
&lt;p&gt;There are phone cases with batteries built in for the more common phones. A quick search on AliExpress turned up options for recent Pixel phones. They aren’t as common as they used to be as Android phones and iPhones generally have good battery life nowadays. Of course there aren’t such options for less common phones like the L5 and PPP.&lt;/p&gt;
&lt;p&gt;It is cheap and easy to buy a portable battery for charging phones, but that’s a separate bulky device and unless the connector is inside a protective case it leaves the phone vulnerable to catastrophic damage if dropped.&lt;/p&gt;
&lt;p&gt;So can a suitable battery case be designed and 3D printed?&lt;/p&gt;
&lt;h2&gt;Cheap Batteries&lt;/h2&gt;
&lt;p&gt;According to Wikipedia the 18650 LiIon cell is the most commonly used LiIon battery, that is 18mm in diameter and 65mm in length. For a phone case thinner batteries would be more convenient but economies of scale make the 18650 cheap to buy new and commonly available on the second hand market. The current prices on AliExpress (in Australian dollars) are about $8 per cell when buying 10 at a time. Most of the cells on AliExpress don’t have wires attached so they can be swapped in a carrier the way AA batteries are used, but the cells are symmetrical (no bump for positive) so the user has to take care of polarity. Chargers are around $22 for a 4 cell charger or $52 for a 12 cell charger.&lt;/p&gt;
&lt;p&gt;I’ve seen prices as low as $1 per cell on the second hand market, I haven’t investigated the amount of usable capacity in such cells. Probably the prices for chargers I’ve found aren’t the best available but they are good enough to start the design. 10 cells and a 4 cell charger is about $100. That’s about 130Wh while a 74Wh USB-C battery pack costs about $50. So the price per Wh is OK.&lt;/p&gt;
&lt;p&gt;I have read about an attempt to do this for the L5 with two of the batteries designed for the L5 in a case attached to it, so you have 3*L5 batteries. It’s an interesting approach but those batteries have poor value for money when compared to 18650 ($29US for 4500mAh compared to $8 for 3500mAh) and they also don’t ship them outside the US at this time. The 18650 batteries are available everywhere cheaply and have multiple uses.&lt;/p&gt;
&lt;h2&gt;How They Fit&lt;/h2&gt;
&lt;p&gt;According to my measurements the PPP is 76mm wide and the L5 is 73mm wide. That’s wide enough for 3*18mm or 4*18mm cells side by side arranged parallel to the long side of the phone or one 65mm long cell going across the phone with the necessary spring and wires.&lt;/p&gt;
&lt;p&gt;The L5 is about 151mm long and the PPP is about 5mm longer. So that means that for just the cells we could have 2 cells in a row in parallel to the long side of the phone giving a 2*3 or 2*4 array or we could have a row of 8 cells parallel to the short side of the phone.&lt;/p&gt;
&lt;p&gt;A quick search for controllers for a battery of LiIon cells that outputs USB-PD turned up one of the smaller ones as 40*28mm, &lt;a href=&quot;https://www.aliexpress.com/item/1005009329156591.html&quot;&gt;here is the AliExpress page [4]&lt;/a&gt;. So that means we could have a maximum of about 4 cells and the controller while leaving space for the camera. Looking at other similar items it seems that most of them take a large portion of the 73mm width available and take a bit less than 30mm height. The price range for DC-DC voltage converters ranges from about $3 to $20, the one I linked to is currently $8.&lt;/p&gt;
&lt;p&gt;The mass of 18650 cells is around 45g so 4 of them would be about 180g before counting the weight of the case and electronics. A L5 weighs 262g and a PPP weighs 220g so 180g of battery will make a significant difference, not an impossible difference but holding a PPP while reading an ebook is already annoying. Maybe the case could be designed to be easier to hold, a loop of wool attached to the top could be used to suspend the phone from one finger while the rest of the hand just keeps it steady.&lt;/p&gt;
&lt;p&gt;In a default configuration the L5 has a 4500mAh 3.8V battery and the PPP has a 3000mAh 3.8V battery. The 18650 cells have up to 4000mAh with 3500mAh being common. So 4 such cells could multiply the battery life of a PPP by a factor of 5 or a L5 by 4. That would not be enough to last for a whole day without charging so they need to be easy to swap.&lt;/p&gt;
&lt;p&gt;A 3 cell battery seems like a good option, 135g of batteries so the project overall wouldn’t even double the weight of the phone with battery case. As it doesn’t seem possible to put in enough cells to last a day of reasonable use (running a web browser, checking email, reading wikipedia, and having some IM systems checking for notifications) there doesn’t seem to be a benefit in trying to stuff the maximum number of cells in. Going to 4 or 5 cells doesn’t provide much benefit over 3 while increasing the weight and making the design more difficult. The modules for DC Voltage conversion often have configuration for the number of cells to be used so it wouldn’t be difficult to print a new case and reconfigure the Voltage converter.&lt;/p&gt;
&lt;h2&gt;Design&lt;/h2&gt;
&lt;p&gt;A case needs to provide protection as well as hold the batteries. The lack of cases for the L5 and PPP is a problem even without the extra weight of a battery pack increasing the kinetic energy of falling phone. Ideally a drop from 1M on to concrete would not cause any damage to the phone, destruction of the case is OK as it would be 3D printed and can be rebuilt easily.&lt;/p&gt;
&lt;p&gt;I think that a case where the phone slides in from the top would be best. To change cells one would slide the phone out and the cells would be immediately accessible with no divider between the phone and the cells. Sliding the phone in would hold the cells against the back of the case and as there is a gap of about 3mm on each side of the PPP between the display area and the edge of the phone there’s plenty of space for the case to wrap around it at the sides and bottom. At the top there would have to be some sort of plastic clip. The PPP only has buttons on the top right so the case can be snug on all sides apart from the top right. The L5 has switches at the top left and buttons at the top right so whatever clips on to the top would really need some strength to cover the fall flat on face case.&lt;/p&gt;
&lt;p&gt;The USB C plug would need to be held in place well enough to allow the phone to easily slide on to it but also be weak enough that it would move if a drop forced the phone out of the case.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.thingiverse.com/thing:4961260&quot;&gt;Thingiverse has a design for a L5 case [5]&lt;/a&gt; (with several derivatives) and &lt;a href=&quot;https://www.thingiverse.com/thing:4933237&quot;&gt;a design for a PPP case [6]&lt;/a&gt;. Those cases could be used as starting points and then changed to store batteries and the voltage change circuit board. I have just learned that it’s possible to use rubberised material in a 3D printer which is apparently what those designs are for. If a case was printed with rubberised material the top could just stick in place after being pushed in.&lt;/p&gt;
&lt;h2&gt;Potential for Excessive Excitement&lt;/h2&gt;
&lt;p&gt;Having an exploding device in your pocket would be the exciting in a bad way. My initial idea was to have multiple 18650 cells in series. The problem is that if the cells have different capacity levels then one can run out before the rest and get to a deep discharge state which at a minimum causes damage to the cell.&lt;/p&gt;
&lt;p&gt;One way of minimising risk is to have only a single cell in use at one time, &lt;a href=&quot;https://www.aliexpress.com/item/1005007555665949.html&quot;&gt;here is a converter for a single cell to 5V [7]&lt;/a&gt;. It is possible to run multiple cells in parallel by simply wiring them together, but it’s recommended to make sure that the voltage difference between cells is less than 0.2V to avoid high current when connecting.&lt;/p&gt;
&lt;p&gt;The arrangement of cells is often referred to as nS or nP to refer to n cells in series or parallel. Aliexpress has a range of 1S to 6S devices. Some of the 2S devices have a connector for the mid point which permits separate voltage monitoring for both cells but there doesn’t seem to be anything equivalent for 3S or more. They also don’t appear to have anything to specifically manage 2P or 3P arrangements at the moment (they had a 3P board on sale when I looked into this last year).&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This is a bigger project than I expected when I first started investigating it. I’ve played with FreeCAD which seems OK but will take a lot of learning and practice. Then I need to do more investigation into the DC-DC converters to find one that works well and is unlikely to start a fire.&lt;/p&gt;
&lt;p&gt;I will look into other phone options as well and keep chasing Furilabs people about my phone replacement.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[1]&lt;a href=&quot;https://grapheneos.org/&quot;&gt; https://grapheneos.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[2]&lt;a href=&quot;https://kdeconnect.kde.org/&quot;&gt; https://kdeconnect.kde.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[3]&lt;a href=&quot;https://etbe.coker.com.au/2026/10/06/kdeconnect-dbus/&quot;&gt; https://etbe.coker.com.au/2026/10/06/kdeconnect-dbus/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[4]&lt;a href=&quot;https://www.aliexpress.com/item/1005009329156591.html&quot;&gt; https://www.aliexpress.com/item/1005009329156591.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[5]&lt;a href=&quot;https://www.thingiverse.com/thing:4961260&quot;&gt; https://www.thingiverse.com/thing:4961260&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[6]&lt;a href=&quot;https://www.thingiverse.com/thing:4933237&quot;&gt; https://www.thingiverse.com/thing:4933237&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[7]&lt;a href=&quot;https://www.aliexpress.com/item/1005007555665949.html&quot;&gt; https://www.aliexpress.com/item/1005007555665949.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;yarpp yarpp-related yarpp-related-rss yarpp-template-list&quot;&gt;

&lt;p&gt;Related posts:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2012/12/21/galaxy-s3-power-case/&quot; rel=&quot;bookmark&quot; title=&quot;Samsung Galaxy S3 First Review with Power Case&quot;&gt;Samsung Galaxy S3 First Review with Power Case&lt;/a&gt; &lt;small&gt;My new Samsung Galaxy S3 arrived a couple of days...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2013/01/24/power-supplies-wires/&quot; rel=&quot;bookmark&quot; title=&quot;Power Supplies and Wires&quot;&gt;Power Supplies and Wires&lt;/a&gt; &lt;small&gt;For some time I’ve been wondering how the wire size...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2024/04/29/usb-psus/&quot; rel=&quot;bookmark&quot; title=&quot;USB PSUs&quot;&gt;USB PSUs&lt;/a&gt; &lt;small&gt;I just bought a new USB PSU from AliExpress [1]....&lt;/small&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Tue, 06 Oct 2026 08:08:04 +0000</pubDate>

</item> 
<item>
	<title>Russell Coker: Kdeconnect DBUS</title>
	<guid>https://etbe.coker.com.au/?p=6310</guid>
	<link>https://etbe.coker.com.au/2026/10/06/kdeconnect-dbus/</link>
     <description>  &lt;p&gt;I’ve tested the DBUS interfaces for Kdeconnect (the system for connecting a KDE desktop to a phone or another computer). Unlike most DBUS interfaces it has a significant tree of interfaces so the busctl command to get the tree is important. Here’s the useful things I discovered:&lt;/p&gt;
&lt;pre&gt;# list basic interfaces for kdeconnect
qdbus6 org.kde.kdeconnect.daemon /modules/kdeconnect
# get tree of interfaces for kdeconnect
busctl --user tree org.kde.kdeconnect.daemon
# get list of devices
qdbus6 --literal org.kde.kdeconnect.daemon /modules/kdeconnect org.kde.kdeconnect.daemon.deviceNames
# list interfaces for a device (DEVID is a hex string from the above command)
qdbus6 org.kde.kdeconnect.daemon /modules/kdeconnect/devices/$DEVID
# get battery charge
qdbus6 org.kde.kdeconnect.daemon /modules/kdeconnect/devices/$DEVID/battery org.kde.kdeconnect.device.battery.charge&lt;/pre&gt;
&lt;p&gt;Sending an SMS apparently requires using the QVariantList type which is more pain than I wanted so I tried the kdeconnect-cli command. Here’s a quick summary of how to use it:&lt;/p&gt;
&lt;pre&gt;# list devices
kdeconnect-cli -l
# send a SMS
kdeconnect-cli -d $DEVID --send-sms &quot;the message&quot; --destination $NUMBER
# find device (ring)
kdeconnect-cli --ring -d $DEVID
# send a notification message
kdeconnect-cli --ping-msg &quot;this is the message&quot; -d $DEVID
# unlock and lock screen (only works on Debian devices for me not Android devices)
kdeconnect-cli --unlock -d $DEVID
kdeconnect-cli --lock -d $DEVID&lt;/pre&gt;
&lt;p&gt;There doesn’t seem to be support for making phone calls via kdeconnect which is a significant omission. It’s a very common situation to want to call a number that’s listed on a web site or in some other data source that’s easier to access on a PC than on a phone. The clipboard could be used but that’s needless pain.&lt;/p&gt;
&lt;div class=&quot;yarpp yarpp-related yarpp-related-rss yarpp-template-list&quot;&gt;

&lt;p&gt;Related posts:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2026/09/17/nheko-dbus/&quot; rel=&quot;bookmark&quot; title=&quot;Nheko DBUS&quot;&gt;Nheko DBUS&lt;/a&gt; &lt;small&gt;Nheko is my current favourite client for the Matrix IM...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2024/11/02/moving-between-devices/&quot; rel=&quot;bookmark&quot; title=&quot;Moving Between Devices&quot;&gt;Moving Between Devices&lt;/a&gt; &lt;small&gt;I previously wrote about the possibility of transferring work between...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2007/01/15/dbus-error/&quot; rel=&quot;bookmark&quot; title=&quot;dbus error&quot;&gt;dbus error&lt;/a&gt; &lt;small&gt;Strange dbus error from the KDE power monitoring tool...&lt;/small&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Mon, 05 Oct 2026 22:22:49 +0000</pubDate>

</item> 
<item>
	<title>Utkarsh Gupta: FOSS Activities in September 2026</title>
	<guid>https://utkarsh2102.org/posts/foss-in-sept-26/</guid>
	<link>https://utkarsh2102.org/posts/foss-in-sept-26/</link>
     <description>  &lt;p&gt;Here’s my monthly but brief update about the activities I’ve done in the FOSS world.&lt;/p&gt;
&lt;h2 id=&quot;debian&quot;&gt;Debian&lt;/h2&gt;
&lt;figure&gt;
&lt;img src=&quot;https://utkarsh2102.org/images/debian-logo-small.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;Whilst I didn’t have much time, here are still a few things that I worked on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sponsored &lt;a href=&quot;https://tracker.debian.org/news/1798457/accepted-ubuntu-dev-tools-0214-source-into-unstable/&quot;&gt;ubuntu-dev-tools/0.214&lt;/a&gt; for Florent ‘Skia’ Jacquet, which updates &lt;code&gt;seeded-in-ubuntu&lt;/code&gt; to use the new per-series indexer (&lt;a href=&quot;https://bugs.launchpad.net/bugs/2160240&quot;&gt;LP: #2160240&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Assisted a few folks in getting their patches submitted via Salsa.&lt;/li&gt;
&lt;li&gt;Mentoring for newcomers.&lt;/li&gt;
&lt;li&gt;Moderation of -project mailing list.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;ubuntu&quot;&gt;Ubuntu&lt;/h2&gt;
&lt;figure&gt;
&lt;img src=&quot;https://utkarsh2102.org/images/ubuntu-logo-small.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;I joined &lt;a href=&quot;https://utkarsh2102.org/posts/hello-canonical/&quot;&gt;Canonical to work on Ubuntu full-time&lt;/a&gt; back in February 2021.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;With 26.10 in Feature Freeze, wore my Release team hat to:
&lt;ul&gt;
&lt;li&gt;Review and approve a bunch of Feature Freeze Exceptions, including the Go 1.27 transition, Qt 6.11.2, rust-coreutils 0.12.0, devscripts 2.6.12, kdump-tools moving to dracut, and a few GCE packages.&lt;/li&gt;
&lt;li&gt;Point linux-entra-sso to the SRU team, as it didn’t need an FFe at all, and milestone a couple of bugs for 26.10.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Continued to push for infrastructure improvements:
&lt;ul&gt;
&lt;li&gt;Made ubuntu-cdimage more resilient to Launchpad hiccups (&lt;a href=&quot;https://code.launchpad.net/~utkarsh/ubuntu-cdimage/+git/ubuntu-cdimage/+merge/511948&quot;&gt;MP&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Taught &lt;code&gt;generate-freeze-block&lt;/code&gt; in ubuntu-archive-tools a couple of new options (&lt;code&gt;--skip-update&lt;/code&gt; and &lt;code&gt;--series&lt;/code&gt;) and better error handling (&lt;a href=&quot;https://code.launchpad.net/~utkarsh/ubuntu-archive-tools/+git/ubuntu-archive-tools/+merge/511844&quot;&gt;MP&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Bumped the arm64 generic non-cloud image to 4.5G in livecd-rootfs and uploaded it as &lt;a href=&quot;https://launchpad.net/ubuntu/+source/livecd-rootfs/26.10.16&quot;&gt;26.10.16&lt;/a&gt;; also sponsored the follow-up &lt;a href=&quot;https://launchpad.net/ubuntu/+source/livecd-rootfs/26.10.17&quot;&gt;26.10.17&lt;/a&gt; for Chloé.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Sponsored &lt;a href=&quot;https://launchpad.net/ubuntu/+source/aevol/9.4.0-2ubuntu1&quot;&gt;aevol/9.4.0-2ubuntu1&lt;/a&gt; for Matthieu, fixing an FTBFS with GCC 15’s LTO (&lt;a href=&quot;https://bugs.launchpad.net/bugs/2167811&quot;&gt;LP: #2167811&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Reviewed quite a lot of MPs - britney hints, meta-release, ubuntu-release-tools, ubuntu-archive-tools, ubuntu-cdimage, livecd-rootfs, ubuntu-seeds, and so on.&lt;/li&gt;
&lt;li&gt;Enabled &lt;a href=&quot;https://discourse.ubuntu.com/t/upgrades-from-ubuntu-24-04-lts-to-ubuntu-26-04-1-lts-now-enabled/88502&quot;&gt;upgrades to 26.04 LTS&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Released 26.10 Beta and &lt;a href=&quot;https://discourse.ubuntu.com/t/ubuntu-26-10-stonking-stingray-beta-released/88662&quot;&gt;announced it on Discourse&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Did Archive Admin, DMB, and Release team duties as usual.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2 id=&quot;debian-elts&quot;&gt;Debian (E)LTS&lt;/h2&gt;
&lt;figure&gt;
&lt;img src=&quot;https://utkarsh2102.org/images/debian-lts-small.png&quot; /&gt;
&lt;/figure&gt;
&lt;p&gt;This month I have worked 33.5 hours
on &lt;a href=&quot;https://www.freexian.com/lts/debian/&quot;&gt;Debian Long Term Support (LTS)&lt;/a&gt;
and on its sister &lt;a href=&quot;https://www.freexian.com/lts/extended/&quot;&gt;Extended LTS&lt;/a&gt;
project and did the following things:&lt;/p&gt;
&lt;p&gt;(A quick note that I did quite a lot of the work during my work as Frontdesk that went on till 4th Oct, so 33.50 hours include the work I did till 4th October 2026.)&lt;/p&gt;
&lt;h3 id=&quot;released-security-updates&quot;&gt;Released Security Updates&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;node-lodash&lt;/strong&gt;: Prototype pollution in &lt;code&gt;_.unset&lt;/code&gt; and &lt;code&gt;_.omit&lt;/code&gt; (plus a bypass of the initial fix for it), and code injection via the &lt;code&gt;imports&lt;/code&gt; option of &lt;code&gt;_.template&lt;/code&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;[LTS]&lt;/strong&gt;: Fixed &lt;a href=&quot;https://security-tracker.debian.org/tracker/CVE-2025-13465&quot;&gt;CVE-2025-13465&lt;/a&gt;, &lt;a href=&quot;https://security-tracker.debian.org/tracker/CVE-2026-2950&quot;&gt;CVE-2026-2950&lt;/a&gt;, and &lt;a href=&quot;https://security-tracker.debian.org/tracker/CVE-2026-4800&quot;&gt;CVE-2026-4800&lt;/a&gt; via &lt;a href=&quot;https://tracker.debian.org/news/1806836/accepted-node-lodash-41721dfsgcs83119820210220-9deb12u1-source-into-oldstable-security/&quot;&gt;&lt;strong&gt;4.17.21+dfsg+~cs8.31.198.20210220-9+deb12u1&lt;/strong&gt;&lt;/a&gt; for bookworm. This has been released as &lt;a href=&quot;https://www.debian.org/lts/security/2026/DLA-4820-1&quot;&gt;&lt;strong&gt;DLA 4820-1&lt;/strong&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;This is the bookworm follow-up to DLA 4663-1 that I carried over from July. The update had been sitting prepared and tested on &lt;a href=&quot;https://debusine.debian.net/debian/developers/work-request/908246/&quot;&gt;debusine&lt;/a&gt;, so once the upstream discussion wrapped up, it went straight out. It also carries an extra patch to the lodash-cli dependency map - without it, the regenerated &lt;code&gt;lodash.template&lt;/code&gt; module throws “assignWith is not defined” at runtime, which node-gulp-util’s autopkgtest caught.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;libpng1.6&lt;/strong&gt;: Use-after-free of zlib input in &lt;code&gt;png_read_end()&lt;/code&gt; after incomplete zTXt, iTXt, or iCCP decompression, which could result in denial of service.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;[LTS]&lt;/strong&gt;: Fixed &lt;a href=&quot;https://security-tracker.debian.org/tracker/CVE-2026-46675&quot;&gt;CVE-2026-46675&lt;/a&gt; via &lt;a href=&quot;https://tracker.debian.org/news/1807401/accepted-libpng16-1639-2deb12u6-source-into-oldstable-security/&quot;&gt;&lt;strong&gt;1.6.39-2+deb12u6&lt;/strong&gt;&lt;/a&gt; for bookworm. This has been released as &lt;a href=&quot;https://www.debian.org/lts/security/2026/DLA-4824-1&quot;&gt;&lt;strong&gt;DLA 4824-1&lt;/strong&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;I picked this one up whilst on front desk; the upstream fix that went into trixie via &lt;a href=&quot;https://lists.debian.org/debian-security-announce/2026/msg00450.html&quot;&gt;DSA 6537-1&lt;/a&gt; applied to 1.6.39 as-is.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;work-in-progress&quot;&gt;Work in Progress&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;libpng1.6&lt;/strong&gt;: The same CVE-2026-46675.
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;[ELTS]&lt;/strong&gt;: Claimed in &lt;code&gt;ela-needed&lt;/code&gt;; the same upstream fix applies to all three ELTS suites, so this should go out shortly.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;other-activities&quot;&gt;Other Activities&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;[E/LTS]&lt;/strong&gt; Did my front-desk week from 28-09 to 04-10.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Over the week I did roughly:
&lt;ul&gt;
&lt;li&gt;Triage of &lt;strong&gt;524 unique CVEs&lt;/strong&gt; across &lt;strong&gt;192 source packages&lt;/strong&gt; and all four suites. And 1 automated ELTS end-of-life sweep.&lt;/li&gt;
&lt;li&gt;Additional data is now part of the front-desk job too, so 75 commits record it for 179 CVEs across 71 packages.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Newly queued &lt;strong&gt;22 source packages&lt;/strong&gt; - 13 in &lt;code&gt;dla-needed&lt;/code&gt; (apache2, chromium, firefox-esr, libnet-idn-encode-perl, libpng1.6, node-shell-quote, nvidia-graphics-drivers, openssl, pcre2, php-mongodb, php8.2, social-auth-core, and wpa) and 16 in &lt;code&gt;ela-needed&lt;/code&gt; (apache2, firefox-esr, gegl, lemonldap-ng, libnet-idn-encode-perl, libpng1.6, libwebsockets, nsd, nvidia-graphics-drivers, pcre2, php7.0, php7.3, php7.4, rar, unrar-nonfree, and wpa), 7 of them in both. Also widened 3 ELTS entries to bullseye - antiword, ocaml, and openvswitch.&lt;/li&gt;
&lt;li&gt;Most of the interesting work was again in the &lt;code&gt;&amp;lt;not-affected&amp;gt;&lt;/code&gt; verdicts: &lt;strong&gt;217 of 263&lt;/strong&gt; (83%, across 57 packages) rest on showing that the vulnerable code or feature isn’t in the source we ship. Another 17 cover incomplete upstream fixes that we either never shipped or shipped with the follow-up already in (expat, libxml2, node-tar, and pyjwt). 15 come from bundled components we don’t ship - node-ajv again, which uses uri-js and not fast-uri, and nvidia-open, which doesn’t ship the NGX updater. And 13 are vendor- or platform-specific - openssh’s CVE-2026-55654 lives only in a Red Hat GSSAPI patch, and the netdata and PHP ones only affect Windows.&lt;/li&gt;
&lt;li&gt;Did 4 rounds of newly supported bullseye packages (33 packages overall), plus libmail-mboxparser-perl for buster - 34 in all. The existing CVE data mostly held up; the real finds were discovery gaps. One interesting gotcha: sid renamed stunnel4 to stunnel, and two new CVEs were associated only with the new name, so they never showed up for trixie, bookworm, or any ELTS suite. I also sorted the 180 “Triage needed” entries (57 packages) from elts-eol by where each was already handled, and triaged for ELTS the 100 that trixie or bookworm had already decided; the rest come next. And I imported 79 package-level lines for the older source names ELTS still ships (tomcat8, php7.0/7.3/7.4, netty-3.9, openssl1.0, python2.7/3.5/3.7, and pypy).&lt;/li&gt;
&lt;li&gt;Caught some inconsistencies in released advisories: DLA 4801-1 (swift) was missing a CVE, ELA 1831-1 (redis) listed the wrong one, and DLA 4808-1 (network-manager-l2tp) listed CVE-2026-75883 - an ID that was renamed and then reassigned to an unrelated ppp issue. I fixed all three in the tracker’s advisory lists.&lt;/li&gt;
&lt;li&gt;Made the Security team and the uploaders aware of regressions from our own updates:
&lt;ul&gt;
&lt;li&gt;libde265: the CVE-2026-49337 fix in DLA 4789-1/ELA 1828-1 (and DSA 6413-1) misses upstream’s follow-up commit.&lt;/li&gt;
&lt;li&gt;libxml2 CVE-2026-76781 and policykit-1 CVE-2026-85498 were introduced by our own back-ports; the policykit-1 one is harmless.&lt;/li&gt;
&lt;li&gt;expat: the CVE-2025-59375 backport in DLA 4807-1 is compiled out, because &lt;code&gt;XML_GE&lt;/code&gt; is never defined.&lt;/li&gt;
&lt;li&gt;xen: DLA 4818-1’s XSA-491 fix makes XSA-510 reachable.&lt;/li&gt;
&lt;li&gt;gegl: the CVE-2026-2049/2050 back-port in ELA 1650-1 rejects valid RLE .hdr files.&lt;/li&gt;
&lt;li&gt;log4cxx: DLA 4322-1 broke UTF-8 in JSONLayout output. That one is functional, not security.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Helped correct a set of triages and let the Debian Security team know:
&lt;ul&gt;
&lt;li&gt;ruby-json CVE-2026-71847: the vulnerable code was never in a released Debian version.&lt;/li&gt;
&lt;li&gt;openssh CVE-2026-55654: only affects a Red Hat-specific GSSAPI patch.&lt;/li&gt;
&lt;li&gt;three libxml2 issues that don’t affect trixie either.&lt;/li&gt;
&lt;li&gt;the stunnel4 rename above.&lt;/li&gt;
&lt;li&gt;trixie &lt;code&gt;&amp;lt;no-dsa&amp;gt;&lt;/code&gt; lines on jsch, node-qs, and ruby-loofah, where trixie’s version doesn’t have the vulnerable feature at all.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Independently found a security issue in rclone and reported it privately upstream through a GitHub security advisory. Upstream already had a report for the same issue, so they folded mine into the existing advisory and credited me as a co-reporter.
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/rclone/rclone/security/advisories/GHSA-66qv-66mg-9h74&quot;&gt;https://github.com/rclone/rclone/security/advisories/GHSA-66qv-66mg-9h74&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Also found some bugs in the additional-data tooling, e.g. &lt;code&gt;cve-ad --package P --severity tbd&lt;/code&gt; wipes the CVE-level severity, and the schema doesn’t validate package-level entries at all.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;[E/LTS]&lt;/strong&gt; Monitored discussions on mailing lists, IRC, and all the documentation updates.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;[E/LTS]&lt;/strong&gt; Attended the monthly LTS meeting on IRC. &lt;a href=&quot;https://lists.debian.org/debian-lts/2026/09/msg00091.html&quot;&gt;Meeting notes here&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;Until next time.&lt;br /&gt;
&lt;code&gt;:wq&lt;/code&gt; for today.&lt;/p&gt; </description> 
	<pubDate>Mon, 05 Oct 2026 05:41:11 +0000</pubDate>

</item> 
<item>
	<title>Vincent Bernat: Hacking the Go compiler to efficiently map IPv4 to IPv6</title>
	<guid>http://www.luffy.cx/en/blog/2026-go-netip-addrto6.html</guid>
	<link>https://vincent.bernat.ch/en/blog/2026-go-netip-addrto6</link>
     <description>  &lt;p&gt;&lt;a href=&quot;https://pkg.go.dev/net/netip#Addr&quot; title=&quot;net/netip.Addr on Go Packages&quot;&gt;&lt;code&gt;netip.Addr&lt;/code&gt;&lt;/a&gt; features an &lt;a href=&quot;https://pkg.go.dev/net/netip#Addr.Unmap&quot; title=&quot;net/netip.Addr.Unmap on Go Packages&quot;&gt;&lt;code&gt;Unmap()&lt;/code&gt;&lt;/a&gt;
method returning the unwrapped IPv4 contained in an &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc4291#section-2.5.5.2&quot; title=&quot;RFC 4291: IP Version 6 Addressing Architecture&quot;&gt;IPv4-mapped IPv6
address&lt;/a&gt;: from &lt;code&gt;::ffff:203.0.113.10&lt;/code&gt; or &lt;code&gt;::ffff:cb00:710a&lt;/code&gt;, it returns
&lt;code&gt;203.0.113.10&lt;/code&gt;.&lt;sup id=&quot;fnref:why&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:why&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; There is no &lt;code&gt;Map()&lt;/code&gt; or &lt;code&gt;To6()&lt;/code&gt; method for the reverse
direction. Such a method is trivial to implement, but Go maintainers have
&lt;a href=&quot;https://github.com/golang/go/issues/54365#issuecomment-1570607144&quot; title=&quot;Issue #54365: proposal: net/netip: add netip.Addr.Map&quot;&gt;rejected&lt;/a&gt; it on the grounds that users should write
&lt;code&gt;netip.AddrFrom16(ip.As16())&lt;/code&gt; and let the compiler optimize it.&lt;sup id=&quot;fnref:equiv&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:equiv&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; Today,
this pattern is eight times slower than a native method. How can we teach the
compiler to optimize this sequence?&lt;/p&gt;
&lt;div class=&quot;toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#the-alternatives&quot;&gt;The alternatives&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#modifying-the-go-standard-library&quot;&gt;Modifying the Go standard library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#as-a-helper&quot;&gt;As a helper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#as-an-unsafe-function&quot;&gt;As an unsafe function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#benchmarks&quot;&gt;Benchmarks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#assembly-code&quot;&gt;Assembly code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#hacking-the-go-compiler&quot;&gt;Hacking the Go compiler&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#the-hammer&quot;&gt;The hammer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#the-screwdriver&quot;&gt;The screwdriver&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#on-paper&quot;&gt;On paper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#in-practice&quot;&gt;In practice&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#out-of-order&quot;&gt;Out of order&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#back-in-order&quot;&gt;Back in order&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#next-steps&quot;&gt;Next steps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h1 id=&quot;the-alternatives&quot;&gt;The alternatives&lt;/h1&gt;
&lt;p&gt;Let’s explore three ways to implement the map semantics for &lt;code&gt;netip.Addr&lt;/code&gt;. My
favorite is to add it to the Go standard library. Go maintainers prefer a small
external helper chaining &lt;code&gt;netip.AddrFrom16()&lt;/code&gt; and &lt;code&gt;netip.Addr.As16()&lt;/code&gt;, hoping
the compiler eventually optimizes it. The &lt;a href=&quot;https://pkg.go.dev/unsafe&quot; title=&quot;unsafe on Go Packages&quot;&gt;&lt;code&gt;unsafe&lt;/code&gt; package&lt;/a&gt;
opens a third path, with the same performance as the first solution.&lt;/p&gt;
&lt;h2 id=&quot;modifying-the-go-standard-library&quot;&gt;Modifying the Go standard library&lt;/h2&gt;
&lt;p&gt;Internally, &lt;a href=&quot;https://pkg.go.dev/net/netip#Addr&quot; title=&quot;net/netip.Addr on Go Packages&quot;&gt;&lt;code&gt;netip.Addr&lt;/code&gt;&lt;/a&gt; stores any IP address as a
128-bit value with an extra field &lt;code&gt;z&lt;/code&gt; to encode the family and the zone:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;uint128&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrDetail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrDetail&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isV6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// IPv4 is false, IPv6 is true.&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;zoneV6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// != &quot;&quot; only if IsV6 is true.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrDetail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z4&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrDetail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z6noz&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrDetail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isV6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://pkg.go.dev/net/netip#AddrFrom4&quot; title=&quot;net/netip.AddrFrom4 on Go Packages&quot;&gt;&lt;code&gt;AddrFrom4()&lt;/code&gt;&lt;/a&gt; encodes an IPv4 address as an
IPv4-mapped IPv6 address and sets &lt;code&gt;z&lt;/code&gt; to the unique value &lt;code&gt;z4&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AddrFrom4 returns the address of the IPv4 address given by the bytes in addr.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AddrFrom4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;uint128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xffff00000000&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])},&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://pkg.go.dev/net/netip#Addr.Unmap&quot; title=&quot;net/netip.Addr.Unmap on Go Packages&quot;&gt;&lt;code&gt;Unmap()&lt;/code&gt;&lt;/a&gt; turns an IPv4-mapped IPv6 address into an
IPv4 address by setting the &lt;code&gt;z&lt;/code&gt; field to &lt;code&gt;z4&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Unmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Is4In6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z4&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Implementing the reverse direction inside the Go standard library is trivial: we
set the &lt;code&gt;z&lt;/code&gt; field to &lt;code&gt;z6noz&lt;/code&gt; if the address is IPv4.&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// To6 maps an IPv4 address to an IPv4-mapped IPv6 address. It returns an&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// IPv6 address unmodified.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;To6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Is4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z6noz&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&quot;admonition&quot;&gt;
&lt;p class=&quot;admonition-title&quot;&gt;Update (2026-10)&lt;/p&gt;
&lt;p&gt;Instead of patching Go, we can use the &lt;a href=&quot;https://pkg.go.dev/cmd/go#hdr-Compile_packages_and_dependencies&quot; title=&quot;go build documentation&quot;&gt;&lt;code&gt;-overlay&lt;/code&gt;
flag&lt;/a&gt; of &lt;code&gt;go build&lt;/code&gt; to hijack any package, including the standard
library. In our case, it can &lt;a href=&quot;https://github.com/vincentbernat/go-netip-addrto6/commit/dcc2e1af2af48301d8e992db22d97682bda37b8c&quot; title=&quot;Add an alternative using an overlay&quot;&gt;add &lt;code&gt;To6()&lt;/code&gt; to &lt;code&gt;net/netip&lt;/code&gt;&lt;/a&gt;. Yet
it is cumbersome:&lt;sup id=&quot;fnref:inconvenient&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:inconvenient&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; the flag expects a JSON file mapping absolute
paths in &lt;code&gt;GOROOT&lt;/code&gt; to replacement files, and you need to add it to every &lt;code&gt;go&lt;/code&gt;
command.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;as-a-helper&quot;&gt;As a helper&lt;/h2&gt;
&lt;p&gt;We can’t access the &lt;code&gt;z&lt;/code&gt; field from outside the &lt;code&gt;net/netip&lt;/code&gt; package. Instead, we
build a small helper around the &lt;code&gt;netip.AddrFrom16(ip.As16())&lt;/code&gt; pattern:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AddrTo6 maps an IPv4 address to an IPv4-mapped IPv6 address. It returns an&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// IPv6 address unmodified.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AddrTo6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Is4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AddrFrom16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;As16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;as-an-unsafe-function&quot;&gt;As an unsafe function&lt;/h2&gt;
&lt;p&gt;Another solution uses the &lt;code&gt;unsafe&lt;/code&gt; package to alter the &lt;code&gt;Addr&lt;/code&gt; struct through
a proxy with the same memory layout:&lt;sup id=&quot;fnref:tests&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:tests&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// addrProxy has the same memory layout as netip.Addr.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrProxy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// netip.uint128&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Pointer&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// unique.Handle[netip.addrDetail]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;anyIPv6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;IPv6Unspecified&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netipZ6noz&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;anyIPv6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// AddrTo6 maps an IPv4 address to an IPv4-mapped IPv6 address. It returns an&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// IPv6 address unmodified.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AddrTo6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Is4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netipZ6noz&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;benchmarks&quot;&gt;Benchmarks&lt;/h2&gt;
&lt;p&gt;On my computer, with Go 1.27.1, the standard library solution costs 0.88 ns per
operation, while the solution favored by Go maintainers costs 7.14 ns. The
unsafe solution matches the performance of the first one.&lt;/p&gt;
&lt;div class=&quot;language-text-only codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;goos: linux
goarch: amd64
pkg: github.com/vincentbernat/go-netip-addrto6
cpu: AMD Ryzen 5 5600X 6-Core Processor
                   │     sec/op     │
AddrTo6/safe            7.137n ± 0%
AddrTo6/unsafe         0.8682n ± 2%
AddrTo6/builtin        0.8775n ± 2%
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;assembly-code&quot;&gt;Assembly code&lt;/h2&gt;
&lt;p&gt;Let’s check the assembly code the compiler generates for each solution.&lt;sup id=&quot;fnref:dis&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:dis&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;
The one built into the standard library looks like this:&lt;sup id=&quot;fnref:inline&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:inline&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-go-assembly codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AX = input.addr.hi, BX = input.addr.lo, CX = input.z&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CMPQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; check &quot;z&quot; if this is an IPv4 address&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JNE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; if not, stop here&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; CX = netip.z6noz&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RET&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// return value = Addr{hi: AX, lo: BX, z: CX}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Go’s &lt;a href=&quot;https://go.dev/doc/asm&quot; title=&quot;A Quick Guide to Go&#39;s Assembler&quot;&gt;assembly language&lt;/a&gt; is not a direct representation of the underlying
machine language: it operates on a semi-abstract instruction set derived from
&lt;a href=&quot;https://9p.io/sys/doc/asm.html&quot; title=&quot; A Manual for the Plan 9 assembler&quot;&gt;Plan 9’s assembler&lt;/a&gt;. It has four pseudo-registers: FP (frame pointer
for function arguments), PC (program counter), SB (static base pointer for
global symbols), and SP (stack pointer). It also has architecture-specific
registers like &lt;code&gt;AX&lt;/code&gt;, &lt;code&gt;CX&lt;/code&gt;, &lt;code&gt;DX&lt;/code&gt;, &lt;code&gt;BX&lt;/code&gt;, &lt;code&gt;SI&lt;/code&gt;, &lt;code&gt;DI&lt;/code&gt;, and &lt;code&gt;R8&lt;/code&gt; to &lt;code&gt;R15&lt;/code&gt;.
Instructions storing data use their last argument as the destination.
Instructions can carry an explicit size suffix: &lt;code&gt;MOVB&lt;/code&gt; moves a byte, &lt;code&gt;MOVW&lt;/code&gt; 16
bits, &lt;code&gt;MOVL&lt;/code&gt; 32 bits, and &lt;code&gt;MOVQ&lt;/code&gt; 64 bits. In the example above, the first
instruction compares the 64-bit value &lt;code&gt;z4&lt;/code&gt; with the &lt;code&gt;CX&lt;/code&gt; register.&lt;/p&gt;
&lt;p&gt;The unsafe solution looks almost the same:&lt;/p&gt;
&lt;div class=&quot;language-go-assembly codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AX = input.addr.hi, BX = input.addr.lo, CX = input.z&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CMPQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; check &quot;z&quot; if this is an IPv4 address&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JNE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; if not, stop here&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;netipZ6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; CX = netip.z6noz&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RET&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// return value = Addr{hi: AX, lo: BX, z: CX}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The helper solution has far more instructions. To understand why, let’s look at
the code for &lt;a href=&quot;https://pkg.go.dev/net/netip#Addr.As16&quot; title=&quot;net/netip.Addr.As16 on Go Packages&quot;&gt;&lt;code&gt;As16()&lt;/code&gt;&lt;/a&gt; and
&lt;a href=&quot;https://pkg.go.dev/net/netip#AddrFrom16&quot; title=&quot;net/netip.AddrFrom16 on Go Packages&quot;&gt;&lt;code&gt;AddrFrom16()&lt;/code&gt;&lt;/a&gt;. They are short enough for the compiler
to inline them.&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;As16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEPutUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEPutUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AddrFrom16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;uint128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]),&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can already guess the pattern to optimize: the code packs the IP address into
an array, copies it, then unpacks it. If we inline the Go code by hand, we get:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AddrTo6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Is4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEPutUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEPutUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:])&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z6noz&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As humans, we can mentally derive the optimized form:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AddrTo6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Is4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z6noz&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p id=&quot;asm-addrto6safe&quot;&gt;Unfortunately, as of Go 1.26.8, the compiler is not smart enough to do the same:&lt;/p&gt;
&lt;div class=&quot;language-go-assembly codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AX = input.addr.hi, BX = input.addr.lo, CX = input.z&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; Push the stack (32 bytes):&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;    0(SP) addr netip.uint128&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;   16(SP) a16 [16]byte&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;PUSHQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BP&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BP&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SUBQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CMPQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; check &quot;z&quot; if this is an IPv4 address&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JNE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; if not, stop here&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; Pack: byteorder.BEPutUint64(a16[:8], input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;       byteorder.BEPutUint64(a16[8:], input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBEQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;AX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBEQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; addr = a16, 16 bytes at once through the vector register X0&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVUPS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;X0&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVUPS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;X0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; CX = netip.z6noz&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; Unpack: output.addr.hi = byteorder.BEUint64(addr[:8])&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;         output.addr.lo = byteorder.BEUint64(addr[8:])&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBEQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;AX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBEQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·addr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ADDQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;POPQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BP&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RET&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// return value = Addr{hi: AX, lo: BX, z: CX}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The compiler does a decent job on the byte shuffling: the eight byte stores of
&lt;code&gt;BEPutUint64()&lt;/code&gt; become a single &lt;code&gt;MOVBEQ&lt;/code&gt;, which stores a register byte-swapped.
The eight byte loads of &lt;code&gt;BEUint64()&lt;/code&gt; become a single &lt;code&gt;MOVBEQ&lt;/code&gt; the other way
round.&lt;sup id=&quot;fnref:amd64v3&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:amd64v3&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; Three groups of instructions remain: a pack, a copy, and an
unpack.&lt;/p&gt;
&lt;h1 id=&quot;hacking-the-go-compiler&quot;&gt;Hacking the Go compiler&lt;/h1&gt;
&lt;p&gt;The Go compiler has &lt;a href=&quot;https://github.com/golang/go/blob/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/README.md&quot; title=&quot;Introduction to the Go compiler&quot;&gt;several phases&lt;/a&gt;:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;Parsing&lt;/dt&gt;
&lt;dd&gt;The compiler &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/syntax&quot; title=&quot;cmd/compile/internal/syntax&quot;&gt;tokenizes and parses the source code&lt;/a&gt;. It builds a syntax tree
  for each source file.&lt;/dd&gt;
&lt;dt&gt;Type checking&lt;/dt&gt;
&lt;dd&gt;The compiler &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/types2&quot; title=&quot;cmd/compile/internal/types2&quot;&gt;maps each identifier to the object it denotes&lt;/a&gt;, folds
  constants, and infers the type of every expression.&lt;/dd&gt;
&lt;dt&gt;&lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt; construction&lt;/dt&gt;
&lt;dd&gt;The compiler converts the syntax tree and its types into its own &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ir&quot; title=&quot;cmd/compile/internal/ir&quot;&gt;intermediate
  representation&lt;/a&gt; (&lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt;). This process, called “&lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/noder&quot; title=&quot;cmd/compile/internal/noder&quot;&gt;noding&lt;/a&gt;,” goes through
  a serialization format named unified &lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt;.&lt;/dd&gt;
&lt;dt&gt;Middle end&lt;/dt&gt;
&lt;dd&gt;The compiler performs several optimization passes on the &lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt;,
  such as &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/devirtualize&quot; title=&quot;cmd/compile/internal/devirtualize&quot;&gt;devirtualization&lt;/a&gt;, &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/inline&quot; title=&quot;cmd/compile/internal/inline&quot;&gt;function call inlining&lt;/a&gt;,
  and &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/escape&quot; title=&quot;cmd/compile/internal/escape&quot;&gt;escape analysis&lt;/a&gt;.&lt;/dd&gt;
&lt;dt&gt;Walk&lt;/dt&gt;
&lt;dd&gt;This phase runs &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/walk&quot; title=&quot;cmd/compile/internal/walk&quot;&gt;two steps&lt;/a&gt;: order of evaluation decomposes complex
  statements into simpler ones, and desugaring transforms higher-level Go
  constructs, like &lt;code&gt;switch&lt;/code&gt; or channels, into more primitive instructions or
  calls to the runtime.&lt;/dd&gt;
&lt;dt&gt;Generic &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt;&lt;/dt&gt;
&lt;dd&gt;The compiler &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ssagen&quot; title=&quot;cmd/compile/internal/ssagen&quot;&gt;converts the &lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt;&lt;/a&gt; into Static Single Assignment (&lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt;)
  form, a lower-level intermediate representation suited for
  &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ssa&quot; title=&quot;cmd/compile/internal/ssa&quot;&gt;machine-independent optimizations and rewrite rules&lt;/a&gt;.&lt;/dd&gt;
&lt;dt&gt;Machine code generation&lt;/dt&gt;
&lt;dd&gt;The compiler rewrites the &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; form into &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ssa/_gen&quot; title=&quot;cmd/compile/internal/ssa/_gen&quot;&gt;machine-specific variants&lt;/a&gt;,
  allocates registers, and applies more optimization passes. At the end, &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/internal/obj&quot; title=&quot;cmd/internal/obj&quot;&gt;the
  assembler&lt;/a&gt; turns the generated instructions into machine code.&lt;/dd&gt;
&lt;/dl&gt;
&lt;h2 id=&quot;the-hammer&quot;&gt;The hammer&lt;/h2&gt;
&lt;p&gt;My first idea is to replace occurrences of &lt;code&gt;netip.AddrFrom16(ip.As16())&lt;/code&gt; with
&lt;code&gt;netip.Addr{addr: ip.addr, z: netip.z6noz}&lt;/code&gt; as early as possible, during the
“noding” process. Before that, the type checking phase prevents
us from accessing unexported struct fields.&lt;/p&gt;
&lt;p&gt;Go 1.27 introduced a convenient debug option to dump the &lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt; of a function at
interesting points during compilation:&lt;/p&gt;
&lt;div class=&quot;language-bash-session codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOTOOLCHAIN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;go1.27.1&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOAMD64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;v3&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;go&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;build&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-a&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-gcflags&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-d=astdump=AddrTo6Safe&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;.
&lt;span class=&quot;go&quot;&gt;Writing text ast output for AddrTo6Safe to AddrTo6Safe.ast&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Writing html ast output for AddrTo6Safe to AddrTo6Safe.html&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Writing html syntax output for AddrTo6Safe to AddrTo6Safe.syntax.html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the HTML file, the first column shows the &lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt; as it comes out of noding:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ir codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;DCLFUNC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;addrto6.AddrTo6Safe&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ABI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ABIInternal&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FUNC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;func(netip.Addr)&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;k&quot;&gt;DCLFUNC-Dcl&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.ip&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.~r0&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAMOUT&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;k&quot;&gt;DCLFUNC-body&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;IF&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# ipv6_safe.go:11:2&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;IF-Cond&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;bool
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC-Fun&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;METHEXPR&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;addrto6.Is4&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FUNC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;func(netip.Addr)&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;bool
&lt;span class=&quot;w&quot;&gt;. . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;TYPE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PEXTERN&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;type&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC-Args&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.ip&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;IF-Body&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# ipv6_safe.go:12:6&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.ip&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC-Fun&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;. . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;netip.AddrFrom16&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PFUNC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FUNC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;func([&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;]byte)&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC-Args&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;ARRAY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;[&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;]byte
&lt;span class=&quot;w&quot;&gt;. . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC-Fun&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;. . . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;METHEXPR&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;addrto6.As16&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FUNC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;func(netip.Addr)&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;[&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;]byte
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;. . . . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;TYPE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PEXTERN&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;type&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC-Args&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.ip&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;RETURN&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# ipv6_safe.go:14:2&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;RETURN-Results&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.ip&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the body of the &lt;code&gt;if&lt;/code&gt; statement, we spot the calls to the method
&lt;code&gt;netip.Addr.As16()&lt;/code&gt; and to the function &lt;code&gt;netip.AddrFrom16()&lt;/code&gt;. Our goal is to
patch them with a struct literal:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ir codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;IF-Body&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# ipv6_safe.go:12:6&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.ip&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;STRUCTLIT&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;STRUCTLIT-List&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;STRUCTKEY&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.addr
&lt;span class=&quot;w&quot;&gt;. . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;DOT&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.addr&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.uint128
&lt;span class=&quot;w&quot;&gt;. . . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.ip&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;STRUCTKEY&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.z
&lt;span class=&quot;w&quot;&gt;. . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;netip.z6noz&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PEXTERN&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;unique.Handle[net/netip.addrDetail]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In &lt;a href=&quot;https://github.com/golang/go/blob/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/noder/reader.go&quot; title=&quot;reader.go&quot;&gt;noder’s &lt;code&gt;reader.go&lt;/code&gt;&lt;/a&gt;, the &lt;code&gt;expr()&lt;/code&gt; method builds the &lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt; tree for
an expression. At the end of the &lt;code&gt;exprCall&lt;/code&gt; case, we add a call to a
&lt;code&gt;rewriteAddrFrom16As16()&lt;/code&gt; function. It takes the current node and returns the
struct literal on success, or &lt;code&gt;nil&lt;/code&gt; if the rewrite is not possible. First, we
check that we have the expected pattern: a call to the &lt;code&gt;netip.AddrFrom16()&lt;/code&gt;
function with a call to the &lt;code&gt;netip.Addr.As16()&lt;/code&gt; method as its only argument:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rewriteAddrFrom16As16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;CallExpr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;OCALLFUNC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isNetipFunc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;AddrFrom16&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;CallExpr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;OCALLFUNC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isNetipFunc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Addr.As16&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// [...]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, we fetch &lt;code&gt;netip.z6noz&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;z6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lookupVar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;StaticCalleeName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Sym&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Pkg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;z6noz&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And we build the struct literal:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;typ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Node&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;typ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Node&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Sym&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;addr&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;typecheck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;DotField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;z&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z6noz&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;NewStructKeyExpr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;lit&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;NewCompLitExpr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;OSTRUCTLIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;typ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;lit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SetTypecheck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Have a look at the &lt;a href=&quot;https://github.com/vincentbernat/go/commit/netipmap-fix2&quot; title=&quot;cmd/compile: optimize netip.AddrFrom16(ip.As16()) in the noder&quot;&gt;complete patch&lt;/a&gt;.&lt;sup id=&quot;fnref:statement&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:statement&quot;&gt;8&lt;/a&gt;&lt;/sup&gt; We can test it
with the following commands:&lt;/p&gt;
&lt;div class=&quot;language-bash-session codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;src
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;./make.bash
&lt;span class=&quot;go&quot;&gt;Building Go cmd/dist using /usr/lib/go-1.27. (go1.27.1 linux/amd64)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Building Go toolchain1 and bootstrap cmd/go (go_bootstrap) using /usr/lib/go-1.27.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Building Go toolchain2 using go_bootstrap and Go toolchain1.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Building Go toolchain3 and commands using go_bootstrap and Go toolchain2.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Checking command staleness for linux/amd64.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Installed Go for linux/amd64 in /home/bernat/code/free/go&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Installed commands in /home/bernat/code/free/go/bin&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;*** You need to add /home/bernat/code/free/go/bin to your PATH.&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;export&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PWD&lt;/span&gt;/../bin:&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;go&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;version
&lt;span class=&quot;go&quot;&gt;go version go1.28-devel_9834516e20 Sat Sep 12 08:23:11 2026 -0700 linux/amd64&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;go&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;net/netip/...
&lt;span class=&quot;go&quot;&gt;ok      net/netip   0.224s&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;../../go-netip-addrto6
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;go&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;.
&lt;span class=&quot;go&quot;&gt;ok      github.com/vincentbernat/go-netip-addrto6   0.062s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The generated code for the helper is now the shortest possible version!&lt;/p&gt;
&lt;div class=&quot;language-go-assembly codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AX = input.addr.hi, BX = input.addr.lo, CX = input.z&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CMPQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; check &quot;z&quot; if this is an IPv4 address&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JNE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; if not, stop here&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; CX = netip.z6noz&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RET&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// return value = Addr{hi: AX, lo: BX, z: CX}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Go maintainers are unlikely to accept this change. It relies on the internal
structure of &lt;code&gt;net/netip.Addr&lt;/code&gt;. It’s an ugly hack in the noder, whose job is to
faithfully translate the type-checked AST into the &lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt;. And it’s harder to
maintain than adding a &lt;code&gt;To6()&lt;/code&gt; method.&lt;/p&gt;
&lt;h2 id=&quot;the-screwdriver&quot;&gt;The screwdriver&lt;/h2&gt;
&lt;p&gt;The right place for such an optimization is the &lt;a href=&quot;https://github.com/golang/go/blob/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ssa/README.md&quot; title=&quot;Introduction to the Go compiler&#39;s SSA backend&quot;&gt;generic &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; phase&lt;/a&gt;. One of
the last machine-independent passes is &lt;code&gt;memcombine&lt;/code&gt;. With the appropriate debug
flag, the compiler dumps the &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; form after this pass:&lt;sup id=&quot;fnref:html&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:html&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-bash-session codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOTOOLCHAIN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;go1.26.8&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOAMD64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;v3&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt; &lt;/span&gt;go&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;build&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-a&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-gcflags&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;-d=ssa/memcombine/dump=AddrTo6Safe&#39;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;.
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;head&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-5&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;AddrTo6Safe_01__memcombine.dump
&lt;span class=&quot;go&quot;&gt;AddrTo6Safe func(netip.Addr) netip.Addr&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  b2:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    (?) v1 = InitMem &amp;lt;mem&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    (?) v2 = SP &amp;lt;uintptr&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    (?) v3 = SB &amp;lt;uintptr&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The result of the &lt;code&gt;memcombine&lt;/code&gt; pass follows the same structure as the assembly
code for &lt;code&gt;AddrTo6Safe()&lt;/code&gt; &lt;a href=&quot;https://vincent.bernat.ch#asm-addrto6safe&quot;&gt;we looked at earlier&lt;/a&gt;: two stores,
one move, and two loads we would like to optimize away.&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;; […]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+0}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+8}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v466&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*netip.addrDetail&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[2]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.z&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; […]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v23&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[:8] = bswap(hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v415&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr[:8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v299&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v415&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr[8:]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v39&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.lo&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; […]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Each line features a value identifier (&lt;code&gt;v442&lt;/code&gt;), an operation with its type
(&lt;code&gt;Bswap64 &amp;lt;uint64&amp;gt;&lt;/code&gt;), and its arguments (&lt;code&gt;v490&lt;/code&gt;).&lt;sup id=&quot;fnref:lines&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:lines&quot;&gt;10&lt;/a&gt;&lt;/sup&gt; Values are the basic
building blocks of &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; and are defined exactly once. Square brackets enclose
integer parameters (&lt;code&gt;[8]&lt;/code&gt;) and curly braces contain auxiliary arguments
(&lt;code&gt;{netip.addr}&lt;/code&gt;). Operations writing to memory produce a new memory state. Every
memory operation takes the current state as its last argument, which keeps them
in order.&lt;/p&gt;
&lt;h3 id=&quot;on-paper&quot;&gt;On paper&lt;/h3&gt;
&lt;p&gt;Let’s focus on &lt;code&gt;output.addr.lo&lt;/code&gt;, aka &lt;code&gt;v39&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+8}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v415&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v415&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr[8:]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v39&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.lo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To simplify this code, we could apply three rewriting rules:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The first one adds a shortcut when &lt;strong&gt;loading through a move&lt;/strong&gt;: &lt;code&gt;(Load (OffPtr
   [o] p) (Move p src mem)) =&amp;gt; (Load (OffPtr [o] src) mem)&lt;/code&gt;. This matches &lt;code&gt;v174&lt;/code&gt;
   with its arguments &lt;code&gt;v415&lt;/code&gt; and &lt;code&gt;v286&lt;/code&gt; and creates a new value &lt;code&gt;v600&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+8}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v415&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr[8]&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v600&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v600&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v39&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.lo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The second one simplifies a &lt;strong&gt;load following a store&lt;/strong&gt;: &lt;code&gt;(Load p (Store p x
   _)) =&amp;gt; x&lt;/code&gt;. The load is &lt;em&gt;forwarded&lt;/em&gt;: the stored value replaces it and no memory
   access remains. It matches &lt;code&gt;v174&lt;/code&gt;. It notices that &lt;code&gt;v600&lt;/code&gt; and &lt;code&gt;v173&lt;/code&gt; are the
   same address and replaces &lt;code&gt;v174&lt;/code&gt; with a copy of &lt;code&gt;v442&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+8}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v415&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v600&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.lo)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v39&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.lo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The last step &lt;strong&gt;cancels the two byte swaps&lt;/strong&gt;: &lt;code&gt;(Bswap64 (Bswap64 x)) =&amp;gt; x&lt;/code&gt;.
   &lt;code&gt;v39&lt;/code&gt; becomes a copy of &lt;code&gt;v490&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+8}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v415&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v600&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v39&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.lo = input.addr.lo&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If we ignore the values not needed to compute &lt;code&gt;v39&lt;/code&gt;, only this &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; form remains:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+8}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v39&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;             &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.lo = input.addr.lo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s switch to &lt;code&gt;output.addr.hi&lt;/code&gt;, aka &lt;code&gt;v299&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+0}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v23&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[:8] = bswap(hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr[:8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v299&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.hi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To optimize it away, we also apply three rewriting rules:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The first one also adds a shortcut when &lt;strong&gt;loading through a move&lt;/strong&gt;, but
   without an offset: &lt;code&gt;(Load p (Move p src mem)) =&amp;gt; (Load src mem)&lt;/code&gt;. This rewrites &lt;code&gt;v416&lt;/code&gt;
   to use arguments from &lt;code&gt;v286&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+0}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v23&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[:8] = bswap(hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[:8]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v299&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.hi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The second rule &lt;strong&gt;forwards a value stored one step earlier&lt;/strong&gt;, skipping over a
   store to another address: &lt;code&gt;(Load p (Store q _ (Store p x _))) =&amp;gt; x&lt;/code&gt;. This
   matches &lt;code&gt;v416&lt;/code&gt;: &lt;code&gt;x&lt;/code&gt; is &lt;code&gt;v542&lt;/code&gt;, &lt;code&gt;p&lt;/code&gt; is &lt;code&gt;v22&lt;/code&gt; (&lt;code&gt;&amp;amp;a16&lt;/code&gt;), &lt;code&gt;q&lt;/code&gt; is &lt;code&gt;v173&lt;/code&gt;
   (&lt;code&gt;&amp;amp;a16[8]&lt;/code&gt;), and &lt;code&gt;p&lt;/code&gt; and &lt;code&gt;q&lt;/code&gt; do not overlap for &lt;code&gt;uint64&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+0}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v23&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[:8] = bswap(hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.hi)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v299&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.hi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The third rule &lt;strong&gt;cancels two byte swaps&lt;/strong&gt;: &lt;code&gt;(Bswap64 (Bswap64 x)) =&amp;gt; x&lt;/code&gt;.
   &lt;code&gt;v299&lt;/code&gt; becomes a copy of &lt;code&gt;v502&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+0}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v23&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[:8] = bswap(hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v299&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.hi = input.addr.hi&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If we remove the values not used to compute &lt;code&gt;v299&lt;/code&gt;, we get this &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; form:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+0}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v299&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.hi = input.addr.hi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;in-practice&quot;&gt;In practice&lt;/h3&gt;
&lt;p&gt;Most of these rules already exist in &lt;a href=&quot;https://github.com/golang/go/blob/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ssa/_gen/generic.rules&quot; title=&quot;generic.rules&quot;&gt;&lt;code&gt;generic.rules&lt;/code&gt;&lt;/a&gt;. They use
conditions to validate their context: &lt;code&gt;ssa.IsSamePtr()&lt;/code&gt; for the same address,
&lt;code&gt;ssa.Disjoint()&lt;/code&gt; for addresses that do not overlap. The rule forwarding a stored
value to a load already exists with three variants looking through several other
stores. Here are the two we need:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa-rules codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;t1&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p1&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{t2}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;x&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;_&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ssa.IsSamePtr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;p1,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;copyCompatibleType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;t1,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;x.Type&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;t1.Size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;t2.Size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;x
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;t1&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p1&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{t2}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;_&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{t3}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p3&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;x&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;_&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ssa.IsSamePtr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;p1,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p3&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;copyCompatibleType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;t1,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;x.Type&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;t1.Size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;t3.Size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ssa.Disjoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;p3,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;t3,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;t2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Go 1.27 added the rule loading through a move with &lt;a href=&quot;https://go-review.googlesource.com/c/go/+/748200&quot; title=&quot;cmd/compile: forward small Load through Move to avoid redundant copies&quot;&gt;CL 748200&lt;/a&gt; to fix
&lt;a href=&quot;https://github.com/golang/go/issues/77720&quot; title=&quot;cmd/compile: field access on struct-returning method copies entire struct&quot;&gt;issue #77720&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa-rules codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;t1&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;op1:&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[o1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p1&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;move:&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[n]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;src&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;mem&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;o1&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;o1&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;t1.Size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;n&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ssa.IsSamePtr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;p1,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ssa.IsVolatile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;src&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@move.Block&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;t1&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;op1.Type&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[o1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;src&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;mem&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It lacks a variant without an offset:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa-rules codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;t1&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p1&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;move:&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[n]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;src&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;mem&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p1.Op&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;ssaop.OpOffPtr
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;t1.Size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;n&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ssa.IsSamePtr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;p1,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ssa.IsVolatile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;src&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@move.Block&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;t1&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;p1.Type&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;src&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;mem&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There is no generic rule to cancel two byte swaps, but the &lt;a href=&quot;https://github.com/golang/go/blob/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ssa/_gen/AMD64.rules&quot; title=&quot;AMD64.rules&quot;&gt;AMD64 lowering
pass&lt;/a&gt; includes this rule:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa-rules codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;BSWAP(Q|L)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;BSWAP(Q|L)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After switching to Go’s development branch and &lt;a href=&quot;https://github.com/vincentbernat/go/commit/netipmap-fix3&quot; title=&quot;cmd/compile/internal/ssa: forward small offset-less Load through Move&quot;&gt;adding the missing
rule&lt;/a&gt;, the generated assembly code is worse than with Go 1.26.8,
even though our additional rule slightly improves the situation at the end:&lt;/p&gt;
&lt;div class=&quot;language-go-assembly codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AX = input.addr.hi, BX = input.addr.lo, CX = input.z&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; Push the stack (16 bytes):&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;    0(SP) a16 [16]byte&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;PUSHQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BP&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BP&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SUBQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CMPQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; check &quot;z&quot; if this is an IPv4 address&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JNE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; if not, stop here&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; The four forwarded bytes: the low half of input.addr.lo is taken apart and&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; put back together in registers&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; DX = input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHRQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; BX = input.addr.lo &amp;gt;&amp;gt; 24&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SI&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; SI = input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHRQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; DX = input.addr.lo &amp;gt;&amp;gt; 16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DI&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; DI = input.addr.lo, kept for the pack&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHRQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SI&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; SI = input.addr.lo &amp;gt;&amp;gt; 8&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;DIB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;R8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; R8 = byte(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;SIB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SI&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; SI = byte(input.addr.lo &amp;gt;&amp;gt; 8)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHLQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SI&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;R8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SI&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; SI = two low bytes of input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; DX = byte(input.addr.lo &amp;gt;&amp;gt; 16)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHLQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; BX = byte(input.addr.lo &amp;gt;&amp;gt; 24)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHLQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; BX = input.addr.lo &amp;amp; 0xffffffff&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; Pack: byteorder.BEPutUint64(a16[:8], input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;       byteorder.BEPutUint64(a16[8:], input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBEQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;AX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBEQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; The four other bytes of input.addr.lo, read one by one from a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[11]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHLQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[10]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHLQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[9]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHLQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;48&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHLQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;56&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; output.z = netip.z6noz&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; output.addr.hi = byteorder.BEUint64(a16[:8])&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBEQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;AX&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.lo assembled from the previous steps&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;LEAVEQ&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RET&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// return value = Addr{hi: AX, lo: BX, z: CX}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The rule loading through a move, added in Go 1.27, introduced this regression.&lt;/p&gt;
&lt;h3 id=&quot;out-of-order&quot;&gt;Out of order&lt;/h3&gt;
&lt;p&gt;Let’s not give up now! In reality, the rewriting rules run before &lt;code&gt;memcombine&lt;/code&gt;,
notably in the &lt;code&gt;late opt&lt;/code&gt; pass. At this point, the inlined versions of
&lt;code&gt;BEPutUint64()&lt;/code&gt; and &lt;code&gt;BEUint64()&lt;/code&gt; still expand to sixteen byte stores and sixteen
byte loads, matching their &lt;a href=&quot;https://pkg.go.dev/internal/byteorder#BEUint64&quot; title=&quot;internal/byteorder.BEUint64 on Go Packages&quot;&gt;source code&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// bounds check hint to compiler; see golang.org/issue/14808&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;48&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;56&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s follow two bytes of &lt;code&gt;output.addr.lo&lt;/code&gt;: &lt;code&gt;addr[15]&lt;/code&gt; and &lt;code&gt;addr[11]&lt;/code&gt;. Here is
a simplified &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; form before &lt;code&gt;late opt&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v273&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Trunc64to8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; byte(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v226&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Trunc64to8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v225&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; byte(input.addr.lo &amp;gt;&amp;gt; 32)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; […]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v235&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v233&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v226&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v223&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[11] = byte(lo &amp;gt;&amp;gt; 32)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v247&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v245&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v238&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v235&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[12] = …&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v259&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v257&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v250&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v247&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[13] = …&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v271&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v269&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v262&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v259&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[14] = …&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v280&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v273&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v271&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[15] = byte(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; […]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v433&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[15]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr[15]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v435&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v433&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr[15]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v479&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[11]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr[11]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v481&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v479&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr[11]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The first rule loads through the move: &lt;code&gt;(Load (OffPtr [o] p) (Move p src mem))
=&amp;gt; (Load (OffPtr [o] src) mem)&lt;/code&gt;. It matches both loads, which now read &lt;code&gt;a16&lt;/code&gt;
with the memory state before the copy:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v600&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[15]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[15]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v435&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v600&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[15]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v601&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[11]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[11]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v481&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v601&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[11]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The second rule shortcuts a load following a store: &lt;code&gt;(Load p (Store p x _)) =&amp;gt;
x&lt;/code&gt;. It matches &lt;code&gt;v435&lt;/code&gt;, as &lt;code&gt;v282&lt;/code&gt; stores &lt;code&gt;a16[15]&lt;/code&gt;. It does not match &lt;code&gt;v481&lt;/code&gt;:
&lt;code&gt;v235&lt;/code&gt; stores &lt;code&gt;a16[11]&lt;/code&gt; four stores earlier in the chain, while the variants of
this rule look through three stores at most.&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v435&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v273&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; byte(input.addr.lo)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v601&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[11]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[11]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v481&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v601&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[11]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The same happens to the other bytes: the rule forwards the four bytes stored
last, &lt;code&gt;a16[12]&lt;/code&gt; to &lt;code&gt;a16[15]&lt;/code&gt;. The twelve other loads now read &lt;code&gt;a16&lt;/code&gt; instead of
&lt;code&gt;addr&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;BEUint64()&lt;/code&gt; becomes a chain of &lt;code&gt;Or64&lt;/code&gt;, each one adding a byte shifted into
place. &lt;code&gt;memcombine&lt;/code&gt; is a &lt;a href=&quot;https://github.com/golang/go/blob/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ssacompile/memcombine.go&quot; title=&quot;memcombine.go&quot;&gt;pass written in Go&lt;/a&gt;, not a set of rewrite
rules. It starts from the last &lt;code&gt;Or64&lt;/code&gt; of the chain and collects up to eight
terms. If each term is a byte load, extended to 64 bits and shifted, and if the
eight loads read consecutive addresses from the same pointer with the same
memory state, it replaces the whole chain with a single 64-bit load and a byte
swap. Otherwise, it tries again with four, then two terms, and from each
intermediate &lt;code&gt;Or64&lt;/code&gt;. Here is the loop checking each term in a simplified version
of &lt;code&gt;combineLoads()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Op&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shiftOp&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;peelShift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Op&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extOp&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Op&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ssaop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;OpLoad&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;splitPtr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;LoadRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For &lt;code&gt;output.addr.hi&lt;/code&gt;, the eight loads read &lt;code&gt;a16&lt;/code&gt; with the same memory state
&lt;code&gt;v282&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v13&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;               &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[0]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v530&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v14&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;               &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[1]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v488&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v504&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[2]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v405&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v537&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[3]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v385&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v397&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[4]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v361&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v373&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[5]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v196&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v63&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;               &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[6]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v432&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v315&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[7]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v319&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ZeroExt8to64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v432&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; uint64(a16[7])&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v329&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ZeroExt8to64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v196&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; uint64(a16[6])&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v330&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Lsh64x64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[true]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v329&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v138&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; uint64(a16[6]) &amp;lt;&amp;lt; 8&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v331&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v319&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v330&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[7] | a16[6] &amp;lt;&amp;lt; 8&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; […] same for a16[5] to a16[1]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v401&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ZeroExt8to64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v13&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; uint64(a16[0])&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v402&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Lsh64x64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[true]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v401&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v55&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; uint64(a16[0]) &amp;lt;&amp;lt; 56&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v403&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v402&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v391&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | a16[0] &amp;lt;&amp;lt; 56 = output.addr.hi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;memcombine&lt;/code&gt; merges them into one load and a swap:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[:8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.hi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For &lt;code&gt;output.addr.lo&lt;/code&gt;, here is the chain &lt;code&gt;memcombine&lt;/code&gt; sees after &lt;code&gt;late opt&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v436&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ZeroExt8to64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v273&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr[15], forwarded&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v448&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v436&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v447&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | addr[14] &amp;lt;&amp;lt; 8, forwarded&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v460&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v459&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v448&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | addr[13] &amp;lt;&amp;lt; 16, forwarded&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v472&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v471&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v460&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | addr[12] &amp;lt;&amp;lt; 24, forwarded&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v484&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v483&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v472&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | a16[11] &amp;lt;&amp;lt; 32, loaded&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v496&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v495&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v484&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | a16[10] &amp;lt;&amp;lt; 40, loaded&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v508&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v507&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v496&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | a16[9] &amp;lt;&amp;lt; 48, loaded&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v520&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v519&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v508&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | a16[8] &amp;lt;&amp;lt; 56, loaded&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;From &lt;code&gt;v520&lt;/code&gt;, four of the eight terms are forwarded bytes, not loads from memory,
and &lt;code&gt;memcombine&lt;/code&gt; can’t combine them. It doesn’t merge the four remaining loads
either, as they sit on top of the forwarded bytes.&lt;/p&gt;
&lt;h3 id=&quot;back-in-order&quot;&gt;Back in order&lt;/h3&gt;
&lt;p&gt;In summary, the rewriting rules run too early to be effective. A quick
workaround exists: run an earlier round of &lt;code&gt;memcombine&lt;/code&gt; before &lt;code&gt;late opt&lt;/code&gt;. After
&lt;a href=&quot;https://github.com/vincentbernat/go/commit/netipmap-fix4&quot; title=&quot;cmd/compile/internal/ssacompile: run memcombine before late opt&quot;&gt;this change&lt;/a&gt;, the generated code for the helper is back to the
shortest possible version:&lt;/p&gt;
&lt;div class=&quot;language-go-assembly codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AX = input.addr.hi, BX = input.addr.lo, CX = input.z&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CMPQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; check &quot;z&quot; if this is an IPv4 address&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JNE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; if not, stop here&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; CX = netip.z6noz&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RET&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// return value = Addr{hi: AX, lo: BX, z: CX}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And the benchmark confirms it! ✌️&lt;/p&gt;
&lt;div class=&quot;language-text-only codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;goos: linux
goarch: amd64
pkg: github.com/vincentbernat/go-netip-addrto6
cpu: AMD Ryzen 5 5600X 6-Core Processor
                   │   Go 1.26.8    │             Our branch              │
                   │     sec/op     │    sec/op     vs base               │
AddrTo6/safe          6.5470n ±  0%   0.8944n ± 4%  -86.34% (p=0.002 n=6)
AddrTo6/unsafe        0.9071n ±  3%   0.8682n ± 1%   -4.28% (p=0.002 n=6)
AddrTo6/builtin       0.8871n ±  2%   0.8785n ± 1%        ~ (p=0.310 n=6)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id=&quot;next-steps&quot;&gt;Next steps&lt;/h1&gt;
&lt;p&gt;I think Go maintainers would reject this change because of the additional
&lt;code&gt;memcombine&lt;/code&gt; pass. Instead, I plan to publish this blog post and bring up the
subject again as a follow-up to &lt;a href=&quot;https://github.com/golang/go/issues/54365&quot; title=&quot;proposal: net/netip: add netip.Addr.Map · Issue #54365 · golang/go&quot;&gt;issue #54365&lt;/a&gt;. Either the sheer complexity and
the Go 1.27 regression convince the maintainers that adding a &lt;code&gt;To6()&lt;/code&gt; method is
simpler and more efficient, or they advise me on how to move forward. Either
way, digging into this subject taught me a lot about the Go compiler! ⚙️&lt;/p&gt;
&lt;div class=&quot;admonition&quot;&gt;
&lt;p class=&quot;admonition-title&quot;&gt;Update (2026-10)&lt;/p&gt;
&lt;p&gt;I opened &lt;a href=&quot;https://github.com/golang/go/issues/81994&quot; title=&quot;proposal: net/netip: add netip.Addr.To6() · Issue #81994 · golang/go&quot;&gt;issue #81994&lt;/a&gt; to propose &lt;code&gt;Addr.To6()&lt;/code&gt;. Give it a 👍 if you want it in Go!&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn:why&quot;&gt;
&lt;p&gt;IPv4-mapped IPv6 addresses let you handle only IPv6 addresses in your code
and keep conversions at a few well-defined boundaries. I use them in
&lt;a href=&quot;https://github.com/akvorado/akvorado&quot; title=&quot;Akvorado: flow collector, enricher and visualizer&quot;&gt;Akvorado&lt;/a&gt;. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:why&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:equiv&quot;&gt;
&lt;p&gt;This is not strictly equivalent. The zero value becomes &lt;code&gt;::&lt;/code&gt; while it would
make more sense to leave it untouched. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:equiv&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:inconvenient&quot;&gt;
&lt;p&gt;I suppose Go maintainers keep it inconvenient on purpose: they don’t want
random packages to patch the standard library or other packages. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:inconvenient&quot; title=&quot;Jump back to footnote 3 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:tests&quot;&gt;
&lt;p&gt;To avoid catastrophic bugs when &lt;code&gt;netip.Addr&lt;/code&gt;’s layout changes, you must &lt;a href=&quot;https://github.com/vincentbernat/go-netip-addrto6/blob/main/ipv6_unsafe_test.go&quot; title=&quot;Tests for unsafe AddrTo6() function&quot;&gt;add
tests&lt;/a&gt; to detect it. This is more dangerous if you put this code in a
package. Either ask users to run the tests themselves, or detect the change
at run time and panic. Hiding this optimization behind a build tag would
make users aware of this potential trap. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:tests&quot; title=&quot;Jump back to footnote 4 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:dis&quot;&gt;
&lt;p&gt;I produced the assembly code with &lt;code&gt;GOTOOLCHAIN=go1.26.8 GOAMD64=v3 ./go-asm
&#39;\.asm&#39;&lt;/code&gt; from the &lt;a href=&quot;https://github.com/vincentbernat/go-netip-addrto6&quot;&gt;companion repository&lt;/a&gt;, then edited it a bit to keep this
article from turning into an endless rabbit hole. Due to an unfortunate
sequence of events, we switch between versions: Go 1.27 introduced a
regression that blurs the point of this article. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:dis&quot; title=&quot;Jump back to footnote 5 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:inline&quot;&gt;
&lt;p&gt;The function is short enough for the compiler to inline it, so the assembly
code may vary depending on the surrounding code. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:inline&quot; title=&quot;Jump back to footnote 6 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:amd64v3&quot;&gt;
&lt;p&gt;&lt;code&gt;MOVBEQ&lt;/code&gt; requires &lt;code&gt;GOAMD64=v3&lt;/code&gt;, matching the &lt;a href=&quot;https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels&quot; title=&quot;X86-64 on Wikipedia&quot;&gt;x86-64-v3
microarchitecture&lt;/a&gt; from 2013. Otherwise, the compiler translates
&lt;code&gt;BEPutUint64()&lt;/code&gt; to &lt;code&gt;BSWAPQ&lt;/code&gt;+&lt;code&gt;MOVQ&lt;/code&gt; and &lt;code&gt;BEUint64()&lt;/code&gt; to &lt;code&gt;MOVQ&lt;/code&gt;+&lt;code&gt;BSWAPQ&lt;/code&gt;. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:amd64v3&quot; title=&quot;Jump back to footnote 7 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:statement&quot;&gt;
&lt;p&gt;When the call is used as a statement, a struct literal alone is invalid. The
patch then turns it into &lt;code&gt;_ = netip.Addr{…}&lt;/code&gt;. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:statement&quot; title=&quot;Jump back to footnote 8 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:html&quot;&gt;
&lt;p&gt;The compiler can also write an HTML file with the result of each pass:&lt;/p&gt;
&lt;div class=&quot;language-bash-session codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOSSAFUNC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;AddrTo6Safe&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOTOOLCHAIN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;go1.26.8&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOAMD64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;v3&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;go&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;build&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-a&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;.
&lt;span class=&quot;go&quot;&gt;dumped SSA for AddrTo6Safe,1 to ./ssa.html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:html&quot; title=&quot;Jump back to footnote 9 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:lines&quot;&gt;
&lt;p&gt;Source line numbers in parentheses follow value identifiers, but I removed
them from the examples. The &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; form also features branches, but we don’t
need them to understand our optimizations. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:lines&quot; title=&quot;Jump back to footnote 10 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Sun, 04 Oct 2026 14:12:19 +0000</pubDate>

</item> 
<item>
	<title>Vincent Bernat: Hacking the Go compiler to efficiently map IPv4 to IPv6</title>
	<guid>http://www.luffy.cx/en/blog/2026-go-compiler-optimization-netip.html</guid>
	<link>https://vincent.bernat.ch/en/blog/2026-go-compiler-optimization-netip</link>
     <description>  &lt;p&gt;&lt;a href=&quot;https://pkg.go.dev/netip.addr&quot; title=&quot;netip.addr on Go Packages&quot;&gt;&lt;code&gt;netip.Addr&lt;/code&gt;&lt;/a&gt; features an &lt;a href=&quot;https://pkg.go.dev/netip.addr.Unmap&quot; title=&quot;netip.addr.Unmap on Go Packages&quot;&gt;&lt;code&gt;Unmap()&lt;/code&gt;&lt;/a&gt;
method returning the unwrapped IPv4 contained in an &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc4291#section-2.5.5.2&quot; title=&quot;RFC 4291: IP Version 6 Addressing Architecture&quot;&gt;IPv4-mapped IPv6
address&lt;/a&gt;: from &lt;code&gt;::ffff:203.0.113.10&lt;/code&gt; or &lt;code&gt;::ffff:cb00:710a&lt;/code&gt;, it returns
&lt;code&gt;203.0.113.10&lt;/code&gt;.&lt;sup id=&quot;fnref:why&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:why&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; There is no &lt;code&gt;Map()&lt;/code&gt; or &lt;code&gt;To6()&lt;/code&gt; method for the reverse
direction. Such a method is trivial to implement, but Go maintainers have
&lt;a href=&quot;https://github.com/golang/go/issues/54365#issuecomment-1570607144&quot; title=&quot;Issue #54365: proposal: net/netip: add netip.Addr.Map&quot;&gt;rejected&lt;/a&gt; it on the grounds that users should write
&lt;code&gt;netip.AddrFrom16(ip.As16())&lt;/code&gt; and let the compiler optimize it.&lt;sup id=&quot;fnref:equiv&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:equiv&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; Today,
this pattern is eight times slower than a native method. How can we teach the
compiler to optimize this sequence?&lt;/p&gt;
&lt;div class=&quot;toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#the-alternatives&quot;&gt;The alternatives&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#modifying-the-go-standard-library&quot;&gt;Modifying the Go standard library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#as-a-helper&quot;&gt;As a helper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#as-an-unsafe-function&quot;&gt;As an unsafe function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#benchmarks&quot;&gt;Benchmarks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#assembly-code&quot;&gt;Assembly code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#hacking-the-go-compiler&quot;&gt;Hacking the Go compiler&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#the-hammer&quot;&gt;The hammer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#the-screwdriver&quot;&gt;The screwdriver&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#on-paper&quot;&gt;On paper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#in-practice&quot;&gt;In practice&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#out-of-order&quot;&gt;Out of order&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#back-in-order&quot;&gt;Back in order&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#next-steps&quot;&gt;Next steps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h1 id=&quot;the-alternatives&quot;&gt;The alternatives&lt;/h1&gt;
&lt;p&gt;Let’s explore three ways to implement the map semantics for &lt;code&gt;netip.Addr&lt;/code&gt;. My
favorite is to add it to the Go standard library. Go maintainers prefer a small
external helper chaining &lt;code&gt;netip.AddrFrom16()&lt;/code&gt; and &lt;code&gt;netip.Addr.As16()&lt;/code&gt;, hoping
the compiler eventually optimizes it. The &lt;a href=&quot;https://pkg.go.dev/unsafe&quot; title=&quot;unsafe on Go Packages&quot;&gt;&lt;code&gt;unsafe&lt;/code&gt; package&lt;/a&gt;
opens a third path, with the same performance as the first solution.&lt;/p&gt;
&lt;h2 id=&quot;modifying-the-go-standard-library&quot;&gt;Modifying the Go standard library&lt;/h2&gt;
&lt;p&gt;Internally, &lt;a href=&quot;https://pkg.go.dev/net/netip#Addr&quot; title=&quot;net/netip.Addr on Go Packages&quot;&gt;&lt;code&gt;netip.Addr&lt;/code&gt;&lt;/a&gt; stores any IP address as a
128-bit value with an extra field &lt;code&gt;z&lt;/code&gt; to encode the family and the zone:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;uint128&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrDetail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrDetail&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isV6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// IPv4 is false, IPv6 is true.&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;zoneV6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// != &quot;&quot; only if IsV6 is true.&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrDetail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z4&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrDetail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z6noz&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Make&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrDetail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isV6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://pkg.go.dev/net/netip#AddrFrom4&quot; title=&quot;net/netip.AddrFrom4 on Go Packages&quot;&gt;&lt;code&gt;AddrFrom4()&lt;/code&gt;&lt;/a&gt; encodes an IPv4 address as an
IPv4-mapped IPv6 address and sets &lt;code&gt;z&lt;/code&gt; to the unique value &lt;code&gt;z4&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AddrFrom4 returns the address of the IPv4 address given by the bytes in addr.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AddrFrom4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;uint128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xffff00000000&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])},&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://pkg.go.dev/net/netip#Addr.Unmap&quot; title=&quot;net/netip.Addr.Unmap on Go Packages&quot;&gt;&lt;code&gt;Unmap()&lt;/code&gt;&lt;/a&gt; turns an IPv4-mapped IPv6 address into an
IPv4 address by setting the &lt;code&gt;z&lt;/code&gt; field to &lt;code&gt;z4&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Unmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Is4In6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z4&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Implementing the reverse direction inside the Go standard library is trivial: we
set the &lt;code&gt;z&lt;/code&gt; field to &lt;code&gt;z6noz&lt;/code&gt; if the address is IPv4.&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// To6 maps an IPv4 address to an IPv4-mapped IPv6 address. It returns an&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// IPv6 address unmodified.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;To6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Is4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z6noz&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;as-a-helper&quot;&gt;As a helper&lt;/h2&gt;
&lt;p&gt;We can’t access the &lt;code&gt;z&lt;/code&gt; field from outside the &lt;code&gt;net/netip&lt;/code&gt; package. Instead, we
build a small helper around the &lt;code&gt;netip.AddrFrom16(ip.As16())&lt;/code&gt; pattern:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AddrTo6 maps an IPv4 address to an IPv4-mapped IPv6 address. It returns an&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// IPv6 address unmodified.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AddrTo6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Is4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AddrFrom16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;As16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;as-an-unsafe-function&quot;&gt;As an unsafe function&lt;/h2&gt;
&lt;p&gt;Another solution uses the &lt;code&gt;unsafe&lt;/code&gt; package to alter the &lt;code&gt;Addr&lt;/code&gt; struct through
a proxy with the same memory layout:&lt;sup id=&quot;fnref:tests&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:tests&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// addrProxy has the same memory layout as netip.Addr.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrProxy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// netip.uint128&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Pointer&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// unique.Handle[netip.addrDetail]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;anyIPv6&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;IPv6Unspecified&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netipZ6noz&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;anyIPv6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// AddrTo6 maps an IPv4 address to an IPv4-mapped IPv6 address. It returns an&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// IPv6 address unmodified.&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AddrTo6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Is4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addrProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unsafe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Pointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netipZ6noz&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;benchmarks&quot;&gt;Benchmarks&lt;/h2&gt;
&lt;p&gt;On my computer, with Go 1.27.1, the standard library solution costs 0.88 ns per
operation, while the solution favored by Go maintainers costs 7.14 ns. The
unsafe solution matches the performance of the first one.&lt;/p&gt;
&lt;div class=&quot;language-text-only codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;goos: linux
goarch: amd64
pkg: github.com/vincentbernat/go-netip-addrto6
cpu: AMD Ryzen 5 5600X 6-Core Processor
                   │     sec/op     │
AddrTo6/safe            7.137n ± 0%
AddrTo6/unsafe         0.8682n ± 2%
AddrTo6/builtin        0.8775n ± 2%
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;assembly-code&quot;&gt;Assembly code&lt;/h2&gt;
&lt;p&gt;Let’s check the assembly code the compiler generates for each solution.&lt;sup id=&quot;fnref:dis&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:dis&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;
The one built into the standard library looks like this:&lt;sup id=&quot;fnref:inline&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:inline&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-go-assembly codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AX = input.addr.hi, BX = input.addr.lo, CX = input.z&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CMPQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; check &quot;z&quot; if this is an IPv4 address&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JNE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; if not, stop here&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; CX = netip.z6noz&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RET&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// return value = Addr{hi: AX, lo: BX, z: CX}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Go’s &lt;a href=&quot;https://go.dev/doc/asm&quot; title=&quot;A Quick Guide to Go&#39;s Assembler&quot;&gt;assembly language&lt;/a&gt; is not a direct representation of the underlying
machine language: it operates on a semi-abstract instruction set derived from
&lt;a href=&quot;https://9p.io/sys/doc/asm.html&quot; title=&quot; A Manual for the Plan 9 assembler&quot;&gt;Plan 9’s assembler&lt;/a&gt;. It has four pseudo-registers: FP (frame pointer
for function arguments), PC (program counter), SB (static base pointer for
global symbols), and SP (stack pointer). It also has architecture-specific
registers like &lt;code&gt;AX&lt;/code&gt;, &lt;code&gt;CX&lt;/code&gt;, &lt;code&gt;DX&lt;/code&gt;, &lt;code&gt;BX&lt;/code&gt;, &lt;code&gt;SI&lt;/code&gt;, &lt;code&gt;DI&lt;/code&gt;, and &lt;code&gt;R8&lt;/code&gt; to &lt;code&gt;R15&lt;/code&gt;.
Instructions storing data use their last argument as the destination.
Instructions can carry an explicit size suffix: &lt;code&gt;MOVB&lt;/code&gt; moves a byte, &lt;code&gt;MOVW&lt;/code&gt; 16
bits, &lt;code&gt;MOVL&lt;/code&gt; 32 bits, and &lt;code&gt;MOVQ&lt;/code&gt; 64 bits. In the example above, the first
instruction compares the 64-bit value &lt;code&gt;z4&lt;/code&gt; with the &lt;code&gt;CX&lt;/code&gt; register.&lt;/p&gt;
&lt;p&gt;The unsafe solution looks almost the same:&lt;/p&gt;
&lt;div class=&quot;language-go-assembly codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AX = input.addr.hi, BX = input.addr.lo, CX = input.z&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CMPQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; check &quot;z&quot; if this is an IPv4 address&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JNE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; if not, stop here&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;netipZ6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; CX = netip.z6noz&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RET&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// return value = Addr{hi: AX, lo: BX, z: CX}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The helper solution has far more instructions. To understand why, let’s look at
the code for &lt;a href=&quot;https://pkg.go.dev/netip.addr.As16&quot; title=&quot;netip.addr.As16 on Go Packages&quot;&gt;&lt;code&gt;As16()&lt;/code&gt;&lt;/a&gt; and
&lt;a href=&quot;https://pkg.go.dev/netip.AddrFrom16&quot; title=&quot;netip.AddrFrom16 on Go Packages&quot;&gt;&lt;code&gt;AddrFrom16()&lt;/code&gt;&lt;/a&gt;. They are short enough for the compiler
to inline them.&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;As16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEPutUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEPutUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AddrFrom16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;uint128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]),&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can already guess the pattern to optimize: the code packs the IP address into
an array, copies it, then unpacks it. If we inline the Go code by hand, we get:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AddrTo6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Is4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEPutUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEPutUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a16&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byteorder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:])&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z6noz&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As humans, we can mentally derive the optimized form:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AddrTo6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Is4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hi&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;netip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z6noz&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;output&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p id=&quot;asm-addrto6safe&quot;&gt;Unfortunately, as of Go 1.26.8, the compiler is not smart enough to do the same:&lt;/p&gt;
&lt;div class=&quot;language-go-assembly codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AX = input.addr.hi, BX = input.addr.lo, CX = input.z&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; Push the stack (32 bytes):&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;    0(SP) addr netip.uint128&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;   16(SP) a16 [16]byte&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;PUSHQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BP&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BP&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SUBQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CMPQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; check &quot;z&quot; if this is an IPv4 address&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JNE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; if not, stop here&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; Pack: byteorder.BEPutUint64(a16[:8], input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;       byteorder.BEPutUint64(a16[8:], input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBEQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;AX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBEQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; addr = a16, 16 bytes at once through the vector register X0&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVUPS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;X0&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVUPS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;X0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; CX = netip.z6noz&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; Unpack: output.addr.hi = byteorder.BEUint64(addr[:8])&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;         output.addr.lo = byteorder.BEUint64(addr[8:])&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBEQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;AX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBEQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·addr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ADDQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;POPQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BP&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RET&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// return value = Addr{hi: AX, lo: BX, z: CX}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The compiler does a decent job on the byte shuffling: the eight byte stores of
&lt;code&gt;BEPutUint64()&lt;/code&gt; become a single &lt;code&gt;MOVBEQ&lt;/code&gt;, which stores a register byte-swapped.
The eight byte loads of &lt;code&gt;BEUint64()&lt;/code&gt; become a single &lt;code&gt;MOVBEQ&lt;/code&gt; the other way
round.&lt;sup id=&quot;fnref:amd64v3&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:amd64v3&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; Three groups of instructions remain: a pack, a copy, and an
unpack.&lt;/p&gt;
&lt;h1 id=&quot;hacking-the-go-compiler&quot;&gt;Hacking the Go compiler&lt;/h1&gt;
&lt;p&gt;The Go compiler has &lt;a href=&quot;https://github.com/golang/go/blob/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/README.md&quot; title=&quot;Introduction to the Go compiler&quot;&gt;several phases&lt;/a&gt;:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;Parsing&lt;/dt&gt;
&lt;dd&gt;The compiler &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/syntax&quot; title=&quot;cmd/compile/internal/syntax&quot;&gt;tokenizes and parses the source code&lt;/a&gt;. It builds a syntax tree
  for each source file.&lt;/dd&gt;
&lt;dt&gt;Type checking&lt;/dt&gt;
&lt;dd&gt;The compiler &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/types2&quot; title=&quot;cmd/compile/internal/types2&quot;&gt;maps each identifier to the object it denotes&lt;/a&gt;, folds
  constants, and infers the type of every expression.&lt;/dd&gt;
&lt;dt&gt;&lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt; construction&lt;/dt&gt;
&lt;dd&gt;The compiler converts the syntax tree and its types into its own &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ir&quot; title=&quot;cmd/compile/internal/ir&quot;&gt;intermediate
  representation&lt;/a&gt; (&lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt;). This process, called “&lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/noder&quot; title=&quot;cmd/compile/internal/noder&quot;&gt;noding&lt;/a&gt;,” goes through
  a serialization format named unified &lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt;.&lt;/dd&gt;
&lt;dt&gt;Middle end&lt;/dt&gt;
&lt;dd&gt;The compiler performs several optimization passes on the &lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt;,
  such as &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/devirtualize&quot; title=&quot;cmd/compile/internal/devirtualize&quot;&gt;devirtualization&lt;/a&gt;, &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/inline&quot; title=&quot;cmd/compile/internal/inline&quot;&gt;function call inlining&lt;/a&gt;,
  and &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/escape&quot; title=&quot;cmd/compile/internal/escape&quot;&gt;escape analysis&lt;/a&gt;.&lt;/dd&gt;
&lt;dt&gt;Walk&lt;/dt&gt;
&lt;dd&gt;This phase runs &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/walk&quot; title=&quot;cmd/compile/internal/walk&quot;&gt;two steps&lt;/a&gt;: order of evaluation decomposes complex
  statements into simpler ones, and desugaring transforms higher-level Go
  constructs, like &lt;code&gt;switch&lt;/code&gt; or channels, into more primitive instructions or
  calls to the runtime.&lt;/dd&gt;
&lt;dt&gt;Generic &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt;&lt;/dt&gt;
&lt;dd&gt;The compiler &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ssagen&quot; title=&quot;cmd/compile/internal/ssagen&quot;&gt;converts the &lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt;&lt;/a&gt; into Static Single Assignment (&lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt;)
  form, a lower-level intermediate representation suited for
  &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ssa&quot; title=&quot;cmd/compile/internal/ssa&quot;&gt;machine-independent optimizations and rewrite rules&lt;/a&gt;.&lt;/dd&gt;
&lt;dt&gt;Machine code generation&lt;/dt&gt;
&lt;dd&gt;The compiler rewrites the &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; form into &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ssa/_gen&quot; title=&quot;cmd/compile/internal/ssa/_gen&quot;&gt;machine-specific variants&lt;/a&gt;,
  allocates registers, and applies more optimization passes. At the end, &lt;a href=&quot;https://github.com/golang/go/tree/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/internal/obj&quot; title=&quot;cmd/internal/obj&quot;&gt;the
  assembler&lt;/a&gt; turns the generated instructions into machine code.&lt;/dd&gt;
&lt;/dl&gt;
&lt;h2 id=&quot;the-hammer&quot;&gt;The hammer&lt;/h2&gt;
&lt;p&gt;My first idea is to replace occurrences of &lt;code&gt;netip.AddrFrom16(ip.As16())&lt;/code&gt; with
&lt;code&gt;netip.Addr{addr: ip.addr, z: netip.z6noz}&lt;/code&gt; as early as possible, during the
“noding” process. Before that, the type checking phase prevents
us from accessing unexported struct fields.&lt;/p&gt;
&lt;p&gt;Go 1.27 introduced a convenient debug option to dump the &lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt; of a function at
interesting points during compilation:&lt;/p&gt;
&lt;div class=&quot;language-bash-session codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOTOOLCHAIN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;go1.27.1&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOAMD64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;v3&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;go&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;build&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-a&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-gcflags&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;-d=astdump=AddrTo6Safe&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;.
&lt;span class=&quot;go&quot;&gt;Writing text ast output for AddrTo6Safe to AddrTo6Safe.ast&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Writing html ast output for AddrTo6Safe to AddrTo6Safe.html&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Writing html syntax output for AddrTo6Safe to AddrTo6Safe.syntax.html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the HTML file, the first column shows the &lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt; as it comes out of noding:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ir codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;DCLFUNC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;addrto6.AddrTo6Safe&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ABI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ABIInternal&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FUNC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;func(netip.Addr)&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;k&quot;&gt;DCLFUNC-Dcl&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.ip&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.~r0&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAMOUT&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;k&quot;&gt;DCLFUNC-body&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;IF&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# ipv6_safe.go:11:2&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;IF-Cond&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;bool
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC-Fun&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;METHEXPR&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;addrto6.Is4&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FUNC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;func(netip.Addr)&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;bool
&lt;span class=&quot;w&quot;&gt;. . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;TYPE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PEXTERN&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;type&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC-Args&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.ip&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;IF-Body&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# ipv6_safe.go:12:6&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.ip&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC-Fun&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;. . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;netip.AddrFrom16&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PFUNC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FUNC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;func([&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;]byte)&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC-Args&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;ARRAY&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;[&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;]byte
&lt;span class=&quot;w&quot;&gt;. . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC-Fun&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;. . . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;METHEXPR&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;addrto6.As16&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FUNC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;func(netip.Addr)&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;[&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;]byte
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;. . . . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;TYPE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PEXTERN&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;type&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;CALLFUNC-Args&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.ip&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;RETURN&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# ipv6_safe.go:14:2&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;RETURN-Results&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.ip&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the body of the &lt;code&gt;if&lt;/code&gt; statement, we spot the calls to the method
&lt;code&gt;netip.Addr.As16()&lt;/code&gt; and to the function &lt;code&gt;netip.AddrFrom16()&lt;/code&gt;. Our goal is to
patch them with a struct literal:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ir codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;IF-Body&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;AS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# ipv6_safe.go:12:6&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.ip&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;STRUCTLIT&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;STRUCTLIT-List&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;STRUCTKEY&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.addr
&lt;span class=&quot;w&quot;&gt;. . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;DOT&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.addr&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.uint128
&lt;span class=&quot;w&quot;&gt;. . . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;addrto6.ip&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PPARAM&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;OnStack&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Used&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.Addr
&lt;span class=&quot;w&quot;&gt;. . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;STRUCTKEY&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;netip.z
&lt;span class=&quot;w&quot;&gt;. . . . &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;NAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;netip.z6noz&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;PEXTERN&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;unique.Handle[net/netip.addrDetail]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In &lt;a href=&quot;https://github.com/golang/go/blob/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/noder/reader.go&quot; title=&quot;reader.go&quot;&gt;noder’s &lt;code&gt;reader.go&lt;/code&gt;&lt;/a&gt;, the &lt;code&gt;expr()&lt;/code&gt; method builds the &lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt; tree for
an expression. At the end of the &lt;code&gt;exprCall&lt;/code&gt; case, we add a call to a
&lt;code&gt;rewriteAddrFrom16As16()&lt;/code&gt; function. It takes the current node and returns the
struct literal on success, or &lt;code&gt;nil&lt;/code&gt; if the rewrite is not possible. First, we
check that we have the expected pattern: a call to the &lt;code&gt;netip.AddrFrom16()&lt;/code&gt;
function with a call to the &lt;code&gt;netip.Addr.As16()&lt;/code&gt; method as its only argument:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rewriteAddrFrom16As16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;CallExpr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;OCALLFUNC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isNetipFunc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;AddrFrom16&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;CallExpr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;OCALLFUNC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isNetipFunc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Addr.As16&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;inner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// [...]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, we fetch &lt;code&gt;netip.z6noz&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;z6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lookupVar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;StaticCalleeName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Fun&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Sym&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Pkg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;z6noz&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And we build the struct literal:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nx&quot;&gt;typ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Node&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;typ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Node&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Sym&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;addr&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;typecheck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;DotField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;z&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z6noz&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;NewStructKeyExpr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;lit&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;NewCompLitExpr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;OSTRUCTLIT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;typ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;lit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SetTypecheck&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Have a look at the &lt;a href=&quot;https://github.com/vincentbernat/go/commit/netipmap-fix2&quot; title=&quot;cmd/compile: optimize netip.AddrFrom16(ip.As16()) in the noder&quot;&gt;complete patch&lt;/a&gt;.&lt;sup id=&quot;fnref:statement&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:statement&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; We can test it
with the following commands:&lt;/p&gt;
&lt;div class=&quot;language-bash-session codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;src
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;./make.bash
&lt;span class=&quot;go&quot;&gt;Building Go cmd/dist using /usr/lib/go-1.27. (go1.27.1 linux/amd64)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Building Go toolchain1 and bootstrap cmd/go (go_bootstrap) using /usr/lib/go-1.27.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Building Go toolchain2 using go_bootstrap and Go toolchain1.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Building Go toolchain3 and commands using go_bootstrap and Go toolchain2.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Checking command staleness for linux/amd64.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Installed Go for linux/amd64 in /home/bernat/code/free/go&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Installed commands in /home/bernat/code/free/go/bin&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;*** You need to add /home/bernat/code/free/go/bin to your PATH.&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;export&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PWD&lt;/span&gt;/../bin:&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;go&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;version
&lt;span class=&quot;go&quot;&gt;go version go1.28-devel_9834516e20 Sat Sep 12 08:23:11 2026 -0700 linux/amd64&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;go&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;net/netip/...
&lt;span class=&quot;go&quot;&gt;ok      net/netip   0.224s&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;../../go-netip-addrto6
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;go&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;.
&lt;span class=&quot;go&quot;&gt;ok      github.com/vincentbernat/go-netip-addrto6   0.062s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The generated code for the helper is now the shortest possible version!&lt;/p&gt;
&lt;div class=&quot;language-go-assembly codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AX = input.addr.hi, BX = input.addr.lo, CX = input.z&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CMPQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; check &quot;z&quot; if this is an IPv4 address&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JNE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; if not, stop here&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; CX = netip.z6noz&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RET&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// return value = Addr{hi: AX, lo: BX, z: CX}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Go maintainers are unlikely to accept this change. It relies on the internal
structure of &lt;code&gt;net/netip.Addr&lt;/code&gt;. It’s an ugly hack in the noder, whose job is to
faithfully translate the type-checked AST into the &lt;abbr title=&quot;Intermediate Representation&quot;&gt;IR&lt;/abbr&gt;. And it’s harder to
maintain than adding a &lt;code&gt;To6()&lt;/code&gt; method.&lt;/p&gt;
&lt;h2 id=&quot;the-screwdriver&quot;&gt;The screwdriver&lt;/h2&gt;
&lt;p&gt;The right place for such an optimization is the &lt;a href=&quot;https://github.com/golang/go/blob/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ssa/README.md&quot; title=&quot;Introduction to the Go compiler&#39;s SSA backend&quot;&gt;generic &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; phase&lt;/a&gt;. One of
the last machine-independent passes is &lt;code&gt;memcombine&lt;/code&gt;. With the appropriate debug
flag, the compiler dumps the &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; form after this pass:&lt;sup id=&quot;fnref:html&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:html&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-bash-session codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOTOOLCHAIN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;go1.26.8&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOAMD64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;v3&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt; &lt;/span&gt;go&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;build&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-a&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-gcflags&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;-d=ssa/memcombine/dump=AddrTo6Safe&#39;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;.
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;head&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-5&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;AddrTo6Safe_01__memcombine.dump
&lt;span class=&quot;go&quot;&gt;AddrTo6Safe func(netip.Addr) netip.Addr&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  b2:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    (?) v1 = InitMem &amp;lt;mem&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    (?) v2 = SP &amp;lt;uintptr&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    (?) v3 = SB &amp;lt;uintptr&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The result of the &lt;code&gt;memcombine&lt;/code&gt; pass follows the same structure as the assembly
code for &lt;code&gt;AddrTo6Safe()&lt;/code&gt; &lt;a href=&quot;https://vincent.bernat.ch#asm-addrto6safe&quot;&gt;we looked at earlier&lt;/a&gt;: two stores,
one move, and two loads we would like to optimize away.&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;; […]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+0}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+8}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v466&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*netip.addrDetail&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[2]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.z&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; […]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v23&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[:8] = bswap(hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v415&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr[:8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v299&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v415&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr[8:]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v39&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.lo&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; […]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Each line features a value identifier (&lt;code&gt;v442&lt;/code&gt;), an operation with its type
(&lt;code&gt;Bswap64 &amp;lt;uint64&amp;gt;&lt;/code&gt;), and its arguments (&lt;code&gt;v490&lt;/code&gt;).&lt;sup id=&quot;fnref:lines&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:lines&quot;&gt;9&lt;/a&gt;&lt;/sup&gt; Values are the basic
building blocks of &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; and are defined exactly once. Square brackets enclose
integer parameters (&lt;code&gt;[8]&lt;/code&gt;) and curly braces contain auxiliary arguments
(&lt;code&gt;{netip.addr}&lt;/code&gt;). Operations writing to memory produce a new memory state. Every
memory operation takes the current state as its last argument, which keeps them
in order.&lt;/p&gt;
&lt;h3 id=&quot;on-paper&quot;&gt;On paper&lt;/h3&gt;
&lt;p&gt;Let’s focus on &lt;code&gt;output.addr.lo&lt;/code&gt;, aka &lt;code&gt;v39&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+8}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v415&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v415&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr[8:]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v39&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.lo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To simplify this code, we could apply three rewriting rules:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The first one adds a shortcut when &lt;strong&gt;loading through a move&lt;/strong&gt;: &lt;code&gt;(Load (OffPtr
   [o] p) (Move p src mem)) =&amp;gt; (Load (OffPtr [o] src) mem)&lt;/code&gt;. This matches &lt;code&gt;v174&lt;/code&gt;
   with its arguments &lt;code&gt;v415&lt;/code&gt; and &lt;code&gt;v286&lt;/code&gt; and creates a new value &lt;code&gt;v600&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+8}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v415&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr[8]&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v600&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v600&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v39&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.lo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The second one simplifies a &lt;strong&gt;load following a store&lt;/strong&gt;: &lt;code&gt;(Load p (Store p x
   _)) =&amp;gt; x&lt;/code&gt;. The load is &lt;em&gt;forwarded&lt;/em&gt;: the stored value replaces it and no memory
   access remains. It matches &lt;code&gt;v174&lt;/code&gt;. It notices that &lt;code&gt;v600&lt;/code&gt; and &lt;code&gt;v173&lt;/code&gt; are the
   same address and replaces &lt;code&gt;v174&lt;/code&gt; with a copy of &lt;code&gt;v442&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+8}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v415&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v600&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.lo)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v39&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.lo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The last step &lt;strong&gt;cancels the two byte swaps&lt;/strong&gt;: &lt;code&gt;(Bswap64 (Bswap64 x)) =&amp;gt; x&lt;/code&gt;.
   &lt;code&gt;v39&lt;/code&gt; becomes a copy of &lt;code&gt;v490&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+8}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v415&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v600&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v174&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v39&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.lo = input.addr.lo&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If we ignore the values not needed to compute &lt;code&gt;v39&lt;/code&gt;, only this &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; form remains:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+8}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v39&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;             &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.lo = input.addr.lo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s switch to &lt;code&gt;output.addr.hi&lt;/code&gt;, aka &lt;code&gt;v299&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+0}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v23&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[:8] = bswap(hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr[:8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v299&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.hi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To optimize it away, we also apply three rewriting rules:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The first one also adds a shortcut when &lt;strong&gt;loading through a move&lt;/strong&gt;, but
   without an offset: &lt;code&gt;(Load p (Move p src mem)) =&amp;gt; (Load src mem)&lt;/code&gt;. This rewrites &lt;code&gt;v416&lt;/code&gt;
   to use arguments from &lt;code&gt;v286&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+0}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v23&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[:8] = bswap(hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[:8]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v299&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.hi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The second rule &lt;strong&gt;forwards a value stored one step earlier&lt;/strong&gt;, skipping over a
   store to another address: &lt;code&gt;(Load p (Store q _ (Store p x _))) =&amp;gt; x&lt;/code&gt;. This
   matches &lt;code&gt;v416&lt;/code&gt;: &lt;code&gt;x&lt;/code&gt; is &lt;code&gt;v542&lt;/code&gt;, &lt;code&gt;p&lt;/code&gt; is &lt;code&gt;v22&lt;/code&gt; (&lt;code&gt;&amp;amp;a16&lt;/code&gt;), &lt;code&gt;q&lt;/code&gt; is &lt;code&gt;v173&lt;/code&gt;
   (&lt;code&gt;&amp;amp;a16[8]&lt;/code&gt;), and &lt;code&gt;p&lt;/code&gt; and &lt;code&gt;q&lt;/code&gt; do not overlap for &lt;code&gt;uint64&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+0}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v23&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[:8] = bswap(hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.hi)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v299&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.hi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The third rule &lt;strong&gt;cancels two byte swaps&lt;/strong&gt;: &lt;code&gt;(Bswap64 (Bswap64 x)) =&amp;gt; x&lt;/code&gt;.
   &lt;code&gt;v299&lt;/code&gt; becomes a copy of &lt;code&gt;v502&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+0}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.a16}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[8]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v23&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[:8] = bswap(hi)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{uint64}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v173&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v442&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v161&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8:] = bswap(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v416&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v542&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; bswap(input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v299&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.hi = input.addr.hi&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If we remove the values not used to compute &lt;code&gt;v299&lt;/code&gt;, we get this &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; form:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ArgIntReg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{ip+0}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; input.addr.hi&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v299&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v502&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.hi = input.addr.hi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;in-practice&quot;&gt;In practice&lt;/h3&gt;
&lt;p&gt;Most of these rules already exist in &lt;a href=&quot;https://github.com/golang/go/blob/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ssa/_gen/generic.rules&quot; title=&quot;generic.rules&quot;&gt;&lt;code&gt;generic.rules&lt;/code&gt;&lt;/a&gt;. They use
conditions to validate their context: &lt;code&gt;ssa.IsSamePtr()&lt;/code&gt; for the same address,
&lt;code&gt;ssa.Disjoint()&lt;/code&gt; for addresses that do not overlap. The rule forwarding a stored
value to a load already exists with three variants looking through several other
stores. Here are the two we need:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa-rules codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;t1&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p1&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{t2}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;x&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;_&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ssa.IsSamePtr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;p1,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;copyCompatibleType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;t1,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;x.Type&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;t1.Size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;t2.Size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;x
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;t1&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p1&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{t2}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;_&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{t3}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p3&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;x&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;_&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ssa.IsSamePtr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;p1,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p3&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;copyCompatibleType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;t1,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;x.Type&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;t1.Size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;t3.Size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ssa.Disjoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;p3,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;t3,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;t2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;x
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Go 1.27 added the rule loading through a move with &lt;a href=&quot;https://go-review.googlesource.com/c/go/+/748200&quot; title=&quot;cmd/compile: forward small Load through Move to avoid redundant copies&quot;&gt;CL 748200&lt;/a&gt; to fix
&lt;a href=&quot;https://github.com/golang/go/issues/77720&quot; title=&quot;cmd/compile: field access on struct-returning method copies entire struct&quot;&gt;issue #77720&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa-rules codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;t1&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;op1:&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[o1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p1&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;move:&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[n]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;src&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;mem&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;o1&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;o1&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;t1.Size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;n&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ssa.IsSamePtr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;p1,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ssa.IsVolatile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;src&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@move.Block&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;t1&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;op1.Type&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[o1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;src&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;mem&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It lacks a variant without an offset:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa-rules codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;t1&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p1&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;move:&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[n]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;src&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;mem&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p1.Op&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;ssaop.OpOffPtr
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;t1.Size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;n&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ssa.IsSamePtr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;p1,&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p2&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ssa.IsVolatile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;src&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;@move.Block&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;t1&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;p1.Type&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[0]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;src&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;mem&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There is no generic rule to cancel two byte swaps, but the &lt;a href=&quot;https://github.com/golang/go/blob/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ssa/_gen/AMD64.rules&quot; title=&quot;AMD64.rules&quot;&gt;AMD64 lowering
pass&lt;/a&gt; includes this rule:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa-rules codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;BSWAP(Q|L)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;BSWAP(Q|L)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;p
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After switching to Go’s development branch and &lt;a href=&quot;https://github.com/vincentbernat/go/commit/netipmap-fix3&quot; title=&quot;cmd/compile/internal/ssa: forward small offset-less Load through Move&quot;&gt;adding the missing
rule&lt;/a&gt;, the generated assembly code is worse than with Go 1.26.8,
even though our additional rule slightly improves the situation at the end:&lt;/p&gt;
&lt;div class=&quot;language-go-assembly codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AX = input.addr.hi, BX = input.addr.lo, CX = input.z&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; Push the stack (16 bytes):&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;    0(SP) a16 [16]byte&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;PUSHQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BP&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BP&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SUBQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;

&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CMPQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; check &quot;z&quot; if this is an IPv4 address&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JNE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; if not, stop here&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; The four forwarded bytes: the low half of input.addr.lo is taken apart and&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; put back together in registers&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; DX = input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHRQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; BX = input.addr.lo &amp;gt;&amp;gt; 24&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SI&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; SI = input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHRQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; DX = input.addr.lo &amp;gt;&amp;gt; 16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DI&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; DI = input.addr.lo, kept for the pack&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHRQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SI&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; SI = input.addr.lo &amp;gt;&amp;gt; 8&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;DIB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;R8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; R8 = byte(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;SIB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SI&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; SI = byte(input.addr.lo &amp;gt;&amp;gt; 8)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHLQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SI&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;R8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SI&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; SI = two low bytes of input.addr.lo&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; DX = byte(input.addr.lo &amp;gt;&amp;gt; 16)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHLQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; BX = byte(input.addr.lo &amp;gt;&amp;gt; 24)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHLQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; BX = input.addr.lo &amp;amp; 0xffffffff&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; Pack: byteorder.BEPutUint64(a16[:8], input.addr.hi)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;;       byteorder.BEPutUint64(a16[8:], input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBEQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;AX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBEQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; The four other bytes of input.addr.lo, read one by one from a16&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[11]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHLQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[10]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHLQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[9]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHLQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;48&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBLZX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SHLQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;56&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; output.z = netip.z6noz&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; output.addr.hi = byteorder.BEUint64(a16[:8])&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVBEQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·a16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;AX&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.lo assembled from the previous steps&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ORQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;DX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BX&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;LEAVEQ&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RET&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// return value = Addr{hi: AX, lo: BX, z: CX}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The rule loading through a move, added in Go 1.27, introduced this regression.&lt;/p&gt;
&lt;h3 id=&quot;out-of-order&quot;&gt;Out of order&lt;/h3&gt;
&lt;p&gt;Let’s not give up now! In reality, the rewriting rules run before &lt;code&gt;memcombine&lt;/code&gt;,
notably in the &lt;code&gt;late opt&lt;/code&gt; pass. At this point, the inlined versions of
&lt;code&gt;BEPutUint64()&lt;/code&gt; and &lt;code&gt;BEUint64()&lt;/code&gt; still expand to sixteen byte stores and sixteen
byte loads, matching their &lt;a href=&quot;https://pkg.go.dev/internal/byteorder#BEUint64&quot; title=&quot;internal/byteorder.BEUint64 on Go Packages&quot;&gt;source code&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;BEUint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// bounds check hint to compiler; see golang.org/issue/14808&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;48&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;56&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let’s follow two bytes of &lt;code&gt;output.addr.lo&lt;/code&gt;: &lt;code&gt;addr[15]&lt;/code&gt; and &lt;code&gt;addr[11]&lt;/code&gt;. Here is
a simplified &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; form before &lt;code&gt;late opt&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v273&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Trunc64to8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v490&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; byte(input.addr.lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v226&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Trunc64to8&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v225&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; byte(input.addr.lo &amp;gt;&amp;gt; 32)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; […]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v235&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v233&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v226&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v223&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[11] = byte(lo &amp;gt;&amp;gt; 32)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v247&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v245&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v238&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v235&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[12] = …&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v259&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v257&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v250&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v247&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[13] = …&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v271&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v269&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v262&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v259&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[14] = …&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Store&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v280&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v273&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v271&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[15] = byte(lo)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;LocalAddr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*[16]byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{netip.addr}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Move&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;mem&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;{[16]byte}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[16]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr = a16&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; […]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v433&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[15]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr[15]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v435&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v433&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr[15]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v479&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[11]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;addr[11]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v481&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v479&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr[11]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The first rule loads through the move: &lt;code&gt;(Load (OffPtr [o] p) (Move p src mem))
=&amp;gt; (Load (OffPtr [o] src) mem)&lt;/code&gt;. It matches both loads, which now read &lt;code&gt;a16&lt;/code&gt;
with the memory state before the copy:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v600&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[15]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[15]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v435&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v600&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[15]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v601&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[11]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[11]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v481&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v601&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[11]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The second rule shortcuts a load following a store: &lt;code&gt;(Load p (Store p x _)) =&amp;gt;
x&lt;/code&gt;. It matches &lt;code&gt;v435&lt;/code&gt;, as &lt;code&gt;v282&lt;/code&gt; stores &lt;code&gt;a16[15]&lt;/code&gt;. It does not match &lt;code&gt;v481&lt;/code&gt;:
&lt;code&gt;v235&lt;/code&gt; stores &lt;code&gt;a16[11]&lt;/code&gt; four stores earlier in the chain, while the variants of
this rule look through three stores at most.&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v435&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Copy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v273&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; byte(input.addr.lo)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v601&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OffPtr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;*byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[11]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; &amp;amp;a16[11]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v481&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v601&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[11]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The same happens to the other bytes: the rule forwards the four bytes stored
last, &lt;code&gt;a16[12]&lt;/code&gt; to &lt;code&gt;a16[15]&lt;/code&gt;. The twelve other loads now read &lt;code&gt;a16&lt;/code&gt; instead of
&lt;code&gt;addr&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;BEUint64()&lt;/code&gt; becomes a chain of &lt;code&gt;Or64&lt;/code&gt;, each one adding a byte shifted into
place. &lt;code&gt;memcombine&lt;/code&gt; is a &lt;a href=&quot;https://github.com/golang/go/blob/1e963f82914ddfb47820034c5c85205a362ed73f/src/cmd/compile/internal/ssacompile/memcombine.go&quot; title=&quot;memcombine.go&quot;&gt;pass written in Go&lt;/a&gt;, not a set of rewrite
rules. It starts from the last &lt;code&gt;Or64&lt;/code&gt; of the chain and collects up to eight
terms. If each term is a byte load, extended to 64 bits and shifted, and if the
eight loads read consecutive addresses from the same pointer with the same
memory state, it replaces the whole chain with a single 64-bit load and a byte
swap. Otherwise, it tries again with four, then two terms, and from each
intermediate &lt;code&gt;Or64&lt;/code&gt;. Here is the loop checking each term in a simplified version
of &lt;code&gt;combineLoads()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Op&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shiftOp&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;peelShift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Op&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extOp&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Op&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ssaop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;OpLoad&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mem&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;splitPtr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;LoadRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For &lt;code&gt;output.addr.hi&lt;/code&gt;, the eight loads read &lt;code&gt;a16&lt;/code&gt; with the same memory state
&lt;code&gt;v282&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v13&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;               &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[0]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v530&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v14&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;               &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[1]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v488&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v504&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[2]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v405&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v537&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[3]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v385&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v397&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[4]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v361&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v373&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[5]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v196&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v63&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;               &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[6]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v432&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;byte&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v315&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[7]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v319&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ZeroExt8to64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v432&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; uint64(a16[7])&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v329&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ZeroExt8to64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v196&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;         &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; uint64(a16[6])&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v330&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Lsh64x64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[true]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v329&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v138&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; uint64(a16[6]) &amp;lt;&amp;lt; 8&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v331&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v319&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v330&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[7] | a16[6] &amp;lt;&amp;lt; 8&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;; […] same for a16[5] to a16[1]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v401&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ZeroExt8to64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v13&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; uint64(a16[0])&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v402&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Lsh64x64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;[true]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v401&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v55&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; uint64(a16[0]) &amp;lt;&amp;lt; 56&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v403&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v402&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v391&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | a16[0] &amp;lt;&amp;lt; 56 = output.addr.hi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;memcombine&lt;/code&gt; merges them into one load and a swap:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v282&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; a16[:8]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v285&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Bswap64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v286&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; output.addr.hi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For &lt;code&gt;output.addr.lo&lt;/code&gt;, here is the chain &lt;code&gt;memcombine&lt;/code&gt; sees after &lt;code&gt;late opt&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-go-compiler-ssa codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v436&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ZeroExt8to64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v273&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; addr[15], forwarded&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v448&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v436&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v447&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | addr[14] &amp;lt;&amp;lt; 8, forwarded&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v460&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v459&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v448&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | addr[13] &amp;lt;&amp;lt; 16, forwarded&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v472&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v471&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v460&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | addr[12] &amp;lt;&amp;lt; 24, forwarded&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v484&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v483&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v472&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | a16[11] &amp;lt;&amp;lt; 32, loaded&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v496&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v495&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v484&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | a16[10] &amp;lt;&amp;lt; 40, loaded&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v508&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v507&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v496&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | a16[9] &amp;lt;&amp;lt; 48, loaded&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v520&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Or64&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;&amp;lt;uint64&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v519&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;v508&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; | a16[8] &amp;lt;&amp;lt; 56, loaded&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;From &lt;code&gt;v520&lt;/code&gt;, four of the eight terms are forwarded bytes, not loads from memory,
and &lt;code&gt;memcombine&lt;/code&gt; can’t combine them. It doesn’t merge the four remaining loads
either, as they sit on top of the forwarded bytes.&lt;/p&gt;
&lt;h3 id=&quot;back-in-order&quot;&gt;Back in order&lt;/h3&gt;
&lt;p&gt;In summary, the rewriting rules run too early to be effective. A quick
workaround exists: run an earlier round of &lt;code&gt;memcombine&lt;/code&gt; before &lt;code&gt;late opt&lt;/code&gt;. After
&lt;a href=&quot;https://github.com/vincentbernat/go/commit/netipmap-fix4&quot; title=&quot;cmd/compile/internal/ssacompile: run memcombine before late opt&quot;&gt;this change&lt;/a&gt;, the generated code for the helper is back to the
shortest possible version:&lt;/p&gt;
&lt;div class=&quot;language-go-assembly codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// AX = input.addr.hi, BX = input.addr.lo, CX = input.z&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CMPQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; check &quot;z&quot; if this is an IPv4 address&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;JNE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;     &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; if not, stop here&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;MOVQ&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;net/netip·z6noz&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;SB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;; CX = netip.z6noz&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RET&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// return value = Addr{hi: AX, lo: BX, z: CX}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And the benchmark confirms it! ✌️&lt;/p&gt;
&lt;div class=&quot;language-text-only codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;goos: linux
goarch: amd64
pkg: github.com/vincentbernat/go-netip-addrto6
cpu: AMD Ryzen 5 5600X 6-Core Processor
                   │   Go 1.26.8    │             Our branch              │
                   │     sec/op     │    sec/op     vs base               │
AddrTo6/safe          6.5470n ±  0%   0.8944n ± 4%  -86.34% (p=0.002 n=6)
AddrTo6/unsafe        0.9071n ±  3%   0.8682n ± 1%   -4.28% (p=0.002 n=6)
AddrTo6/builtin       0.8871n ±  2%   0.8785n ± 1%        ~ (p=0.310 n=6)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id=&quot;next-steps&quot;&gt;Next steps&lt;/h1&gt;
&lt;p&gt;I think Go maintainers would reject this change because of the additional
&lt;code&gt;memcombine&lt;/code&gt; pass. Instead, I plan to publish this blog post and bring up the
subject again as a follow-up to &lt;a href=&quot;https://github.com/golang/go/issues/54365&quot; title=&quot;proposal: net/netip: add netip.Addr.Map · Issue #54365 · golang/go&quot;&gt;issue #54365&lt;/a&gt;. Either the sheer complexity and
the Go 1.27 regression convince the maintainers that adding a &lt;code&gt;To6()&lt;/code&gt; method is
simpler and more efficient, or they advise me on how to move forward. Either
way, digging into this subject taught me a lot about the Go compiler! ⚙️&lt;/p&gt;
&lt;div class=&quot;footnote&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn:why&quot;&gt;
&lt;p&gt;IPv4-mapped IPv6 addresses let you handle only IPv6 addresses in your code
and keep conversions at a few well-defined boundaries. I use them in
&lt;a href=&quot;https://github.com/akvorado/akvorado&quot; title=&quot;Akvorado: flow collector, enricher and visualizer&quot;&gt;Akvorado&lt;/a&gt;. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:why&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:equiv&quot;&gt;
&lt;p&gt;This is not strictly equivalent. The zero value becomes &lt;code&gt;::&lt;/code&gt; while it would
make more sense to leave it untouched. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:equiv&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:tests&quot;&gt;
&lt;p&gt;To avoid catastrophic bugs when &lt;code&gt;netip.Addr&lt;/code&gt;’s layout changes, you must &lt;a href=&quot;https://github.com/vincentbernat/go-netip-addrto6/blob/main/ipv6_unsafe_test.go&quot; title=&quot;Tests for unsafe AddrTo6() function&quot;&gt;add
tests&lt;/a&gt; to detect it. This is more dangerous if you put this code in a
package. Either ask users to run the tests themselves, or detect the change
at run time and panic. Hiding this optimization behind a build tag would
make users aware of this potential trap. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:tests&quot; title=&quot;Jump back to footnote 3 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:dis&quot;&gt;
&lt;p&gt;I produced the assembly code with &lt;code&gt;GOTOOLCHAIN=go1.26.8 GOAMD64=v3 ./go-asm
&#39;\.asm&#39;&lt;/code&gt; from the &lt;a href=&quot;https://github.com/vincentbernat/go-netip-addrto6&quot;&gt;companion repository&lt;/a&gt;, then edited it a bit to keep this
article from turning into an endless rabbit hole. Due to an unfortunate
sequence of events, we switch between versions: Go 1.27 introduced a
regression that blurs the point of this article. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:dis&quot; title=&quot;Jump back to footnote 4 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:inline&quot;&gt;
&lt;p&gt;The function is short enough for the compiler to inline it, so the assembly
code may vary depending on the surrounding code. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:inline&quot; title=&quot;Jump back to footnote 5 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:amd64v3&quot;&gt;
&lt;p&gt;&lt;code&gt;MOVBEQ&lt;/code&gt; requires &lt;code&gt;GOAMD64=v3&lt;/code&gt;, matching the &lt;a href=&quot;https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels&quot; title=&quot;X86-64 on Wikipedia&quot;&gt;x86-64-v3
microarchitecture&lt;/a&gt; from 2013. Otherwise, the compiler translates
&lt;code&gt;BEPutUint64()&lt;/code&gt; to &lt;code&gt;BSWAPQ&lt;/code&gt;+&lt;code&gt;MOVQ&lt;/code&gt; and &lt;code&gt;BEUint64()&lt;/code&gt; to &lt;code&gt;MOVQ&lt;/code&gt;+&lt;code&gt;BSWAPQ&lt;/code&gt;. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:amd64v3&quot; title=&quot;Jump back to footnote 6 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:statement&quot;&gt;
&lt;p&gt;When the call is used as a statement, a struct literal alone is invalid. The
patch then turns it into &lt;code&gt;_ = netip.Addr{…}&lt;/code&gt;. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:statement&quot; title=&quot;Jump back to footnote 7 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:html&quot;&gt;
&lt;p&gt;The compiler can also write an HTML file with the result of each pass:&lt;/p&gt;
&lt;div class=&quot;language-bash-session codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOSSAFUNC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;AddrTo6Safe&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOTOOLCHAIN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;go1.26.8&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;GOAMD64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;v3&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;go&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;build&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-a&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;.
&lt;span class=&quot;go&quot;&gt;dumped SSA for AddrTo6Safe,1 to ./ssa.html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:html&quot; title=&quot;Jump back to footnote 8 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:lines&quot;&gt;
&lt;p&gt;Source line numbers in parentheses follow value identifiers, but I removed
them from the examples. The &lt;abbr title=&quot;Static Single Assignment&quot;&gt;SSA&lt;/abbr&gt; form also features branches, but we don’t
need them to understand our optimizations. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:lines&quot; title=&quot;Jump back to footnote 9 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Sun, 04 Oct 2026 13:27:25 +0000</pubDate>

</item> 
<item>
	<title>Vincent Bernat: Self-hosted HTTP tunnels with SSH and nginx</title>
	<guid>http://www.luffy.cx/en/blog/2026-http-over-ssh.html</guid>
	<link>https://vincent.bernat.ch/en/blog/2026-http-over-ssh</link>
     <description>  &lt;p&gt;A friend wants to proofread your work-in-progress blog post, but its preview
only runs on &lt;code&gt;localhost:8080&lt;/code&gt;. &lt;a href=&quot;https://github.com/anderspitman/awesome-tunneling&quot; title=&quot;awesome-tunneling: a list of tunneling software and services&quot;&gt;Several tools&lt;/a&gt; can help. Some run as a
commercial service, like &lt;a href=&quot;https://ngrok.com/&quot; title=&quot;ngrok&quot;&gt;ngrok&lt;/a&gt; or &lt;a href=&quot;https://developers.cloudflare.com/tunnel/get-started/quick-tunnels/&quot; title=&quot;Quick Tunnels with TryCloudflare&quot;&gt;Cloudflare Quick Tunnels&lt;/a&gt;. Some are
self-hostable but require a specific client, like &lt;a href=&quot;https://github.com/fatedier/frp&quot; title=&quot;frp: a fast reverse proxy&quot;&gt;frp&lt;/a&gt; or &lt;a href=&quot;https://github.com/localtunnel/localtunnel&quot; title=&quot;localtunnel: expose your localhost to the world&quot;&gt;localtunnel&lt;/a&gt;.
Some only require a plain SSH client but rely on a specific SSH server, like
&lt;a href=&quot;https://docs.ssi.sh/&quot; title=&quot;sish: host public web services on localhost&quot;&gt;sish&lt;/a&gt;. Let’s implement a self-hosted solution with only &lt;em&gt;OpenSSH&lt;/em&gt; and
&lt;em&gt;nginx&lt;/em&gt;!&lt;/p&gt;
&lt;div class=&quot;language-bash-session codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;ssh&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-R&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;:localhost:8080&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;http-over-ssh
&lt;span class=&quot;go&quot;&gt;Allocated port 41535 for remote forward to localhost:8080&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;https://6J3jK1WmB15c6WmjW_X-Wg--1789928654@p41535.ssh.luffy.cx/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id=&quot;basic-setup&quot;&gt;Basic setup&lt;/h1&gt;
&lt;p&gt;First, we forward connections from a port on a remote server to your local
service:&lt;/p&gt;
&lt;div class=&quot;language-bash-session codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;ssh&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-N&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-R&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;:localhost:8080&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;web02.luffy.cx
&lt;span class=&quot;go&quot;&gt;Allocated port 41535 for remote forward to localhost:8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When you specify &lt;code&gt;0&lt;/code&gt; as the remote port, the server allocates a free port.
Then, we configure nginx to proxy requests from &lt;code&gt;https://p41535.ssh.luffy.cx&lt;/code&gt; to
&lt;code&gt;http://127.0.0.1:41535&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-nginx-configuration-file codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;0.0.0.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;443&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ssl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;[::0]:443&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ssl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;^p(?&amp;lt;port&amp;gt;\d\d\d\d\d)\.ssh\.luffy\.cx$;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;proxy_pass&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;http://127.0.0.1:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We also need to add DNS records for &lt;code&gt;*.ssh.luffy.cx&lt;/code&gt; and get a wildcard
certificate through &lt;a href=&quot;https://letsencrypt.org/&quot;&gt;Let’s Encrypt&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;language-zone codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;*.ssh.luffy.cx.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;               &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;CNAME&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;l&quot;&gt;web02.luffy.cx.&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ssh.luffy.cx.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                 &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;CAA&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;l&quot;&gt;issuewild&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;letsencrypt.org&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;_acme-challenge.ssh.luffy.cx&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;CNAME&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;l&quot;&gt;ssh.luffy.cx.acme.luffy.cx.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;acme.luffy.cx&lt;/code&gt; is a zone hosted on Route 53. I use it for &lt;a href=&quot;https://letsencrypt.org/docs/challenge-types/#dns-01-challenge&quot; title=&quot;DNS-01 challenge&quot;&gt;ACME DNS-01
challenges&lt;/a&gt;, both for wildcard certificates and for domains served by
several web servers. In my case, NixOS &lt;a href=&quot;https://wiki.nixos.org/wiki/ACME&quot; title=&quot;ACME on the NixOS Wiki&quot;&gt;gets the certificates
automatically&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&quot;access-control&quot;&gt;Access control&lt;/h1&gt;
&lt;p&gt;The port is the only “secret”&lt;sup id=&quot;fnref:port&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:port&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; keeping the content confidential. Other
forwarding solutions add a random string to the domain name to prevent an
intruder from enumerating the possible values.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href=&quot;https://nginx.org/en/docs/http/ngx_http_secure_link_module.html&quot; title=&quot;Module ngx_http_secure_link_module for nginx&quot;&gt;&lt;code&gt;ngx_http_secure_link_module&lt;/code&gt;&lt;/a&gt;, we can secure
this setup a bit. This module computes a hash&lt;sup id=&quot;fnref:md5&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:md5&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; over a set of values,
including a secret, and compares it with the hash from the request. The hash is
base64-encoded, so we cannot put it in the domain name, which is
case-insensitive. Instead, we put it in the URL as a username, along with its
expiration timestamp:&lt;sup id=&quot;fnref:expiration&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:expiration&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-text-only codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;https://6J3jK1WmB15c6WmjW_X-Wg--1789928654@p41535.ssh.luffy.cx/en/blog
        ╰─────────┬──────────╯  ╰───┬────╯  ╰─┬─╯             ╰──┬───╯
                hash             expires    port               path
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The client sends the username to the server with &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc7617&quot; title=&quot;RFC 7617: The &#39;Basic&#39; HTTP Authentication Scheme&quot;&gt;HTTP basic
authentication&lt;/a&gt;. This works with most HTTP clients, including &lt;code&gt;curl&lt;/code&gt;.
Nginx exposes the username in the &lt;code&gt;$remote_user&lt;/code&gt; variable. The module expects
the hash and the expiration timestamp separated by a comma. We use a &lt;code&gt;map&lt;/code&gt;
directive to extract the two parts from &lt;code&gt;$remote_user&lt;/code&gt; and join them with a
comma.&lt;sup id=&quot;fnref:comma&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:comma&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; We also give the module the string to hash. It contains the
expiration timestamp, the port, and a secret:&lt;/p&gt;
&lt;div class=&quot;language-nginx-configuration-file codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$remote_user&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$httpssh_link&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;&quot;~^([-_A-Za-z0-9]{22})--([0-9]+)$&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1,$2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# […]&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;secure_link&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$httpssh_link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;secure_link_md5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$secure_link_expires&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$port&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ZuPerS3cr3!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The module returns the status of the check in the &lt;code&gt;$secure_link&lt;/code&gt; variable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;empty if the hashes do not match,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&quot;0&quot;&lt;/code&gt; if they match but the link has expired, or&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&quot;1&quot;&lt;/code&gt; otherwise.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the hash is incorrect or missing, we return a 401 error with a
&lt;code&gt;WWW-Authenticate&lt;/code&gt; header to ask for credentials. If the link has expired, we
return a 410 error. We remove the &lt;code&gt;Authorization&lt;/code&gt; header before forwarding the
request and add a few directives to &lt;a href=&quot;https://nginx.org/en/docs/http/websocket.html&quot; title=&quot;nginx documentation: WebSocket proxying&quot;&gt;proxy WebSocket connections&lt;/a&gt;.
Here is the complete configuration:&lt;sup id=&quot;fnref:security&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:security&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-nginx-configuration-file codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$remote_user&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$httpssh_link&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;&quot;~^([-_A-Za-z0-9]{22})--([0-9]+)$&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1,$2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;0.0.0.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;443&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ssl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;[::0]:443&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ssl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;^p(?&amp;lt;port&amp;gt;\d\d\d\d\d)\.ssh\.luffy\.cx$;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;secure_link&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$httpssh_link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;secure_link_md5&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$secure_link_expires&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$port&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ZuPerS3cr3!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$secure_link&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;add_header&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;WWW-Authenticate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&#39;Basic&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;realm=&quot;tunnel&quot;&#39;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;401&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$secure_link&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0&quot;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;410&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;proxy_pass&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;http://127.0.0.1:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Host&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$host&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;X-Forwarded-For&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Authorization&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;proxy_http_version&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Upgrade&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$http_upgrade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Connection&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;upgrade&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;proxy_buffering&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;proxy_read_timeout&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I think you are now asking yourself the obvious question: “How should I generate
the hash?” Easy peasy!&lt;/p&gt;
&lt;div class=&quot;language-bash-session codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;expires&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$((&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;date&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;+%s&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;86400&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;41535&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;ZuPerS3cr3!&#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;%s %s %s&#39;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$expires&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$port&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$secret&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;openssl&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;md5&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-binary&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;openssl&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;base64&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;tr&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;+/&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-_&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;tr&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-d&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;6J3jK1WmB15c6WmjW_X-Wg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Well, I suppose you are now saying: “Vincent, this is not very convenient! I’ll stick
with ngrok if you don’t mind.” Okay, I hear you. Let’s write a helper script.&lt;/p&gt;
&lt;h1 id=&quot;helper-script&quot;&gt;Helper script&lt;/h1&gt;
&lt;p&gt;The main difficulty is finding the ephemeral port that OpenSSH allocates, as it
does not appear in any environment variable.&lt;sup id=&quot;fnref:env&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:env&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; To work around this obstacle,
we look for the ancestor &lt;code&gt;sshd-session&lt;/code&gt; processes:&lt;sup id=&quot;fnref:sshd-session&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:sshd-session&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-bash codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;pids&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$$&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$pid&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-gt&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;ps&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-o&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;comm&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;,pid&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;,ppid&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-p&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$pid&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;##* &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;awk&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;$1 == &quot;sshd-session&quot; { printf &quot;pid=%s,\n&quot;, $2 }&#39;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-z&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$pids&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;not an ssh session&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&amp;gt;&lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, we get the listening ports associated with these &lt;code&gt;sshd-session&lt;/code&gt;
processes:&lt;sup id=&quot;fnref:sudo&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:sudo&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-bash codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;sudo&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-n&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;ss&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;--listening&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;--numeric&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;--tcp&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;--processes&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;--no-header&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;grep&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-F&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$pids&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;awk&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;{ print $4 }&#39;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;awk&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-F:&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;{ print $NF }&#39;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;sort&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-un&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-z&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ports&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;then&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;no forwarded port, use ssh -R 0:localhost:PORT&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&amp;gt;&lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, we display the URLs and keep the session open:&lt;/p&gt;
&lt;div class=&quot;language-bash codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;lifetime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;86400&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;ZuPerS3cr3!&#39;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;expires&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$((&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;date&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;+%s&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lifetime&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;port&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ports&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;%s %s %s&#39;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$expires&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$port&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$secret&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;openssl&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;md5&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-binary&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;openssl&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;base64&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;tr&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;+/&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-_&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;tr&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-d&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$token&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$expires&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@p&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$port&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.ssh.luffy.cx/&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
sleep&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;infinity
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I install this script as &lt;code&gt;http-over-ssh&lt;/code&gt; on the server and add this entry to my
&lt;code&gt;~/.ssh/config&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-ssh-config codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;Host&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;http-over-ssh
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Hostname&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;web02.luffy.cx
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;RemoteCommand&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;http-over-ssh
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;ControlPath&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;none
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With this solution, I only rely on OpenSSH and nginx, two pieces of software
already running on this server. One short command gives me a self-hosted tunnel
and a URL to share. To try it, grab the &lt;a href=&quot;https://github.com/vincentbernat/nixops-take1/blob/master/tags/http-over-ssh.sh&quot; title=&quot;nixops-take1/tags/http-over-ssh.sh at master&quot;&gt;complete helper script&lt;/a&gt;, which
includes a few minor improvements. If you run NixOS, as any person of taste
would, have a look at my &lt;a href=&quot;https://github.com/vincentbernat/nixops-take1/blob/master/tags/http-over-ssh.nix&quot; title=&quot;nixops-take1/tags/http-over-ssh.nix at master&quot;&gt;&lt;code&gt;http-over-ssh.nix&lt;/code&gt;&lt;/a&gt; instead. ❄️&lt;/p&gt;
&lt;div class=&quot;admonition&quot;&gt;
&lt;p class=&quot;admonition-title&quot;&gt;Update (2026-10)&lt;/p&gt;
&lt;p&gt;This post was widely discussed on &lt;a href=&quot;https://news.ycombinator.com/item?id=49958569&quot;&gt;Hacker News&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;footnote&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn:port&quot;&gt;
&lt;p&gt;Since the kernel allocates it from the local port range, its entropy is low.
Moreover, on Linux, we lose one more bit because the kernel &lt;a href=&quot;https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ipv4/inet_connection_sock.c?h=v7.2#n349&quot; title=&quot;net/ipv4/inet_connection_sock.c&quot;&gt;favors odd
ports&lt;/a&gt; when it picks a random free port.&lt;/p&gt;
&lt;div class=&quot;language-bash-session codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;sysctl&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-n&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;net.ipv4.ip_local_port_range&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;awk&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;{print $1&quot;—&quot;$2&quot; ≈ &quot;log($2-$1+1)/log(2)&quot; bits&quot;}&#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;32768—60999 ≈ 14.785 bits&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:port&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:md5&quot;&gt;
&lt;p&gt;The module relies on MD5. Its security is weak but good enough for this
use. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:md5&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:expiration&quot;&gt;
&lt;p&gt;We need an expiration date because a later session could reuse the port,
and we have no way to detect this case. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:expiration&quot; title=&quot;Jump back to footnote 3 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:comma&quot;&gt;
&lt;p&gt;The username could use a comma directly instead of a double dash. But some
applications do not recognize the URL correctly, making it harder to share. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:comma&quot; title=&quot;Jump back to footnote 4 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:security&quot;&gt;
&lt;p&gt;This configuration exposes any TCP port listening on &lt;code&gt;127.0.0.1&lt;/code&gt; or
&lt;code&gt;0.0.0.0&lt;/code&gt; to anyone with the secret, bypassing most firewall rules. You
could strengthen it by limiting the &lt;code&gt;server_name&lt;/code&gt; regex to the ephemeral
port range. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:security&quot; title=&quot;Jump back to footnote 5 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:env&quot;&gt;
&lt;p&gt;One SSH session can contain several tunnels, and the client can add or
remove them at any time. This is unlike tun device forwarding (&lt;code&gt;ssh -w&lt;/code&gt;),
which gets its own &lt;code&gt;SSH_TUNNEL&lt;/code&gt; environment variable. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:env&quot; title=&quot;Jump back to footnote 6 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:sshd-session&quot;&gt;
&lt;p&gt;Since OpenSSH 9.8, &lt;code&gt;sshd-session&lt;/code&gt; is the name of the helper handling the
session. With older versions, look for &lt;code&gt;sshd&lt;/code&gt; instead. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:sshd-session&quot; title=&quot;Jump back to footnote 7 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:sudo&quot;&gt;
&lt;p&gt;We need &lt;code&gt;sudo&lt;/code&gt; because the &lt;code&gt;sshd-session&lt;/code&gt; process dropped its privileges.
The kernel then marks it as not dumpable, and its &lt;a href=&quot;https://manpages.debian.org/proc_pid.5.html&quot; title=&quot;Manual page for proc_pid(5)&quot;&gt;&lt;code&gt;/proc/PID/fd&lt;/code&gt; directory
belongs to root&lt;/a&gt;. Without access to this directory, &lt;code&gt;ss&lt;/code&gt; cannot
find which process owns a socket. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:sudo&quot; title=&quot;Jump back to footnote 8 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Sat, 03 Oct 2026 07:23:12 +0000</pubDate>

</item> 
<item>
	<title>Ben Hutchings: FOSS activity in September 2026</title>
	<guid>https://www.decadent.org.uk/ben/blog/2026/10/02/foss-activity-in-september-2026</guid>
	<link>https://www.decadent.org.uk/ben/blog/2026/10/02/foss-activity-in-september-2026.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/benh.png&quot; width=&quot;109&quot; height=&quot;100&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;ul&gt;
  &lt;li&gt;Debian packages:
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/firmware-nonfree&quot;&gt;firmware-nonfree&lt;/a&gt;:
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/src:firmware-nonfree&quot;&gt;Bugs&lt;/a&gt;:
            &lt;ul&gt;
              &lt;li&gt;closed &lt;a href=&quot;https://bugs.debian.org/1148284&quot;&gt;#1148284: firmware-amd-graphics: AMD AV1 hardware decoding produces severe video artifacts with firmware 20260810-1&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;Merge requests:
            &lt;ul&gt;
              &lt;li&gt;opened and merged &lt;a href=&quot;https://salsa.debian.org/kernel-team/firmware-nonfree/-/merge_requests/154&quot;&gt;!154: Update to 20260916; fix some license information&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/firmware-nonfree/news/&quot;&gt;Uploads&lt;/a&gt;:
            &lt;ul&gt;
              &lt;li&gt;uploaded version 20260810-1~bpo13+1 to trixie-backports&lt;/li&gt;
              &lt;li&gt;uploaded version 20260916-1 to unstable&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/initramfs-tools&quot;&gt;initramfs-tools&lt;/a&gt;:
        &lt;ul&gt;
          &lt;li&gt;Merge requests:
            &lt;ul&gt;
              &lt;li&gt;closed &lt;a href=&quot;https://salsa.debian.org/kernel-team/initramfs-tools/-/merge_requests/202&quot;&gt;!202: mkinitramfs: fix path to kernel config in /lib/modules&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/kernel-team&quot;&gt;kernel-team&lt;/a&gt;:
        &lt;ul&gt;
          &lt;li&gt;Merge requests:
            &lt;ul&gt;
              &lt;li&gt;merged &lt;a href=&quot;https://salsa.debian.org/kernel-team/kernel-team/-/merge_requests/14&quot;&gt;!14: find-recent-urgent: Sort bugs from linux first&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;opened &lt;a href=&quot;https://salsa.debian.org/kernel-team/kernel-team/-/merge_requests/15&quot;&gt;!15: Add form responses for common problems with bug reports&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/linux&quot;&gt;linux&lt;/a&gt;:
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/src:linux&quot;&gt;Bugs&lt;/a&gt;:
            &lt;ul&gt;
              &lt;li&gt;closed &lt;a href=&quot;https://bugs.debian.org/1146373&quot;&gt;#1146373: linux-libc-dev: sbrk(2) allocates more than memory + swap space&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;Merge requests:
            &lt;ul&gt;
              &lt;li&gt;closed &lt;a href=&quot;https://salsa.debian.org/kernel-team/linux/-/merge_requests/2010&quot;&gt;!2010: [x86] Backport security fixes for KVM&lt;/a&gt; (LTS)&lt;/li&gt;
              &lt;li&gt;merged &lt;a href=&quot;https://salsa.debian.org/kernel-team/linux/-/merge_requests/2083&quot;&gt;!2083: linux-image: Bump Pre-Depends version on linux-base (&amp;gt;= 4.17~)&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;reviewed and merged &lt;a href=&quot;https://salsa.debian.org/kernel-team/linux/-/merge_requests/2095&quot;&gt;!2095: 6.1 stable updates&lt;/a&gt; (LTS)&lt;/li&gt;
              &lt;li&gt;merged &lt;a href=&quot;https://salsa.debian.org/kernel-team/linux/-/merge_requests/2108&quot;&gt;!2108: [alpha] Reenable CONFIG_COMPACTION&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;merged &lt;a href=&quot;https://salsa.debian.org/kernel-team/linux/-/merge_requests/2109&quot;&gt;!2109: Enable BMI323 support as a module&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;merged &lt;a href=&quot;https://salsa.debian.org/kernel-team/linux/-/merge_requests/2110&quot;&gt;!2110: riscv64 config update for linux 7.3&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/linux/news/&quot;&gt;Uploads&lt;/a&gt;:
            &lt;ul&gt;
              &lt;li&gt;uploaded version 7.1.13-1~bpo13+1 to trixie-backports&lt;/li&gt;
              &lt;li&gt;uploaded version 7.2.6-1~bpo13+1 to trixie-backports&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/linux-6.1&quot;&gt;linux-6.1&lt;/a&gt; (LTS):
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;https://bugs.debian.org/src:linux-6.1&quot;&gt;Bugs&lt;/a&gt;:
            &lt;ul&gt;
              &lt;li&gt;closed &lt;a href=&quot;https://bugs.debian.org/1117674&quot;&gt;#1117674: Please enable udebs for the 6.1 backport&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/linux-6.12&quot;&gt;linux-6.12&lt;/a&gt; (LTS):
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/linux-6.12/news/&quot;&gt;Uploads&lt;/a&gt;:
            &lt;ul&gt;
              &lt;li&gt;uploaded version 6.12.107-1~deb12u1 to bookworm-security&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;merged changes from trixie’s 6.12.111-1&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/linux-base&quot;&gt;linux-base&lt;/a&gt;:
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/linux-base/news/&quot;&gt;Uploads&lt;/a&gt;:
            &lt;ul&gt;
              &lt;li&gt;uploaded version 4.17~bpo13+1 to trixie-backports&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/nfs-utils&quot;&gt;nfs-utils&lt;/a&gt;:
        &lt;ul&gt;
          &lt;li&gt;Merge requests:
            &lt;ul&gt;
              &lt;li&gt;reviewed &lt;a href=&quot;https://salsa.debian.org/kernel-team/nfs-utils/-/merge_requests/37&quot;&gt;!37: Install and use sysusers.d/tmpfiles.d config files&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/wireless-regdb&quot;&gt;wireless-regdb&lt;/a&gt;:
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/wireless-regdb/news/&quot;&gt;Uploads&lt;/a&gt;:
            &lt;ul&gt;
              &lt;li&gt;uploaded version 2026.09.03-1 to unstable&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Mailing lists:
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;https://lists.debian.org/debian-kernel/&quot;&gt;debian-kernel&lt;/a&gt;:
        &lt;ul&gt;
          &lt;li&gt;posted &lt;a href=&quot;https://lists.debian.org/9c807a025be2c54c60792124b0ef4210feda5aeb.camel@decadent.org.uk&quot;&gt;Agenda items for kernel-team meeting on 2026-09-30&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;replied to &lt;a href=&quot;https://lists.debian.org/9becdbad09e5c8180d83cab692313ae1b445e9b6.camel@decadent.org.uk&quot;&gt;Meta packages for modules&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;replied to &lt;a href=&quot;https://lists.debian.org/9cf5c87217aac57405690daa34660786a33b0f8c.camel@decadent.org.uk&quot;&gt;Updating linux-6.12 (bookworm-security) to 6.12.107&lt;/a&gt; (LTS)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;https://lists.debian.org/debian-lts-announce/&quot;&gt;debian-lts-announce&lt;/a&gt;:
        &lt;ul&gt;
          &lt;li&gt;posted &lt;a href=&quot;https://lists.debian.org/aq70MTniNMFjPuqA@decadent.org.uk&quot;&gt;[SECURITY] [DLA 4788-1] linux-6.12 security update&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt; </description> 
	<pubDate>Fri, 02 Oct 2026 14:34:15 +0000</pubDate>

</item> 
<item>
	<title>Junichi Uekawa: Tokyo has been raining for many days but finally there&#39;s some sunny days.</title>
	<guid>http://www.netfort.gr.jp/~dancer/diary/daily/2026-Oct-2.html.en#2026-Oct-2-16:56:37</guid>
	<link>http://www.netfort.gr.jp/~dancer/diary/daily/2026-Oct-2.html.en#2026-Oct-2-16:56:37</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dancer.png&quot; width=&quot;75&quot; height=&quot;97&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  Tokyo has been raining for many days but finally there&#39;s some sunny days.
        &lt;p&gt;&lt;/p&gt; </description> 
	<pubDate>Fri, 02 Oct 2026 07:56:37 +0000</pubDate>

</item> 
<item>
	<title>Dirk Eddelbuettel: RcppFastAD 0.0.6 on CRAN: Agentic Fix</title>
	<guid>http://dirk.eddelbuettel.com/blog/2026/10/01#rcppfastad_0.0.6</guid>
	<link>http://dirk.eddelbuettel.com/blog/2026/10/01#rcppfastad_0.0.6</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/dirk.png&quot; width=&quot;65&quot; height=&quot;90&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;A week ago, &lt;a href=&quot;https://dirk.eddelbuettel.com/blog/2026/09/24#rcppfastad_0.0.5&quot;&gt;release
0.0.5&lt;/a&gt; of the &lt;a href=&quot;https://github.com/eddelbuettel/rcppfastad&quot;&gt;RcppFastAD&lt;/a&gt; package
went to &lt;a href=&quot;https://cran.r-project.org&quot;&gt;CRAN&lt;/a&gt;, and &lt;a href=&quot;https://dirk.eddelbuettel.com/blog/2026/09/24#rcppfastad_0.0.5&quot;&gt;we
noted&lt;/a&gt; that it provided a stop-gap measure against a gnarly segfault
with &lt;code&gt;g++-16&lt;/code&gt; under heavier optimization / inlining. We are
happy to now announce that a new and fixed version 0.0.6 of &lt;a href=&quot;https://github.com/eddelbuettel/rcppfastad&quot;&gt;RcppFastAD&lt;/a&gt; is now
on &lt;a href=&quot;https://cran.r-project.org&quot;&gt;CRAN&lt;/a&gt;, and has been built for
&lt;a href=&quot;https://eddelbuettel.github.io/r2u/&quot;&gt;r2u&lt;/a&gt; as well as at &lt;a href=&quot;https://eddelbuettel.r-universe.dev/RcppFastAD&quot;&gt;r-universe&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/eddelbuettel/rcppfastad&quot;&gt;RcppFastAD&lt;/a&gt;
wraps the &lt;a href=&quot;https://github.com/JamesYang007/FastAD&quot;&gt;FastAD&lt;/a&gt;
header-only C++ library by &lt;a href=&quot;https://github.com/JamesYang007&quot;&gt;James&lt;/a&gt; which provides a C++
implementation of both forward and reverse mode of automatic
differentiation. It offers an easy-to-use header library that is both
lightweight and performant. With a little of bit of &lt;a href=&quot;https://www.rcpp.org&quot;&gt;Rcpp&lt;/a&gt; glue, it is also easy to use from R
in simple C++ applications.&lt;/p&gt;
&lt;p&gt;This release takes advantage of some large-language model inference
access I now get via Debian. The Deepseek v4 flash-0731 model, driven in
a container via the pi.dev harness, took just about no time finding a
small workaround for the issue &lt;a href=&quot;https://dirk.eddelbuettel.com/blog/2026/09/24#rcppfastad_0.0.5&quot;&gt;described
last week&lt;/a&gt; where we could see segfaults under heavier optimization
and inlining. The fix was to prohibit inlining the local
&lt;code&gt;bind()&lt;/code&gt; reimplementation. We have also sent this upstream as
a patch. It is nice to have an option of querying something a little
more powerful than the local models I experimented with before. We
suppress more compiler warnings in local builds via another option, and
did some standard maintenance.&lt;/p&gt;
&lt;p&gt;The NEWS file for this release follows.&lt;/p&gt;
&lt;blockquote&gt;
&lt;h4 id=&quot;changes-in-version-0.0.6-2026-10-01&quot;&gt;Changes in version 0.0.6
(2026-10-01)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The expression-template view rebinding is protected against
&lt;code&gt;g++ -O3&lt;/code&gt; (which led to wrong &lt;code&gt;Eigen::Map&lt;/code&gt;
dimensions, an &lt;code&gt;Eigen::Map&lt;/code&gt; resize assertion, and a
segfault.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;bind()&lt;/code&gt; helpers are marked non-inline and are
also protected from operating on a &lt;code&gt;nullptr&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Both items co-written with DeepSeek V4 Flash, and have been sent
upstream in a PR.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Suppress another compiler warning when local build
detected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add r-universe badge to README.md.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Courtesy of my &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/&quot;&gt;CRANberries&lt;/a&gt;, there
is also a diffstat report for the &lt;a href=&quot;https://dirk.eddelbuettel.com/cranberries/2026/10/01#RcppFastAD_0.0.6&quot;&gt;most
recent release&lt;/a&gt;. More information is available at the &lt;a href=&quot;https://github.com/eddelbuettel/rcppfastad&quot;&gt;repository&lt;/a&gt; or the
&lt;a href=&quot;https://dirk.eddelbuettel.com/code/rcpp.fastad.html&quot;&gt;package
page&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot;font-size: 80%; font-style: italic;&quot;&gt;
This post by &lt;a href=&quot;https://dirk.eddelbuettel.com&quot;&gt;Dirk
Eddelbuettel&lt;/a&gt; originated on his &lt;a href=&quot;https://dirk.eddelbuettel.com/blog/&quot;&gt;Thinking inside the box&lt;/a&gt;
blog. If you like this or other open-source work I do, you can now &lt;a href=&quot;https://github.com/sponsors/eddelbuettel&quot;&gt;sponsor me at
GitHub&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;&lt;/p&gt; </description> 
	<pubDate>Thu, 01 Oct 2026 17:05:00 +0000</pubDate>

</item> 
<item>
	<title>Ludovic Rousseau: macOS Golden Gate and smart cards status</title>
	<guid>https://blog.apdu.fr/posts/2026/09/macos-golden-gate-and-smart-cards-status/</guid>
	<link>https://blog.apdu.fr/posts/2026/09/macos-golden-gate-and-smart-cards-status/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/rousseau.png&quot; width=&quot;65&quot; height=&quot;95&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;I will compare this version of macOS with the previous one, Tahoe, which
I presented in &lt;a class=&quot;reference external&quot; href=&quot;https://blog.apdu.fr/posts/2025/10/macos-tahoe-and-smart-cards-status/&quot;&gt;macOS Tahoe and smart cards status&lt;/a&gt;.&lt;/p&gt;
&lt;img alt=&quot;/images/2026/09/macOS-GoldenGate.png&quot; class=&quot;align-center&quot; src=&quot;https://blog.apdu.fr/images/2026/09/macOS-GoldenGate.png&quot; /&gt;
&lt;section id=&quot;ccid&quot;&gt;
&lt;h2&gt;CCID&lt;/h2&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;code console&quot;&gt;&lt;a href=&quot;https://blog.apdu.fr/posts/2026/09/macos-golden-gate-and-smart-cards-status/#rest_code_82e7d8b3c3ba4d218fd206dd6f9c9a92-1&quot; id=&quot;rest_code_82e7d8b3c3ba4d218fd206dd6f9c9a92-1&quot; name=&quot;rest_code_82e7d8b3c3ba4d218fd206dd6f9c9a92-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;gp&quot;&gt;    $ &lt;/span&gt;grep&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-A&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;CFBundleShortVersionString&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/usr/libexec/SmartCardServices/drivers/ifd-ccid.bundle/Contents/Info.plist
&lt;a href=&quot;https://blog.apdu.fr/posts/2026/09/macos-golden-gate-and-smart-cards-status/#rest_code_82e7d8b3c3ba4d218fd206dd6f9c9a92-2&quot; id=&quot;rest_code_82e7d8b3c3ba4d218fd206dd6f9c9a92-2&quot; name=&quot;rest_code_82e7d8b3c3ba4d218fd206dd6f9c9a92-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;go&quot;&gt;            &amp;lt;key&amp;gt;CFBundleShortVersionString&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;a href=&quot;https://blog.apdu.fr/posts/2026/09/macos-golden-gate-and-smart-cards-status/#rest_code_82e7d8b3c3ba4d218fd206dd6f9c9a92-3&quot; id=&quot;rest_code_82e7d8b3c3ba4d218fd206dd6f9c9a92-3&quot; name=&quot;rest_code_82e7d8b3c3ba4d218fd206dd6f9c9a92-3&quot;&gt;&lt;/a&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;go&quot;&gt;            &amp;lt;string&amp;gt;1.5.1&amp;lt;/string&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There has been no change since the release of macOS Sonoma in 2023. The
version of &lt;a class=&quot;reference external&quot; href=&quot;https://ccid.apdu.fr/&quot;&gt;my CCID driver&lt;/a&gt; included in macOS
is still 1.5.1.&lt;/p&gt;
&lt;section id=&quot;apple-open-source&quot;&gt;
&lt;h3&gt;Apple Open Source&lt;/h3&gt;
&lt;p&gt;The Open Source components included in macOS can be found at
&amp;lt;&lt;a class=&quot;reference external&quot; href=&quot;https://opensource.apple.com/releases/&quot;&gt;https://opensource.apple.com/releases/&lt;/a&gt;&amp;gt;&lt;/p&gt;
&lt;p&gt;The Open Source components for Golden Gate 27.0 are not yet available.&lt;/p&gt;
&lt;p&gt;The SmartcardCCID software is available at
&lt;a class=&quot;reference external&quot; href=&quot;https://github.com/apple-oss-distributions/SmartcardCCID&quot;&gt;https://github.com/apple-oss-distributions/SmartcardCCID&lt;/a&gt;. The git
history shows that the code has not been modified since September 2024.&lt;/p&gt;
&lt;/section&gt;
&lt;section id=&quot;new-readers-supported-since-release-1-5-1&quot;&gt;
&lt;h3&gt;New readers supported since release 1.5.1&lt;/h3&gt;
&lt;p&gt;Since the release 1.5.1 of my CCID driver in November 2022, many new readers
have been added. The latest version is 1.8.4 (released in September
2026).&lt;/p&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;&lt;p&gt;1.8.4&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;THALES PKI Transaction Pad&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;1.8.3&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Broadcom Corp 58200 0x5884&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Broadcom Corp 58200 0x5885&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Broadcom Corp 58200 0x5886&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Broadcom Corp 58200 0x5887&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Circle CIR135 ICC&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DigiFlow LLP. KAZTOKEN&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HID Global Crescendo NFC Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HID Global OMNIKEY Plug&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HID Global OMNIKEY SE Plug&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Neowave LinkeoC-PRO&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Swissbit iShield Key 2 Pro&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;1.8.0&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GLSolutions NM61 PC/SC&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Identiv uTrust FIDO2 Security Key&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kensington VeriMark NFC+ USB-C Security Key&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;MARX CryptoTech LP Tokey 3 FIDO&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;mCore Contact-Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;mCore Contactless-Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;mCore DualSlot-Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pol Henarejos Pico Fido&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pol Henarejos Pico HSM&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pol Henarejos Pico OpenPGP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Richmond Technologies CO. LLC AEGIS PRO4 Smart Card Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SCR Prime&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;1.7.1&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ACS APG8201-B2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;BUDGET E-ID BUD001&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CHERRY Smart Board 1150&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CryptnoxCR CryptnoxCR&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Diebold Nixdorf PN7362au CCID&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;FT BioPass FIDO2 Pro&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nitrokey Nitrokey Passkey&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;1.7.0&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GIGA-TMS NFC CCID Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Identiv Identiv SmartOS Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SEC1210URT, single slot variant of SEC1210 serial&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TOKEN2 FIDO2 Security Key(0013),PIN+ Mini with OTP + PGP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TOKEN2 FIDO2 Security Key(0014),PIN+ Mini with FIDO + PGP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TOKEN2 FIDO2 Security Key(0015),PIN+ Mini with PGP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TOKEN2 FIDO2 Security Key(0016),PIN+ Mini with OTP + PGP + FIDO&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TOKEN2 FIDO2 Security Key(0023),PIN+ Series with OTP + PGP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TOKEN2 FIDO2 Security Key(0024),PIN+ Series with FIDO + PGP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TOKEN2 FIDO2 Security Key(0025),PIN+ Series with PGP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TOKEN2 FIDO2 Security Key(0203),Bio3 Dual with OTP + PGP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TOKEN2 FIDO2 Security Key(0204),Bio3 Dual with FIDO + PGP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TOKEN2 FIDO2 Security Key(0205),Bio3 Dual with PGP&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TOKEN2 FIDO2 Security Key(0206),Bio3 Dual with OTP + PGP + FIDO&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TOKEN2 Molto2 (older version)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;VIX TECHNOLOGY SECURE READER&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;1.6.2&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Arculus AuthentiKey&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;BHDC Reader-HHD02&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CHERRY Smart Terminal 1150&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HSIC CCID-Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ledger Flex&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SYC USB CCID Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Thales RF CR2000&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TOKEN2 FIDO2 Security Key(0026)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;1.6.0&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Aladdin R.D. JCR SecurBio&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AvidCard CAC Smart Card Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;FujitsuTechnologySolutions GmbH Dual Smartcard Reader D321&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ledger Stax&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;NXP Pegoda 3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;authenton #1- CTAP2.1&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;1.5.5&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Alpha-Project ANGARA Token&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Broadcom Corp 58200 (idProduct: 0x5864)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Broadcom Corp 58200 (idProduct: 0x5865)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Imprivata USB CCID&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;KAPELSE eS-KAP-Ad&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kapelse inSide&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;KAPELSE KAP-Care&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;KAPELSE KAP-eCV&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;KAPELSE KAP-GO&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;KAPELSE KAP-LINK2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kapelse KAP-Move&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kapelse Ti-Kap&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;rf IDEAS USB CCID&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SIMHUB pcsc reader&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;1.5.3&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ACS ACR1552 1S CL Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ACS ACR1552 CL Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ACS ACR1581&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ACS ACR40T ICC Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ACS ACR40U ICC Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ACS WalletMate 1S CL Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Aktiv Rutoken SCR 3101 NFC Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CIRIGHT ONE PASS U2F&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dexon Tecnologias Digitais LTDA eSmartDX&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Excelsecu Card reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GHI NC001&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Identiv uTrust Token Flex&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SpringCard M519 with idProduct: 0x6212&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SpringCard M519 with idProduct: 0x621A&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;WCMi SD5931&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;1.5.2&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;KAPELSE KAP-LINK&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;LDU LANDI&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sensyl SSC-HV Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TOKEN2 MFA NFC Reader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TOKEN2 Molto2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Thales RF Reader&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Due to SIP (System Integrity Protection,
&lt;a class=&quot;reference external&quot; href=&quot;https://support.apple.com/guide/security/secb7ea06b49/web&quot;&gt;https://support.apple.com/guide/security/secb7ea06b49/web&lt;/a&gt;) it is
difficult to update the configuration of the installed CCID driver
(version 1.5.1).&lt;/p&gt;
&lt;p&gt;If you have one of the 96 readers listed above, and the Apple driver is
not working for you, installing an updated version of my CCID driver is
the only option.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id=&quot;apple-ccid-driver&quot;&gt;
&lt;h2&gt;Apple CCID driver&lt;/h2&gt;
&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;code console&quot;&gt;&lt;a href=&quot;https://blog.apdu.fr/posts/2026/09/macos-golden-gate-and-smart-cards-status/#rest_code_bb28adf529e2494b830aad869a3802af-1&quot; id=&quot;rest_code_bb28adf529e2494b830aad869a3802af-1&quot; name=&quot;rest_code_bb28adf529e2494b830aad869a3802af-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;/span&gt;defaults&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/Library/Preferences/com.apple.security.smartcard.plist
&lt;a href=&quot;https://blog.apdu.fr/posts/2026/09/macos-golden-gate-and-smart-cards-status/#rest_code_bb28adf529e2494b830aad869a3802af-2&quot; id=&quot;rest_code_bb28adf529e2494b830aad869a3802af-2&quot; name=&quot;rest_code_bb28adf529e2494b830aad869a3802af-2&quot;&gt;&lt;/a&gt;&lt;span class=&quot;go&quot;&gt;{&lt;/span&gt;
&lt;a href=&quot;https://blog.apdu.fr/posts/2026/09/macos-golden-gate-and-smart-cards-status/#rest_code_bb28adf529e2494b830aad869a3802af-3&quot; id=&quot;rest_code_bb28adf529e2494b830aad869a3802af-3&quot; name=&quot;rest_code_bb28adf529e2494b830aad869a3802af-3&quot;&gt;&lt;/a&gt;&lt;span class=&quot;go&quot;&gt;        Logging = 0;&lt;/span&gt;
&lt;a href=&quot;https://blog.apdu.fr/posts/2026/09/macos-golden-gate-and-smart-cards-status/#rest_code_bb28adf529e2494b830aad869a3802af-4&quot; id=&quot;rest_code_bb28adf529e2494b830aad869a3802af-4&quot; name=&quot;rest_code_bb28adf529e2494b830aad869a3802af-4&quot;&gt;&lt;/a&gt;&lt;span class=&quot;go&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The Apple CCID driver is used by default.&lt;/p&gt;
&lt;p&gt;If you want or need to use my CCID driver instead, simply follow follow the
instructions at
&lt;a class=&quot;reference external&quot; href=&quot;https://blog.apdu.fr/posts/2023/11/apple-own-ccid-driver-in-sonoma/#enable-my-ccid-driver&quot;&gt;Apple&#39;s own CCID driver in Sonoma&lt;/a&gt;.&lt;/p&gt;
&lt;section id=&quot;known-bugs&quot;&gt;
&lt;h3&gt;Known bugs&lt;/h3&gt;
&lt;p&gt;The page listing the bugs I found in macOS Sonoma can be found under
&lt;a class=&quot;reference external&quot; href=&quot;https://blog.apdu.fr/posts/2023/09/macos-sonoma-and-smart-cards-known-bugs/&quot;&gt;macOS Sonoma and smart cards: known bugs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Apple has not informed me that any of these bugs have been fixed in
Golden Gate (or Tahoe). I therefore assume that the bugs are still
present.&lt;/p&gt;
&lt;p&gt;I have just verified that the issue involving &lt;code class=&quot;docutils literal&quot;&gt;SCardControl()&lt;/code&gt;
(&lt;a class=&quot;reference external&quot; href=&quot;https://blog.apdu.fr/posts/2024/02/macos-sonoma-bug-scardcontrol-part-2/&quot;&gt;macOS Sonoma bug: SCardControl() (part 2)&lt;/a&gt;) is still present. Its
behaviour is slightly different now though, so I assume Apple has
changed some of the code.  If you have a pinpad reader and want to use
the Secure PIN Entry feature, you should switch to using my CCID driver.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id=&quot;conclusion&quot;&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;As I mentioned in my article about macOS Tahoe, if you encounter any
issues with your smart card on macOS Golden Gate, I recommend switching
from the Apple driver to my CCID driver and checking again.&lt;/p&gt;
&lt;/section&gt; </description> 
	<pubDate>Wed, 30 Sep 2026 13:13:27 +0000</pubDate>

</item> 
<item>
	<title>Gunnar Wolf: The Origins of GPU Computing</title>
	<guid>https://gwolf.org/2026/09/the-origins-of-gpu-computing.html</guid>
	<link>https://gwolf.org/2026/09/the-origins-of-gpu-computing.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/gwolf.png&quot; width=&quot;69&quot; height=&quot;83&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;blockquote&gt;
		 
		   This post is an &lt;em&gt;unpublished&lt;/em&gt; review
		 
		     
		       
		         for &lt;em&gt;&lt;a href=&quot;https://dl.acm.org/doi/full/10.1145/3778248&quot;&gt;The Origins of GPU Computing&lt;/a&gt;&lt;/em&gt;
		       
		     
		     
		   &lt;/blockquote&gt;
		 
		 &lt;p&gt;This article appears in the “Communications of the ACM” magazine as part of
a series devoting to showcasing relevant examples of technologies where
federal funding of academic research have resulted in widely impacting,
clearly identifiable technological advances that have visibly improved –or,
at least, changed– life far beyond the technological arena.&lt;/p&gt;

&lt;p&gt;The road leading from the first parallel computing technologies built
completely for research, through a phase that was preeminently directed at
gaming, and back to leading current GPUs, that are basically massively
parallel supercomputers used for LLM training and inference and other IA
tasks, is far from trivial, and the authors make a good job outlining it in
few pages. The article is written in a clearly divulgatory way, staying as
clear of technical language as possible.&lt;/p&gt;

&lt;p&gt;The authors present three main enabling technologies for current GPU
technologies: Parallel computing, parallel graphics systems, and stream
processing.&lt;/p&gt;

&lt;p&gt;Coming from a technical formation myself, although clearly better grounded
in the software side of Computer Engineering than on the electronics side,
the most interesting “nugget of information” I take is that parallel
computing was born due to the fact that transistor switching consumes very
little energy, whereas communication along wires consumes much more — so
the more simultaneous operations can be carried out on-chip at once, the
less power will be dissipated as heat (and the less time that will be lost
due to data stores and loads).&lt;/p&gt;

&lt;p&gt;Graphics systems are a natural match for parallel systems, as rendering
realistic images basically requires repeating the same blocks of
instructions to a large array of items. Early GPU implementations were
built on fixed-function graphics pipelines, but by the turn of the century,
when nVidia spinned off the research labs at Stanford and started marketing
their product, introducing along the way the &lt;em&gt;Graphical Processing Unit&lt;/em&gt;
term, product, they enabled it to implement the full OpenGL graphics
pipeline on a single chip.&lt;/p&gt;

&lt;p&gt;Stream processing is the arrangement of in-chip electronics so that they
can better exploit producer-consumer locality between stages, in order to
achieve greater arithmetic intensity (this is, a greater
computation-to-bandwidth ratio), decreasing the total number of access to
memory accesses.&lt;/p&gt;

&lt;p&gt;The authors explain in broad terms the described technologies and how they
fit together, and how the technology was transferred from the universities
to the companies that became the most dynamic companies behind today’s top
trending technologies.&lt;/p&gt;

&lt;p&gt;I felt the article to be engaging and easy to read. As a technologist, I
did miss more details — dates when specific advances were made, how some of
the advances joined into further inventions… But I understand the aim of
the “Federal Funding of Academic Research” series’ aim is more towards
outsiders. And, as such, this work very well explains how trillion-dollar
technologies are only the result of decades of funding research ideas.&lt;/p&gt; </description> 
	<pubDate>Tue, 29 Sep 2026 18:55:02 +0000</pubDate>

</item> 
<item>
	<title>Otto Kekäläinen: Using multiple git remotes for true distributed version control</title>
	<guid>https://optimizedbyotto.com/post/multiple-git-remotes/</guid>
	<link>https://optimizedbyotto.com/post/multiple-git-remotes/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/otto.png&quot; width=&quot;64&quot; height=&quot;90&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;img alt=&quot;Featured image of post Using multiple git remotes for true distributed version control&quot; src=&quot;https://optimizedbyotto.com/post/multiple-git-remotes/featured-image.jpg&quot; /&gt;&lt;p&gt;One of the primary design principles for Linus Torvalds when creating Git is that it should be a &lt;em&gt;distributed&lt;/em&gt; system, capable of working with multiple remotes. However, most people seem to use Git with just one remote, typically having GitHub or GitLab as the only &lt;code&gt;origin&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Version control systems before &lt;a class=&quot;link&quot; href=&quot;https://en.wikipedia.org/wiki/Git_%28software%29&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Git&lt;/a&gt; relied on a centralized model. For example in Subversion or CVS you could only sync with one single remote server, which was considered the primary host of the source code. Git however is not just a &lt;a class=&quot;link&quot; href=&quot;https://en.wikipedia.org/wiki/Version_control&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;VCS&lt;/a&gt;, but a &lt;a class=&quot;link&quot; href=&quot;https://en.wikipedia.org/wiki/Distributed_version_control&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;DVCS&lt;/a&gt;, for &lt;em&gt;distributed version control system&lt;/em&gt;. If you currently use Git with just one single remote as if it was a centralized version control system, now is the time to change that and learn how to add multiple remotes, and configure more flexible &lt;code&gt;git pull&lt;/code&gt; and &lt;code&gt;git push&lt;/code&gt; rules.&lt;/p&gt;
&lt;p&gt;The first concept to grasp is that &lt;strong&gt;Git can have multiple remotes&lt;/strong&gt;. For example, after running a basic clone command such as &lt;code&gt;git clone https://github.com/ottok/debcraft.git&lt;/code&gt; you would end up with a single remote &lt;code&gt;origin&lt;/code&gt; pointing to GitHub:&lt;/p&gt;
&lt;div class=&quot;codeblock &quot;&gt;
&lt;header&gt;
&lt;span class=&quot;codeblock-lang&quot;&gt;&lt;/span&gt;
&lt;button class=&quot;codeblock-copy&quot;&gt;
Copy
&lt;/button&gt;
&lt;/header&gt;
&lt;code id=&quot;codeblock-id-0&quot; style=&quot;display: none;&quot;&gt;$ git remote --verbose
origin https://github.com/ottok/debcraft.git (fetch)
origin https://github.com/ottok/debcraft.git (push)&lt;/code&gt;&lt;pre&gt;&lt;code&gt;$ git remote --verbose
origin https://github.com/ottok/debcraft.git (fetch)
origin https://github.com/ottok/debcraft.git (push)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can however configure multiple remotes with the command &lt;code&gt;git remote&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;codeblock &quot;&gt;
&lt;header&gt;
&lt;span class=&quot;codeblock-lang&quot;&gt;&lt;/span&gt;
&lt;button class=&quot;codeblock-copy&quot;&gt;
Copy
&lt;/button&gt;
&lt;/header&gt;
&lt;code id=&quot;codeblock-id-1&quot; style=&quot;display: none;&quot;&gt;$ git remote rename origin github
$ git remote add gitlab https://gitlab.com/ottok/debcraft.git
$ git remote --verbose
github https://github.com/ottok/debcraft.git (fetch)
github https://github.com/ottok/debcraft.git (push)
gitlab https://gitlab.com/ottok/debcraft.git (fetch)
gitlab https://gitlab.com/ottok/debcraft.git (push)&lt;/code&gt;&lt;pre&gt;&lt;code&gt;$ git remote rename origin github
$ git remote add gitlab https://gitlab.com/ottok/debcraft.git
$ git remote --verbose
github https://github.com/ottok/debcraft.git (fetch)
github https://github.com/ottok/debcraft.git (push)
gitlab https://gitlab.com/ottok/debcraft.git (fetch)
gitlab https://gitlab.com/ottok/debcraft.git (push)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can push and pull from these individually, or from all at once:&lt;/p&gt;
&lt;div class=&quot;codeblock &quot;&gt;
&lt;header&gt;
&lt;span class=&quot;codeblock-lang&quot;&gt;&lt;/span&gt;
&lt;button class=&quot;codeblock-copy&quot;&gt;
Copy
&lt;/button&gt;
&lt;/header&gt;
&lt;code id=&quot;codeblock-id-2&quot; style=&quot;display: none;&quot;&gt;$ git pull --all
Fetching github
Fetching gitlab
Already up to date.&lt;/code&gt;&lt;pre&gt;&lt;code&gt;$ git pull --all
Fetching github
Fetching gitlab
Already up to date.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When you review the git history, note the labels &lt;code&gt;gitlab/main&lt;/code&gt; and &lt;code&gt;github/main&lt;/code&gt; which tell which commit the branch &lt;code&gt;main&lt;/code&gt; points to on various remotes. In this case they are all in sync and point to the same &lt;code&gt;5d1815c&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;codeblock &quot;&gt;
&lt;header&gt;
&lt;span class=&quot;codeblock-lang&quot;&gt;&lt;/span&gt;
&lt;button class=&quot;codeblock-copy&quot;&gt;
Copy
&lt;/button&gt;
&lt;/header&gt;
&lt;code id=&quot;codeblock-id-3&quot; style=&quot;display: none;&quot;&gt;$ git log --oneline
5d1815c (HEAD -&amp;gt; main, gitlab/main, github/main) Bump Debhelper version from 13 to 14
ca518a7 Temporarily disable automatic copyright year bumping due to frequent bugs
d6e201e Exclude .pm from codespell to decrease false positives (Closes: #1140488)
708ee35 Exclude debian/copyright from codespell due to frequent false positives&lt;/code&gt;&lt;pre&gt;&lt;code&gt;$ git log --oneline
5d1815c (HEAD -&amp;gt; main, gitlab/main, github/main) Bump Debhelper version from 13 to 14
ca518a7 Temporarily disable automatic copyright year bumping due to frequent bugs
d6e201e Exclude .pm from codespell to decrease false positives (Closes: #1140488)
708ee35 Exclude debian/copyright from codespell due to frequent false positives&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;When pushing, you can choose what remote to push to. For example, if I am working on branch &lt;code&gt;dev&lt;/code&gt; and I only want to push it to GitLab to trigger a CI run there, I can run &lt;code&gt;git push gitlab dev&lt;/code&gt;. You can also configure a default remote by running once &lt;code&gt;git push --set-upstream gitlab dev&lt;/code&gt; and thereafter simply run &lt;code&gt;git push&lt;/code&gt; and it will automatically push the branch &lt;code&gt;dev&lt;/code&gt; only to that remote.&lt;/p&gt;
&lt;p&gt;A related setting is &lt;code&gt;remote.pushDefault&lt;/code&gt;, which tells git which remote to push to when a branch does not define one of its own, and it applies to every branch that lacks a &lt;code&gt;[branch]&lt;/code&gt; section in &lt;code&gt;.git/config&lt;/code&gt;. Setting it once is what lets a repository have a per-branch pull remote, like the debcraft example below, and still have a single, predictable &lt;code&gt;git push&lt;/code&gt; target. To see which remote git will use for each of your branches, run &lt;code&gt;git branch -vv&lt;/code&gt;, and to refresh the remote-tracking branches of all remotes at once, run &lt;code&gt;git fetch --all --prune&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you want to have multiple remotes, but automatically push and pull to all of them at once, you configure one single remote to have multiple URLs with &lt;code&gt;git remote set-url --add&lt;/code&gt;. Since git prints one line per push URL, &lt;code&gt;git remote -v&lt;/code&gt; then shows the same remote several times, once for each URL it pushes to.&lt;/p&gt;
&lt;p&gt;As an illustration, in my actual local &lt;a class=&quot;link&quot; href=&quot;https://salsa.debian.org/debian/debcraft&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Debcraft&lt;/a&gt; development project I have all these configured:&lt;/p&gt;
&lt;div class=&quot;codeblock &quot;&gt;
&lt;header&gt;
&lt;span class=&quot;codeblock-lang&quot;&gt;&lt;/span&gt;
&lt;button class=&quot;codeblock-copy&quot;&gt;
Copy
&lt;/button&gt;
&lt;/header&gt;
&lt;code id=&quot;codeblock-id-4&quot; style=&quot;display: none;&quot;&gt;$ git remote -v
github-pull-requests git@github.com:ottok/debcraft.git (fetch)
github-pull-requests git@github.com:ottok/debcraft.git (push)
gitlab-merge-requests git@gitlab.com:ottok/debcraft.git (fetch)
gitlab-merge-requests git@gitlab.com:ottok/debcraft.git (push)
origin git@salsa.debian.org:debian/debcraft.git (fetch)
origin git@salsa.debian.org:debian/debcraft.git (push)
origin git@gitlab.com:ottok/debcraft.git (push)
origin git@github.com:ottok/debcraft.git (push)
otto git@salsa.debian.org:otto/debcraft.git (fetch)
otto git@salsa.debian.org:otto/debcraft.git (push)
otto git@gitlab.com:ottok/debcraft.git (push)
otto git@github.com:ottok/debcraft.git (push)
otto git@git.sr.ht:~ottok/debcraft (push)
otto ssh://git@codeberg.org/ottok/Debcraft.git (push)
salsa-merge-requests git@salsa.debian.org:debian/debcraft.git (fetch)
salsa-merge-requests git@salsa.debian.org:debian/debcraft.git (push)&lt;/code&gt;&lt;pre&gt;&lt;code&gt;$ git remote -v
github-pull-requests git@github.com:ottok/debcraft.git (fetch)
github-pull-requests git@github.com:ottok/debcraft.git (push)
gitlab-merge-requests git@gitlab.com:ottok/debcraft.git (fetch)
gitlab-merge-requests git@gitlab.com:ottok/debcraft.git (push)
origin git@salsa.debian.org:debian/debcraft.git (fetch)
origin git@salsa.debian.org:debian/debcraft.git (push)
origin git@gitlab.com:ottok/debcraft.git (push)
origin git@github.com:ottok/debcraft.git (push)
otto git@salsa.debian.org:otto/debcraft.git (fetch)
otto git@salsa.debian.org:otto/debcraft.git (push)
otto git@gitlab.com:ottok/debcraft.git (push)
otto git@github.com:ottok/debcraft.git (push)
otto git@git.sr.ht:~ottok/debcraft (push)
otto ssh://git@codeberg.org/ottok/Debcraft.git (push)
salsa-merge-requests git@salsa.debian.org:debian/debcraft.git (fetch)
salsa-merge-requests git@salsa.debian.org:debian/debcraft.git (push)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The settings can also be viewed directly in the config file:&lt;/p&gt;
&lt;div class=&quot;codeblock &quot;&gt;
&lt;header&gt;
&lt;span class=&quot;codeblock-lang&quot;&gt;&lt;/span&gt;
&lt;button class=&quot;codeblock-copy&quot;&gt;
Copy
&lt;/button&gt;
&lt;/header&gt;
&lt;code id=&quot;codeblock-id-5&quot; style=&quot;display: none;&quot;&gt;$ cat .git/config
...
[remote &quot;origin&quot;]
url = git@salsa.debian.org:debian/debcraft.git
fetch = +refs/heads/*:refs/remotes/origin/*
pushurl = git@salsa.debian.org:debian/debcraft.git
pushurl = git@gitlab.com:ottok/debcraft.git
pushurl = git@github.com:ottok/debcraft.git
[remote &quot;otto&quot;]
url = git@salsa.debian.org:otto/debcraft.git
fetch = +refs/heads/*:refs/remotes/otto/*
pushurl = git@salsa.debian.org:otto/debcraft.git
pushurl = git@gitlab.com:ottok/debcraft.git
pushurl = git@github.com:ottok/debcraft.git
pushurl = git@git.sr.ht:~ottok/debcraft
pushurl = ssh://git@codeberg.org/ottok/Debcraft.git
...
[branch &quot;main&quot;]
remote = origin
merge = refs/heads/main
[branch &quot;dev&quot;]
remote = otto
merge = refs/heads/dev
...&lt;/code&gt;&lt;pre&gt;&lt;code&gt;$ cat .git/config
...
[remote &quot;origin&quot;]
url = git@salsa.debian.org:debian/debcraft.git
fetch = +refs/heads/*:refs/remotes/origin/*
pushurl = git@salsa.debian.org:debian/debcraft.git
pushurl = git@gitlab.com:ottok/debcraft.git
pushurl = git@github.com:ottok/debcraft.git
[remote &quot;otto&quot;]
url = git@salsa.debian.org:otto/debcraft.git
fetch = +refs/heads/*:refs/remotes/otto/*
pushurl = git@salsa.debian.org:otto/debcraft.git
pushurl = git@gitlab.com:ottok/debcraft.git
pushurl = git@github.com:ottok/debcraft.git
pushurl = git@git.sr.ht:~ottok/debcraft
pushurl = ssh://git@codeberg.org/ottok/Debcraft.git
...
[branch &quot;main&quot;]
remote = origin
merge = refs/heads/main
[branch &quot;dev&quot;]
remote = otto
merge = refs/heads/dev
...&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On branch &lt;code&gt;main&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Running &lt;code&gt;git pull&lt;/code&gt; will fetch from &lt;code&gt;salsa.debian.org/debian/debcraft&lt;/code&gt; (the primary git hosting for this project)&lt;/li&gt;
&lt;li&gt;Running &lt;code&gt;git push&lt;/code&gt; will push to Salsa, GitLab and GitHub, one after the other, making sure they all have the latest &lt;code&gt;main&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On branch &lt;code&gt;dev&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Running &lt;code&gt;git pull&lt;/code&gt; will fetch from &lt;code&gt;salsa.debian.org/otto/debcraft&lt;/code&gt; (the personal fork)&lt;/li&gt;
&lt;li&gt;Running &lt;code&gt;git push&lt;/code&gt; will push to Salsa, GitLab, GitHub, Sourcehut and Codeberg all one after the other&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The command output will have the same message three times, once for each remote (assuming they were all already up-to-date):&lt;/p&gt;
&lt;div class=&quot;codeblock &quot;&gt;
&lt;header&gt;
&lt;span class=&quot;codeblock-lang&quot;&gt;&lt;/span&gt;
&lt;button class=&quot;codeblock-copy&quot;&gt;
Copy
&lt;/button&gt;
&lt;/header&gt;
&lt;code id=&quot;codeblock-id-6&quot; style=&quot;display: none;&quot;&gt;$ git push
Everything up-to-date
Everything up-to-date
Everything up-to-date&lt;/code&gt;&lt;pre&gt;&lt;code&gt;$ git push
Everything up-to-date
Everything up-to-date
Everything up-to-date&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;use-cases-for-distributed-version-control&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://optimizedbyotto.com/index.xml#use-cases-for-distributed-version-control&quot;&gt;&lt;/a&gt;Use cases for distributed version control
&lt;/h2&gt;&lt;p&gt;The most obvious use case for any distributed system is improved availability. In this example, the &lt;a class=&quot;link&quot; href=&quot;https://salsa.debian.org/&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;salsa.debian.org&lt;/a&gt; is often overloaded/unavailable, so pushing to GitLab and GitHub as well allows collaborators to use them to fetch git commits if the primary code hosting site is unresponsive. Once it comes back online again, the next git push/pull will automatically bring it up to the same content as what backup hosts had.&lt;/p&gt;
&lt;p&gt;The second main benefit is that having the code live on multiple &lt;a class=&quot;link&quot; href=&quot;https://en.wikipedia.org/wiki/Forge_%28software%29&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;code forges&lt;/a&gt; allows collaborators to use their own favorite host. Debcraft itself is a great example of this, as collaborators who don’t have a Salsa account can - and have - submitted &lt;a class=&quot;link&quot; href=&quot;https://gitlab.com/ottok/debcraft/-/merge_requests/?sort=created_date&amp;amp;state=all&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Merge Requests on GitLab.com&lt;/a&gt; and &lt;a class=&quot;link&quot; href=&quot;https://github.com/ottok/debcraft/pulls?q=is%3Apr+state%3Aclosed&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;Pull Requests on GitHub.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A third use case is code hosting migrations. If you for example want to gradually phase out GitHub.com and replace it with something else, you could configure git to pull from the old location and push to both, ensuring that other collaborators can start using the new code hosting location without disruptions to those who have not yet updated their remotes or done a fresh git clone from the new location.&lt;/p&gt;
&lt;h2 id=&quot;automating-setting-up-a-project-on-multiple-code-forges&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://optimizedbyotto.com/index.xml#automating-setting-up-a-project-on-multiple-code-forges&quot;&gt;&lt;/a&gt;Automating setting up a project on multiple code forges
&lt;/h2&gt;&lt;p&gt;While I don’t push all projects I work on to all Salsa/GitLab/GitHub, I do set up multiple remotes for enough git projects that I have this script to automate configuring a git repository that is cloned from Salsa to also push to GitLab and GitHub. It accepts the repository whether it was cloned over SSH or HTTPS, and it adds the push URLs and then pushes the current branch, all branches, and tags for you:&lt;/p&gt;
&lt;div class=&quot;codeblock &quot;&gt;
&lt;header&gt;
&lt;span class=&quot;codeblock-lang&quot;&gt;&lt;/span&gt;
&lt;button class=&quot;codeblock-copy&quot;&gt;
Copy
&lt;/button&gt;
&lt;/header&gt;
&lt;code id=&quot;codeblock-id-7&quot; style=&quot;display: none;&quot;&gt;#!/bin/bash
# Add GitLab and GitHub push URLs to an existing git remote, so that a plain
# &quot;git push&quot; writes the same commits to all three code forges.
#
# Usage: ./git-multipush-salsa.sh
#
# Environment:
# SALSA_REMOTE remote to turn into a mirror, default origin
# SALSA_USER your Salsa user, only used to detect that the source
# remote is somebody else&#39;s project
# GITLAB_USER your GitLab user, default ottok
# GITHUB_USER your GitHub user, default ottok
# PROTOCOL ssh (default) or https, for the push URLs
set -euo pipefail
SCRIPT=$(basename &quot;$0&quot;)
SALSA_REMOTE=${SALSA_REMOTE:-origin}
SALSA_USER=${SALSA_USER:-otto}
GITLAB_USER=${GITLAB_USER:-ottok}
GITHUB_USER=${GITHUB_USER:-ottok}
PROTOCOL=${PROTOCOL:-ssh}
die() { echo &quot;$SCRIPT: $*&quot; &amp;gt;&amp;amp;2; exit 1; }
# A failing command leaves the push URLs half configured behind, so say how
# to get back to where we started
fail()
{
echo &quot;$SCRIPT: &#39;$*&#39; failed, the push URLs may already have been added&quot; &amp;gt;&amp;amp;2
echo &quot; git config --unset-all remote.${SALSA_REMOTE}.pushurl&quot; &amp;gt;&amp;amp;2
echo &quot; git remote set-url --add --push ${SALSA_REMOTE} ${SALSA_URL}&quot; &amp;gt;&amp;amp;2
exit 1
}
git rev-parse --git-dir &amp;gt; /dev/null 2&amp;gt;&amp;amp;1 || die &quot;not inside a git repository&quot;
git remote | grep -qx &quot;$SALSA_REMOTE&quot; || die &quot;no remote named &#39;$SALSA_REMOTE&#39;&quot;
# Example: git@salsa.debian.org:otto/salsa-ci-pipeline.git
SALSA_URL=$(git remote get-url &quot;$SALSA_REMOTE&quot;)
# The source remote may use any of the URL forms salsa.debian.org accepts,
# for example git@salsa.debian.org:otto/salsa-ci-pipeline.git or
# https://salsa.debian.org/otto/salsa-ci-pipeline.git
case &quot;$SALSA_URL&quot; in
git@salsa.debian.org:*) SALSA_PATH=${SALSA_URL#git@salsa.debian.org:} ;;
ssh://git@salsa.debian.org/*) SALSA_PATH=${SALSA_URL#ssh://git@salsa.debian.org/} ;;
https://salsa.debian.org/*) SALSA_PATH=${SALSA_URL#https://salsa.debian.org/} ;;
http://salsa.debian.org/*) SALSA_PATH=${SALSA_URL#http://salsa.debian.org/} ;;
*) die &quot;unexpected source URL &#39;$SALSA_URL&#39;, expected a salsa.debian.org URL&quot; ;;
esac
SALSA_PATH=${SALSA_PATH%/}
SALSA_PATH=${SALSA_PATH%.git}
SOURCE_USER=${SALSA_PATH%%/*}
PROJECT=${SALSA_PATH##*/}
# Write the push URLs in one and the same protocol, no matter how the
# repository happens to have been cloned
if [ &quot;$PROTOCOL&quot; = &quot;https&quot; ]
then
SALSA_URL=&quot;https://salsa.debian.org/${SALSA_PATH}.git&quot;
GITLAB_URL=&quot;https://gitlab.com/${GITLAB_USER}/${PROJECT}.git&quot;
GITHUB_URL=&quot;https://github.com/${GITHUB_USER}/${PROJECT}.git&quot;
else
SALSA_URL=&quot;git@salsa.debian.org:${SALSA_PATH}.git&quot;
GITLAB_URL=&quot;git@gitlab.com:${GITLAB_USER}/${PROJECT}.git&quot;
GITHUB_URL=&quot;git@github.com:${GITHUB_USER}/${PROJECT}.git&quot;
fi
# Mirroring somebody else&#39;s project is fine, but it is usually not what you
# want: you most likely want to mirror your own fork instead
if [ &quot;$SOURCE_USER&quot; != &quot;$SALSA_USER&quot; ]
then
echo &quot;Note: $SALSA_REMOTE points to $SOURCE_USER&#39;s project, not your own.&quot;
echo &quot;To mirror your own fork, run this with SALSA_REMOTE set to its name.&quot;
echo
fi
# Bail out instead of adding the same push URLs twice
EXISTING=$(git remote get-url --push --all &quot;$SALSA_REMOTE&quot;)
if [ &quot;$(printf &#39;%s\n&#39; &quot;$EXISTING&quot; | wc -l)&quot; -gt 1 ]
then
die &quot;remote &#39;$SALSA_REMOTE&#39; already has multiple push URLs:
$EXISTING&quot;
fi
echo &quot;Mirroring $SALSA_URL to $GITLAB_URL and $GITHUB_URL&quot;
git remote set-url --add --push &quot;$SALSA_REMOTE&quot; &quot;$SALSA_URL&quot;
git remote set-url --add --push &quot;$SALSA_REMOTE&quot; &quot;$GITLAB_URL&quot;
git remote set-url --add --push &quot;$SALSA_REMOTE&quot; &quot;$GITHUB_URL&quot;
# Push the branch you have checked out first, and never with --force: the
# first branch a GitLab or GitHub project receives becomes its default branch,
# the one you then protect
DEFAULT_BRANCH=$(git symbolic-ref --short HEAD) || die &quot;not on a branch, check out a branch first&quot;
git push -u &quot;$SALSA_REMOTE&quot; &quot;$DEFAULT_BRANCH&quot;
git push &quot;$SALSA_REMOTE&quot; --all
git push &quot;$SALSA_REMOTE&quot; --tags
# The push above creates the GitLab and GitHub projects, but GitLab projects
# are private by default, so make the new mirror public with glab if installed.
if command -v glab &amp;gt; /dev/null
then
echo &quot;Make the GitLab project public and describe it as a mirror:&quot;
glab api -X PUT &quot;projects/${GITLAB_USER}%2F${PROJECT}&quot; \
-f visibility=public \
-f description=&quot;Mirror of ${SALSA_URL}&quot; \
-f notification_email=disabled
else
echo &quot;Install glab to do the same automatically, or visit&quot;
echo &quot;https://gitlab.com/${GITLAB_USER}/${PROJECT}/edit to make the project public&quot;
fi
echo &quot;To undo, drop all push URLs and add back only the original one:&quot;
echo &quot; git config --unset-all remote.${SALSA_REMOTE}.pushurl&quot;
echo &quot; git remote set-url --add --push ${SALSA_REMOTE} ${SALSA_URL}&quot;&lt;/code&gt;&lt;pre&gt;&lt;code&gt;#!/bin/bash
# Add GitLab and GitHub push URLs to an existing git remote, so that a plain
# &quot;git push&quot; writes the same commits to all three code forges.
#
# Usage: ./git-multipush-salsa.sh
#
# Environment:
# SALSA_REMOTE remote to turn into a mirror, default origin
# SALSA_USER your Salsa user, only used to detect that the source
# remote is somebody else&#39;s project
# GITLAB_USER your GitLab user, default ottok
# GITHUB_USER your GitHub user, default ottok
# PROTOCOL ssh (default) or https, for the push URLs
set -euo pipefail
SCRIPT=$(basename &quot;$0&quot;)
SALSA_REMOTE=${SALSA_REMOTE:-origin}
SALSA_USER=${SALSA_USER:-otto}
GITLAB_USER=${GITLAB_USER:-ottok}
GITHUB_USER=${GITHUB_USER:-ottok}
PROTOCOL=${PROTOCOL:-ssh}
die() { echo &quot;$SCRIPT: $*&quot; &amp;gt;&amp;amp;2; exit 1; }
# A failing command leaves the push URLs half configured behind, so say how
# to get back to where we started
fail()
{
echo &quot;$SCRIPT: &#39;$*&#39; failed, the push URLs may already have been added&quot; &amp;gt;&amp;amp;2
echo &quot; git config --unset-all remote.${SALSA_REMOTE}.pushurl&quot; &amp;gt;&amp;amp;2
echo &quot; git remote set-url --add --push ${SALSA_REMOTE} ${SALSA_URL}&quot; &amp;gt;&amp;amp;2
exit 1
}
git rev-parse --git-dir &amp;gt; /dev/null 2&amp;gt;&amp;amp;1 || die &quot;not inside a git repository&quot;
git remote | grep -qx &quot;$SALSA_REMOTE&quot; || die &quot;no remote named &#39;$SALSA_REMOTE&#39;&quot;
# Example: git@salsa.debian.org:otto/salsa-ci-pipeline.git
SALSA_URL=$(git remote get-url &quot;$SALSA_REMOTE&quot;)
# The source remote may use any of the URL forms salsa.debian.org accepts,
# for example git@salsa.debian.org:otto/salsa-ci-pipeline.git or
# https://salsa.debian.org/otto/salsa-ci-pipeline.git
case &quot;$SALSA_URL&quot; in
git@salsa.debian.org:*) SALSA_PATH=${SALSA_URL#git@salsa.debian.org:} ;;
ssh://git@salsa.debian.org/*) SALSA_PATH=${SALSA_URL#ssh://git@salsa.debian.org/} ;;
https://salsa.debian.org/*) SALSA_PATH=${SALSA_URL#https://salsa.debian.org/} ;;
http://salsa.debian.org/*) SALSA_PATH=${SALSA_URL#http://salsa.debian.org/} ;;
*) die &quot;unexpected source URL &#39;$SALSA_URL&#39;, expected a salsa.debian.org URL&quot; ;;
esac
SALSA_PATH=${SALSA_PATH%/}
SALSA_PATH=${SALSA_PATH%.git}
SOURCE_USER=${SALSA_PATH%%/*}
PROJECT=${SALSA_PATH##*/}
# Write the push URLs in one and the same protocol, no matter how the
# repository happens to have been cloned
if [ &quot;$PROTOCOL&quot; = &quot;https&quot; ]
then
SALSA_URL=&quot;https://salsa.debian.org/${SALSA_PATH}.git&quot;
GITLAB_URL=&quot;https://gitlab.com/${GITLAB_USER}/${PROJECT}.git&quot;
GITHUB_URL=&quot;https://github.com/${GITHUB_USER}/${PROJECT}.git&quot;
else
SALSA_URL=&quot;git@salsa.debian.org:${SALSA_PATH}.git&quot;
GITLAB_URL=&quot;git@gitlab.com:${GITLAB_USER}/${PROJECT}.git&quot;
GITHUB_URL=&quot;git@github.com:${GITHUB_USER}/${PROJECT}.git&quot;
fi
# Mirroring somebody else&#39;s project is fine, but it is usually not what you
# want: you most likely want to mirror your own fork instead
if [ &quot;$SOURCE_USER&quot; != &quot;$SALSA_USER&quot; ]
then
echo &quot;Note: $SALSA_REMOTE points to $SOURCE_USER&#39;s project, not your own.&quot;
echo &quot;To mirror your own fork, run this with SALSA_REMOTE set to its name.&quot;
echo
fi
# Bail out instead of adding the same push URLs twice
EXISTING=$(git remote get-url --push --all &quot;$SALSA_REMOTE&quot;)
if [ &quot;$(printf &#39;%s\n&#39; &quot;$EXISTING&quot; | wc -l)&quot; -gt 1 ]
then
die &quot;remote &#39;$SALSA_REMOTE&#39; already has multiple push URLs:
$EXISTING&quot;
fi
echo &quot;Mirroring $SALSA_URL to $GITLAB_URL and $GITHUB_URL&quot;
git remote set-url --add --push &quot;$SALSA_REMOTE&quot; &quot;$SALSA_URL&quot;
git remote set-url --add --push &quot;$SALSA_REMOTE&quot; &quot;$GITLAB_URL&quot;
git remote set-url --add --push &quot;$SALSA_REMOTE&quot; &quot;$GITHUB_URL&quot;
# Push the branch you have checked out first, and never with --force: the
# first branch a GitLab or GitHub project receives becomes its default branch,
# the one you then protect
DEFAULT_BRANCH=$(git symbolic-ref --short HEAD) || die &quot;not on a branch, check out a branch first&quot;
git push -u &quot;$SALSA_REMOTE&quot; &quot;$DEFAULT_BRANCH&quot;
git push &quot;$SALSA_REMOTE&quot; --all
git push &quot;$SALSA_REMOTE&quot; --tags
# The push above creates the GitLab and GitHub projects, but GitLab projects
# are private by default, so make the new mirror public with glab if installed.
if command -v glab &amp;gt; /dev/null
then
echo &quot;Make the GitLab project public and describe it as a mirror:&quot;
glab api -X PUT &quot;projects/${GITLAB_USER}%2F${PROJECT}&quot; \
-f visibility=public \
-f description=&quot;Mirror of ${SALSA_URL}&quot; \
-f notification_email=disabled
else
echo &quot;Install glab to do the same automatically, or visit&quot;
echo &quot;https://gitlab.com/${GITLAB_USER}/${PROJECT}/edit to make the project public&quot;
fi
echo &quot;To undo, drop all push URLs and add back only the original one:&quot;
echo &quot; git config --unset-all remote.${SALSA_REMOTE}.pushurl&quot;
echo &quot; git remote set-url --add --push ${SALSA_REMOTE} ${SALSA_URL}&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you prefer not to install &lt;code&gt;glab&lt;/code&gt;, the last part simply reduces to visiting &lt;a class=&quot;link&quot; href=&quot;https://gitlab.com/ottok/debcraft/-/settings&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;the GitLab project settings&lt;/a&gt; once and ticking the project public, and it is also worth setting a description like &lt;code&gt;Mirror of https://salsa.debian.org/debian/debcraft&lt;/code&gt; and disabling notification email there, as nobody wants a mirror sending out a flood of emails every time you push.&lt;/p&gt;
&lt;p&gt;There are a few caveats worth knowing about before mirroring everything everywhere. Every push to a remote with multiple push URLs writes to all of them, so a project with continuous integration configured on three forges will run its CI three times and cost you roughly three times as much. If one of the push URLs fails, say because the host is momentarily unreachable, git prints the error and stops there, leaving the remotes listed after the failing one without the new commits. Simply re-run the push once the host is reachable again; the remotes that did get the commits will just respond with &lt;code&gt;Everything up-to-date&lt;/code&gt;. And you should never force-push to only one of the remotes, as that leaves the mirrors permanently out of sync with your local repository.&lt;/p&gt;
&lt;h2 id=&quot;avoid-pulling-too-much&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://optimizedbyotto.com/index.xml#avoid-pulling-too-much&quot;&gt;&lt;/a&gt;Avoid pulling too much
&lt;/h2&gt;&lt;p&gt;Related to multiple remotes, you should also be aware that git allows one to configure which branches to pull. By default a &lt;code&gt;git clone&lt;/code&gt; will track all branches from the remote and pull everything, which in a typical open source project will bring in a lot of temporary development branches in vain.&lt;/p&gt;
&lt;p&gt;Thus it is better to run &lt;code&gt;git clone&lt;/code&gt; with the &lt;code&gt;--single-branch&lt;/code&gt; and &lt;code&gt;--branch&lt;/code&gt; parameters to fetch only the branch that matters, which in most cases is the &lt;code&gt;main&lt;/code&gt; branch. That can be accomplished with:&lt;/p&gt;
&lt;div class=&quot;codeblock &quot;&gt;
&lt;header&gt;
&lt;span class=&quot;codeblock-lang&quot;&gt;&lt;/span&gt;
&lt;button class=&quot;codeblock-copy&quot;&gt;
Copy
&lt;/button&gt;
&lt;/header&gt;
&lt;code id=&quot;codeblock-id-8&quot; style=&quot;display: none;&quot;&gt;git clone --single-branch --branch main https://github.com/ottok/debcraft.git&lt;/code&gt;&lt;pre&gt;&lt;code&gt;git clone --single-branch --branch main https://github.com/ottok/debcraft.git&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If a repository was already cloned, it can be configured to track only one branch with:&lt;/p&gt;
&lt;div class=&quot;codeblock &quot;&gt;
&lt;header&gt;
&lt;span class=&quot;codeblock-lang&quot;&gt;&lt;/span&gt;
&lt;button class=&quot;codeblock-copy&quot;&gt;
Copy
&lt;/button&gt;
&lt;/header&gt;
&lt;code id=&quot;codeblock-id-9&quot; style=&quot;display: none;&quot;&gt;git config remote.upstream.fetch &quot;+refs/heads/main:refs/remotes/upstream/main&quot;
git fetch upstream
git config --get-all remote.upstream.fetch
+refs/heads/main:refs/remotes/upstream/main&lt;/code&gt;&lt;pre&gt;&lt;code&gt;git config remote.upstream.fetch &quot;+refs/heads/main:refs/remotes/upstream/main&quot;
git fetch upstream
git config --get-all remote.upstream.fetch
+refs/heads/main:refs/remotes/upstream/main&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you later need to track more branches, you can configure them with commands such as:&lt;/p&gt;
&lt;div class=&quot;codeblock &quot;&gt;
&lt;header&gt;
&lt;span class=&quot;codeblock-lang&quot;&gt;&lt;/span&gt;
&lt;button class=&quot;codeblock-copy&quot;&gt;
Copy
&lt;/button&gt;
&lt;/header&gt;
&lt;code id=&quot;codeblock-id-10&quot; style=&quot;display: none;&quot;&gt;git config --add remote.upstream.fetch &quot;+refs/heads/3.2.y:refs/remotes/upstream/3.2.y&quot;
git fetch upstream
git checkout 3.2.y&lt;/code&gt;&lt;pre&gt;&lt;code&gt;git config --add remote.upstream.fetch &quot;+refs/heads/3.2.y:refs/remotes/upstream/3.2.y&quot;
git fetch upstream
git checkout 3.2.y&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For additional details about any of the tips in this post I recommend reading the &lt;a class=&quot;link&quot; href=&quot;https://manpages.debian.org/unstable/git-man/index.html&quot; rel=&quot;noopener&quot; target=&quot;_blank&quot;&gt;git man pages&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;now-go-and-spread-your-code-around&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;https://optimizedbyotto.com/index.xml#now-go-and-spread-your-code-around&quot;&gt;&lt;/a&gt;Now go and spread your code around
&lt;/h2&gt;&lt;p&gt;Distributing your code over multiple code forges costs you almost nothing in configuration, and in return you get availability, a choice of host for your collaborators, and freedom to migrate without a big bang. Add the push URLs to the remotes you already have, push once, and you are done.&lt;/p&gt;
&lt;p&gt;The rest of the git fundamentals are covered in my other posts. If your commits are not yet polished, start with &lt;a class=&quot;link&quot; href=&quot;https://optimizedbyotto.com/post/good-git-commit/&quot;&gt;what makes a good git commit message&lt;/a&gt; and &lt;a class=&quot;link&quot; href=&quot;https://optimizedbyotto.com/post/git-commit-message-examples/&quot;&gt;git commit messages by example&lt;/a&gt;. If you work on Debian packaging, &lt;a class=&quot;link&quot; href=&quot;https://optimizedbyotto.com/post/debian-collaboration-on-git/&quot;&gt;Git-based collaboration in Debian&lt;/a&gt; explains why the Salsa merge request workflow is built the way it is, and &lt;a class=&quot;link&quot; href=&quot;https://optimizedbyotto.com/post/debian-salsa-merge-request-best-practices/&quot;&gt;Salsa merge request best practices&lt;/a&gt; covers the review process itself.&lt;/p&gt; </description> 
	<pubDate>Mon, 28 Sep 2026 00:00:00 +0000</pubDate>

</item> 
<item>
	<title>Maytham Alsudany: Briefly looking at DNS and nameservers under the hood</title>
	<guid>https://maytham.aezign.au/blog/how-dns-and-nameservers-work</guid>
	<link>https://maytham.aezign.au/blog/how-dns-and-nameservers-work</link>
     <description>  &lt;article&gt;&lt;p&gt;I&#39;ve always known that the browser uses the Domain Name Resolution (DNS) system to convert domain names like &lt;code&gt;aezign.com.au&lt;/code&gt; into raw IP addresses, but have never actually understood how it works, outside of making sure my network config uses &lt;code&gt;1.1.1.1&lt;/code&gt; or &lt;code&gt;8.8.8.8&lt;/code&gt; instead of the crappy one the ISP provides. In this article, I set out to understand what nameservers do, and how they help anything that uses the internet find the right records.&lt;/p&gt;&lt;h2 id=&quot;dns-in-a-nutshell&quot;&gt;DNS in a nutshell&lt;/h2&gt;&lt;p&gt;A well-used analogy is a phonebook; when you have someone&#39;s name and need to find their phone number, you look through the phonebook. Overall, DNS does the same thing: when you enter an address like example.com, your browser will contact a DNS server (the &quot;phonebook&quot;) to determine its IP addresses. On Linux (or MacOS) systems, you can use &lt;a href=&quot;https://manpages.debian.org/stable/bind9-dnsutils/dig.1.en.html&quot;&gt;&lt;code&gt;dig&lt;/code&gt;&lt;/a&gt; on the command line to perform a DNS lookup and see what this looks like:&lt;/p&gt;&lt;pre&gt;$ dig example.com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; example.com
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 42782
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;example.com.                   IN      A

;; ANSWER SECTION:
example.com.            221     IN      A       104.20.23.154
example.com.            221     IN      A       172.66.147.243

;; Query time: 20 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Sun Sep 27 21:07:50 AWST 2026
;; MSG SIZE  rcvd: 72&lt;/pre&gt;&lt;p&gt;Here, you can see the DNS server being used is &lt;code&gt;1.1.1.1&lt;/code&gt; (Cloudflare&#39;s DNS server), and that it found the IPs &lt;code&gt;104.20.23.154&lt;/code&gt; and &lt;code&gt;172.66.147.243&lt;/code&gt; associated with the domain name &lt;code&gt;example.com&lt;/code&gt;. Your browser will then contact these IP addresses directly to load the website you are trying to open.&lt;/p&gt;&lt;h3 id=&quot;configuring-dns-servers&quot;&gt;Configuring DNS servers&lt;/h3&gt;&lt;p&gt;You can configure DNS servers through your operating system&#39;s network settings, and for some applications such as Firefox, with the application itself. If you don&#39;t manually set a DNS server, your computer will use the ones provided by your modem. If those are not configured, the default defined by the modem manufacturer or your ISP will be used.&lt;/p&gt;&lt;p&gt;The most well-used and reliable DNS servers you can use are Cloudflare&#39;s (&lt;code&gt;1.1.1.1&lt;/code&gt; and &lt;code&gt;1.0.0.1&lt;/code&gt;) and Google&#39;s (&lt;code&gt;8.8.8.8&lt;/code&gt; and &lt;code&gt;8.8.4.4&lt;/code&gt;). Having more than one DNS server means that if the first one in the list doesn&#39;t work or doesn&#39;t find the matching IPs for a domain name, it will move to the next one in the list, a backup DNS server.&lt;/p&gt;&lt;p&gt;DNS servers must be configured as IP addresses. If your computer tried to use a DNS server at a domain name, then where would your computer find the IP address for that domain name? It wouldn&#39;t be able to, as this is the exact gap that DNS servers fulfill.&lt;/p&gt;&lt;h2 id=&quot;records&quot;&gt;Records&lt;/h2&gt;&lt;p&gt;DNS is not used only to find IPs for a domain, but a whole host of other things. Collectively they are referred to as &quot;records&quot; (or &quot;DNS records&quot;). Each record is associated to a domain (e.g. &lt;code&gt;example.com&lt;/code&gt;) or a subdomain (e.g. &lt;code&gt;bar.example.com&lt;/code&gt;, &lt;code&gt;foo.bar.example.com&lt;/code&gt;) Here are some of the most common and important types:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;A - Map to an IPv4 address (e.g. &lt;code&gt;104.20.23.154&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;This is the fundamental function of DNS: to map from a domain name to a server&#39;s IP address. Multiple A records leads to load balancing, where browsers will randomly select one of the returned IP addresses such that traffic is evenly split between them.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;AAAA - Map to an IPv6 address (e.g. &lt;code&gt;2606:4700:10::6814:179a&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;This serves the same purpose as A records but for IPv6. Multiple AAAA records results in the same load balancing behaviour. All modern websites should have both an A record for legacy compatibility, and an AAAA record to future-proof for the gradual shift towards IPv6 addresses.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;CNAME - Alias to another domain name (e.g. &lt;code&gt;example.com&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;DNS servers will recursively lookup records for the aliased domain name until they reach an IP address (in an A or AAAA record).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;MX - Specify a Mail Exchange server (e.g. &lt;code&gt;mail.example.com&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;This record tells email SMTP servers where to direct emails to. For instance, the MX record for &lt;code&gt;aezign.com.au&lt;/code&gt; is &lt;code&gt;mail.aezign.au&lt;/code&gt;; this directs SMTP servers like Gmail and Outlook to send emails to the mailserver running at &lt;code&gt;mail.aezign.au&lt;/code&gt;. This also allows specifying a priority field, so that you can define multiple MX records (such as a main and a backup) and consumers will try to connect to the listed mailservers from lowest priority to highest.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;TXT - Store arbitrary text data&lt;/p&gt;&lt;p&gt;This is most commonly used for site verification (for instance, to link your website to Google Search Console) and for email security measures like DKIM, DMARC, and SPF.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;NS - Specify the nameservers for a domain (e.g. &lt;code&gt;zeus.ns.cloudflare.com&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;These authoritative nameservers are responsible for providing all the other record types when needed.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;code&gt;dig&lt;/code&gt; lets you query each of these. For instance, to list the MX records against &lt;code&gt;aezign.com.au&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;$ dig MX aezign.com.au

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; MX aezign.com.au
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 28213
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;aezign.com.au.                 IN      MX

;; ANSWER SECTION:
aezign.com.au.          300     IN      MX      10 mail.aezign.au.

;; Query time: 104 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Sun Sep 27 22:04:58 AWST 2026
;; MSG SIZE  rcvd: 70&lt;/pre&gt;&lt;p&gt;Here you can see there is only one mailserver configured for &lt;code&gt;aezign.com.au&lt;/code&gt;, which is &lt;code&gt;mail.aezign.au&lt;/code&gt;, and it has a priority of 10.&lt;/p&gt;&lt;p&gt;If you compare this against something like &lt;code&gt;gmail.com&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;$ dig MX gmail.com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; MX gmail.com
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 16538
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;gmail.com.                     IN      MX

;; ANSWER SECTION:
gmail.com.              2497    IN      MX      40 alt4.gmail-smtp-in.l.google.com.
gmail.com.              2497    IN      MX      20 alt2.gmail-smtp-in.l.google.com.
gmail.com.              2497    IN      MX      5 gmail-smtp-in.l.google.com.
gmail.com.              2497    IN      MX      10 alt1.gmail-smtp-in.l.google.com.
gmail.com.              2497    IN      MX      30 alt3.gmail-smtp-in.l.google.com.

;; Query time: 120 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Sun Sep 27 22:06:04 AWST 2026
;; MSG SIZE  rcvd: 161&lt;/pre&gt;&lt;p&gt;You can see that &lt;code&gt;gmail.com&lt;/code&gt; has several mailservers configured as redundancies due to the Gmail&#39;s sheer scale. &lt;code&gt;gmail-smtp-in.l.google.com&lt;/code&gt; has the highest priority of 5, so SMTP servers will attempt to contact that mailserver first, followed by &lt;code&gt;alt1.gmail-smtp-in.l.google.com&lt;/code&gt; and so on.&lt;/p&gt;&lt;h2 id=&quot;nameservers&quot;&gt;Nameservers&lt;/h2&gt;&lt;p&gt;Now there needs to be somewhere for DNS records against a domain name to be defined, right? This is where nameservers come in.&lt;/p&gt;&lt;p&gt;Nameservers are DNS servers that answer queries about the domains they are authoritative for i.e. the domains they are in charge of. For example, the authoritative nameservers for &lt;code&gt;example.com&lt;/code&gt; are &lt;code&gt;hera.ns.cloudflare.com&lt;/code&gt; and &lt;code&gt;elliott.ns.cloudflare.com&lt;/code&gt;, which means Cloudflare&#39;s nameservers are the source of truth when looking up DNS records for &lt;code&gt;example.com&lt;/code&gt;. You can check this with &lt;code&gt;dig&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;$ dig NS example.com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; NS example.com
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 37717
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;example.com.                   IN      NS

;; ANSWER SECTION:
example.com.            81837   IN      NS      hera.ns.cloudflare.com.
example.com.            81837   IN      NS      elliott.ns.cloudflare.com.

;; Query time: 140 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Sun Sep 27 23:27:19 AWST 2026
;; MSG SIZE  rcvd: 95&lt;/pre&gt;&lt;p&gt;Nameservers are configured with your domain name&#39;s registrar. The nameserver you set dictates where your remaining DNS records will live. For &lt;code&gt;example.com&lt;/code&gt;, this means you would configure all your records on Cloudflare&#39;s dashboard, since they are responsible for the domain&#39;s DNS records.&lt;/p&gt;&lt;h2 id=&quot;recursive-resolution&quot;&gt;Recursive resolution&lt;/h2&gt;&lt;p&gt;The DNS servers that our computers use follow a &lt;strong&gt;recursive resolution&lt;/strong&gt; process behind-the-scenes to find the authoritative nameservers for a domain, followed by the records you are querying.&lt;/p&gt;&lt;h3 id=&quot;finding-the-root-nameservers&quot;&gt;Finding the root nameservers&lt;/h3&gt;&lt;p&gt;Due to the recursive nature of the resolution process, there needs to be a starting point: the root (&lt;code&gt;.&lt;/code&gt;) nameservers. The resolver uses a fixed list of root nameservers called &lt;a href=&quot;https://www.iana.org/domains/root/files&quot;&gt;root hints&lt;/a&gt; issued by IANA (&lt;a href=&quot;https://www.internic.net/domain/named.root&quot;&gt;&lt;code&gt;named.root&lt;/code&gt;&lt;/a&gt;), to locate and contact the root nameservers. Resolvers will have this provided to them initially, and can dynamically update it themselves by querying one of the root nameservers for the root NS records to obtain a fresh list. For instance, we can query &lt;code&gt;198.41.0.4&lt;/code&gt; (&lt;code&gt;a.root-servers.net&lt;/code&gt;) to obtain a new list of root nameservers:&lt;/p&gt;&lt;pre&gt;$ dig @198.41.0.4 NS .

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; @198.41.0.4 NS .
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 43677
;; flags: qr aa rd; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 27
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;.				IN	NS

;; ANSWER SECTION:
.			518400	IN	NS	l.root-servers.net.
.			518400	IN	NS	j.root-servers.net.
.			518400	IN	NS	f.root-servers.net.
.			518400	IN	NS	h.root-servers.net.
.			518400	IN	NS	d.root-servers.net.
.			518400	IN	NS	b.root-servers.net.
.			518400	IN	NS	k.root-servers.net.
.			518400	IN	NS	i.root-servers.net.
.			518400	IN	NS	m.root-servers.net.
.			518400	IN	NS	e.root-servers.net.
.			518400	IN	NS	g.root-servers.net.
.			518400	IN	NS	c.root-servers.net.
.			518400	IN	NS	a.root-servers.net.

;; ADDITIONAL SECTION:
l.root-servers.net.	518400	IN	A	199.7.83.42
l.root-servers.net.	518400	IN	AAAA	2001:500:9f::42
j.root-servers.net.	518400	IN	A	192.58.128.30
j.root-servers.net.	518400	IN	AAAA	2001:503:c27::2:30
f.root-servers.net.	518400	IN	A	192.5.5.241
f.root-servers.net.	518400	IN	AAAA	2001:500:2f::f
h.root-servers.net.	518400	IN	A	198.97.190.53
h.root-servers.net.	518400	IN	AAAA	2001:500:1::53
d.root-servers.net.	518400	IN	A	199.7.91.13
d.root-servers.net.	518400	IN	AAAA	2001:500:2d::d
b.root-servers.net.	518400	IN	A	170.247.170.2
b.root-servers.net.	518400	IN	AAAA	2801:1b8:10::b
k.root-servers.net.	518400	IN	A	193.0.14.129
k.root-servers.net.	518400	IN	AAAA	2001:7fd::1
i.root-servers.net.	518400	IN	A	192.36.148.17
i.root-servers.net.	518400	IN	AAAA	2001:7fe::53
m.root-servers.net.	518400	IN	A	202.12.27.33
m.root-servers.net.	518400	IN	AAAA	2001:dc3::35
e.root-servers.net.	518400	IN	A	192.203.230.10
e.root-servers.net.	518400	IN	AAAA	2001:500:a8::e
g.root-servers.net.	518400	IN	A	192.112.36.4
g.root-servers.net.	518400	IN	AAAA	2001:500:12::d0d
c.root-servers.net.	518400	IN	A	192.33.4.12
c.root-servers.net.	518400	IN	AAAA	2001:500:2::c
a.root-servers.net.	518400	IN	A	198.41.0.4
a.root-servers.net.	518400	IN	AAAA	2001:503:ba3e::2:30

;; Query time: 476 msec
;; SERVER: 198.41.0.4#53(198.41.0.4) (UDP)
;; WHEN: Mon Sep 28 00:01:08 AWST 2026
;; MSG SIZE  rcvd: 811&lt;/pre&gt;&lt;h3 id=&quot;querying-the-root-nameservers&quot;&gt;Querying the root nameservers&lt;/h3&gt;&lt;p&gt;For &lt;code&gt;example.com&lt;/code&gt;, the first step is to query the root (&lt;code&gt;.&lt;/code&gt;) nameservers to find the nameservers for the &lt;code&gt;.com&lt;/code&gt; top-level domain (TLD). Using &lt;code&gt;a.root-servers.net&lt;/code&gt; again:&lt;/p&gt;&lt;pre&gt;$ dig @198.41.0.4 NS com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; @198.41.0.4 NS com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 22528
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 13, ADDITIONAL: 27
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;com.				IN	NS

;; AUTHORITY SECTION:
com.			172800	IN	NS	l.gtld-servers.net.
com.			172800	IN	NS	j.gtld-servers.net.
com.			172800	IN	NS	h.gtld-servers.net.
com.			172800	IN	NS	d.gtld-servers.net.
com.			172800	IN	NS	b.gtld-servers.net.
com.			172800	IN	NS	f.gtld-servers.net.
com.			172800	IN	NS	k.gtld-servers.net.
com.			172800	IN	NS	m.gtld-servers.net.
com.			172800	IN	NS	i.gtld-servers.net.
com.			172800	IN	NS	g.gtld-servers.net.
com.			172800	IN	NS	a.gtld-servers.net.
com.			172800	IN	NS	c.gtld-servers.net.
com.			172800	IN	NS	e.gtld-servers.net.

;; ADDITIONAL SECTION:
l.gtld-servers.net.	172800	IN	A	192.41.162.30
l.gtld-servers.net.	172800	IN	AAAA	2001:500:d937::30
j.gtld-servers.net.	172800	IN	A	192.48.79.30
j.gtld-servers.net.	172800	IN	AAAA	2001:502:7094::30
h.gtld-servers.net.	172800	IN	A	192.54.112.30
h.gtld-servers.net.	172800	IN	AAAA	2001:502:8cc::30
d.gtld-servers.net.	172800	IN	A	192.31.80.30
d.gtld-servers.net.	172800	IN	AAAA	2001:500:856e::30
b.gtld-servers.net.	172800	IN	A	192.33.14.30
b.gtld-servers.net.	172800	IN	AAAA	2001:503:231d::2:30
f.gtld-servers.net.	172800	IN	A	192.35.51.30
f.gtld-servers.net.	172800	IN	AAAA	2001:503:d414::30
k.gtld-servers.net.	172800	IN	A	192.52.178.30
k.gtld-servers.net.	172800	IN	AAAA	2001:503:d2d::30
m.gtld-servers.net.	172800	IN	A	192.55.83.30
m.gtld-servers.net.	172800	IN	AAAA	2001:501:b1f9::30
i.gtld-servers.net.	172800	IN	A	192.43.172.30
i.gtld-servers.net.	172800	IN	AAAA	2001:503:39c1::30
g.gtld-servers.net.	172800	IN	A	192.42.93.30
g.gtld-servers.net.	172800	IN	AAAA	2001:503:eea3::30
a.gtld-servers.net.	172800	IN	A	192.5.6.30
a.gtld-servers.net.	172800	IN	AAAA	2001:503:a83e::2:30
c.gtld-servers.net.	172800	IN	A	192.26.92.30
c.gtld-servers.net.	172800	IN	AAAA	2001:503:83eb::30
e.gtld-servers.net.	172800	IN	A	192.12.94.30
e.gtld-servers.net.	172800	IN	AAAA	2001:502:1ca1::30

;; Query time: 772 msec
;; SERVER: 198.41.0.4#53(198.41.0.4) (UDP)
;; WHEN: Mon Sep 28 00:09:25 AWST 2026
;; MSG SIZE  rcvd: 828&lt;/pre&gt;&lt;h3 id=&quot;querying-the-tld-nameservers&quot;&gt;Querying the TLD nameservers&lt;/h3&gt;&lt;p&gt;Now the resolver has &lt;code&gt;.com&lt;/code&gt; nameservers and their IPs. We can use one of these, such as &lt;code&gt;192.5.6.30&lt;/code&gt; (&lt;code&gt;a.gtld-servers.net&lt;/code&gt;) to find the nameservers for &lt;code&gt;example.com&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;$ dig @192.5.6.30 NS example.com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; @192.5.6.30 NS example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 37419
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 13
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.com.                   IN      NS

;; AUTHORITY SECTION:
example.com.            172800  IN      NS      hera.ns.cloudflare.com.
example.com.            172800  IN      NS      elliott.ns.cloudflare.com.

;; ADDITIONAL SECTION:
hera.ns.cloudflare.com. 172800  IN      A       108.162.192.162
hera.ns.cloudflare.com. 172800  IN      A       172.64.32.162
hera.ns.cloudflare.com. 172800  IN      A       173.245.58.162
hera.ns.cloudflare.com. 172800  IN      AAAA    2606:4700:50::adf5:3aa2
hera.ns.cloudflare.com. 172800  IN      AAAA    2803:f800:50::6ca2:c0a2
hera.ns.cloudflare.com. 172800  IN      AAAA    2a06:98c1:50::ac40:20a2
elliott.ns.cloudflare.com. 172800 IN    A       108.162.195.228
elliott.ns.cloudflare.com. 172800 IN    A       162.159.44.228
elliott.ns.cloudflare.com. 172800 IN    A       172.64.35.228
elliott.ns.cloudflare.com. 172800 IN    AAAA    2606:4700:58::a29f:2ce4
elliott.ns.cloudflare.com. 172800 IN    AAAA    2803:f800:50::6ca2:c3e4
elliott.ns.cloudflare.com. 172800 IN    AAAA    2a06:98c1:50::ac40:23e4

;; Query time: 80 msec
;; SERVER: 192.5.6.30#53(192.5.6.30) (UDP)
;; WHEN: Mon Sep 28 00:12:19 AWST 2026
;; MSG SIZE  rcvd: 359&lt;/pre&gt;&lt;h3 id=&quot;finding-the-domains-nameserver&quot;&gt;Finding the domain&#39;s nameserver&lt;/h3&gt;&lt;p&gt;The response tells the resolver that the nameservers for &lt;code&gt;example.com&lt;/code&gt; are &lt;code&gt;hera.ns.cloudflare.com&lt;/code&gt; and &lt;code&gt;elliott.ns.cloudflare.com&lt;/code&gt;. Now since these Cloudflare nameservers are also &lt;code&gt;.com&lt;/code&gt; domains and Cloudflare is so commonly used, the &lt;code&gt;.com&lt;/code&gt; nameserver provides optional &lt;strong&gt;sibling glue&lt;/strong&gt; records as defined in &lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc9471&quot;&gt;RFC 9471&lt;/a&gt; to prevent further roundtrips and optimize the process.&lt;/p&gt;&lt;p&gt;If we ignore the sibling glue records provided, the resolver would have to ask the &lt;code&gt;.com&lt;/code&gt; nameservers for the nameservers for &lt;code&gt;cloudflare.com&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;$ dig @192.5.6.30 NS cloudflare.com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; @192.5.6.30 NS cloudflare.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 40307
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 5, ADDITIONAL: 21
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;cloudflare.com.                        IN      NS

;; AUTHORITY SECTION:
cloudflare.com.         172800  IN      NS      ns3.cloudflare.com.
cloudflare.com.         172800  IN      NS      ns5.cloudflare.com.
cloudflare.com.         172800  IN      NS      ns4.cloudflare.com.
cloudflare.com.         172800  IN      NS      ns6.cloudflare.com.
cloudflare.com.         172800  IN      NS      ns7.cloudflare.com.

;; ADDITIONAL SECTION:
ns3.cloudflare.com.     172800  IN      A       162.159.0.33
ns3.cloudflare.com.     172800  IN      A       162.159.7.226
ns3.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:21
ns3.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:7e2
ns5.cloudflare.com.     172800  IN      A       162.159.2.9
ns5.cloudflare.com.     172800  IN      A       162.159.9.55
ns5.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:209
ns5.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:937
ns4.cloudflare.com.     172800  IN      A       162.159.1.33
ns4.cloudflare.com.     172800  IN      A       162.159.8.55
ns4.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:121
ns4.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:837
ns6.cloudflare.com.     172800  IN      A       162.159.3.11
ns6.cloudflare.com.     172800  IN      A       162.159.5.6
ns6.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:30b
ns6.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:506
ns7.cloudflare.com.     172800  IN      A       162.159.4.8
ns7.cloudflare.com.     172800  IN      A       162.159.6.6
ns7.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:408
ns7.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:606

;; Query time: 163 msec
;; SERVER: 192.5.6.30#53(192.5.6.30) (UDP)
;; WHEN: Mon Sep 28 00:26:53 AWST 2026
;; MSG SIZE  rcvd: 573&lt;/pre&gt;&lt;p&gt;Here, the &lt;code&gt;.com&lt;/code&gt; nameserver provides &lt;strong&gt;in-domain glue&lt;/strong&gt; records for &lt;code&gt;cloudflare.com&lt;/code&gt;&#39;s nameservers. Without these, there would be a circular dependency, since the nameserver named is a subdomain of the domain being queried for. This is because nameservers are always defined by name, which means that in order to actually contact the nameserver, your computer needs to obtain its IP address with another DNS lookup.&lt;/p&gt;&lt;p&gt;Next, we&#39;d use one of these nameservers, say &lt;code&gt;ns3.cloudflare.com&lt;/code&gt;, to obtain the IP for &lt;code&gt;hera.ns.cloudflare.com&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;$ dig @162.159.0.33 hera.ns.cloudflare.com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; @162.159.0.33 hera.ns.cloudflare.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 16801
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;hera.ns.cloudflare.com.                IN      A

;; ANSWER SECTION:
hera.ns.cloudflare.com. 86353   IN      A       108.162.192.162
hera.ns.cloudflare.com. 86353   IN      A       173.245.58.162
hera.ns.cloudflare.com. 86353   IN      A       172.64.32.162

;; Query time: 123 msec
;; SERVER: 162.159.0.33#53(162.159.0.33) (UDP)
;; WHEN: Mon Sep 28 01:11:37 AWST 2026
;; MSG SIZE  rcvd: 99&lt;/pre&gt;&lt;h3 id=&quot;querying-the-domains-authoritative-nameserver&quot;&gt;Querying the domain&#39;s authoritative nameserver&lt;/h3&gt;&lt;p&gt;Now we&#39;ve reached the authoritative nameserver for &lt;code&gt;example.com&lt;/code&gt;! The last thing to do is to fetch the A record for &lt;code&gt;example.com&lt;/code&gt; to obtain its server&#39;s IP address:&lt;/p&gt;&lt;pre&gt;$ dig @108.162.192.162 example.com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; @108.162.192.162 example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 43082
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;example.com.                   IN      A

;; ANSWER SECTION:
example.com.            300     IN      A       104.20.23.154
example.com.            300     IN      A       172.66.147.243

;; Query time: 123 msec
;; SERVER: 108.162.192.162#53(108.162.192.162) (UDP)
;; WHEN: Mon Sep 28 01:13:47 AWST 2026
;; MSG SIZE  rcvd: 72&lt;/pre&gt;&lt;p&gt;At last, we&#39;ve determined that the IP addresses of the servers behind &lt;code&gt;example.com&lt;/code&gt; are &lt;code&gt;104.20.23.154&lt;/code&gt; and &lt;code&gt;172.66.147.243&lt;/code&gt;. This matches our earlier lookup directly against your computer&#39;s configured DNS server.&lt;/p&gt;&lt;p&gt;The DNS servers your computer uses encapsulate this recursive resolution process behind the scenes, so that your computer only needs to make one round trip, and the servers can use their much faster data center connections and caching to optimize the process and make the query as fast as possible.&lt;/p&gt;&lt;h2 id=&quot;checking-dns-records&quot;&gt;Checking DNS records&lt;/h2&gt;&lt;p&gt;To check a website&#39;s records, the first thing to do is to ensure the domain name is pointed at the correct nameserver. For instance, &lt;code&gt;aezign.com.au&lt;/code&gt; is supposed to use Cloudflare, since that is where all the DNS records have been set up. We can verify this using &lt;code&gt;dig&lt;/code&gt;, (or alternatively with online tools like &lt;a href=&quot;https://dnschecker.org&quot;&gt;dnschecker.org&lt;/a&gt;):&lt;/p&gt;&lt;pre&gt;$ dig NS aezign.com.au

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; NS aezign.com.au
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 44172
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;aezign.com.au.                 IN      NS

;; ANSWER SECTION:
aezign.com.au.          86400   IN      NS      rosalie.ns.cloudflare.com.
aezign.com.au.          86400   IN      NS      zeus.ns.cloudflare.com.

;; Query time: 92 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Mon Sep 28 01:39:22 AWST 2026
;; MSG SIZE  rcvd: 100&lt;/pre&gt;&lt;p&gt;If this is not set correctly, the DNS records you configure will not work, as resolvers will be fetching records from somewhere else. In most cases, you can update this in your domain registrar&#39;s settings. This is especially common for new domain names, which default to the registrar&#39;s nameservers; unless you plan to use their built-in DNS management, you&#39;ll need to point them to your chosen provider.&lt;/p&gt;&lt;p&gt;Now we can check that the DNS records configured match those your DNS server returns. For &lt;code&gt;aezign.com.au&lt;/code&gt;, these are the MX and TXT records configured on Cloudflare.&lt;/p&gt;&lt;figure class=&quot;mx-auto w-fit&quot;&gt;&lt;source type=&quot;image/avif&quot; /&gt;&lt;source type=&quot;image/webp&quot; /&gt; &lt;img alt=&quot;Extract of Cloudflare&#39;s DNS record listing showing the MX record and TXT records for aezign.com.au.&quot; class=&quot;mx-0&quot; height=&quot;200&quot; src=&quot;https://maytham.aezign.au/_app/immutable/assets/aezign.com.au-cloudflare-dns-records.DzdwFvIV.png&quot; width=&quot;993&quot; /&gt; &lt;p&gt;The MX record and some TXT records configured for &lt;code&gt;aezign.com.au&lt;/code&gt; on Cloudflare&#39;s dashboard.&lt;/p&gt;&lt;/figure&gt;&lt;p&gt;We can check these using &lt;code&gt;dig&lt;/code&gt;, and using the &lt;code&gt;+short&lt;/code&gt; option to show only the content of the records.&lt;/p&gt;&lt;pre&gt;$ dig MX aezign.com.au +short

10 mail.aezign.au.

$ dig TXT aezign.com.au +short

&quot;google-site-verification=KFqTU5xH8fFf6OtszEL4oudfxple29Tm-TvxVtCWkAM&quot;
&quot;v=spf1 mx a:mail.aezign.au -all&quot;

$ dig TXT _dmarc.aezign.com.au +short

&quot;v=DMARC1;p=quarantine;sp=quarantine;adkim=r;aspf=r&quot;

$ dig TXT aezign.com.au-2026._domainkey.aezign.com.au +short

&quot;v=DKIM1; h=sha256; k=rsa; s=email; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzL04yXZgB72YkoxS+tLK//aWx65TS4UA3F0qJ7el68SEuD4ehmg+61Ta9iS31H6U074dnjyoPDeaiGBa7ToTNCtiIts4/ghD/8nrENROE6hQAwRmTK18ODDHrRDW73hWe6Dg4cK5vmXi82/wWRZU9SDKbme28IE9uCVir3lCkKYLs1&quot; &quot;j16gR1Sjqr6a2+3o+EeVXnLJ4wXmJMm7KCIdn7zv0t9Z1eYcw672PdpYPAMpGb8uUsgaDBsNSpTcupPkz4SWj6TrOB80CPHjWseVY8EOJeRsNKQ/8LFoQEBl4Rxtb3HAmu4UIxSZ4QMVOLnXz67e85mA5XjcNIsVMzaWaowwIDAQAB&quot;&lt;/pre&gt;&lt;p&gt;As we can see, this matches, which means that the nameservers for &lt;code&gt;aezign.com.au&lt;/code&gt; are correct and the DNS records are what we intend them to be.&lt;/p&gt;&lt;p&gt;Note that if you&#39;ve recently changed the nameserver or DNS records for your domain, it can take anywhere between 10 seconds and 24 hours for the changes to take effect and propagate across the different DNS servers globally. Tools like &lt;a href=&quot;https://dnschecker.org&quot;&gt;dnschecker.org&lt;/a&gt; can check your records on different DNS servers worldwide to see if they&#39;re reflecting your changes. The reason for this is caching: DNS servers like &lt;code&gt;1.1.1.1&lt;/code&gt; will cache results so it doesn&#39;t have to do the full resolution process every time, and uses the Time-To-Live (TTL) you configure in your DNS records as a guideline for caching duration.&lt;/p&gt;&lt;/article&gt; </description> 
	<pubDate>Mon, 28 Sep 2026 00:00:00 +0000</pubDate>

</item> 
<item>
	<title>Reproducible Builds (diffoscope): diffoscope 332 released</title>
	<guid>https://diffoscope.org/news/diffoscope-332-released/</guid>
	<link>https://diffoscope.org/news/diffoscope-332-released/</link>
     <description>  &lt;p&gt;The diffoscope maintainers are pleased to announce the release of diffoscope
version &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;332&lt;/code&gt;. This version includes the following changes:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ Chris Lamb ]
* Do not Build-Depend on GNU Guix. Thanks to Vagrant and Holger for the
  reports. (Closes: #1149132)

[ Guillaume Girol ]
* Update more tests to support new versions of Radare.
  (Closes: reproducible-builds/diffoscope#432)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You find out more by &lt;a href=&quot;https://diffoscope.org&quot;&gt;visiting the project homepage&lt;/a&gt;.&lt;/p&gt; </description> 
	<pubDate>Mon, 28 Sep 2026 00:00:00 +0000</pubDate>

</item> 
<item>
	<title>Maytham Alsudany: A Brief Explanation of DNS and Nameservers</title>
	<guid>https://aezign.com.au/resources/how-dns-and-nameservers-work</guid>
	<link>https://aezign.com.au/resources/how-dns-and-nameservers-work</link>
     <description>  &lt;article&gt;&lt;p&gt;The Domain Name System (DNS) is a fundamental piece of technology behind the modern internet. Thanks to its introduction in 1983, you&#39;re able to enter domain names like &lt;code&gt;aezign.com.au&lt;/code&gt; instead of raw IP addresses in your browser&#39;s address bar and when sending emails. This article explains what it is, how it works, and how you can inspect your own website&#39;s DNS and ensure it is set up correctly.&lt;/p&gt;&lt;h2 id=&quot;dns-in-a-nutshell&quot;&gt;DNS in a nutshell&lt;/h2&gt;&lt;p&gt;A well-used analogy is a phonebook; when you have someone&#39;s name and need to find their phone number, you look through the phonebook. Overall, DNS does the same thing: when you enter an address like example.com, your browser will contact a DNS server (the &quot;phonebook&quot;) to determine its IP addresses. On Linux (or MacOS) systems, you can use &lt;a href=&quot;https://manpages.debian.org/stable/bind9-dnsutils/dig.1.en.html&quot;&gt;&lt;code&gt;dig&lt;/code&gt;&lt;/a&gt; on the command line to perform a DNS lookup and see what this looks like:&lt;/p&gt;&lt;pre&gt;$ dig example.com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; example.com
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 42782
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;example.com.                   IN      A

;; ANSWER SECTION:
example.com.            221     IN      A       104.20.23.154
example.com.            221     IN      A       172.66.147.243

;; Query time: 20 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Sun Sep 27 21:07:50 AWST 2026
;; MSG SIZE  rcvd: 72&lt;/pre&gt;&lt;p&gt;Here, you can see the DNS server being used is &lt;code&gt;1.1.1.1&lt;/code&gt; (Cloudflare&#39;s DNS server), and that it found the IPs &lt;code&gt;104.20.23.154&lt;/code&gt; and &lt;code&gt;172.66.147.243&lt;/code&gt; associated with the domain name &lt;code&gt;example.com&lt;/code&gt;. Your browser will then contact these IP addresses directly to load the website you are trying to open.&lt;/p&gt;&lt;h3 id=&quot;configuring-dns-servers&quot;&gt;Configuring DNS servers&lt;/h3&gt;&lt;p&gt;You can configure DNS servers through your operating system&#39;s network settings, and for some applications such as Firefox, with the application itself. If you don&#39;t manually set a DNS server, your computer will use the ones provided by your modem. If those are not configured, the default defined by the modem manufacturer or your ISP will be used.&lt;/p&gt;&lt;p&gt;The most well-used and reliable DNS servers you can use are Cloudflare&#39;s (&lt;code&gt;1.1.1.1&lt;/code&gt; and &lt;code&gt;1.0.0.1&lt;/code&gt;) and Google&#39;s (&lt;code&gt;8.8.8.8&lt;/code&gt; and &lt;code&gt;8.8.4.4&lt;/code&gt;). Having more than one DNS server means that if the first one in the list doesn&#39;t work or doesn&#39;t find the matching IPs for a domain name, it will move to the next one in the list, a backup DNS server.&lt;/p&gt;&lt;p&gt;DNS servers must be configured as IP addresses. If your computer tried to use a DNS server at a domain name, then where would your computer find the IP address for that domain name? It wouldn&#39;t be able to, as this is the exact gap that DNS servers fulfill.&lt;/p&gt;&lt;h2 id=&quot;records&quot;&gt;Records&lt;/h2&gt;&lt;p&gt;DNS is not used only to find IPs for a domain, but a whole host of other things. Collectively they are referred to as &quot;records&quot; (or &quot;DNS records&quot;). Each record is associated to a domain (e.g. &lt;code&gt;example.com&lt;/code&gt;) or a subdomain (e.g. &lt;code&gt;bar.example.com&lt;/code&gt;, &lt;code&gt;foo.bar.example.com&lt;/code&gt;) Here are some of the most common and important types:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;A - Map to an IPv4 address (e.g. &lt;code&gt;104.20.23.154&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;This is the fundamental function of DNS: to map from a domain name to a server&#39;s IP address. Multiple A records leads to load balancing, where browsers will randomly select one of the returned IP addresses such that traffic is evenly split between them.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;AAAA - Map to an IPv6 address (e.g. &lt;code&gt;2606:4700:10::6814:179a&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;This serves the same purpose as A records but for IPv6. Multiple AAAA records results in the same load balancing behaviour. All modern websites should have both an A record for legacy compatibility, and an AAAA record to future-proof for the gradual shift towards IPv6 addresses.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;CNAME - Alias to another domain name (e.g. &lt;code&gt;example.com&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;DNS servers will recursively lookup records for the aliased domain name until they reach an IP address (in an A or AAAA record).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;MX - Specify a Mail Exchange server (e.g. &lt;code&gt;mail.example.com&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;This record tells email SMTP servers where to direct emails to. For instance, the MX record for &lt;code&gt;aezign.com.au&lt;/code&gt; is &lt;code&gt;mail.aezign.au&lt;/code&gt;; this directs SMTP servers like Gmail and Outlook to send emails to the mailserver running at &lt;code&gt;mail.aezign.au&lt;/code&gt;. This also allows specifying a priority field, so that you can define multiple MX records (such as a main and a backup) and consumers will try to connect to the listed mailservers from lowest priority to highest.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;TXT - Store arbitrary text data&lt;/p&gt;&lt;p&gt;This is most commonly used for site verification (for instance, to link your website to Google Search Console) and for email security measures like DKIM, DMARC, and SPF.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;NS - Specify the nameservers for a domain (e.g. &lt;code&gt;zeus.ns.cloudflare.com&lt;/code&gt;).&lt;/p&gt;&lt;p&gt;These authoritative nameservers are responsible for providing all the other record types when needed.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;code&gt;dig&lt;/code&gt; lets you query each of these. For instance, to list the MX records against &lt;code&gt;aezign.com.au&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;$ dig MX aezign.com.au

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; MX aezign.com.au
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 28213
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;aezign.com.au.                 IN      MX

;; ANSWER SECTION:
aezign.com.au.          300     IN      MX      10 mail.aezign.au.

;; Query time: 104 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Sun Sep 27 22:04:58 AWST 2026
;; MSG SIZE  rcvd: 70&lt;/pre&gt;&lt;p&gt;Here you can see there is only one mailserver configured for &lt;code&gt;aezign.com.au&lt;/code&gt;, which is &lt;code&gt;mail.aezign.au&lt;/code&gt;, and it has a priority of 10.&lt;/p&gt;&lt;p&gt;If you compare this against something like &lt;code&gt;gmail.com&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;$ dig MX gmail.com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; MX gmail.com
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 16538
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;gmail.com.                     IN      MX

;; ANSWER SECTION:
gmail.com.              2497    IN      MX      40 alt4.gmail-smtp-in.l.google.com.
gmail.com.              2497    IN      MX      20 alt2.gmail-smtp-in.l.google.com.
gmail.com.              2497    IN      MX      5 gmail-smtp-in.l.google.com.
gmail.com.              2497    IN      MX      10 alt1.gmail-smtp-in.l.google.com.
gmail.com.              2497    IN      MX      30 alt3.gmail-smtp-in.l.google.com.

;; Query time: 120 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Sun Sep 27 22:06:04 AWST 2026
;; MSG SIZE  rcvd: 161&lt;/pre&gt;&lt;p&gt;You can see that &lt;code&gt;gmail.com&lt;/code&gt; has several mailservers configured as redundancies due to the Gmail&#39;s sheer scale. &lt;code&gt;gmail-smtp-in.l.google.com&lt;/code&gt; has the highest priority of 5, so SMTP servers will attempt to contact that mailserver first, followed by &lt;code&gt;alt1.gmail-smtp-in.l.google.com&lt;/code&gt; and so on.&lt;/p&gt;&lt;h2 id=&quot;nameservers&quot;&gt;Nameservers&lt;/h2&gt;&lt;p&gt;Now there needs to be somewhere for DNS records against a domain name to be defined, right? This is where nameservers come in.&lt;/p&gt;&lt;p&gt;Nameservers are DNS servers that answer queries about the domains they are authoritative for i.e. the domains they are in charge of. For example, the authoritative nameservers for &lt;code&gt;example.com&lt;/code&gt; are &lt;code&gt;hera.ns.cloudflare.com&lt;/code&gt; and &lt;code&gt;elliott.ns.cloudflare.com&lt;/code&gt;, which means Cloudflare&#39;s nameservers are the source of truth when looking up DNS records for &lt;code&gt;example.com&lt;/code&gt;. You can check this with &lt;code&gt;dig&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;$ dig NS example.com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; NS example.com
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 37717
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;example.com.                   IN      NS

;; ANSWER SECTION:
example.com.            81837   IN      NS      hera.ns.cloudflare.com.
example.com.            81837   IN      NS      elliott.ns.cloudflare.com.

;; Query time: 140 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Sun Sep 27 23:27:19 AWST 2026
;; MSG SIZE  rcvd: 95&lt;/pre&gt;&lt;p&gt;Nameservers are configured with your domain name&#39;s registrar. The nameserver you set dictates where your remaining DNS records will live. For &lt;code&gt;example.com&lt;/code&gt;, this means you would configure all your records on Cloudflare&#39;s dashboard, since they are responsible for the domain&#39;s DNS records.&lt;/p&gt;&lt;h2 id=&quot;recursive-resolution&quot;&gt;Recursive resolution&lt;/h2&gt;&lt;p&gt;The DNS servers that our computers use follow a &lt;strong&gt;recursive resolution&lt;/strong&gt; process behind-the-scenes to find the authoritative nameservers for a domain, followed by the records you are querying.&lt;/p&gt;&lt;h3 id=&quot;finding-the-root-nameservers&quot;&gt;Finding the root nameservers&lt;/h3&gt;&lt;p&gt;Due to the recursive nature of the resolution process, there needs to be a starting point: the root (&lt;code&gt;.&lt;/code&gt;) nameservers. The resolver uses a fixed list of root nameservers called &lt;a href=&quot;https://www.iana.org/domains/root/files&quot;&gt;root hints&lt;/a&gt; issued by IANA (&lt;a href=&quot;https://www.internic.net/domain/named.root&quot;&gt;&lt;code&gt;named.root&lt;/code&gt;&lt;/a&gt;), to locate and contact the root nameservers. Resolvers will have this provided to them initially, and can dynamically update it themselves by querying one of the root nameservers for the root NS records to obtain a fresh list. For instance, we can query &lt;code&gt;198.41.0.4&lt;/code&gt; (&lt;code&gt;a.root-servers.net&lt;/code&gt;) to obtain a new list of root nameservers:&lt;/p&gt;&lt;pre&gt;$ dig @198.41.0.4 NS .

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; @198.41.0.4 NS .
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 43677
;; flags: qr aa rd; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 27
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;.				IN	NS

;; ANSWER SECTION:
.			518400	IN	NS	l.root-servers.net.
.			518400	IN	NS	j.root-servers.net.
.			518400	IN	NS	f.root-servers.net.
.			518400	IN	NS	h.root-servers.net.
.			518400	IN	NS	d.root-servers.net.
.			518400	IN	NS	b.root-servers.net.
.			518400	IN	NS	k.root-servers.net.
.			518400	IN	NS	i.root-servers.net.
.			518400	IN	NS	m.root-servers.net.
.			518400	IN	NS	e.root-servers.net.
.			518400	IN	NS	g.root-servers.net.
.			518400	IN	NS	c.root-servers.net.
.			518400	IN	NS	a.root-servers.net.

;; ADDITIONAL SECTION:
l.root-servers.net.	518400	IN	A	199.7.83.42
l.root-servers.net.	518400	IN	AAAA	2001:500:9f::42
j.root-servers.net.	518400	IN	A	192.58.128.30
j.root-servers.net.	518400	IN	AAAA	2001:503:c27::2:30
f.root-servers.net.	518400	IN	A	192.5.5.241
f.root-servers.net.	518400	IN	AAAA	2001:500:2f::f
h.root-servers.net.	518400	IN	A	198.97.190.53
h.root-servers.net.	518400	IN	AAAA	2001:500:1::53
d.root-servers.net.	518400	IN	A	199.7.91.13
d.root-servers.net.	518400	IN	AAAA	2001:500:2d::d
b.root-servers.net.	518400	IN	A	170.247.170.2
b.root-servers.net.	518400	IN	AAAA	2801:1b8:10::b
k.root-servers.net.	518400	IN	A	193.0.14.129
k.root-servers.net.	518400	IN	AAAA	2001:7fd::1
i.root-servers.net.	518400	IN	A	192.36.148.17
i.root-servers.net.	518400	IN	AAAA	2001:7fe::53
m.root-servers.net.	518400	IN	A	202.12.27.33
m.root-servers.net.	518400	IN	AAAA	2001:dc3::35
e.root-servers.net.	518400	IN	A	192.203.230.10
e.root-servers.net.	518400	IN	AAAA	2001:500:a8::e
g.root-servers.net.	518400	IN	A	192.112.36.4
g.root-servers.net.	518400	IN	AAAA	2001:500:12::d0d
c.root-servers.net.	518400	IN	A	192.33.4.12
c.root-servers.net.	518400	IN	AAAA	2001:500:2::c
a.root-servers.net.	518400	IN	A	198.41.0.4
a.root-servers.net.	518400	IN	AAAA	2001:503:ba3e::2:30

;; Query time: 476 msec
;; SERVER: 198.41.0.4#53(198.41.0.4) (UDP)
;; WHEN: Mon Sep 28 00:01:08 AWST 2026
;; MSG SIZE  rcvd: 811&lt;/pre&gt;&lt;h3 id=&quot;querying-the-root-nameservers&quot;&gt;Querying the root nameservers&lt;/h3&gt;&lt;p&gt;For &lt;code&gt;example.com&lt;/code&gt;, the first step is to query the root (&lt;code&gt;.&lt;/code&gt;) nameservers to find the nameservers for the &lt;code&gt;.com&lt;/code&gt; top-level domain (TLD). Using &lt;code&gt;a.root-servers.net&lt;/code&gt; again:&lt;/p&gt;&lt;pre&gt;$ dig @198.41.0.4 NS com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; @198.41.0.4 NS com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 22528
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 13, ADDITIONAL: 27
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;com.				IN	NS

;; AUTHORITY SECTION:
com.			172800	IN	NS	l.gtld-servers.net.
com.			172800	IN	NS	j.gtld-servers.net.
com.			172800	IN	NS	h.gtld-servers.net.
com.			172800	IN	NS	d.gtld-servers.net.
com.			172800	IN	NS	b.gtld-servers.net.
com.			172800	IN	NS	f.gtld-servers.net.
com.			172800	IN	NS	k.gtld-servers.net.
com.			172800	IN	NS	m.gtld-servers.net.
com.			172800	IN	NS	i.gtld-servers.net.
com.			172800	IN	NS	g.gtld-servers.net.
com.			172800	IN	NS	a.gtld-servers.net.
com.			172800	IN	NS	c.gtld-servers.net.
com.			172800	IN	NS	e.gtld-servers.net.

;; ADDITIONAL SECTION:
l.gtld-servers.net.	172800	IN	A	192.41.162.30
l.gtld-servers.net.	172800	IN	AAAA	2001:500:d937::30
j.gtld-servers.net.	172800	IN	A	192.48.79.30
j.gtld-servers.net.	172800	IN	AAAA	2001:502:7094::30
h.gtld-servers.net.	172800	IN	A	192.54.112.30
h.gtld-servers.net.	172800	IN	AAAA	2001:502:8cc::30
d.gtld-servers.net.	172800	IN	A	192.31.80.30
d.gtld-servers.net.	172800	IN	AAAA	2001:500:856e::30
b.gtld-servers.net.	172800	IN	A	192.33.14.30
b.gtld-servers.net.	172800	IN	AAAA	2001:503:231d::2:30
f.gtld-servers.net.	172800	IN	A	192.35.51.30
f.gtld-servers.net.	172800	IN	AAAA	2001:503:d414::30
k.gtld-servers.net.	172800	IN	A	192.52.178.30
k.gtld-servers.net.	172800	IN	AAAA	2001:503:d2d::30
m.gtld-servers.net.	172800	IN	A	192.55.83.30
m.gtld-servers.net.	172800	IN	AAAA	2001:501:b1f9::30
i.gtld-servers.net.	172800	IN	A	192.43.172.30
i.gtld-servers.net.	172800	IN	AAAA	2001:503:39c1::30
g.gtld-servers.net.	172800	IN	A	192.42.93.30
g.gtld-servers.net.	172800	IN	AAAA	2001:503:eea3::30
a.gtld-servers.net.	172800	IN	A	192.5.6.30
a.gtld-servers.net.	172800	IN	AAAA	2001:503:a83e::2:30
c.gtld-servers.net.	172800	IN	A	192.26.92.30
c.gtld-servers.net.	172800	IN	AAAA	2001:503:83eb::30
e.gtld-servers.net.	172800	IN	A	192.12.94.30
e.gtld-servers.net.	172800	IN	AAAA	2001:502:1ca1::30

;; Query time: 772 msec
;; SERVER: 198.41.0.4#53(198.41.0.4) (UDP)
;; WHEN: Mon Sep 28 00:09:25 AWST 2026
;; MSG SIZE  rcvd: 828&lt;/pre&gt;&lt;h3 id=&quot;querying-the-tld-nameservers&quot;&gt;Querying the TLD nameservers&lt;/h3&gt;&lt;p&gt;Now the resolver has &lt;code&gt;.com&lt;/code&gt; nameservers and their IPs. We can use one of these, such as &lt;code&gt;192.5.6.30&lt;/code&gt; (&lt;code&gt;a.gtld-servers.net&lt;/code&gt;) to find the nameservers for &lt;code&gt;example.com&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;$ dig @192.5.6.30 NS example.com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; @192.5.6.30 NS example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 37419
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 2, ADDITIONAL: 13
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;example.com.                   IN      NS

;; AUTHORITY SECTION:
example.com.            172800  IN      NS      hera.ns.cloudflare.com.
example.com.            172800  IN      NS      elliott.ns.cloudflare.com.

;; ADDITIONAL SECTION:
hera.ns.cloudflare.com. 172800  IN      A       108.162.192.162
hera.ns.cloudflare.com. 172800  IN      A       172.64.32.162
hera.ns.cloudflare.com. 172800  IN      A       173.245.58.162
hera.ns.cloudflare.com. 172800  IN      AAAA    2606:4700:50::adf5:3aa2
hera.ns.cloudflare.com. 172800  IN      AAAA    2803:f800:50::6ca2:c0a2
hera.ns.cloudflare.com. 172800  IN      AAAA    2a06:98c1:50::ac40:20a2
elliott.ns.cloudflare.com. 172800 IN    A       108.162.195.228
elliott.ns.cloudflare.com. 172800 IN    A       162.159.44.228
elliott.ns.cloudflare.com. 172800 IN    A       172.64.35.228
elliott.ns.cloudflare.com. 172800 IN    AAAA    2606:4700:58::a29f:2ce4
elliott.ns.cloudflare.com. 172800 IN    AAAA    2803:f800:50::6ca2:c3e4
elliott.ns.cloudflare.com. 172800 IN    AAAA    2a06:98c1:50::ac40:23e4

;; Query time: 80 msec
;; SERVER: 192.5.6.30#53(192.5.6.30) (UDP)
;; WHEN: Mon Sep 28 00:12:19 AWST 2026
;; MSG SIZE  rcvd: 359&lt;/pre&gt;&lt;h3 id=&quot;finding-the-domains-nameserver&quot;&gt;Finding the domain&#39;s nameserver&lt;/h3&gt;&lt;p&gt;The response tells the resolver that the nameservers for &lt;code&gt;example.com&lt;/code&gt; are &lt;code&gt;hera.ns.cloudflare.com&lt;/code&gt; and &lt;code&gt;elliott.ns.cloudflare.com&lt;/code&gt;. Now since these Cloudflare nameservers are also &lt;code&gt;.com&lt;/code&gt; domains and Cloudflare is so commonly used, the &lt;code&gt;.com&lt;/code&gt; nameserver provides optional &lt;strong&gt;sibling glue&lt;/strong&gt; records as defined in &lt;a href=&quot;https://datatracker.ietf.org/doc/html/rfc9471&quot;&gt;RFC 9471&lt;/a&gt; to prevent further roundtrips and optimize the process.&lt;/p&gt;&lt;p&gt;If we ignore the sibling glue records provided, the resolver would have to ask the &lt;code&gt;.com&lt;/code&gt; nameservers for the nameservers for &lt;code&gt;cloudflare.com&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;$ dig @192.5.6.30 NS cloudflare.com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; @192.5.6.30 NS cloudflare.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 40307
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 5, ADDITIONAL: 21
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;cloudflare.com.                        IN      NS

;; AUTHORITY SECTION:
cloudflare.com.         172800  IN      NS      ns3.cloudflare.com.
cloudflare.com.         172800  IN      NS      ns5.cloudflare.com.
cloudflare.com.         172800  IN      NS      ns4.cloudflare.com.
cloudflare.com.         172800  IN      NS      ns6.cloudflare.com.
cloudflare.com.         172800  IN      NS      ns7.cloudflare.com.

;; ADDITIONAL SECTION:
ns3.cloudflare.com.     172800  IN      A       162.159.0.33
ns3.cloudflare.com.     172800  IN      A       162.159.7.226
ns3.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:21
ns3.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:7e2
ns5.cloudflare.com.     172800  IN      A       162.159.2.9
ns5.cloudflare.com.     172800  IN      A       162.159.9.55
ns5.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:209
ns5.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:937
ns4.cloudflare.com.     172800  IN      A       162.159.1.33
ns4.cloudflare.com.     172800  IN      A       162.159.8.55
ns4.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:121
ns4.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:837
ns6.cloudflare.com.     172800  IN      A       162.159.3.11
ns6.cloudflare.com.     172800  IN      A       162.159.5.6
ns6.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:30b
ns6.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:506
ns7.cloudflare.com.     172800  IN      A       162.159.4.8
ns7.cloudflare.com.     172800  IN      A       162.159.6.6
ns7.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:408
ns7.cloudflare.com.     172800  IN      AAAA    2400:cb00:2049:1::a29f:606

;; Query time: 163 msec
;; SERVER: 192.5.6.30#53(192.5.6.30) (UDP)
;; WHEN: Mon Sep 28 00:26:53 AWST 2026
;; MSG SIZE  rcvd: 573&lt;/pre&gt;&lt;p&gt;Here, the &lt;code&gt;.com&lt;/code&gt; nameserver provides &lt;strong&gt;in-domain glue&lt;/strong&gt; records for &lt;code&gt;cloudflare.com&lt;/code&gt;&#39;s nameservers. Without these, there would be a circular dependency, since the nameserver named is a subdomain of the domain being queried for. This is because nameservers are always defined by name, which means that in order to actually contact the nameserver, your computer needs to obtain its IP address with another DNS lookup.&lt;/p&gt;&lt;p&gt;Next, we&#39;d use one of these nameservers, say &lt;code&gt;ns3.cloudflare.com&lt;/code&gt;, to obtain the IP for &lt;code&gt;hera.ns.cloudflare.com&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;$ dig @162.159.0.33 hera.ns.cloudflare.com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; @162.159.0.33 hera.ns.cloudflare.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 16801
;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;hera.ns.cloudflare.com.                IN      A

;; ANSWER SECTION:
hera.ns.cloudflare.com. 86353   IN      A       108.162.192.162
hera.ns.cloudflare.com. 86353   IN      A       173.245.58.162
hera.ns.cloudflare.com. 86353   IN      A       172.64.32.162

;; Query time: 123 msec
;; SERVER: 162.159.0.33#53(162.159.0.33) (UDP)
;; WHEN: Mon Sep 28 01:11:37 AWST 2026
;; MSG SIZE  rcvd: 99&lt;/pre&gt;&lt;h3 id=&quot;querying-the-domains-authoritative-nameserver&quot;&gt;Querying the domain&#39;s authoritative nameserver&lt;/h3&gt;&lt;p&gt;Now we&#39;ve reached the authoritative nameserver for &lt;code&gt;example.com&lt;/code&gt;! The last thing to do is to fetch the A record for &lt;code&gt;example.com&lt;/code&gt; to obtain its server&#39;s IP address:&lt;/p&gt;&lt;pre&gt;$ dig @108.162.192.162 example.com

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; @108.162.192.162 example.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 43082
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;example.com.                   IN      A

;; ANSWER SECTION:
example.com.            300     IN      A       104.20.23.154
example.com.            300     IN      A       172.66.147.243

;; Query time: 123 msec
;; SERVER: 108.162.192.162#53(108.162.192.162) (UDP)
;; WHEN: Mon Sep 28 01:13:47 AWST 2026
;; MSG SIZE  rcvd: 72&lt;/pre&gt;&lt;p&gt;At last, we&#39;ve determined that the IP addresses of the servers behind &lt;code&gt;example.com&lt;/code&gt; are &lt;code&gt;104.20.23.154&lt;/code&gt; and &lt;code&gt;172.66.147.243&lt;/code&gt;. This matches our earlier lookup directly against your computer&#39;s configured DNS server.&lt;/p&gt;&lt;p&gt;The DNS servers your computer uses employ this recursive resolution technique behind the scenes, so that your computer only needs to make one round trip, and the servers can use their much faster data center connections and caching to optimize the process and make the query as fast as possible.&lt;/p&gt;&lt;h2 id=&quot;verify-your-dns-records&quot;&gt;Verify your DNS records&lt;/h2&gt;&lt;p&gt;To check your website&#39;s records, the first thing you&#39;ll want to do is ensure your domain name is pointed at the correct nameserver. For instance, &lt;code&gt;aezign.com.au&lt;/code&gt; is supposed to use Cloudflare, since that is where all the DNS records have been set up. We can verify this using &lt;code&gt;dig&lt;/code&gt;, (or alternatively with online tools like &lt;a href=&quot;https://dnschecker.org&quot;&gt;dnschecker.org&lt;/a&gt;):&lt;/p&gt;&lt;pre&gt;$ dig NS aezign.com.au

; &amp;lt;&amp;lt;&amp;gt;&amp;gt; DiG 9.20.29-1-Debian &amp;lt;&amp;lt;&amp;gt;&amp;gt; NS aezign.com.au
;; global options: +cmd
;; Got answer:
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NOERROR, id: 44172
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;aezign.com.au.                 IN      NS

;; ANSWER SECTION:
aezign.com.au.          86400   IN      NS      rosalie.ns.cloudflare.com.
aezign.com.au.          86400   IN      NS      zeus.ns.cloudflare.com.

;; Query time: 92 msec
;; SERVER: 1.1.1.1#53(1.1.1.1) (UDP)
;; WHEN: Mon Sep 28 01:39:22 AWST 2026
;; MSG SIZE  rcvd: 100&lt;/pre&gt;&lt;p&gt;If this is not set correctly, the DNS records you configure will not work, as resolvers will be fetching records from somewhere else. In most cases, you can update this in your domain registrar&#39;s settings. This is especially common for new domain names, which default to the registrar&#39;s nameservers; unless you plan to use their built-in DNS management, you&#39;ll need to point them to your chosen provider.&lt;/p&gt;&lt;p&gt;Now we can check that the DNS records you&#39;ve configured match those your DNS server returns. For &lt;code&gt;aezign.com.au&lt;/code&gt;, these are the MX and TXT records configured on Cloudflare.&lt;/p&gt;&lt;figure class=&quot;mx-auto w-fit&quot;&gt;&lt;source type=&quot;image/avif&quot; /&gt;&lt;source type=&quot;image/webp&quot; /&gt;&lt;source type=&quot;image/png&quot; /&gt; &lt;img alt=&quot;Extract of Cloudflare&#39;s DNS record listing showing the MX record and TXT records for aezign.com.au.&quot; class=&quot;mx-0&quot; height=&quot;200&quot; src=&quot;https://maytham.aezign.au/_app/immutable/assets/aezign.com.au-cloudflare-dns-records.DzdwFvIV.png&quot; width=&quot;993&quot; /&gt; &lt;p&gt;The MX record and some TXT records configured for &lt;code&gt;aezign.com.au&lt;/code&gt; on Cloudflare&#39;s dashboard.&lt;/p&gt;&lt;/figure&gt;&lt;p&gt;We can check these using &lt;code&gt;dig&lt;/code&gt;, and using the &lt;code&gt;+short&lt;/code&gt; option to show only the content of the records.&lt;/p&gt;&lt;pre&gt;$ dig MX aezign.com.au +short

10 mail.aezign.au.

$ dig TXT aezign.com.au +short

&quot;google-site-verification=KFqTU5xH8fFf6OtszEL4oudfxple29Tm-TvxVtCWkAM&quot;
&quot;v=spf1 mx a:mail.aezign.au -all&quot;

$ dig TXT _dmarc.aezign.com.au +short

&quot;v=DMARC1;p=quarantine;sp=quarantine;adkim=r;aspf=r&quot;

$ dig TXT aezign.com.au-2026._domainkey.aezign.com.au +short

&quot;v=DKIM1; h=sha256; k=rsa; s=email; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzL04yXZgB72YkoxS+tLK//aWx65TS4UA3F0qJ7el68SEuD4ehmg+61Ta9iS31H6U074dnjyoPDeaiGBa7ToTNCtiIts4/ghD/8nrENROE6hQAwRmTK18ODDHrRDW73hWe6Dg4cK5vmXi82/wWRZU9SDKbme28IE9uCVir3lCkKYLs1&quot; &quot;j16gR1Sjqr6a2+3o+EeVXnLJ4wXmJMm7KCIdn7zv0t9Z1eYcw672PdpYPAMpGb8uUsgaDBsNSpTcupPkz4SWj6TrOB80CPHjWseVY8EOJeRsNKQ/8LFoQEBl4Rxtb3HAmu4UIxSZ4QMVOLnXz67e85mA5XjcNIsVMzaWaowwIDAQAB&quot;&lt;/pre&gt;&lt;p&gt;As we can see, this matches, which means that the nameservers for &lt;code&gt;aezign.com.au&lt;/code&gt; are correct and the DNS records are what we intend them to be.&lt;/p&gt;&lt;p&gt;Note that if you&#39;ve recently changed the nameserver or DNS records for your domain, it can take anywhere between 10 seconds and 24 hours for the changes to take effect and propagate across the different DNS servers worldwide. Tools like &lt;a href=&quot;https://dnschecker.org&quot;&gt;dnschecker.org&lt;/a&gt; can check your records on different DNS servers worldwide to see if they&#39;re reflecting your changes. The reason for this is caching: DNS servers like &lt;code&gt;1.1.1.1&lt;/code&gt; will cache results so it doesn&#39;t have to do the full resolution process every time, and uses the Time-To-Live (TTL) you configure in your DNS records as a guideline for caching duration.&lt;/p&gt;&lt;/article&gt; </description> 
	<pubDate>Mon, 28 Sep 2026 00:00:00 +0000</pubDate>

</item> 
<item>
	<title>Dima Kogan: Lunar terminator paradox</title>
	<guid>https://notes.secretsauce.net/notes/2026/09/27_lunar-terminator-paradox.html</guid>
	<link>http://notes.secretsauce.net/notes/2026/09/27_lunar-terminator-paradox.html</link>
     <description>  &lt;p&gt;
There&#39;s an optical illusion known by names like the &quot;lunar terminator paradox&quot;.
This has much discussion and descriptions online, but none made sense in my
head, so I wrote &lt;a href=&quot;https://github.com/dkogan/moon&quot;&gt;this program&lt;/a&gt; to figure out what was going on. The paradox:
&lt;/p&gt;

&lt;ul class=&quot;org-ul&quot;&gt;
&lt;li&gt;The moon is illuminated by the sun
&lt;/li&gt;
&lt;li&gt;After sunset, the sun is below, so we would expect the illuminated portion of
the moon to point down, towards where the sun is
&lt;/li&gt;
&lt;li&gt;This isn&#39;t what always happens!
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
I was camping in the mountains with a friend recently. We were looking up at the
sky, just after the sun has set. The moon was clearly pointing up.
&lt;/p&gt;

&lt;p&gt;
After playing with &lt;a href=&quot;https://github.com/dkogan/moon&quot;&gt;this program&lt;/a&gt;, I have clarity: we&#39;re looking up at the moon
from below. The most pathological case is a full moon. Let&#39;s say the moon is on
the horizon: elevation=0. If we&#39;re looking at this low moon, and the moon is
full, the sun is directly behind us. The moon is fully illuminated, and we see
100% of the moon disc lit up.
&lt;/p&gt;

&lt;p&gt;
Now, what happens if the moon is not at the horizon, but higher up at the sky?
Effectively, the sun is infinitely far away, so the same part of the moon is lit
up. But we&#39;re now looking at the moon from below, and we would see some of the
dark side on the bottom edge. I.e. the moon appears bright at the top, but has a
dark slice missing at the bottom: it points up! Even at sunset.
&lt;/p&gt;

&lt;p&gt;
This is the most clearly weird case. A half-moon has no paradoxical behavior,
and the more full the moon, the more clearly we can observe the bright moon
pointing up despite the sun being down.
&lt;/p&gt;

&lt;p&gt;
I produce two plots. At 3/4-full moon at sunset we look at the moon as it rises
from the horizon all the way up to the zenith:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img alt=&quot;scan-moon-el.svg&quot; src=&quot;https://notes.secretsauce.net/../../../notes/2026/09/27_lunar-terminator-paradox/scan-moon-el.svg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
If the moon is at the horizon (elevation = 0), we see the expected 3/4-lit disc.
As the moon rises, we see more and more of its bottom, and thus more and more
dark areas show up: It clearly points up at sunset!
&lt;/p&gt;

&lt;p&gt;
We can also move the sun around. Let&#39;s say the moon is 60deg up; let&#39;s move the
sun from new-moon to a full-moon:
&lt;/p&gt;


&lt;div class=&quot;figure&quot;&gt;
&lt;p&gt;&lt;img alt=&quot;scan-sun-az.svg&quot; src=&quot;https://notes.secretsauce.net/../../../notes/2026/09/27_lunar-terminator-paradox/scan-sun-az.svg&quot; /&gt;
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
In the darkest configuration, we can still see a lit crescent on the bottom: the
illumination is all on the opposite side, but we can see a slice of the
illuminated back side. As the sun swings around, we see more and more of the
moon. At azimuth = 90deg, we have a half-lit moon. Past that, more and more of
the moon is visible, always pointing up.
&lt;/p&gt;

&lt;p&gt;
This was also a super interesting study of the current state of AI tools. As I
was writing this and debugging, I would talk to Claude and Gemini about how this
worked and what I should be seeing. They were both completely unable to
comprehend this, and would make infinite circular arguments. Clearly they read
some incomplete explanations on the internet (as I have), and lack the reasoning
capability necessary to distill it into something resembling &quot;understanding&quot;.
AGI is not here yet.
&lt;/p&gt; </description> 
	<pubDate>Sun, 27 Sep 2026 21:04:00 +0000</pubDate>

</item> 
<item>
	<title>Aquila Macedo Costa: Testing library transitions before they reach unstable</title>
	<guid>https://aquilamacedo.xyz/debian/salsa-ci/2026/09/27/transition-aware-rebuilds</guid>
	<link>https://aquilamacedo.xyz/debian/salsa-ci/2026/09/27/transition-aware-rebuilds/</link>
     <description>  &lt;p&gt;A &lt;a href=&quot;https://wiki.debian.org/PackageTransition&quot;&gt;library transition&lt;/a&gt; can affect
many packages in Debian. I added a way for Salsa CI to rebuild the ones that
depend on the changing library, so maintainers can test the transition before
it reaches unstable.&lt;/p&gt;

&lt;p&gt;The need for this became clear during a proposed
&lt;a href=&quot;https://poppler.freedesktop.org/&quot;&gt;Poppler&lt;/a&gt; transition. Poppler is a library
for rendering PDFs. The reverse-dependency job I had added to Salsa CI queued
&lt;strong&gt;100 of 115 candidate rebuilds&lt;/strong&gt;, even though &lt;strong&gt;only about 21&lt;/strong&gt; were relevant.
The problem was documented in &lt;a href=&quot;https://salsa.debian.org/salsa-ci-team/pipeline/-/work_items/571&quot;&gt;issue
#571&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before this change, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ratt&lt;/code&gt; used every binary package produced by Poppler to
decide what to rebuild. That also picked up packages unrelated to the library
transition. The tracker listed the old and new library package names, so I used
them to focus the selection.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Poppler transition tracker showing its Affected, Good, and Bad expressions&quot; src=&quot;https://aquilamacedo.xyz/assets/images/poppler-transition-tracker.png&quot; /&gt;
&lt;sub&gt;The Poppler transition tracker identifies the old and new runtime library package names.&lt;/sub&gt;&lt;/p&gt;

&lt;p&gt;I added &lt;a href=&quot;https://github.com/Debian/ratt/pull/37&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-transition_affected&lt;/code&gt; to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ratt&lt;/code&gt;&lt;/a&gt; to implement this selection. The
option performs the scan against the selected archive indexes and injects
locally built &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.deb&lt;/code&gt; files into each source rebuild. It expects a regex of
dependency package names, not a complete Ben expression, so the tracker’s
&lt;em&gt;Affected&lt;/em&gt; expression must be adapted first.&lt;/p&gt;

&lt;p&gt;I then &lt;a href=&quot;https://salsa.debian.org/salsa-ci-team/pipeline/-/merge_requests/749&quot;&gt;integrated the mode into Salsa
CI&lt;/a&gt;.
Maintainers can &lt;a href=&quot;https://salsa.debian.org/salsa-ci-team/pipeline#transition-aware-reverse-dependencies-for-library-transitions&quot;&gt;enable transition-aware
rebuilds&lt;/a&gt;
by setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SALSA_CI_BUILD_REVERSE_DEPENDENCIES_TRANSITION_AFFECTED_REGEX&lt;/code&gt;. If
the variable is unset, the pipeline keeps the existing selection.&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;Salsa CI pipeline showing selected Poppler rebuild jobs&quot; src=&quot;https://aquilamacedo.xyz/assets/images/poppler-salsa-ci-rebuild-jobs.png&quot; /&gt;
&lt;sub&gt;A Poppler test showing the selected rebuild jobs. Three jobs reached the CI timeout, they were not confirmed package regressions.&lt;/sub&gt;&lt;/p&gt;

&lt;p&gt;I also changed &lt;a href=&quot;https://github.com/Debian/ratt/pull/36&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ratt&lt;/code&gt;&lt;/a&gt; to cover
packages targeting
&lt;a href=&quot;https://wiki.debian.org/DebianExperimental&quot;&gt;experimental&lt;/a&gt;. By default, it
resolves and rebuilds reverse dependencies from unstable while still injecting
the locally built &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.deb&lt;/code&gt; files. This lets a maintainer test a transition staged
in experimental against packages currently in unstable.&lt;/p&gt;

&lt;p&gt;Together, these changes help maintainers focus CI on packages relevant to a
library transition and review rebuild results before the new library reaches
unstable.&lt;/p&gt; </description> 
	<pubDate>Sun, 27 Sep 2026 05:58:14 +0000</pubDate>

</item> 
<item>
	<title>Russ Allbery: Review: Ode to the Half-Broken</title>
	<guid>https://www.eyrie.org/~eagle/reviews/books/0-7564-2013-X.html</guid>
	<link>https://www.eyrie.org/~eagle/reviews/books/0-7564-2013-X.html</link>
     <description>  &lt;p&gt;Review: &lt;cite&gt;Ode to the Half-Broken&lt;/cite&gt;, by Suzanne Palmer&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;&lt;tr&gt;
    &lt;td&gt;Publisher:&lt;/td&gt;
    &lt;td&gt;DAW&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Copyright:&lt;/td&gt;
    &lt;td&gt;May 2026&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;ISBN:&lt;/td&gt;
    &lt;td&gt;0-7564-2013-X&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Format:&lt;/td&gt;
    &lt;td&gt;Kindle&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;Pages:&lt;/td&gt;
    &lt;td&gt;441&lt;/td&gt;
  &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;
&lt;cite&gt;Ode to the Half-Broken&lt;/cite&gt; is a standalone post-apocalyptic (sort of)
science fiction novel.
&lt;/p&gt;

&lt;p&gt;
As this novel opens, the unnamed first-person protagonist is waking up in
a bathtub in an abandoned building. They are covered in electromagnets and
missing one leg.
&lt;/p&gt;

&lt;p&gt;
Waking up involved a secure reboot from a protected core kernel, so it is
immediately obvious that the protagonist is a robot. That also explains
the electromagnets, which interfere with their ability to control their
body. Or they would, if the protagonist didn&#39;t have long-dormant combat
routines available to deploy EM shielding and free themselves from the
bathtub. There are no immediate answers to why someone embedded a virus in
the data attached to a scientific paper on ants, an act so precisely
targeted that it had to be personal. Or what happened to their leg.
&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;
    &quot;There are a number of electromagnets in the next room,&quot; I say. I
    point. &quot;Behind that wall with all the holes in it.&quot;
&lt;/p&gt;

&lt;p&gt;
    &quot;Those are big holes. And fresh, too,&quot; the dog says. &quot;I wonder what
    made them.&quot;
&lt;/p&gt;

&lt;p&gt;
    &quot;Electromagnets experiencing sudden velocity.&quot;
&lt;/p&gt;

&lt;p&gt;
    The dog gives another of its short barks, and I am more convinced now
    it is laughing, though I was not attempting to be funny.
&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;
&lt;cite&gt;Ode to the Half-Broken&lt;/cite&gt; has a classic science fiction beginning:
&lt;i&gt;in medias res&lt;/i&gt; in a future science fiction version of Earth where
nothing is immediately explained, leaving the reader to work out the date
and the setting. Helping us out is the protagonist, who is neither chatty
nor very sociable with other characters but keeps up an analytical
monologue about the world as they narrate events.
&lt;/p&gt;

&lt;p&gt;
We are some decades into a grim future. The United States has largely
collapsed. Large parts of New York City are dangerous to humans due to
disease and radiation. Neither of those hazards bother the large number of
sentient robots; their scarcity, and therefore economy, is instead based
on power. Robots that control solar power stations act as low-level mob
bosses, trading power for information or labor.
&lt;/p&gt;

&lt;p&gt;
Our protagonist doesn&#39;t want to care about any of this. They retreated
from the world long ago for a solitary life in the former New York
Botanical Gardens studying ants. But they need a new leg and the best
robot repair person nearby is a human woman outside of the city, so they
reluctantly head in that direction, accompanied somewhat surprisingly by a
cyborg dog.
&lt;/p&gt;

&lt;p&gt;
The typical science fiction apocalypse is caused by something specific.
Classically, that event is a nuclear war, but writers found various
alternatives before, during, and after the Cold War era:
&lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/1-931520-03-8.html&quot;&gt;alien invasions&lt;/a&gt;,
&lt;a href=&quot;https://en.wikipedia.org/wiki/The_Day_of_the_Triffids&quot;&gt;meteor
showers&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/The_Stand&quot;&gt;plagues&lt;/a&gt;,
&lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/0-316-26233-1.html&quot;&gt;sea level rise&lt;/a&gt;, and &lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/1-59780-158-5.html&quot;&gt;peak oil and general environmental collapse&lt;/a&gt;, among many others. Less
common is a post-apocalyptic novel where the collapse comes from multiple
overlapping crises and accumulating failures, from a general failure to
meet what Adam Tooze and others call
&lt;a href=&quot;https://en.wikipedia.org/wiki/Polycrisis&quot;&gt;polycrisis&lt;/a&gt;. The first
time I encountered that style of post-apocalyptic story was in Octavia
Butler&#39;s &lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/0-446-60197-7.html&quot;&gt;&lt;cite&gt;Parable of the Sower&lt;/cite&gt;&lt;/a&gt;. It was
one of the choices that made (and still makes) that book feel so
chillingly realistic.
&lt;/p&gt;

&lt;p&gt;
The world background in &lt;cite&gt;Ode to the Half-Broken&lt;/cite&gt; is shaped by that
sort of polycrisis collapse. There is no one reason why New York City is a
dangerous, irradiated ruin and society has collapsed into isolated and
sometimes warring factions. It is not runaway artificial intelligence, or
at least not directly; sentient robots were a late-stage innovation of the
collapsing US civilization and a tool and accelerator of its many wars,
but they were not the cause and may be a critical ingredient in building
some functional replacement. Instead, society fell apart because we failed
to address any of the growing problems and then turned on each other in
the resulting ruins. The reader gets an idiosyncratic view of that
collapse in flashback chapters intermixed with the main narrative of the
initially unnamed robot protagonist, flashbacks told from the perspective
of the man who invented the key component for robot sentience. As you
would expect, those two narratives are linked. The reader will not
discover how they are linked until late in the story.
&lt;/p&gt;

&lt;p&gt;
This book could have been extremely depressing. It is not, which says a
great deal about Palmer&#39;s skill in telling it. The clinical distance of
the protagonist in the early chapters helps considerably: They have
rejected involvement in this world and therefore can describe it in
detached, factual terms, aided by the tendency of most robots in this
story to be slightly more precise, logical, and verbose than the human
characters. But as the protagonist&#39;s clinical distance fades, as it must
to allow the story&#39;s emotional stakes to rise, Palmer fills this book with
moments of beauty and hope. A former nuclear submarine that has become the
mind of a subway car is a key early ally. A collective has turned the
Hudson Bridge into a thriving if chaotic community. Self-regulating
enclaves of humans and robots are working together to try to build a
livable world. Robots oversee pollinator swarms that are attempting to
restore plant life, for no reason other than that they like order and
stability and see this as a way of restoring both. This is a grim,
post-apocalyptic world that does not dwell on either the grimness or the
apocalypse. It is instead full of small moments of hope, collaboration,
and personal connection.
&lt;/p&gt;

&lt;p&gt;
This is a story with villains, danger, pain, and risk. Despite the similar
keywords and cover aesthetics, it bears little resemblance to Becky
Chambers&#39;s philosophical &lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/1-250-23622-3.html&quot;&gt;Monk and Robot series&lt;/a&gt;.
It is not, in any definition of the term, cozy; it&#39;s a post-apocalyptic
adventure story about a robot and a dog making their way through a ruined
civilization and fighting people who are trying to build something even
worse on the rubble. But it&#39;s also charming and oddly happy. There are
strong found-family vibes in the way that a party coalesces around the
protagonist and eventually gives them a name, there is the quiet happiness
of seeing a grumpy misanthrope slowly come out of their protective shell,
and the rail mechs are an absolute delight.
&lt;/p&gt;

&lt;p&gt;
Like a lot of stories of happy small-group anarchism, I didn&#39;t entirely
believe the politics and have some qualms about the realism of the ending,
although perhaps I should strive to be as optimistic as Palmer writes. The
somewhat dry and fussily precise first-person narration will also not be
to everyone&#39;s taste; it worked for me by the end of the book, but it took
a bit of reading to get used to it. But those quibbles aside, this was
quietly lovely. It&#39;s a satisfying science fiction adventure story in a
world with disturbing parallels to the one we&#39;re living in, but which uses
those parallels to focus on small-scale collective efforts to build
something better. And all the small details of the world-building are
delightful: the different tiers of robots and their odd behaviors, the
machine sense of purpose, even the mix of suspicion and generosity. The
plot has large-scale implications, but it was the human-level details that
charmed me.
&lt;/p&gt;

&lt;p&gt;
I still want &lt;a href=&quot;https://www.eyrie.org/~eagle/reviews/books/0-7564-1888-7.html&quot;&gt;another Fergus novel&lt;/a&gt;, but this was
a highly successful foray outside of that series. Palmer has won two Hugos
for her novellas, so I can&#39;t really say she&#39;s overlooked, but her novels
aren&#39;t getting anywhere near the attention they deserve. Highly
recommended.
&lt;/p&gt;

&lt;p&gt;
There is plenty of world-building room here for a sequel, but &lt;cite&gt;Ode to
the Half-Broken&lt;/cite&gt; reaches a satisfying standalone conclusion. So far as I
know, no sequel is currently planned.
&lt;/p&gt;

&lt;p&gt;Rating: 8 out of 10&lt;/p&gt; </description> 
	<pubDate>Sun, 27 Sep 2026 02:57:00 +0000</pubDate>

</item> 
<item>
	<title>Reproducible Builds (diffoscope): diffoscope 331 released</title>
	<guid>https://diffoscope.org/news/diffoscope-331-released/</guid>
	<link>https://diffoscope.org/news/diffoscope-331-released/</link>
     <description>  &lt;p&gt;The diffoscope maintainers are pleased to announce the release of diffoscope
version &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;331&lt;/code&gt;. This version includes the following changes:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ Chris Lamb ]
* Support radare2 &amp;gt;= 5.9.0. (Closes: reproducible-builds/diffoscope#432)
* Update debian/tests/control.
* Update copyright years.

[ Christopher Baines ]
* Add support for .nar files via Guix.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You find out more by &lt;a href=&quot;https://diffoscope.org&quot;&gt;visiting the project homepage&lt;/a&gt;.&lt;/p&gt; </description> 
	<pubDate>Fri, 25 Sep 2026 00:00:00 +0000</pubDate>

</item> 
<item>
	<title>Russell Coker: Links September 2026</title>
	<guid>https://etbe.coker.com.au/?p=6302</guid>
	<link>https://etbe.coker.com.au/2026/09/24/links-september-2026/</link>
     <description>  &lt;p&gt;&lt;a href=&quot;https://arcan-fe.com/2022/04/02/the-day-of-a-new-command-line-interface-shell/&quot;&gt;Bjorn Stahl of the Arcan project wrote an insightful blog post The Day of a new Command-Line Interface: Shell [1]&lt;/a&gt;. He does a really good job of identifying problems and strategies for dealing with them, the UI of the results isn’t suitable to what I do though.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://fzakaria.com/2026/08/23/your-executable-is-a-sqlite-database&quot;&gt;Using sqlite as an executable format (replacement for ELF) is one of the wildest ideas I’ve seen in a while, it might actually have some good use cases too [2]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://longnow.org/ideas/space-dead/&quot;&gt;Andrew Dana Hudson wrote an interesting LongNow article about SciFi’s focus on space travel when it seems unlikely [3]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://thedriven.io/2026/07/24/a-mining-campaign-dressed-in-an-akubra-the-hands-off-our-fuel-petition-is-not-about-farmers/&quot;&gt;TheDriven has an informative article about the “Hands Off Our Fuel” astroturf campaign that uses farmers as the face of an attempt to give tax exemptions to mining companies [4]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://theconversation.com/china-has-cracked-down-on-ai-companions-what-can-we-learn-from-this-287976&quot;&gt;The Conversation has an interesting article about the new Chinese regulations restricting access to AI systems to prevent emotional dependence and prevent minors from having virtual partners or relatives [5]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://hashman.ca/managing-venvs/&quot;&gt;Elana Hashman wrote an informative blog post about Python virtualenvs, has useful information for people who aren’t Python experts and just need to get stuff done [6]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://dreamstation.systems/personal/ntppool.html&quot;&gt;We need more systems in the NTP pool, I would consider doing this if I had a server with an IP address that won’t change and no risk of bandwidth throttling [7]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://pluralistic.net/2026/08/01/dare-snot/#i-will-fucking-piledrive-you-if-you-mention-ai-again&quot;&gt;Cory Doctorow has some interesting thoughts on the CEO fetish for “AI” even though it is almost never doing any good [8]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.theguardian.com/lifeandstyle/2026/aug/05/journalist-taking-on-tech-fascists-silicon-valley&quot;&gt;Steve Rose wrote an insightful article for The Guardian about the tech fascists of Silicon Valley [9]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.theguardian.com/australia-news/2026/sep/10/jacqui-lambie-says-pauline-hanson-a-bloody-coward-after-one-nation-cartoon-calling-andrew-hastie-a-traitor-ntwnfb&quot;&gt;Jacqui Lambie calls Pauline Hanson an “angry little woman” and a “bloody coward”, One Nation hate the rule of law [10]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://theconversation.com/regime-change-might-be-2026s-nonfiction-bestseller-heres-why-its-essential-chilling-reading-288382&quot;&gt;The Conversation has an interesting article about Regime Change, the book about Trump by Maggie Haberman and Jonathan Swan [11]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://freedium-mirror.cfd/https://medium.com/@elvirabary/law-is-for-the-weak-why-russians-have-no-respect-for-the-law-bd590d3ef157&quot;&gt;Elvira Barry wrote an insightful article about the many failures of the Russian legal system, it’s interesting to note that ALL those failures match things that the Trump regime is doing [12]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=y50uWvxGb-A&quot;&gt;Pyotr Kurzin – Geopolitics YouTube channel has an interesting interview about “continental” vs “maritime” powers in the context of what the US and Russia are doing [13]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=BXLGV0Sj0n8&quot;&gt;Maxinomica has an interesting video about how China obtained a monopoly on rare earth metals and what happens next [14]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anarc.at/blog/2026-08-18-people-vs-ai-overlords/&quot;&gt;Anarcat wrote an insightful blog post The people vs the AI overlords about the problems that “AI” software development is bringing [15]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://changelog.complete.org/archives/44740-ai-in-debian-the-vote-proposals-and-nuance&quot;&gt;John Goerzen wrote an interesting blog post discussing the issues related to LLM use in FOSS projects [16]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://cybernews.com/security/android-oem-vulnerability-unprivileged-app-root/&quot;&gt;Cybernews has an article about an exploit for Samsung, Xiaomi, Oppo, and OnePlus phones due to bad OEM kernel drivers and bad OEM API proxies, no company should release devices with proprietry drivers [17]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://forwardfuture.com/newsletter/originals/gina-raimondo-says-basic-income-would-end-america-her-new-billion-dollar-org-is-how-she-plans-to-sto&quot;&gt;Scott Santens wrote an insightful article about how retraining fails laid-off workers and why UBI is needed when workers get replaced by LLMs [18]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://libroot.org/posts/what-happened-to-the-snowden-archive&quot;&gt;libroot has some information on the Snowden archive and why so little of it has been used by journalists, we need more answers about this [19]&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://drewdevault.com/weird-guys/&quot;&gt;Drew Devault’s list of Weird little guys of FOSS is interesting history about some people who are best avoided [20]&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[1]&lt;a href=&quot;https://arcan-fe.com/2022/04/02/the-day-of-a-new-command-line-interface-shell/&quot;&gt; https://tinyurl.com/ydye29ta&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[2]&lt;a href=&quot;https://fzakaria.com/2026/08/23/your-executable-is-a-sqlite-database&quot;&gt; https://tinyurl.com/26223e79&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[3]&lt;a href=&quot;https://longnow.org/ideas/space-dead/&quot;&gt; https://longnow.org/ideas/space-dead/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[4]&lt;a href=&quot;https://thedriven.io/2026/07/24/a-mining-campaign-dressed-in-an-akubra-the-hands-off-our-fuel-petition-is-not-about-farmers/&quot;&gt; https://tinyurl.com/287rktuz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[5]&lt;a href=&quot;https://theconversation.com/china-has-cracked-down-on-ai-companions-what-can-we-learn-from-this-287976&quot;&gt; https://tinyurl.com/25a9mag3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[6]&lt;a href=&quot;https://hashman.ca/managing-venvs/&quot;&gt; https://hashman.ca/managing-venvs/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[7]&lt;a href=&quot;https://dreamstation.systems/personal/ntppool.html&quot;&gt; https://dreamstation.systems/personal/ntppool.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[8]&lt;a href=&quot;https://pluralistic.net/2026/08/01/dare-snot/#i-will-fucking-piledrive-you-if-you-mention-ai-again&quot;&gt; https://tinyurl.com/2bzwm5d6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[9]&lt;a href=&quot;https://www.theguardian.com/lifeandstyle/2026/aug/05/journalist-taking-on-tech-fascists-silicon-valley&quot;&gt; https://tinyurl.com/25bj88ss&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[10]&lt;a href=&quot;https://www.theguardian.com/australia-news/2026/sep/10/jacqui-lambie-says-pauline-hanson-a-bloody-coward-after-one-nation-cartoon-calling-andrew-hastie-a-traitor-ntwnfb&quot;&gt; https://tinyurl.com/2ywkupwv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[11]&lt;a href=&quot;https://theconversation.com/regime-change-might-be-2026s-nonfiction-bestseller-heres-why-its-essential-chilling-reading-288382&quot;&gt; https://tinyurl.com/257umlg6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[12]&lt;a href=&quot;https://freedium-mirror.cfd/https://medium.com/@elvirabary/law-is-for-the-weak-why-russians-have-no-respect-for-the-law-bd590d3ef157&quot;&gt; https://tinyurl.com/2cjyev9l&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[13]&lt;a href=&quot;https://www.youtube.com/watch?v=y50uWvxGb-A&quot;&gt; https://www.youtube.com/watch?v=y50uWvxGb-A&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[14]&lt;a href=&quot;https://www.youtube.com/watch?v=BXLGV0Sj0n8&quot;&gt; https://www.youtube.com/watch?v=BXLGV0Sj0n8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[15]&lt;a href=&quot;https://anarc.at/blog/2026-08-18-people-vs-ai-overlords/&quot;&gt; https://anarc.at/blog/2026-08-18-people-vs-ai-overlords/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[16]&lt;a href=&quot;https://changelog.complete.org/archives/44740-ai-in-debian-the-vote-proposals-and-nuance&quot;&gt; https://tinyurl.com/2a8pzj8j&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[17]&lt;a href=&quot;https://cybernews.com/security/android-oem-vulnerability-unprivileged-app-root/&quot;&gt; https://tinyurl.com/249oafcy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[18]&lt;a href=&quot;https://forwardfuture.com/newsletter/originals/gina-raimondo-says-basic-income-would-end-america-her-new-billion-dollar-org-is-how-she-plans-to-sto&quot;&gt; https://tinyurl.com/28f5gdjv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[19]&lt;a href=&quot;https://libroot.org/posts/what-happened-to-the-snowden-archive&quot;&gt; https://tinyurl.com/2cv3v9e7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[20]&lt;a href=&quot;https://drewdevault.com/weird-guys/&quot;&gt; https://drewdevault.com/weird-guys/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;yarpp yarpp-related yarpp-related-rss yarpp-template-list&quot;&gt;

&lt;p&gt;Related posts:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2025/03/31/links-march-2025/&quot; rel=&quot;bookmark&quot; title=&quot;Links March 2025&quot;&gt;Links March 2025&lt;/a&gt; &lt;small&gt;Anarcat’s review of Fish is interesting and shows some benefits...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2026/02/17/links-february-2026/&quot; rel=&quot;bookmark&quot; title=&quot;Links February 2026&quot;&gt;Links February 2026&lt;/a&gt; &lt;small&gt;Charles Stross has a good theory of why “AI” is...&lt;/small&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://etbe.coker.com.au/2024/09/30/links-september-2024/&quot; rel=&quot;bookmark&quot; title=&quot;Links September 2024&quot;&gt;Links September 2024&lt;/a&gt; &lt;small&gt;CNA Insider has an insightful documentary series about Chinese illegal...&lt;/small&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Thu, 24 Sep 2026 10:33:22 +0000</pubDate>

</item> 
<item>
	<title>Mike Gabriel: Looking for Golang + Fullstack Developer with interest in Civic Tech</title>
	<guid>https://sunweavers.net/160 at https://sunweavers.net/blog</guid>
	<link>https://sunweavers.net/blog/node/160</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/sunweaver.png&quot; width=&quot;82&quot; height=&quot;82&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;h3&gt;Who?&lt;/h3&gt;

&lt;p&gt;Fre(i)e Software GmbH is looking for a senior Golang + fullstack developer who can handwrite code and act as meticulous code review partner for another senior developer in the company.&lt;/p&gt;

&lt;h3&gt;What?&lt;/h3&gt;

&lt;p&gt;Most of your work would result in Open Source contributions to the Voxit project [1], an online civic tech tool for digital participation.&lt;/p&gt;

&lt;h3&gt;How and Where?&lt;/h3&gt;

&lt;p&gt;The work can either be delivered on project agreement base via freelancing or via employment (option only available to developers resident in Germany, Austria or Poland).&lt;/p&gt;

&lt;h3&gt;What next?&lt;/h3&gt;

&lt;p&gt;If you are interested, please get in touch and provide your hourly rate to us and your average hours of availability per week.&lt;/p&gt;

&lt;p&gt;[1] &lt;a href=&quot;https://gitlab.com/voxit/&quot; title=&quot;https://gitlab.com/voxit/&quot;&gt;https://gitlab.com/voxit/&lt;/a&gt;&lt;/p&gt; </description> 
	<pubDate>Wed, 23 Sep 2026 20:16:37 +0000</pubDate>

</item> 
<item>
	<title>Reproducible Builds (diffoscope): diffoscope 330 released</title>
	<guid>https://diffoscope.org/news/diffoscope-330-released/</guid>
	<link>https://diffoscope.org/news/diffoscope-330-released/</link>
     <description>  &lt;p&gt;The diffoscope maintainers are pleased to announce the release of diffoscope
version &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;330&lt;/code&gt;. This version includes the following changes:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[ Chris Lamb ]
* Don&#39;t Build-Depend on apksigcopier as it has been removed from testing.
  (Closes: #1146852)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You find out more by &lt;a href=&quot;https://diffoscope.org&quot;&gt;visiting the project homepage&lt;/a&gt;.&lt;/p&gt; </description> 
	<pubDate>Mon, 21 Sep 2026 00:00:00 +0000</pubDate>

</item> 
<item>
	<title>Vincent Bernat: Bot-free self-hosted analytics with GoatCounter on NixOS</title>
	<guid>http://www.luffy.cx/en/blog/2026-goatcounter.html</guid>
	<link>https://vincent.bernat.ch/en/blog/2026-goatcounter</link>
     <description>  &lt;p&gt;In 2016, I &lt;a href=&quot;https://github.com/vincentbernat/vincent.bernat.ch/commit/4c3be65404031bf6638c1ea3d891a3ea58e0a0fc&quot; title=&quot;layout: remove Google Analytics&quot;&gt;removed Google Analytics&lt;/a&gt; from this blog to avoid being
complicit in feeding the biggest machine for harvesting personal data. Instead,
I relied on &lt;a href=&quot;https://goaccess.io/&quot; title=&quot;GoAccess: Visual Web Log Analyzer&quot;&gt;GoAccess&lt;/a&gt; to analyze my server logs.&lt;sup id=&quot;fnref:scrub&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:scrub&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; For the past couple
of years, the statistics have made no sense, despite my attempts to filter bots:
&lt;a href=&quot;https://herman.bearblog.dev/the-great-scrape/&quot; title=&quot;The Great Scrape&quot;&gt;AI scrapers&lt;/a&gt; inflate the number of visitors to around 2,000 per
day. Eventually, I settled on &lt;a href=&quot;https://www.goatcounter.com/&quot; title=&quot;GoatCounter: open source web analytics&quot;&gt;GoatCounter&lt;/a&gt;, an open-source, privacy-friendly
web analytics platform. I replaced the JavaScript client to filter bots more
aggressively and added a CSS fallback. To improve reliability, I implemented a
local proxy running on each of the five web servers serving this blog. The rest
of this post details how these pieces fit together and how I deploy them on
NixOS. ❄️&lt;/p&gt;
&lt;div class=&quot;toc&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#why-goatcounter&quot;&gt;Why GoatCounter?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#custom-javascript-client&quot;&gt;Custom JavaScript client&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#local-proxy&quot;&gt;Local proxy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#deploying-on-nixos&quot;&gt;Deploying on NixOS&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#deploying-applications-in-containers&quot;&gt;Deploying applications in containers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#goatcounter-server&quot;&gt;GoatCounter server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#goatcounter-proxy&quot;&gt;GoatCounter proxy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vincent.bernat.ch#backup-of-the-sqlite-database-with-litestream&quot;&gt;Backup of the SQLite database with Litestream&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h1 id=&quot;why-goatcounter&quot;&gt;Why GoatCounter?&lt;/h1&gt;
&lt;p&gt;GoatCounter does not &lt;a href=&quot;https://www.goatcounter.com/help/sessions#technical-details-11181&quot; title=&quot;GoatCounter documentation: sessions&quot;&gt;collect personal data&lt;/a&gt;: instead of storing the reader’s
IP address or relying on cookies, it creates a session identifier valid for 8
hours from the user agent and the IP address. Its feature set is modest but
sufficient for a blog. If you want to look at the interface, GoatCounter’s
author runs a &lt;a href=&quot;https://stats.arp242.net&quot; title=&quot;Analytics for www.arp242.net&quot;&gt;public instance&lt;/a&gt; for &lt;a href=&quot;https://www.arp242.net&quot; title=&quot;Personal website of Martin Tournoij&quot;&gt;his site&lt;/a&gt;. A hosted
version lets you try it before running your own instance. With a single binary
and an SQLite database, GoatCounter is one of the lightest self-hosted
solutions. Privacy-friendly alternatives, in increasing order of complexity,
include &lt;a href=&quot;https://umami.is/&quot; title=&quot;Umami: Privacy-First Analytics Platform&quot;&gt;Umami&lt;/a&gt;, &lt;a href=&quot;https://plausible.io/&quot; title=&quot;Plausible Analytics: Simple, privacy-friendly Google Analytics alternative&quot;&gt;Plausible&lt;/a&gt;, and &lt;a href=&quot;https://rybbit.com/&quot; title=&quot;Rybbit: Cookieless Google Analytics Replacement&quot;&gt;Rybbit&lt;/a&gt;.&lt;/p&gt;
&lt;figure class=&quot;lf-fullbleed&quot;&gt;&lt;div class=&quot;lf-media-outer&quot; style=&quot;width: 889px;&quot;&gt;&lt;span class=&quot;lf-media-inner&quot;&gt;&lt;img alt=&quot;GoatCounter dashboard showing some statistics from my blog, including an article on the spanning tree protocol with 1,224 views for the past week, the referrers, and the breakdown of browsers (52% Chrome, 32% Firefox, with 16% for Firefox 155 and 6% for Firefox 156)&quot; class=&quot;lf-media lf-opaque&quot; height=&quot;861&quot; src=&quot;https://media-bernat-ch.b-cdn.net/images/goatcounter@1x.a055a7216208d0.png&quot; width=&quot;889&quot; /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/figure&gt;
&lt;h1 id=&quot;custom-javascript-client&quot;&gt;Custom JavaScript client&lt;/h1&gt;
&lt;p&gt;GoatCounter includes a &lt;a href=&quot;https://github.com/arp242/goatcounter/blob/main/public/count.js&quot; title=&quot;GoatCounter&#39;s JavaScript client&quot;&gt;small JavaScript client&lt;/a&gt;—2,189 bytes minified and
gzipped. It ships some features I don’t use: a visitor counter, tracking clicks,
configurable settings, etc. I replace it with this function to register a hit:&lt;/p&gt;
&lt;div class=&quot;language-javascript codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{})&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ow&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;URLSearchParams&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pathname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;referrer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;documentElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clientWidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!!&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rnd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Math&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;36&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`/count?&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keepalive&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}).&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To filter bots,&lt;sup id=&quot;fnref:bot-filter&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:bot-filter&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; I go the extra mile by requiring a user
interaction—an idea I stole from &lt;a href=&quot;https://bearblog.dev/&quot; title=&quot;Bear Blog&quot;&gt;Bear Blog&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;language-javascript codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sendHit&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sendHit&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;touchmove&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;mousemove&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;keydown&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;pointerdown&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;eventName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;eventName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sendHit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;once&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;passive&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}),&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If a reader has disabled JavaScript in their browser, I record the hit using a
CSS image. The &lt;code&gt;:hover&lt;/code&gt; pseudo-class loads it only after an interaction, another
trick &lt;a href=&quot;https://herman.bearblog.dev/how-bear-does-analytics-with-css/&quot; title=&quot;How Bear does analytics with CSS&quot;&gt;stolen from Bear Blog&lt;/a&gt;. About 2% of my visitors fit into this
bucket.&lt;sup id=&quot;fnref:referrer&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:referrer&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-html codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;en&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nojs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// The JavaScript code for this blog requires ES6&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;noModule&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;HTMLScriptElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;documentElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;nojs&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;cm&quot;&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;nojs&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;hover&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;border-width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;border-image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&#39;/count?p=/en/blog/2026-kpi-goodhart&amp;amp;t=Building...&amp;amp;r=NoJS&amp;amp;e=false&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Where GoAccess reported around 2,000 visitors a day, GoatCounter counts fewer
than 200 humans.&lt;sup id=&quot;fnref:rss&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:rss&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; I assume AI scrapers use a low-effort approach: if the
content is available without barriers, as on this blog, they don’t spawn a
complex mechanized browser that could trigger a page view. Even crawlers running
JavaScript, like &lt;a href=&quot;https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics&quot; title=&quot;Google Search Central: Understand the JavaScript SEO basics&quot;&gt;Googlebot with its headless Chromium&lt;/a&gt;, &lt;a href=&quot;https://developers.google.com/search/docs/crawling-indexing/javascript/lazy-loading#:~:text=Google%20Search%20does%20not%20interact%20with%20your%20page&quot; title=&quot;Google Search Central: Fix lazy-loaded content&quot;&gt;do not
interact with the page&lt;/a&gt; and never trigger the events I listen
to. The interaction-based “proof of humanity” I use is likely to keep
working.&lt;sup id=&quot;fnref:css-test&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:css-test&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;h1 id=&quot;local-proxy&quot;&gt;Local proxy&lt;/h1&gt;
&lt;p&gt;Five servers &lt;del&gt;across the world&lt;/del&gt; &lt;ins&gt;in Europe and in North
America&lt;/ins&gt; serve the content of this website, but GoatCounter runs on only
one of them. To avoid losing track of visitors when GoatCounter is down, I run a
local proxy listening on the same &lt;code&gt;/count&lt;/code&gt; endpoint. On each server, it stores
the hits in memory with a buffer large enough to survive several days of
downtime. It sends them in batches to the upstream backend using the
&lt;a href=&quot;https://www.goatcounter.com/help/api&quot; title=&quot;GoatCounter documentation: API&quot;&gt;&lt;code&gt;/api/v0/count&lt;/code&gt; authenticated endpoint&lt;/a&gt;.&lt;/p&gt;
&lt;figure class=&quot;lf-fullbleed&quot;&gt;&lt;div class=&quot;lf-media-outer&quot; style=&quot;width: 836px;&quot;&gt;&lt;span class=&quot;lf-media-inner&quot;&gt;&amp;amp;#128444; Servers on a map. web02 is in Paris, web03 in Helsinki, web04 in Nuremberg,
web05 in Ashburn, web06 in Chicago.&lt;/span&gt;&lt;/div&gt;&lt;/figure&gt;
&lt;p&gt;I proposed the code for the proxy in &lt;a href=&quot;https://github.com/arp242/goatcounter/pull/909&quot; title=&quot;PR #909: add a proxy to forward page counts&quot;&gt;pull request #909&lt;/a&gt;. GoatCounter’s
maintainer declined to maintain so much code for such a niche use case. As a
fellow open-source developer, I often hold the same position for my own
projects: a one-time contributor effort may translate into a long-term
maintainer commitment.&lt;/p&gt;
&lt;p&gt;I expose the endpoint for the proxy on the domain of this website to evade ad
blockers. This sounds like I don’t respect the reader’s choice, but as
GoatCounter is privacy-friendly, I find it acceptable.&lt;/p&gt;
&lt;div class=&quot;language-nginx-configuration-file codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;location&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/count&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;access_log&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;proxy_pass&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;http://127.0.0.3:8087/count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;proxy_pass_request_headers&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;no&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Accept-Language&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$http_accept_language&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;User-Agent&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$http_user_agent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;proxy_set_header&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;X-Real-Ip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$remote_addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h1 id=&quot;deploying-on-nixos&quot;&gt;Deploying on NixOS&lt;/h1&gt;
&lt;p&gt;My web servers run &lt;a href=&quot;https://nixos.org/&quot; title=&quot;Nix &amp;amp; NixOS: Declarative builds and deployments&quot;&gt;NixOS&lt;/a&gt;, a declarative Linux distribution with built-in
configuration management. I manage this small fleet with &lt;a href=&quot;https://colmena.cli.rs/&quot; title=&quot;Colmena documentation&quot;&gt;Colmena&lt;/a&gt;, a
stateless deployment tool for NixOS. My configuration is available on
&lt;a href=&quot;https://github.com/vincentbernat/nixops-take1/&quot; title=&quot;vincentbernat/nixops-take1: Playground for NixOps&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;deploying-applications-in-containers&quot;&gt;Deploying applications in containers&lt;/h2&gt;
&lt;p&gt;For better isolation, each application runs inside an ephemeral lightweight
container, powered by &lt;a href=&quot;https://manpages.debian.org/systemd-nspawn.1.html&quot; title=&quot;Manual page for systemd-nspawn(1)&quot;&gt;systemd-nspawn&lt;/a&gt;. Each container runs a stripped-down
NixOS instance. A &lt;a href=&quot;https://github.com/vincentbernat/nixops-take1/blob/master/modules/container.nix&quot; title=&quot;nixops-take1/modules/container.nix&quot;&gt;module wraps NixOS’s &lt;code&gt;containers&lt;/code&gt; options&lt;/a&gt; to
avoid repeating the same options for each application.&lt;sup id=&quot;fnref:module&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:module&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; The containers
share their network namespace with the host: the additional isolation is not
worth the increased complexity. For a smaller footprint, I also disable a few
non-essential services.&lt;/p&gt;
&lt;div class=&quot;language-nix codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; config&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; lib&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;cfg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;containers&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# User-configurable settings for our custom module&lt;/span&gt;
  options&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;containers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mkOption &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Ephemeral containers sharing the host network.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;types&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;attrsOf &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;types&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;submodule &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mkOption &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;types&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;deferredModule&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;NixOS configuration of the container.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;# Translate our options to NixOS containers&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;containers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mapAttrs
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; container&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;ss&quot;&gt;ephemeral&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&quot;ss&quot;&gt;autoStart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;ss&quot;&gt;privateNetwork&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&quot;ss&quot;&gt;extraFlags&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;--resolv-conf=replace-host&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;          &lt;span class=&quot;ss&quot;&gt;imports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; container&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;config &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/span&gt;          networking&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;firewall&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;enable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          system&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;stateVersion&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;system&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;stateVersion&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          systemd&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;services&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;            console-getty&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;enable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;            systemd-logind&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;enable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;            systemd-oomd&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;enable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;          &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
      cfg&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To configure a GoatCounter instance running in a container and listening on
&lt;code&gt;127.0.0.4:8088&lt;/code&gt;, we import the module&lt;sup id=&quot;fnref:import&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:import&quot;&gt;7&lt;/a&gt;&lt;/sup&gt; and declare the container in the
&lt;code&gt;config.luffy.containers&lt;/code&gt; attribute set:&lt;/p&gt;
&lt;div class=&quot;language-nix codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; pkgs&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; config&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;imports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;l&quot;&gt;./modules/container.nix&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
  config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;containers&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;goatcounter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      services&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;goatcounter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;enable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;127.0.0.4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8088&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;proxy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As the containers are ephemeral, we need to keep persistent data in directories
on the host. We add a &lt;code&gt;mounts&lt;/code&gt; option and ask NixOS’s containers to expose the
configured directories through the &lt;code&gt;bindMounts&lt;/code&gt; option.&lt;/p&gt;
&lt;div class=&quot;language-nix codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; config&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; lib&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;cfg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;containers&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  options&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;containers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mkOption &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;types&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;attrsOf &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;types&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;submodule &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;mounts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mkOption &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;types&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;listOf lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;types&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;str&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Host directories mounted read-write at the same place.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;containers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mapAttrs
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; container&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;bindMounts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
          lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;genAttrs container&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mounts &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;hostPath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; path&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;isReadOnly&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
      cfg&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For example, to persist GoatCounter’s database in the &lt;code&gt;/var/db/goatcounter&lt;/code&gt;
directory on the host, we add the directory to the &lt;code&gt;mounts&lt;/code&gt; option and alter the
service definition to tell GoatCounter where the database is.&lt;/p&gt;
&lt;div class=&quot;language-nix codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; config&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;databaseDirectory&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/var/db/goatcounter&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;containers&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;goatcounter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;mounts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; databaseDirectory &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      services&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;goatcounter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;extraArgs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;-db=sqlite+&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;databaseDirectory&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/db.sqlite&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A container may also need some secrets. Colmena can &lt;a href=&quot;https://colmena.cli.rs/unstable/features/keys.html&quot; title=&quot;Colmena documentation: Secrets&quot;&gt;upload secrets&lt;/a&gt; without
storing them in the Nix store. We add a &lt;code&gt;keys&lt;/code&gt; option to our containers. It
takes an attribute set mapping secret names to the commands to populate them.
Then, the module declares the required secrets to Colmena in the
&lt;code&gt;deployment.keys&lt;/code&gt; option, makes the container depend on the presence of the
secrets, and exposes them to the container.&lt;/p&gt;
&lt;div class=&quot;language-nix codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; config&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; lib&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;cfg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;containers&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  options&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;containers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mkOption &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;types&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;attrsOf &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;types&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;submodule &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;options&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mkOption &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;types&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;attrsOf &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;types&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;listOf lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;types&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;str&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Secrets, as a command to run locally. They are mounted in /etc.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

  &lt;span class=&quot;ss&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Colmena uploads each secret in `/var/keys` and make them available&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# to the group &quot;keys&quot;.&lt;/span&gt;
    deployment&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;concatMapAttrs
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;_&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; container&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mapAttrs
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;_&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; keyCommand&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;inherit&lt;/span&gt; keyCommand&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;keys&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;permissions&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;0640&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;destDir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/var/keys&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
        container&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      cfg&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# The container can only start if the required secrets are available.&lt;/span&gt;
    systemd&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;services&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mapAttrs&#39;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; container&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;units&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;key&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;-key.service&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;attrNames container&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
        lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;nameValuePair &lt;span class=&quot;s2&quot;&gt;&quot;container@&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;name&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;requires&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; units&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;after&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; units&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
      cfg&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Mount each secret inside the container.&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;containers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mapAttrs
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; container&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;bindMounts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mapAttrs&#39;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; _&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;nameValuePair &lt;span class=&quot;s2&quot;&gt;&quot;/etc/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;key&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;ss&quot;&gt;hostPath&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/var/keys/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;key&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;ss&quot;&gt;isReadOnly&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
          container&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;keys&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
      cfg&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For example, GoatCounter needs credentials to download the GeoIP database. I
provide a local command to fetch the secret from my password manager and expose
it inside the container through the &lt;code&gt;/etc/goatcounter.env&lt;/code&gt; environment file.&lt;/p&gt;
&lt;div class=&quot;language-nix codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; pkgs&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; config&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt; 
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;keyCommand&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; variable&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;pkgs&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;runtimeShell&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;-c&quot;&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&quot;pass show personal/nixops/secrets | grep &#39;^&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;variable&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;=&#39;&quot;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;containers&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;goatcounter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    keys&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;goatcounter.env&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; keyCommand &lt;span class=&quot;s2&quot;&gt;&quot;GOATCOUNTER_GEODB&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;ss&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      systemd&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;services&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;goatcounter&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;serviceConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;EnvironmentFile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/etc/goatcounter.env&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;SupplementaryGroups&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;keys&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;goatcounter-server&quot;&gt;GoatCounter server&lt;/h2&gt;
&lt;p&gt;Nixpkgs already packages GoatCounter. By overriding the &lt;code&gt;src&lt;/code&gt; and &lt;code&gt;vendorHash&lt;/code&gt;
attributes, I reuse its definition for my custom version with the proxy:&lt;/p&gt;
&lt;div class=&quot;language-nix codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; goatcounter&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; fetchFromGitHub &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt;
goatcounter&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;overrideAttrs &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;_&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; fetchFromGitHub &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;owner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;vincentbernat&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;repo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;goatcounter&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;rev&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;feature/proxy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;hash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;sha256-dJRlQlFu3tjcEgabT1LEbyFrasJlhmYu4L/T7EkoNcY=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;vendorHash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;sha256-c9Q5OrbZR+q6pD3SgPPWe8JUzcZco1AVUKGaV61k5DE=&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I wrote a &lt;a href=&quot;https://github.com/vincentbernat/nixops-take1/blob/master/modules/goatcounter.nix&quot; title=&quot;nixops-take1/modules/goatcounter.nix&quot;&gt;NixOS module&lt;/a&gt; to encapsulate GoatCounter: the
container definition, the service definition, and the secrets. The module
accepts the following options: &lt;code&gt;package&lt;/code&gt;, &lt;code&gt;serve.enable&lt;/code&gt;, &lt;code&gt;serve.listenAddress&lt;/code&gt;,
&lt;code&gt;serve.port&lt;/code&gt;, and &lt;code&gt;serve.databaseFile&lt;/code&gt;. I already detailed the container
configuration in the previous section. In the end, I chose not to reuse the
GoatCounter module from NixOS: it’s small, so it’s better to insulate my module
from unexpected future changes.&lt;/p&gt;
&lt;div class=&quot;language-nix codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; config&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; pkgs&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; lib&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;cfg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;goatcounter&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;databaseDirectory&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;builtins&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dirOf&lt;/span&gt; cfg&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;serve&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;databaseFile&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;chown&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;pkgs&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;coreutils&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/bin/chown -R&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;containers&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;goatcounter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;systemd&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;services&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;goatcounter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;GoatCounter Web Analytics&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;wantedBy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;multi-user.target&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;serviceConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;EnvironmentFile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/etc/goatcounter.env&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;SupplementaryGroups&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;keys&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;DynamicUser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;Restart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;always&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;ExecStart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;escapeShellArgs &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;getExe cfg&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;package&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;s2&quot;&gt;&quot;serve&quot;&lt;/span&gt;
          &lt;span class=&quot;s2&quot;&gt;&quot;-listen=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;cfg&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;serve&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;listenAddress&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;toString&lt;/span&gt; cfg&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;serve&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
          &lt;span class=&quot;s2&quot;&gt;&quot;-tls=none&quot;&lt;/span&gt;
          &lt;span class=&quot;s2&quot;&gt;&quot;-db=sqlite+&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;cfg&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;serve&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;databaseFile&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
          &lt;span class=&quot;s2&quot;&gt;&quot;-automigrate&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Transfer database ownership to dynamically assigned user &quot;goatcounter&quot;.&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;ExecStartPre&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;+&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;chown&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; goatcounter:goatcounter &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;databaseDirectory&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;ReadWritePaths&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; databaseDirectory&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The following snippet configures GoatCounter to listen on &lt;code&gt;127.0.0.4:8088&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;language-nix codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;goatcounter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;serve&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;enable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;listenAddress&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;127.0.0.4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8088&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The last step is to configure nginx to expose GoatCounter on the Internet. I
disable the &lt;code&gt;/count&lt;/code&gt; endpoint as the local proxy handles it.&lt;/p&gt;
&lt;div class=&quot;language-nix codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; config&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;cfg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;goatcounter&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;serve&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  services&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;nginx&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;virtualHosts&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;goatcounter.luffy.cx&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;forceSSL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;locations&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;/&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;proxyPass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;http://&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;cfg&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;listenAddress&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;toString&lt;/span&gt; cfg&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
      &lt;span class=&quot;s2&quot;&gt;&quot;= /count&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;extraConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s s-Multiline&quot;&gt;&#39;&#39;&lt;/span&gt;
&lt;span class=&quot;s s-Multiline&quot;&gt;        return 404;&lt;/span&gt;
&lt;span class=&quot;s s-Multiline&quot;&gt;      &#39;&#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;goatcounter-proxy&quot;&gt;GoatCounter proxy&lt;/h2&gt;
&lt;p&gt;The same &lt;a href=&quot;https://github.com/vincentbernat/nixops-take1/blob/master/modules/goatcounter.nix&quot; title=&quot;nixops-take1/modules/goatcounter.nix&quot;&gt;NixOS module&lt;/a&gt; configures the local proxy, with the
following options: &lt;code&gt;proxy.enable&lt;/code&gt;, &lt;code&gt;proxy.listenAddress&lt;/code&gt;, &lt;code&gt;proxy.port&lt;/code&gt;, and
&lt;code&gt;proxy.site&lt;/code&gt;—the site receiving the batches of page views. The local proxy has
no persistent data, but it needs the API key to authenticate to the main
GoatCounter instance: its container uses the &lt;code&gt;keys&lt;/code&gt; option but not the &lt;code&gt;mounts&lt;/code&gt;
option.&lt;/p&gt;
&lt;div class=&quot;language-nix codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; config&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; pkgs&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; lib&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;cfg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;goatcounter&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;keyCommand&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; _&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;…&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;containers&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;goatcounter-proxy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    keys&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;goatcounter-proxy.env&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; keyCommand &lt;span class=&quot;s2&quot;&gt;&quot;GOATCOUNTER_API_KEY&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;    config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;systemd&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;services&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;goatcounter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;GoatCounter Proxy.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;wantedBy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;multi-user.target&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;serviceConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;EnvironmentFile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/etc/goatcounter-proxy.env&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;SupplementaryGroups&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;keys&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;DynamicUser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;Restart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;always&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;ExecStart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;escapeShellArgs &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;getExe cfg&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;package&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;s2&quot;&gt;&quot;proxy&quot;&lt;/span&gt;
          &lt;span class=&quot;s2&quot;&gt;&quot;-site=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;cfg&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;proxy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;site&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
          &lt;span class=&quot;s2&quot;&gt;&quot;-listen=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;cfg&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;proxy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;listenAddress&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;toString&lt;/span&gt; cfg&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;proxy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;port&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
          &lt;span class=&quot;s2&quot;&gt;&quot;-ratelimit=10/1&quot;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 10 requests per second per IP&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For each server, I enable the local proxy with the following snippet. The
nginx configuration shown earlier exposes the &lt;code&gt;/count&lt;/code&gt; endpoint under the same
domain as my blog.&lt;/p&gt;
&lt;div class=&quot;language-nix codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;goatcounter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;proxy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;enable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;site&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;goatcounter.luffy.cx&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;listenAddress&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;127.0.0.3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8087&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;backup-of-the-sqlite-database-with-litestream&quot;&gt;Backup of the SQLite database with Litestream&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://litestream.io/&quot; title=&quot;Litestream: Streaming SQLite Replication&quot;&gt;Litestream&lt;/a&gt; is a streaming replication tool for SQLite databases. It
compresses the changes committed to the write-ahead log (&lt;abbr title=&quot;Write-ahead log&quot;&gt;WAL&lt;/abbr&gt;) next to the
database and sends them to a remote destination. I encapsulate its configuration
in a &lt;a href=&quot;https://github.com/vincentbernat/nixops-take1/blob/master/modules/litestream.nix&quot; title=&quot;nixops-take1/modules/litestream.nix&quot;&gt;NixOS module&lt;/a&gt;, which takes an attribute set &lt;code&gt;databases&lt;/code&gt;
mapping a name to the path of the database to back up.&lt;/p&gt;
&lt;p&gt;Litestream also runs in a container. I mount the databases to replicate, as well
as the secrets to push the backups to a &lt;a href=&quot;https://www.hetzner.com/storage/storage-box/&quot; title=&quot;Hetzner Storage Box&quot;&gt;Hetzner storage box&lt;/a&gt; using &lt;abbr title=&quot;Secure File Transfer Protocol&quot;&gt;SFTP&lt;/abbr&gt;:&lt;/p&gt;
&lt;div class=&quot;language-nix codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; config&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; pkgs&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; lib&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;cfg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;litestream&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;databaseDirs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;unique &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;builtins&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dirOf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;builtins&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;attrValues cfg&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;databases&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mkIf &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;cfg&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;databases &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;containers&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;litestream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;mounts&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; databaseDirs&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      keys&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;litestream.env&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;pkgs&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;runtimeShell&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;-c&quot;&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&quot;pass show personal/nixops/secrets | grep &#39;^SQLITE_BACKUP_&#39;&quot;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Inside the container, I configure Litestream through NixOS’s
&lt;code&gt;services.litestream&lt;/code&gt; options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;full snapshots every day, kept for 15 days,&lt;/li&gt;
&lt;li&gt;three &lt;a href=&quot;https://fly.io/blog/litestream-v050-is-here/&quot; title=&quot;Litestream v0.5.0 is Here&quot;&gt;levels of compaction&lt;/a&gt; for transaction files: 5 minutes, 30 minutes, and 3 hours,&lt;/li&gt;
&lt;li&gt;auto-recovery,&lt;sup id=&quot;fnref:auto-recover&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:auto-recover&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;replica stored in a directory matching the host name, and&lt;/li&gt;
&lt;li&gt;credentials read from &lt;code&gt;/etc/litestream.env&lt;/code&gt; and exposed through variable expansion.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;language-nix codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; config&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; pkgs&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; lib&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;cfg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;litestream&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;containers&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;litestream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;ss&quot;&gt;config&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# The databases belong to dynamically allocated users, whose UID is&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# not known here, so Litestream runs as root.&lt;/span&gt;
      systemd&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;services&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;litestream&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;serviceConfig&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mkForce &lt;span class=&quot;s2&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;Group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mkForce &lt;span class=&quot;s2&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# Use NixOS service.&lt;/span&gt;
      services&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;litestream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;enable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;environmentFile&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;/etc/litestream.env&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;ss&quot;&gt;settings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;auto-recover&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;snapshot&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;ss&quot;&gt;interval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;24h&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;ss&quot;&gt;retention&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;360h&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;levels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;interval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;5m&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;interval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;30m&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;interval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;3h&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
          &lt;span class=&quot;ss&quot;&gt;dbs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; lib&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;mapAttrsToList
            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; path&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
              &lt;span class=&quot;k&quot;&gt;inherit&lt;/span&gt; path&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
              &lt;span class=&quot;ss&quot;&gt;replica&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;ss&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;sftp&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;ss&quot;&gt;host&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;{SQLITE_BACKUP_HOST}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;ss&quot;&gt;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;{SQLITE_BACKUP_USER}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;ss&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;{SQLITE_BACKUP_PASSWORD}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;ss&quot;&gt;host-key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\$&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;{SQLITE_BACKUP_HOSTKEY}&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;ss&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;networking&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;hostName&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;name&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
            cfg&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;databases&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To back up GoatCounter’s database, I declare a &lt;code&gt;goatcounter&lt;/code&gt; attribute in
&lt;code&gt;luffy.litestream.databases&lt;/code&gt;, set to the database path:&lt;/p&gt;
&lt;div class=&quot;language-nix codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; config&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt;
  &lt;span class=&quot;ss&quot;&gt;cfg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; config&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;goatcounter&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;serve&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  luffy&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;litestream&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;databases&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;goatcounter&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; cfg&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;databaseFile&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On the &lt;abbr title=&quot;Secure File Transfer Protocol&quot;&gt;SFTP&lt;/abbr&gt; server, we can inspect Litestream’s work, with the compacted
transactions and the full snapshots:&lt;/p&gt;
&lt;div class=&quot;language-bash-session codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;❯ &lt;/span&gt;ls&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;web02/goatcounter/ltx
&lt;span class=&quot;go&quot;&gt;web02/goatcounter/ltx/0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;web02/goatcounter/ltx/1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;web02/goatcounter/ltx/2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;web02/goatcounter/ltx/3&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;web02/goatcounter/ltx/9&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;❯ &lt;/span&gt;ls&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-lh&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;web02/goatcounter/ltx/1
&lt;span class=&quot;go&quot;&gt;29.1K Sep  5 01:25 0000000000003f2a-0000000000003f2b.ltx&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;72.4K Sep  5 02:03 0000000000003f2c-0000000000003f2d.ltx&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;63.3K Sep  5 02:24 0000000000003f2e-0000000000003f2f.ltx&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[…]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;❯ &lt;/span&gt;ls&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-lh&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;web02/goatcounter/ltx/9
&lt;span class=&quot;go&quot;&gt; 8.5M Sep  5 02:00 0000000000000001-0000000000003f2b.ltx&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; 8.5M Sep  6 02:03 0000000000000001-0000000000004008.ltx&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; 8.6M Sep  7 02:03 0000000000000001-00000000000043a8.ltx&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[…]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We can restore the database from the backup with a few shell commands. First, we
stop the containers. Then, we move the damaged database away, invoke &lt;code&gt;litestream
restore&lt;/code&gt; from the right environment, and restart the containers.&lt;sup id=&quot;fnref:slow&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://vincent.bernat.ch#fn:slow&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;div class=&quot;language-bash-session codehilite&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;# &lt;/span&gt;systemctl&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;stop&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;container@goatcounter&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;container@litestream
&lt;span class=&quot;gp&quot;&gt;# &lt;/span&gt;mv&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/var/db/goatcounter/db.sqlite&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;,.old&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;# &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;.&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/etc/nixos-containers/litestream.conf&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-a&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;.&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/var/keys/litestream.env&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;+a&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SYSTEM_PATH&lt;/span&gt;/sw/bin/litestream&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;w&quot;&gt;    &lt;/span&gt;restore&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-config&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$SYSTEM_PATH&lt;/span&gt;/etc/litestream.yml&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/var/db/goatcounter/db.sqlite&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;# &lt;/span&gt;ls&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;-lh&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;/var/db/goatcounter/db.sqlite
&lt;span class=&quot;go&quot;&gt;-rw-r--r-- 1 root root 20M Sep 20 07:33 /var/db/goatcounter/db.sqlite&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;# &lt;/span&gt;systemctl&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;start&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;container@goatcounter&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;container@litestream
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;hr /&gt;
&lt;p&gt;Ten years after &lt;a href=&quot;https://vincent.bernat.ch/en/blog/2018-more-privacy-blog&quot; title=&quot;A more privacy-friendly blog&quot;&gt;removing Google Analytics&lt;/a&gt;, JavaScript-based analytics is
back on this blog, but without storing cookies or IP addresses, and without
involving a third party. I still write for myself first, notably because it lets
me dig into a topic and refer back to it years later. But knowing a bit more
about my fellow human readers is a nice bonus, even the ones disabling
JavaScript. 🐐&lt;/p&gt;
&lt;div class=&quot;footnote&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn:scrub&quot;&gt;
&lt;p&gt;Nginx scrambles IP addresses before storing them, thanks to the &lt;a href=&quot;https://github.com/masonicboom/ipscrub&quot; title=&quot;ipscrub: IP address anonymizer module for nginx&quot;&gt;&lt;code&gt;ipscrub&lt;/code&gt;
nginx module&lt;/a&gt;. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:scrub&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:bot-filter&quot;&gt;
&lt;p&gt;GoatCounter already filters some bots based on the user agent or the IP
address. But AI scrapers lie about their user agent and hide behind
&lt;a href=&quot;https://jacob.gold/posts/residential-proxies-are-a-national-security-threat/&quot; title=&quot;Residential Proxies Are a National Security Threat&quot;&gt;residential proxies&lt;/a&gt;. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:bot-filter&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:referrer&quot;&gt;
&lt;p&gt;Without JavaScript, I cannot send the real referrer. I insert “NoJS”
instead. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:referrer&quot; title=&quot;Jump back to footnote 3 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:rss&quot;&gt;
&lt;p&gt;I am missing the humans reading the RSS feed. I am not comfortable adding a
&lt;a href=&quot;https://www.goatcounter.com/help/pixel&quot; title=&quot;GoatCounter documentation: tracking pixel without JavaScript&quot;&gt;tracking pixel&lt;/a&gt;, and bots are likely to fetch it, compromising the
statistics. I’ll live without counting these readers. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:rss&quot; title=&quot;Jump back to footnote 4 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:css-test&quot;&gt;
&lt;p&gt;In February 2025, I tested another CSS-only approach without the interaction
trick: each page loaded an empty image as a background. Over a month, it
recorded up to ten times fewer page views than the nginx logs, even after
removing user agents identifying as bots. Compared to this experiment,
GoatCounter counts about three times fewer views, 18 months later. As the
time ranges differ, this is not an apples-to-apples comparison, but it gives
a hint about how efficient bot filtering is. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:css-test&quot; title=&quot;Jump back to footnote 5 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:module&quot;&gt;
&lt;p&gt;A &lt;a href=&quot;https://nixos.org/manual/nixos/stable/#sec-writing-modules&quot; title=&quot;NixOS Manual: Writing NixOS Modules&quot;&gt;NixOS module&lt;/a&gt; is a function receiving the configuration of the whole
system as &lt;code&gt;config&lt;/code&gt; and returning three attributes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;imports&lt;/code&gt; adds other modules to import,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;options&lt;/code&gt; declares user-configurable settings, each with a type and a default value, and&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config&lt;/code&gt; sets values for options declared by any module, like &lt;code&gt;containers&lt;/code&gt; from NixOS.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If a module does not need to declare options, you can return the &lt;code&gt;config&lt;/code&gt; attribute
set directly. When a module does not require any argument, you can define it as an attribute
set instead. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:module&quot; title=&quot;Jump back to footnote 6 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:import&quot;&gt;
&lt;p&gt;Most of the time, you don’t need an explicit import. NixOS &lt;a href=&quot;https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/module-list.nix&quot; title=&quot;nixpkgs/nixos/modules/module-list.nix&quot;&gt;automatically
imports&lt;/a&gt; the modules shipped with Nixpkgs. For my own
modules, &lt;a href=&quot;https://github.com/vincentbernat/nixops-take1/blob/master/modules/default.nix&quot; title=&quot;nixops-take1/modules/default.nix&quot;&gt;some machinery&lt;/a&gt; also imports them automatically. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:import&quot; title=&quot;Jump back to footnote 7 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:auto-recover&quot;&gt;
&lt;p&gt;Litestream &lt;a href=&quot;https://litestream.io/reference/config/#auto-recover&quot; title=&quot;Litestream: auto-recover option&quot;&gt;warns against using the &lt;code&gt;auto-recover&lt;/code&gt; option&lt;/a&gt; as
it can cause data loss. But I don’t properly monitor my servers and I prefer
uninterrupted backups to a slight chance of losing the last few records. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:auto-recover&quot; title=&quot;Jump back to footnote 8 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:slow&quot;&gt;
&lt;p&gt;In my case, the process is slow: around 20 minutes for a 20 MiB database.
You can test by restoring to a copy with the &lt;code&gt;-o&lt;/code&gt; option, but you still need
to stop the Litestream container. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://vincent.bernat.ch#fnref:slow&quot; title=&quot;Jump back to footnote 9 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Sun, 20 Sep 2026 19:44:50 +0000</pubDate>

</item> 
<item>
	<title>Andrew Cater: Debian 11 is at end of life from Long Term Support</title>
	<guid>tag:blogger.com,1999:blog-8085113335874848981.post-6303472353413203122</guid>
	<link>http://flosslinuxblog.blogspot.com/2026/09/debian-11-is-at-end-of-life-from-long.html</link>
     <description>  &lt;p&gt; Lots of posts in the debian-user mailing list complaining about updates with Debian 11.11 suddenly failing.&lt;br /&gt;&lt;br /&gt;See&lt;a href=&quot;https://www.debian.org/News/2026/20260831?=0&quot;&gt; Debian 11 Long Term Support reaches end-of-life&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;August 31st, 2026&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;
The Debian Long Term Support (LTS) Team hereby announces that Debian 11
&lt;q&gt;bullseye&lt;/q&gt; support has reached its end-of-life today, 31 August 2026,
five years after its initial release on 14 August 2021.
&lt;/p&gt;
&lt;p&gt;
Starting in September, Debian will not provide further security updates for
Debian 11. A subset of &lt;q&gt;bullseye&lt;/q&gt; packages will be supported by external
parties. Detailed information can be found at
&lt;a href=&quot;https://wiki.debian.org/LTS/Extended&quot;&gt; Extended LTS&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
The Debian LTS Team is currently providing security support for Debian 12
&lt;q&gt;bookworm&lt;/q&gt;, the current oldstable release. Thanks to the combined efforts
of different teams including the Security Team, the Release Team, and the LTS
Team, the Debian 12 life cycle encompasses five years.
Debian 12 will receive Long Term Support until 30 June 2028. The supported
architectures in Debian 12 LTS are amd64, i386, arm64, armhf and ppc64el.
&lt;/p&gt;
&lt;p&gt;
For further information about using &lt;q&gt;bookworm&lt;/q&gt; LTS and upgrading from
&lt;q&gt;bullseye&lt;/q&gt; LTS, please refer to
&lt;a href=&quot;https://wiki.debian.org/LTS/Using&quot;&gt;LTS/Using&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Debian and its LTS Team would like to thank all contributing users, developers,
sponsors and other Debian teams who are making it possible to extend the life
of previous stable releases, and who have made Bullseye LTS a success.
&lt;/p&gt;
&lt;p&gt;
If you rely on Debian LTS, please consider
&lt;a href=&quot;https://wiki.debian.org/LTS/Development&quot;&gt;joining the team&lt;/a&gt;,
providing patches, testing or
&lt;a href=&quot;https://wiki.debian.org/LTS/Funding&quot;&gt;funding the efforts&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt; &lt;/p&gt; </description> 
	<pubDate>Sun, 20 Sep 2026 15:04:40 +0000</pubDate>
  <author>noreply@blogger.com (Andrew Cater)</author>  
</item> 
<item>
	<title>Ludovic Rousseau: New version of libccid: 1.8.4</title>
	<guid>https://blog.apdu.fr/posts/2026/09/new-version-of-libccid-184/</guid>
	<link>https://blog.apdu.fr/posts/2026/09/new-version-of-libccid-184/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/rousseau.png&quot; width=&quot;65&quot; height=&quot;95&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;I have just released &lt;a class=&quot;reference external&quot; href=&quot;https://ccid.apdu.fr/files/&quot;&gt;version 1.8.4&lt;/a&gt; of
&lt;a class=&quot;reference external&quot; href=&quot;https://ccid.apdu.fr/&quot;&gt;libccid&lt;/a&gt; the Free Software CCID class smart
card reader driver.&lt;/p&gt;
&lt;section id=&quot;changes&quot;&gt;
&lt;h2&gt;Changes:&lt;/h2&gt;
&lt;p&gt;1.8.4 - 20 September 2026, Ludovic Rousseau&lt;/p&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;&lt;p&gt;Add support of&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;THALES PKI Transaction Pad&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;fix some minor issues found by an AI tool&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Some other minor improvements&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt; </description> 
	<pubDate>Sun, 20 Sep 2026 13:31:26 +0000</pubDate>

</item> 
<item>
	<title>Freexian Collaborators: Monthly report about Debian Long Term Support, August 2026 (by Thorsten Alteholz)</title>
	<guid>https://www.freexian.com/blog/debian-lts-report-2026-08/</guid>
	<link>https://www.freexian.com/blog/debian-lts-report-2026-08/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/freexian.png&quot; width=&quot;215&quot; height=&quot;101&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;img src=&quot;https://www.freexian.com/images/debian-lts-logo.png&quot; style=&quot;float: right;&quot; /&gt;
&lt;p&gt;The Debian LTS Team, funded by &lt;a href=&quot;https://www.freexian.com/lts/debian/&quot;&gt;Freexian’s Debian LTS offering&lt;/a&gt;,
is pleased to report its activities for August.&lt;/p&gt;
&lt;h3 id=&quot;activity-summary&quot;&gt;Activity summary&lt;/h3&gt;
&lt;p&gt;During the month of August, 19 contributors have been
paid to work on &lt;a href=&quot;https://wiki.debian.org/LTS&quot;&gt;Debian LTS&lt;/a&gt; (links to individual
contributor reports are located below).&lt;/p&gt;
&lt;p&gt;The team released &lt;a href=&quot;https://lists.debian.org/debian-lts-announce/2026/08/threads.html&quot;&gt;58 DLAs&lt;/a&gt; fixing 1885 CVEs.&lt;/p&gt;
&lt;p&gt;Debian 11 (“bullseye”), which
has reached the end of its Long Term Support on 31 August 2026, will
now get security support from Freexian under the
&lt;a href=&quot;https://www.freexian.com/lts/extended/&quot;&gt;Extended LTS&lt;/a&gt; offer.&lt;/p&gt;
&lt;p&gt;The team published several notable updates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;chromium
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4710-1&quot;&gt;DLA 4710-1&lt;/a&gt;),
uploaded by Emilio, to fix 375 security flaws in bookworm, including
issues that could lead to arbitrary code execution.
Further &lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4728-1&quot;&gt;DLA 4728-1&lt;/a&gt;,
uploaded by Emilio as well, fixed additional 41 security issues in bookworm and
&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4739-1&quot;&gt;DLA 4739-1&lt;/a&gt;
fixed 5 issues.
Last but not least,
&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4749-1&quot;&gt;DLA 4749-1&lt;/a&gt;
fixed another 15 issues and
&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4758-1&quot;&gt;DLA 4758-1&lt;/a&gt;
fixed another 7 issues.&lt;/li&gt;
&lt;li&gt;ruby2.7
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4716-1&quot;&gt;DLA 4716-1&lt;/a&gt;),
uploaded by Abhijith, to fix four security flaws in bookworm, including
issues that could lead to arbitrary code execution.&lt;/li&gt;
&lt;li&gt;several DLAs
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4717-1&quot;&gt;DLA 4717-1&lt;/a&gt;,
&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4720-1&quot;&gt;DLA 4720-1&lt;/a&gt;,
&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4723-1&quot;&gt;DLA 4723-1&lt;/a&gt;,
&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4724-1&quot;&gt;DLA 4724-1&lt;/a&gt;,
&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4745-1&quot;&gt;DLA 4745-1&lt;/a&gt;)
have been uploaded by Ben and Emilio to fix myriad security flaws in
different versions of the linux kernel
(5.10.262-1, 6.1.180-1, 6.12.100-1~deb12u1, 6.12.101-1~deb12u1)
in bullseye and bookworm.&lt;/li&gt;
&lt;li&gt;7zip
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4718-1&quot;&gt;DLA 4718-1&lt;/a&gt;)
and p7zip
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4719-1&quot;&gt;DLA 4719-1&lt;/a&gt;),
uploaded by Sylvain, to fix multiple security flaws in bookworm and
bullseye, including issues that could yield to remote code execution.&lt;/li&gt;
&lt;li&gt;ca-certificates
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4726-1&quot;&gt;DLA 4726-1&lt;/a&gt;),
uploaded by Bastien to add some new trusted certificates to bookworm and bullseye,
but also remove some untrusted ones.&lt;/li&gt;
&lt;li&gt;thunderbird
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4727-1&quot;&gt;DLA 4727-1&lt;/a&gt;
and &lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4754-1&quot;&gt;DLA 4754-1&lt;/a&gt;),
uploaded by Emilio to fix 35 and 31 issues in bookworm and bullseye.&lt;/li&gt;
&lt;li&gt;nss
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4729-1&quot;&gt;DLA 4729-1&lt;/a&gt;),
uploaded by Jochen to fix a vulnerability in bookworm and bullseye that could
yield to arbitrary code execution.&lt;/li&gt;
&lt;li&gt;libgd2
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4731-1&quot;&gt;DLA 4731-1&lt;/a&gt;),
uploaded by Guilhem to fix a vulnerability in bookworm and bullseye that could
yield to arbitrary code execution if a malformed GIF file is processed.&lt;/li&gt;
&lt;li&gt;xorg-server
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4737-1&quot;&gt;DLA 4737-1&lt;/a&gt;
and &lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4738-1&quot;&gt;DLA 4738-1&lt;/a&gt;),
uploaded by Arnaud to fix several vulnerabilities in bookworm and bullseye.&lt;/li&gt;
&lt;li&gt;postgresql-15
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4740-1&quot;&gt;DLA 4740-1&lt;/a&gt;),
uploaded by Carlos Henrique Lima Melara to fix 26 vulnerabilities
in bookworm.&lt;/li&gt;
&lt;li&gt;unzip
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4741-1&quot;&gt;DLA 4741-1&lt;/a&gt;),
uploaded by Andrej to fix a vulnerability in bookworm and bullseye
that could yield to arbitrary code execution.&lt;/li&gt;
&lt;li&gt;firefox-esr
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4750-1&quot;&gt;DLA 4750-1&lt;/a&gt;),
uploaded by Emilio to fix 31 vulnerabilities in bookworm and bullseye
that could potentially result in arbitrary code execution, privilege escalation
or information disclosure.&lt;/li&gt;
&lt;li&gt;nvidia-graphics-drivers
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4752-1&quot;&gt;DLA 4752-1&lt;/a&gt; and
&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4753-1&quot;&gt;DLA 4753-1&lt;/a&gt;),
uploaded by Tobias to fix lots of vulnerabilities in bookworm and bullseye.&lt;/li&gt;
&lt;li&gt;roundcube
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4760-1&quot;&gt;DLA 4760-1&lt;/a&gt;),
uploaded by Guilhem to fix ten vulnerabilities in bookworm and bullseye
that could potentially result in remote code execution or information disclosure.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Contributions from outside the LTS Team:&lt;/p&gt;
&lt;p&gt;We are greatly thankful for the contributions from people outside the LTS Team:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Salvatore Bonaccorso released a libyaml-syck-perl security update
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4730-1&quot;&gt;DLA 4730-1&lt;/a&gt;),
to fix a denial of service and potentially arbitrary code execution.&lt;/li&gt;
&lt;li&gt;Thomas Goirand released a neutron security update
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4735-1&quot;&gt;DLA 4735-1&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Thomas Goirand released an ironic security update
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4743-1&quot;&gt;DLA 4743-1&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Thomas Goirand released a designate security update
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DLA-4751-1&quot;&gt;DLA 4751-1&lt;/a&gt;),
to fix a denial of service or DNS hijacking.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The LTS Team has also contributed with updates to the latest Debian releases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;xrdp
(&lt;a href=&quot;https://security-tracker.debian.org/tracker/DSA-6469-1&quot;&gt;DSA 6469-1&lt;/a&gt;),
prepared by Abhijith to address privilege escalation and arbitrary
code execution related flaws.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other contributions:&lt;/p&gt;
&lt;p&gt;Besides the work on security updates, different documentation and tooling
changes were needed. This work was mainly done by Sylvain.&lt;/p&gt;
&lt;h3 id=&quot;individual-debian-lts-contributor-reports&quot;&gt;Individual Debian LTS contributor reports&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://people.debian.org/~abhijith/reports/LTS_ELTS-August-2026.txt&quot;&gt;Abhijith PA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lists.debian.org/msgid-search/ae36c131-2fd4-4725-b29f-1fca50093173@app.fastmail.com&quot;&gt;Andrej Shadura&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lists.debian.org/debian-lts/2026/08/msg00052.html&quot;&gt;Arnaud Rebillout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lists.debian.org/debian-lts/2026/09/msg00011.html&quot;&gt;Bastien Roucariès&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.decadent.org.uk/ben/blog/2026/09/10/foss-activity-in-august-2026.html&quot;&gt;Ben Hutchings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lists.debian.org/msgid-search/ap5Go8M3vj9i0laB@fw13.lan&quot;&gt;Carlos Henrique Lima Melara&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://chris-lamb.co.uk/posts/free-software-activities-in-august-2026&quot;&gt;Chris Lamb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lists.debian.org/debian-lts/2026/09/msg00020.html&quot;&gt;Daniel Leidert&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lists.debian.org/debian-lts/2026/08/msg00055.html&quot;&gt;Emmanuel Arias&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://people.debian.org/~pochu/lts/reports/2026-08.txt&quot;&gt;Emilio Pozuelo Monfort&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lists.debian.org/msgid-search/?m=ckm9huCt4Eclt8aZ@debian.org&quot;&gt;Guilhem Moulin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lists.debian.org/msgid-search/apamT2jJj7C9p_BS@mpd&quot;&gt;Jochen Sprickerhof&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lists.debian.org/debian-lts/2026/09/msg00044.html&quot;&gt;Lee Garrett&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://people.debian.org/~kanashiro/debian/lts/reports/2026-08.txt&quot;&gt;Lucas Kanashiro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dl.gambaru.de/blog/202608_LTS_ELTS_report.txt&quot;&gt;Markus Koschany&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://people.debian.org/~santiago/lts-elts-reports/report-2026-08.txt&quot;&gt;Santiago Ruano Rincón&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lists.debian.org/debian-lts/2026/09/msg00001.html&quot;&gt;Sylvain Beucler&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.alteholz.eu/2026/09/my-debian-activities-in-august-2026/&quot;&gt;Thorsten Alteholz&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://lists.debian.org/debian-lts/2026/09/msg00034.html&quot;&gt;Tobias Frost&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;thanks-to-our-sponsors&quot;&gt;Thanks to our sponsors&lt;/h3&gt;
&lt;p&gt;Sponsors that joined recently are in bold.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Platinum sponsors:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.global.toshiba/ww/top.html&quot;&gt;Toshiba Corporation&lt;/a&gt; (for 131 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cip-project.org&quot;&gt;Civil Infrastructure Platform (CIP)&lt;/a&gt; (for 99 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://vyos.io&quot;&gt;VyOS Inc&lt;/a&gt; (for 64 months)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Gold sponsors:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.roche.com/about/business/diagnostics.htm&quot;&gt;F. Hoffmann-La Roche AG&lt;/a&gt; (for 142 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.conet.de/&quot;&gt;CONET Deutschland GmbH&lt;/a&gt; (for 125 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.ox.ac.uk&quot;&gt;University of Oxford&lt;/a&gt; (for 81 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.edf.fr&quot;&gt;EDF SA&lt;/a&gt; (for 53 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.dataport.de&quot;&gt;Dataport AöR&lt;/a&gt; (for 28 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://home.cern/&quot;&gt;CERN&lt;/a&gt; (for 26 months)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Silver sponsors:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://domainnameshop.com/&quot;&gt;Domeneshop AS&lt;/a&gt; (for 146 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://metropole.nantes.fr/&quot;&gt;Nantes Métropole&lt;/a&gt; (for 140 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.akamai.com/&quot;&gt;Akamai - Linode&lt;/a&gt; (for 136 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.univention.de&quot;&gt;Univention GmbH&lt;/a&gt; (for 132 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://portail.univ-st-etienne.fr/&quot;&gt;Université Jean Monnet de St Etienne&lt;/a&gt; (for 132 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ribboncommunications.com/&quot;&gt;Ribbon Communications, Inc.&lt;/a&gt; (for 126 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.exonet.nl&quot;&gt;Exonet B.V.&lt;/a&gt; (for 116 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.lrz.de&quot;&gt;Leibniz Rechenzentrum&lt;/a&gt; (for 110 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.diplomatie.gouv.fr&quot;&gt;Ministère de l’Europe et des Affaires Étrangères&lt;/a&gt; (for 94 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dinahosting.com&quot;&gt;Dinahosting SL&lt;/a&gt; (for 81 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://upsun.com&quot;&gt;Upsun Formerly Platform.sh&lt;/a&gt; (for 76 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.moxa.com&quot;&gt;Moxa Inc.&lt;/a&gt; (for 69 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://sipgate.de&quot;&gt;sipgate GmbH&lt;/a&gt; (for 67 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ovhcloud.com&quot;&gt;OVH US LLC&lt;/a&gt; (for 65 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tilburguniversity.edu/&quot;&gt;Tilburg University&lt;/a&gt; (for 65 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gsi.de&quot;&gt;GSI Helmholtzzentrum für Schwerionenforschung GmbH&lt;/a&gt; (for 56 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cesky-hosting.cz/&quot;&gt;THINline s.r.o.&lt;/a&gt; (for 29 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.cph.dk&quot;&gt;Copenhagen Airports A/S&lt;/a&gt; (for 23 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.isere.fr&quot;&gt;Conseil Départemental de l’Isère&lt;/a&gt; (for 9 months)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.ceos-gmbh.de/en&quot;&gt;CEOS GmbH&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Bronze sponsors:
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.seznam.cz&quot;&gt;Seznam.cz, a.s.&lt;/a&gt; (for 147 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.evolix.fr&quot;&gt;Evolix&lt;/a&gt; (for 146 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://linuxhotel.de&quot;&gt;Linuxhotel GmbH&lt;/a&gt; (for 144 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://intevation.de&quot;&gt;Intevation GmbH&lt;/a&gt; (for 143 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://waays.fr&quot;&gt;WAAYS&lt;/a&gt; (for 142 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.megaspace.de&quot;&gt;Megaspace Internet Services GmbH&lt;/a&gt; (for 141 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.greenbone.net&quot;&gt;Greenbone AG&lt;/a&gt; (for 140 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://numlog.fr&quot;&gt;NUMLOG&lt;/a&gt; (for 140 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.wingo.ch/&quot;&gt;WinGo AG&lt;/a&gt; (for 139 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.entrouvert.com/&quot;&gt;Entr’ouvert&lt;/a&gt; (for 131 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://adfinis.com&quot;&gt;Adfinis AG&lt;/a&gt; (for 128 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.plathome.com&quot;&gt;Plat’Home&lt;/a&gt; (for 125 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.legi.grenoble-inp.fr&quot;&gt;Laboratoire LEGI - UMR 5519 / CNRS&lt;/a&gt; (for 123 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tesorion.nl/&quot;&gt;Tesorion&lt;/a&gt; (for 123 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://bearstech.com&quot;&gt;Bearstech&lt;/a&gt; (for 114 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://lihas.de&quot;&gt;LiHAS&lt;/a&gt; (for 114 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.catalyst.net.nz&quot;&gt;Catalyst IT Ltd&lt;/a&gt; (for 109 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://demarcq.net&quot;&gt;Demarcq SAS&lt;/a&gt; (for 103 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.univ-grenoble-alpes.fr&quot;&gt;Université Grenoble Alpes&lt;/a&gt; (for 89 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.touchweb.fr&quot;&gt;TouchWeb SAS&lt;/a&gt; (for 81 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.spin-ag.de&quot;&gt;SPiN AG&lt;/a&gt; (for 78 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.corefiling.com&quot;&gt;CoreFiling&lt;/a&gt; (for 74 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.osug.fr/&quot;&gt;Observatoire des Sciences de l’Univers de Grenoble&lt;/a&gt; (for 65 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.werfen.com&quot;&gt;Tem Innovations GmbH&lt;/a&gt; (for 60 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wordfinder.pro&quot;&gt;WordFinder.pro&lt;/a&gt; (for 60 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.resif.fr&quot;&gt;CNRS DT INSU Résif&lt;/a&gt; (for 59 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.alterway.fr&quot;&gt;Alter Way&lt;/a&gt; (for 52 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.sobis.com/&quot;&gt;SOBIS Software GmbH&lt;/a&gt; (for 26 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.tuxera.com&quot;&gt;Tuxera Inc.&lt;/a&gt; (for 18 months)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://opm-op.com&quot;&gt;OPM-OP AS&lt;/a&gt; (for 9 months)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.lu-cix.lu&quot;&gt;LU-CIX Management G.I.E.&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt; </description> 
	<pubDate>Sun, 20 Sep 2026 00:00:00 +0000</pubDate>

</item> 
<item>
	<title>Ludovic Rousseau: New version of pcsc-lite: 2.5.2</title>
	<guid>https://blog.apdu.fr/posts/2026/09/new-version-of-pcsc-lite-252/</guid>
	<link>https://blog.apdu.fr/posts/2026/09/new-version-of-pcsc-lite-252/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/rousseau.png&quot; width=&quot;65&quot; height=&quot;95&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;I have just released a new version of &lt;a class=&quot;reference external&quot; href=&quot;https://pcsclite.apdu.fr/files/&quot;&gt;pcsc-lite 2.5.2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;reference external&quot; href=&quot;https://pcsclite.apdu.fr/&quot;&gt;pcsc-lite&lt;/a&gt; is a Free Software
implementation of the &lt;a class=&quot;reference external&quot; href=&quot;https://www.wikipedia.org/wiki/PC/SC&quot;&gt;PC/SC&lt;/a&gt;
(also known as WinSCard) API for Unix systems. It provides an API for
using &lt;a class=&quot;reference external&quot; href=&quot;https://www.wikipedia.org/wiki/Smart_card&quot;&gt;smart cards&lt;/a&gt; and
smart card readers.&lt;/p&gt;
&lt;section id=&quot;changes&quot;&gt;
&lt;h2&gt;Changes:&lt;/h2&gt;
&lt;p&gt;2.5.2: Ludovic Rousseau
19 September 2026&lt;/p&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;&lt;p&gt;hotplug_libudev: rescan &quot;serial&quot; readers in
&lt;code class=&quot;docutils literal&quot;&gt;HPReCheckSerialReaders()&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;fix minor issues found by AI tool&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/section&gt; </description> 
	<pubDate>Sat, 19 Sep 2026 15:17:57 +0000</pubDate>

</item> 
<item>
	<title>Kentaro Hayashi: Building with dh-bazel, buildsystem support for debhelper experiment updates</title>
	<guid>hatenablog://entry/14945776032079905182</guid>
	<link>https://kenhys.hatenablog.jp/entry/2026/09/19/173344</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/kenhys.png&quot; width=&quot;72&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;h2 id=&quot;Introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;After bazel-bootstrap 7.7.1 was landed into Debian unstable,
I&#39;m working on packaging newer Mozc (Most famous Japanese input method editor) with Bazel.&lt;/p&gt;

&lt;p&gt;Here is the blog entry initial efforts to build Mozc with Bazel at that time.&lt;/p&gt;

&lt;p&gt;&lt;cite class=&quot;hatena-citation&quot;&gt;&lt;a href=&quot;https://kenhys.hatenablog.jp/entry/2026/07/12/231009&quot;&gt;kenhys.hatenablog.jp&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;

&lt;p&gt;Then, I&#39;ve shared implementing PoC &lt;code&gt;dh-bazel&lt;/code&gt; experiment.
See why dh-bazel is needed, and prototype about &lt;code&gt;dh-bazel&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;cite class=&quot;hatena-citation&quot;&gt;&lt;a href=&quot;https://kenhys.hatenablog.jp/entry/2026/09/17/215331&quot;&gt;kenhys.hatenablog.jp&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;

&lt;p&gt;As a Bazel beginner, want to know what should pass to Bazel, what should not pass to Bazel.&lt;/p&gt;

&lt;h2 id=&quot;What-is-improved-in-recent-dh-bazel&quot;&gt;What is improved in recent dh-bazel?&lt;/h2&gt;

&lt;p&gt;In the previous versions of &lt;code&gt;dh-bazel&lt;/code&gt;, it supports only basic features
to build with Bazel as a thin wrapper.&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;%:
        dh $@ --buildsystem=bazel

override_dh_auto_build:
        dh_auto_build -- //:hello&lt;/pre&gt;


&lt;p&gt;Now, with recent changes, it supports the following environment variables to resolve required system libraries in dynamically.&lt;/p&gt;

&lt;p&gt;&lt;cite class=&quot;hatena-citation&quot;&gt;&lt;a href=&quot;https://salsa.debian.org/kenhys/dh-bazel&quot;&gt;salsa.debian.org&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DH_BAZEL_OVERRIDE_MODULE&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;It search the specified modules from bundled dummy modules in &lt;code&gt;dh-bazel&lt;/code&gt;.
It accept &#39;,&#39; separated paramesters. (e.g. DH_BAZEL_OVERRIDE_MODULE=zlib,zstd)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dh-bazel&lt;/code&gt; bundles abseil-cpp, apple_support, buildozer, lz4, openssl, protobuf, rules_android_ndk, rules_apple, rules_swift, zlib and zstd as
dummy modules to linking system libraries.&lt;/p&gt;

&lt;p&gt;Now you can use it in &lt;code&gt;debian/rules&lt;/code&gt; like this:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;#!/usr/bin/make -f
# -*- makefile -*-
#

export DH_BAZEL_OVERRIDE_MODULE=zlib
export DH_VERBOSE=1

%:
        dh $@ --buildsystem=bazel --without=single-binary

override_dh_auto_build:
        dh_auto_build -- //:hello&lt;/pre&gt;


&lt;p&gt;It is impossible to cover all of system libraries in Debian, so in that case, please consider to use the following &lt;code&gt;DH_BAZEL_PKGCONF_MODULE&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DH_BAZEL_PKGCONF_MODULE&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;It search the specified modules with pkgconf. It is useful when there is no bundled modules in dh-bazel if you want.
It accept &#39;,&#39; separated paramesters. (e.g. DH_BAZEL_PKGCONF_MODULE=gtk4-x11,gtk4-unix-print).&lt;/p&gt;

&lt;p&gt;If DH_BAZEL_PKGCONF_MODULE could not match, then dh-bazel fallback to dig into &lt;code&gt;Build-Depends:&lt;/code&gt; field
in debian/control. Note that if it is not deterministic (e.g. -dev package provides multiple .pc files)
dh-bazel gives up fallback with pkgconf.&lt;/p&gt;

&lt;p&gt;Now you can use it in &lt;code&gt;debian/rules&lt;/code&gt; like this:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;#!/usr/bin/make -f
# -*- makefile -*-
#

export DH_BAZEL_PKGCONF_MODULE=gtk4-x11,gtk4-unix-print
export DH_VERBOSE=1

%:
        dh $@ --buildsystem=bazel --without=single-binary

override_dh_auto_build:
        dh_auto_build -- //:hello&lt;/pre&gt;


&lt;h2 id=&quot;Conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;dh-bazel is still in very early stage prototype, but it resolves some sort of packaging glitches a bit by bit.&lt;/p&gt;

&lt;p&gt;I hope that it will help package maintainer using Bazel.
(dh-bazel is not uploaded into debian/unstable yet, so stay tuned!)&lt;/p&gt; </description> 
	<pubDate>Sat, 19 Sep 2026 08:33:44 +0000</pubDate>

</item> 
<item>
	<title>Paul Tagliamonte: Why Write?</title>
	<guid>https://notes.pault.ag/why-write/</guid>
	<link>https://notes.pault.ag/why-write/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/paultag.png&quot; width=&quot;65&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;As a graduate of a liberal arts university, I wound up, unsurprisingly, taking a
lot of classes in every possible academic discipline. Thinking back to the
person that I was going into university, I don’t think I would have chosen to
take them – after all, my degree was in the sciences; I’d have been stoked to
do nothing more than wall-to-wall computer science until I ran out of
coursework and filled the rest of my hours with research and independent
studies with my professors (which, I guess I did actually do, just not as
much as I would have otherwise).&lt;/p&gt;
&lt;p&gt;Even this blog’s CSS theme (now 18 years old and starting to look it) was
something I wrote after receiving and repeatedly re-reading a tattered
third-hand copy of “The Laws of Thought” by George Boole. It was gifted to me
by a college friend majoring in philosophy while I was crashing at his rental
on the beach. He gave it to me because he knew I “liked that shit” and, while
it was definitely computer science in nature, I would not have read it
otherwise. I have vivid memories of sleeping on his la-z-boy surrounded by
towers of books he was working through. He went on to do incredible work,
getting his PhD, doing research, brilliant writing – his death in 2023 has
robbed humanity of more time with him. “The Laws of Thought” sits behind me in
my office, and is one of my most valued possessions.&lt;/p&gt;
&lt;p&gt;My friends mean more to me than I could ever express, and I definitely don’t
show it enough. Each of my classes made me a more thoughtful person. My
professors made me a better, more well-rounded person – and a person who
attempts to live up to the oft repeated credo of being “men and women for
others”. I did the best I could, even though I was never a particularly good
student. Without liberal arts, I don’t think I would, dispositionally, have
been capable of pushing myself – to this day – to continue to learn on nights
and weekends, for no reason other than wanting to learn. I &lt;em&gt;refuse&lt;/em&gt; to stop
expanding my perspective, and do my best to approach new problems with as much
humility and curiosity as I can muster.&lt;/p&gt;
&lt;p&gt;Every few days for the last year or so, I have been thinking back to a reading
assignment from my junior year that, at the time, I thought was a borderline
throwaway filler assignment for the class. The reading is an essay from 1947 by
the french existentialist philosopher and libertarian marxist, Jean-Paul Sartre
(as some of the more erudite may have now already worked out given the blog’s
title), “Why Write?”. I re-read it this week. It is not filler. I remember this
essay better than some of the classwork I considered more important at the
time.&lt;/p&gt;
&lt;h1 id=&quot;why-write&quot;&gt;Why Write?&lt;/h1&gt;
&lt;p&gt;“Why Write?” starts off by describing the ways in which writing – trying to
communicate your thoughts, opinions, or feelings to others – is an act of
&lt;em&gt;projection&lt;/em&gt;. The writer will only ever draw from a place of their “own
subjectivity” – writing is taking your person and putting it on display.
You’re choosing what words to use, how to use them, pulling from knowledge
you’ve accumulated (based on how you’ve chosen to spend your time). Spending
any amount of your finite existence in order to convey a thought is, itself,
announcing to the world that you believe it to be a thought worth sharing.&lt;/p&gt;
&lt;p&gt;Meanwhile, the act of reading is &lt;em&gt;not simply&lt;/em&gt; turning letters into words.
Reading is engaging with the work, and &lt;em&gt;understanding&lt;/em&gt; the work in a process
that looks more like what Sartre terms “re-invention” or “discovery” – “the
literary object, though realized &lt;em&gt;through&lt;/em&gt; language, is never given &lt;em&gt;in&lt;/em&gt;
language”. It is not enough to read the words in a book end-to-end; you must,
as a reader, actively engage with the work to understand what is being
communicated by those words. Reading is to take the words on the page, and
“exceed” the mere words through what he calls “directed creation”. The reader
is “re-inventing”/“discovering” the writer’s thoughts by following their
“landmarks in the void”.&lt;/p&gt;
&lt;p&gt;And this all makes pretty good sense to me – I know if someone is being
sarcastic because I know the writer; I have read their words and have &lt;em&gt;read&lt;/em&gt;
into their words, allowing myself to be directed by the writer into
“discovering” the thought they have left me in their work. I understand that
their words are &lt;em&gt;humorous&lt;/em&gt;, not &lt;em&gt;irate&lt;/em&gt;. Knowing who the author of a work is
can completely change the point of a sentence. The fact I’m writing about
Sartre at all, or that this very writing has been constrained for presentation
in this blog’s CSS is only happening because of who I am, what things I’ve
experienced in life, and what has made me, me. Sartre argues that this dyadic
coupling between writer and writing means that I, as a writer, can never truly
&lt;em&gt;read&lt;/em&gt; my own writing. I will never be capable of &lt;em&gt;reading&lt;/em&gt; my own work and
getting something out of it – the work is already an extension of my own
person. I can discover no thought in my own works.&lt;/p&gt;
&lt;p&gt;Of course, Sartre, as an existentialist, is honor bound to go one step further
here – the reader, by participating in &lt;em&gt;reading&lt;/em&gt; a work, is asserting their
own freedom. Every time a writer writes “[…] the writer appeals to the
reader’s freedom to collaborate in the production of [their] work”. The
creative act may only be complete if both writer and reader have recognized one
another and made a choice to do so. No one is &lt;em&gt;compelled&lt;/em&gt; to complete the
creative act. The things you &lt;em&gt;read&lt;/em&gt; matter. Reading something fundamentally
alters you as a person – you can not simply un-read a thought. Everything you
read changes your universe. I have a hunch Sartre would find things like the
(original early 2010s era) “tl;dr” reply to obviously terrible writing
absolutely hilarious as a reader’s expression of freedom (not to be confused
with modern 2020s era usage as shorthand for “summary section”). Using your
freedom to choose to complete the writer’s creative act (or not) is inherently
asserting your humanity.&lt;/p&gt;
&lt;p&gt;I’m a bit fuzzy on the specifics of this quote, but I think it was
&lt;a href=&quot;https://meta.wikimedia.org/wiki/User:Sj&quot;&gt;sj&lt;/a&gt; who told me at one year’s
&lt;a href=&quot;https://puzzles.mit.edu/&quot;&gt;Mystery Hunt&lt;/a&gt; that “A puzzle is a contract between
puzzle author and puzzle solver, the author promises that the puzzle is
solvable if you’re clever enough”. The puzzle author and puzzle solver are
engaging in a collaborative production of the work that is only possible by
recognizing one another. Similarly, Sartre – “whatever connections [the
reader] may establish among the different parts of the book among the chapters
or the words [the reader] has a guarantee, namely, that they have been
expressly willed”.&lt;/p&gt;
&lt;h1 id=&quot;wall-drawing-123&quot;&gt;Wall Drawing #123&lt;/h1&gt;
&lt;p&gt;It follows, Sartre argues, that the act of writing, as a means to convey a
thought to a reader, may only be completed through the act of &lt;em&gt;reading&lt;/em&gt;.
&lt;em&gt;Reading&lt;/em&gt; can only be done by others; writing, therefore, only exists to be
&lt;em&gt;read&lt;/em&gt; – it can serve no other purpose. Writing and reading are two halves of
the same creative, collaborative act, only satisfied when both writer and
reader acknowledge one another. Combined, writing and reading are the act of
recognizing one another’s humanity, thoughts, experiences, consciousness – the
act of co-creation of thought is the critical aspect of writing and reading –
reconstructing the author’s perspective, thought, intent, point. The
co-creation &lt;em&gt;is the point&lt;/em&gt; of both &lt;em&gt;reading&lt;/em&gt; and &lt;em&gt;writing&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Writing without anyone to &lt;em&gt;read&lt;/em&gt; the work leaves the writer’s bid for
co-creation unsatisfied and humanity unrecognized. No thought has been conveyed
to any reader, no one has understood the reason behind the “landmarks in the
void” you’ve carefully placed, leaving you to either “[…] put down [your] pen
or despair”. Writing is an appeal to the reader’s freedom, and the nature of
that freedom is the writer can not control it – never being understood is
always a possibility any time anyone sets out to write.&lt;/p&gt;
&lt;p&gt;Nearly 12 years ago, I attempted to read the text on the &lt;a href=&quot;https://git-man-page-generator.lokaltog.net/&quot;&gt;git manpage
generator&lt;/a&gt; for the first time –
I remember the &lt;strong&gt;exact&lt;/strong&gt; feeling of my brain going into “git manpage parsing
mode” where every word was dragging git plumbing megaliths through the sand
from their far-flung homes. I can still feel the surface of my desk as I
instinctually started to trace out logical connections between git internals
referenced as I read along. It took me a good 20 seconds to realize what I was
reading made no sense. This website broke Sartre’s writer-reader agreement – I
was attempting to &lt;em&gt;read&lt;/em&gt; this website, but there was nothing there. You can
“mechanically” “read” the &lt;code&gt;git-man-page-generator&lt;/code&gt;, but you can never &lt;em&gt;read&lt;/em&gt; it
– it is not possible to &lt;em&gt;read&lt;/em&gt; it. It was funny – unsettling. Each grasp at a
real-looking image in front of me misses, my hand coming back empty. I
couldn’t get enough of it. I must have tried to read a dozen generations in a
row. I had never had something quite that broken pass that far into my
consciousness before. Although I kept trying, it never did feel quite the same
as that first time; I think fundamentally, I couldn’t forget that it was
random.&lt;/p&gt;
&lt;p&gt;While never having anyone &lt;em&gt;read&lt;/em&gt; your &lt;em&gt;writing&lt;/em&gt; drives them to “put down your
pen or despair”, Sartre never had to contend with the opposite problem – being
asked to &lt;em&gt;read&lt;/em&gt; that which was not &lt;em&gt;written&lt;/em&gt;. &lt;em&gt;Reading&lt;/em&gt; that which was not
&lt;em&gt;written&lt;/em&gt; does not merely leave someone unrecognized when a reader makes a
choice; instead, it is an &lt;strong&gt;inherent violation of the contract between reader
and writer&lt;/strong&gt;. Not only is no humanity being recognized through attempting to
&lt;em&gt;read&lt;/em&gt; words which were not &lt;em&gt;written&lt;/em&gt;, but the &lt;u&gt;reader&lt;/u&gt;, not the writer,
is the one who bears the burden of unexpected apophenia. The &lt;u&gt;reader&lt;/u&gt;,
while engaging in co-creation, must now contort themselves to uphold their end
of the Sartrean agreement, scrutinizing text to ascribe consciousness,
thought and intent only to come back up with pareidolia-fueled echos of
one’s own self and disfigured half-thoughts of others. The reality is, the
modern reader must now “mechanically” “read” most written work they come
across, scrutinizing text for any signs of thought before truly attempting
to &lt;em&gt;read&lt;/em&gt; the work. Failing to do this correctly changes our person –
each time it happens, a small part of us is irrevocably altered. Choosing to
engage in this ballet because you wish to do so is one thing – this is
your right and freedom as a reader – but passing words which were not
&lt;em&gt;written&lt;/em&gt; as your own in an attempt to wrestle a reader’s freedom of
co-creation from them is another entirely.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;If you didn’t write it, I don’t want to read it (dw;dr). Send me your prompt instead.&lt;/strong&gt;&lt;/p&gt; </description> 
	<pubDate>Fri, 18 Sep 2026 17:05:00 +0000</pubDate>

</item> 
<item>
	<title>Petter Reinholdtsen: Long term storage of Mattermost messages with Noark 5 XML</title>
	<guid>http://www.hungry.com/~pere/blog/Long_term_storage_of_Mattermost_messages_with_Noark_5_XML.html</guid>
	<link>http://www.hungry.com/~pere/blog/Long_term_storage_of_Mattermost_messages_with_Noark_5_XML.html</link>
     <description>  &lt;p&gt;It is said that those who cannot remember the past are condemned to
repeat it, a quote often attributed to the American philosopher George
Santayana.  And to remember the past, records must be maintained and
kept accessible to learn from.  With this in mind, it is no wonder
that archivists worldwide consider it crucial to ensure the archival
records are both complete and accurate, with a constant frustration
caused by the knowledge that the archives are neither due to
challenges in tracking down and collecting what should be
archived.&lt;/p&gt;

&lt;p&gt;The last few days, I decided to simplify the collection of Messages
from the &lt;a href=&quot;https://mattermost.com/&quot;&gt;Mattermost&lt;/a&gt; chat
service, used by a few of the organisations I am involved in, to try
to improve the situation slightly.  To achieve this, I had written a
dedicated extraction tool.  Partly to see how hard it would be, and
partly to ensure that if one of the services were shut down or
replaced, everything in it would not be lost.  Of course it is in the
nature of the use of instant messages that most of them are not fit
for permanent storage, at least not according to Norwegian law, where
there is a threshold &quot;worthy of the archive&quot; (arkivverdig) that should
be met, and messages like &quot;should we go to lunch now&quot; are below the
bar and should be filtered out.  The tool can not help with this
filtering, and that will have to be done using other means after
collection.&lt;/p&gt;

&lt;p&gt;The tools I had my bullshit generator write, under strict
supervision and many iterations, will extract every message visible to
the user whose credentials are used to log into Mattermost, and write
it out in Noark 5 extraction XML format and visualize the result.  I
created the visualiser mostly to quickly be able to debug the
extracted XML, but also to make life easier for anyone interested in
testing out the tool set.&lt;/p&gt;

&lt;p&gt;The extractor &lt;tt&gt;mattermost-noark5extract&lt;/tt&gt; create a hierarchy
with arkiv/arkivdel for the Mattermost server, and then individual
mappe for each channel and direct message chat, a registrering for
each message thread, dokumentbeskrivelse for every message in the
tread, and one or more dokumentobjekt for each message and their
attachments/images.  So far it is only tested on one Mattermost
installation, where around 23,000 messages is extracted in 61 seconds
and produce 295M with approximately 600 attachments and around 675,000
lines of XML in arkivstruktur.xml.  You pass it the URL of the
service, a username and password, a directory path where to store the
collection and an optional channel name substring to limit the
collection to only a subset of the messages available.&lt;/p&gt;

&lt;p&gt;The &lt;tt&gt;mattermost-noark5extract-browser&lt;/tt&gt; viewer can load this
collection and visualize it similarly to Mattermost&#39;s web interface,
with the list of channels and direct messages dialogues on the left,
messages chronologically in the centre and a selected thread displayed
on the right.&lt;/p&gt;

&lt;p&gt;I know Mattermost provide several login options.  I&#39;ve only had the
one used on my test server implemented so far, and know the extract
tool will have to be extended a bit for it to handle servers using one
of these options.&lt;/p&gt;

&lt;p&gt;If you would like to examine the new toolkit,
&lt;a href=&quot;https://gitlab.com/petterreinholdtsen/mattermost-noark5extract&quot;&gt;mattermost-noark5extract
is available from gitlab&lt;/a&gt;.  I wanted to put it on codeberg, but as
the recent rule change forbid code mostly written by a bullshit
generator there, it was not really an option.  Note that some years
ago I wrote a similar tool to extract material from
&lt;a href=&quot;https://bestpractical.com/request-tracker/&quot;&gt;the request
tracker system&lt;/a&gt;.  The source for
&lt;a href=&quot;https://codeberg.org/noark/request-tracker-noark5extract&quot;&gt;request-tracker-noark5extract
is also available from codeberg&lt;/a&gt;.  I would love to hear from you if
you test the tools.&lt;/p&gt;

&lt;p&gt;As usual, if you use Bitcoin and wish to support my activities,
please send donations to
&lt;b&gt;&lt;a&gt;15oWEoG9dUPovwmUL9KWAnYRtNJEkP1u1b&lt;/a&gt;&lt;/b&gt;.&lt;/p&gt; </description> 
	<pubDate>Fri, 18 Sep 2026 07:00:00 +0000</pubDate>

</item> 
<item>
	<title>Louis-Philippe Véronneau: Fake Cash: The World Trade Game</title>
	<guid>tag:veronneau.org,2026-09-18:/fake-cash-the-world-trade-game.html</guid>
	<link>https://veronneau.org/fake-cash-the-world-trade-game.html</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/pollo.png&quot; width=&quot;65&quot; height=&quot;70&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;This is a new series&lt;sup id=&quot;fnref:series&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://veronneau.org/feeds/languages/en.atom.xml#fn:series&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; I&#39;m starting on the tools I have been crafting and
buying to play pedagogical games in my Economics classes.&lt;/p&gt;
&lt;p&gt;These games, aside from being just plain fun for the students, often aim to
teach them a lesson via interactive play. Unsurprisingly, it is much easier for
them to &lt;a href=&quot;https://en.wiktionary.org/wiki/grok&quot;&gt;grok&lt;/a&gt; a particular concept this way. Moreover, many students told me
these activities were the best part of the classes I teach.&lt;/p&gt;
&lt;h1&gt;The World Trade Game&lt;/h1&gt;
&lt;p&gt;I found out about The World Trade Game in &lt;em&gt;The Handbook of Pluralist Economics
Education&lt;/em&gt;&lt;sup id=&quot;fnref:handbook&quot;&gt;&lt;a class=&quot;footnote-ref&quot; href=&quot;https://veronneau.org/feeds/languages/en.atom.xml#fn:handbook&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, which also contains many other fun pedagogical games. It
was first developed by &lt;a href=&quot;https://actionaid.org/&quot;&gt;Action Aid&lt;/a&gt;, but has since been refined by &lt;a href=&quot;https://economicsnetwork.ac.uk/showcase/sloman_game&quot;&gt;John
Sloman&lt;/a&gt; and then by Irene van Staveren, who wrote about her use of the game in
the aforementioned book.&lt;/p&gt;
&lt;p&gt;The goal of this blog entry is not to describe the game and teach you how to
play it. If that interests you, either buy the book I mentioned or read about
Sloman&#39;s version &lt;a href=&quot;https://economicsnetwork.ac.uk/showcase/sloman_game&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;No, our focus point here is the &lt;em&gt;tools&lt;/em&gt; to play this game: fake cash! Fake cash
can be used in many economics pedagogical games and in my opinion, is a
worthwhile &quot;investment&quot; of your time and energy. You could indeed play with
regular printed sheets of paper listing a value (I sure did!), but using Play
Money (a more appropriate term, since we&#39;re not trying to defraud anyone) will
up your game and create a more immersive atmosphere in your classes.&lt;/p&gt;
&lt;p&gt;At first, I tried to buy play money. Surely, some commercial offering aiming to
create realistic props for movies and TV productions existed? At least in
Canada, it turns out the answer was no. The only thing I could find were shady
websites and weird expensive listings on AliExpress. Not being tenured yet, I
did not try to convince my employer to take a 50-50 chance on supporting
criminal endeavours.&lt;/p&gt;
&lt;p&gt;As such, the next best thing I found was &lt;a href=&quot;https://www.bankofcanadamuseum.ca/2020/11/printable-play-money/&quot;&gt;printable play money designed by the
Bank of Canada Museum&lt;/a&gt;. Their designs were quite nice and met my needs,
but their PDF layout made it overly complicated to print large quantities of
bills. As such, I played around with GIMP a little and came out with these
files. A commercial printer shouldn&#39;t have issues printing them on glossy
cardstock paper and cutting them up for you:&lt;/p&gt;
&lt;div class=&quot;grid-container&quot;&gt;
    &lt;div class=&quot;grid-item&quot;&gt;
      &lt;a href=&quot;https://veronneau.org/media/blog/2026-09-18/5.pdf&quot;&gt;
        &lt;img alt=&quot;Three Canadian 5$ bills&quot; src=&quot;https://veronneau.org/media/blog/2026-09-18/5.jpg&quot; style=&quot;width: 100%;&quot; title=&quot;Three Canadian 5$ bills&quot; /&gt;
      &lt;/a&gt;
    &lt;/div&gt;
    &lt;div class=&quot;grid-item&quot;&gt;
      &lt;a href=&quot;https://veronneau.org/media/blog/2026-09-18/10.pdf&quot;&gt;
        &lt;img alt=&quot;Three Canadian 10$ bills&quot; src=&quot;https://veronneau.org/media/blog/2026-09-18/10.jpg&quot; style=&quot;width: 100%;&quot; title=&quot;Three Canadian 10$ bills&quot; /&gt;
      &lt;/a&gt;
    &lt;/div&gt;
    &lt;div class=&quot;grid-item&quot;&gt;
      &lt;a href=&quot;https://veronneau.org/media/blog/2026-09-18/20.pdf&quot;&gt;
        &lt;img alt=&quot;Three Canadian 20$ bills&quot; src=&quot;https://veronneau.org/media/blog/2026-09-18/20.jpg&quot; style=&quot;width: 100%;&quot; title=&quot;Three Canadian 20$ bills&quot; /&gt;
      &lt;/a&gt;
    &lt;/div&gt;
    &lt;div class=&quot;grid-item&quot;&gt;
      &lt;a href=&quot;https://veronneau.org/media/blog/2026-09-18/50.pdf&quot;&gt;
        &lt;img alt=&quot;Three Canadian 50$ bills&quot; src=&quot;https://veronneau.org/media/blog/2026-09-18/50.jpg&quot; style=&quot;width: 100%;&quot; title=&quot;Three Canadian 50$ bills&quot; /&gt;
      &lt;/a&gt;
    &lt;/div&gt;
    &lt;div class=&quot;grid-item&quot;&gt;
      &lt;a href=&quot;https://veronneau.org/media/blog/2026-09-18/100.pdf&quot;&gt;
        &lt;img alt=&quot;Three Canadian 100$ bills&quot; src=&quot;https://veronneau.org/media/blog/2026-09-18/100.jpg&quot; style=&quot;width: 100%;&quot; title=&quot;Three Canadian 100$ bills&quot; /&gt;
      &lt;/a&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Once printed and cut, you&#39;ll unfortunately have to fold each bill by hand. To
secure both halves, I ended up using a strip of transparent tape on each long
edge.&lt;/p&gt;
&lt;p&gt;Here is the result, with a real Canadian 20$ bill as a comparison:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Stacks of play money bills, with examples of the 5$, 10$, 20$, 50$ and 100$ bills&quot; src=&quot;https://veronneau.org/media/blog/2026-09-18/stacks.jpg&quot; style=&quot;margin-left: 15%;&quot; title=&quot;Stacks of play money bills, with examples of the 5$, 10$, 20$, 50$ and 100$ bills&quot; width=&quot;70%&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;A real Canadian 20$ bill, side-to-side with the play money version&quot; src=&quot;https://veronneau.org/media/blog/2026-09-18/comparison.jpg&quot; style=&quot;margin-left: 15%;&quot; title=&quot;A real Canadian 20$ bill, side-to-side with the play money version&quot; width=&quot;70%&quot; /&gt;&lt;/p&gt;
&lt;div class=&quot;footnote&quot;&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id=&quot;fn:series&quot;&gt;
&lt;p&gt;Don&#39;t hold your breath though, as I do not currently have a release
schedule. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://veronneau.org/feeds/languages/en.atom.xml#fnref:series&quot; title=&quot;Jump back to footnote 1 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn:handbook&quot;&gt;
&lt;p&gt;Reardon, J. (2009). The Handbook of Pluralist Economic Education. New York : Routledge. &lt;a class=&quot;footnote-backref&quot; href=&quot;https://veronneau.org/feeds/languages/en.atom.xml#fnref:handbook&quot; title=&quot;Jump back to footnote 2 in the text&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt; </description> 
	<pubDate>Fri, 18 Sep 2026 04:00:00 +0000</pubDate>

</item> 
<item>
	<title>Kentaro Hayashi: Building Mozc with dh-bazel, buildsystem support for debhelper</title>
	<guid>hatenablog://entry/14945776032078913000</guid>
	<link>https://kenhys.hatenablog.jp/entry/2026/09/17/215331</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/kenhys.png&quot; width=&quot;72&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;h2 id=&quot;Introduction&quot;&gt;Introduction&lt;/h2&gt;

&lt;p&gt;After bazel-bootstrap 7.7.1 was landed into Debian unstable,
I&#39;m working on packaging newer Mozc (Most famous Japanese input method editor) with Bazel.&lt;/p&gt;

&lt;p&gt;Here is the blog entry initial efforts to build Mozc with Bazel at that time.&lt;/p&gt;

&lt;p&gt;&lt;cite class=&quot;hatena-citation&quot;&gt;&lt;a href=&quot;https://kenhys.hatenablog.jp/entry/2026/07/12/231009&quot;&gt;kenhys.hatenablog.jp&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;

&lt;h2 id=&quot;Why-dh-bazel&quot;&gt;Why dh-bazel?&lt;/h2&gt;

&lt;p&gt;After that, newer Mozc packages are uploaded into experimental and moved to
testing phase on experimental now.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://tracker.debian.org/pkg/mozc&quot;&gt;mozc - Debian Package Tracker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When started packaging efforts for newer Mozc with Bazel, I&#39;m a newbie to do it.
Now I&#39;ve got a knowledge to do it a bit, I want to know best practice on packaging X on Debian with Bazel furturmore.&lt;/p&gt;

&lt;p&gt;Usually there are dh-X for buildsystem X on Debian, but it&#39;s not true for Bazel as far as I know.
This is why I had started to write dh-bazel.&lt;/p&gt;

&lt;p&gt;I&#39;ve wrote initial dh-bazel prototype and post a mail to debian-bazel ML.&lt;/p&gt;

&lt;p&gt;&lt;cite class=&quot;hatena-citation&quot;&gt;&lt;a href=&quot;https://lists.debian.org/debian-bazel/2026/09/msg00000.html&quot;&gt;lists.debian.org&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;

&lt;p&gt;dh-bazel supports the following way:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;%:
        dh $@ --buildsystem=bazel

override_dh_auto_build:
        dh_auto_build -- //:hello&lt;/pre&gt;


&lt;p&gt;If you want to build source under &lt;code&gt;src&lt;/code&gt;,  you could write d/rule like this:&lt;/p&gt;

&lt;pre class=&quot;code&quot;&gt;%:
        dh $@

override_dh_auto_build:
        dh_auto_build --buildsystem=bazel --sourcedirectory=src -- //:hello&lt;/pre&gt;


&lt;h2 id=&quot;Conclusion&quot;&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;dh-bazel is in very early stage prototype, but I have succeeded to build newer Mozc with some modifications to Mozc debian/rules on experimental with dh-bazel locally!&lt;/p&gt;

&lt;p&gt;dh-bazel is a thin wrapper for Bazel, so it does not reduce packaging glitches dramatically, but it helps some sort of packaging tasks IMHO.&lt;/p&gt;

&lt;p&gt;There are some achievement with dh-bazel&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It helps to do similar building way like other debhelper buildsystem&lt;/li&gt;
&lt;li&gt;It sets comprehensive Bazel startup options&lt;/li&gt;
&lt;li&gt;It sets comprehensive Bazel command options&lt;/li&gt;
&lt;li&gt;If you want to set extra flags, just specify it as additional user options (&lt;code&gt;--override_module=&lt;/code&gt;, and so on)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Note that it only simplify &lt;code&gt;dh_auto_build stage&lt;/code&gt;, so you must manually install artifacts
with .install or something correctly.&lt;/p&gt;

&lt;p&gt;I hope that it will help package maintainer using Bazel in the future.
(dh-bazel is not uploaded into debian/unstable yet, so stay tuned!)&lt;/p&gt; </description> 
	<pubDate>Thu, 17 Sep 2026 12:53:31 +0000</pubDate>

</item> 
<item>
	<title>Paul Tagliamonte: DESFire EV3</title>
	<guid>https://notes.pault.ag/desfire-ev3/</guid>
	<link>https://notes.pault.ag/desfire-ev3/</link>
     <description>  &lt;img src=&quot;http://planet.debian.org/heads/paultag.png&quot; width=&quot;65&quot; height=&quot;85&quot; alt=&quot;&quot; align=&quot;right&quot; style=&quot;float: right;&quot;&gt;  &lt;p&gt;I’ve &lt;em&gt;long&lt;/em&gt; been interested in hardware key material storage devices. I’ve been
a fan of &lt;a href=&quot;https://github.com/go-piv/go-ykpiv&quot;&gt;yubikeys&lt;/a&gt; (I still remember
when my fancy new NEO-N showed up), &lt;a href=&quot;https://github.com/paultag/go-piv&quot;&gt;PIV&lt;/a&gt;
(and its associated
&lt;a href=&quot;https://github.com/paultag/go-othername&quot;&gt;smattering&lt;/a&gt; of
&lt;a href=&quot;https://github.com/paultag/go-fasc&quot;&gt;additional&lt;/a&gt;
&lt;a href=&quot;https://github.com/paultag/go-cbeff&quot;&gt;fields&lt;/a&gt;),
&lt;a href=&quot;https://github.com/hallowauth/hallow&quot;&gt;SaaS HSMs&lt;/a&gt;,
the &lt;a href=&quot;https://github.com/paultag/go-keyring&quot;&gt;kernel keyring&lt;/a&gt;, some tooling
I’ve fairly satisfied with the design of at prior companies, and of course,
our dear friend, the TPM. All that is not even to mention the scores of exotic
hardware security modules one generally comes across from time to time when
you’re keeping a sharp eye out that you wind up playing with.&lt;/p&gt;
&lt;aside class=&quot;right&quot;&gt;
I have not used any LLMs in the course of this adventure. Not for
writing these posts, and not for this code. The intent here was to learn
more about how DESFire works. LLMs defeat that purpose.
&lt;/aside&gt;
&lt;p&gt;The concept of storing private key material on a disk, or even having it in
RAM has always skeeved me out, so I have a natural inclination to hardware
modules, and how shifting keying material around can change your risks
and threat model(s) in interesting ways.&lt;/p&gt;
&lt;p&gt;I don’t remember when I first came across the
&lt;a href=&quot;https://www.nxp.com/products/MF3DHx3&quot;&gt;MIFARE DESFire EV3&lt;/a&gt;, but a few weeks ago
I did a deep-dive into the state of the art of authentication schemes using
ID cards. My complete overview of what tradeoffs exist is pretty extensive
(and likely not interesting to the vast majority of the world), but the tl;dr
wound up being one of “use PIV” or “use MIFARE DESFire EV3”. I wound up
picking DESFire for a recent project, and figured it’s worth talking
a bit about what I learned, share some thoughts, and some code. That code is
published on &lt;a href=&quot;https://crates.io/crates/desox&quot;&gt;crates.io/desox&lt;/a&gt;, and docs,
as is our custom, may be found at
&lt;a href=&quot;https://docs.rs/desox/latest/desox/&quot;&gt;docs.rs/desox&lt;/a&gt;&lt;/p&gt;
&lt;aside class=&quot;left&quot;&gt;
PIV, while oft-maligned, is exceptional for public key cryptography using
asymmetric keys, and can safely interoperate with x.509. If any of those things
are a hard must, I don&#39;t think that&#39;s going anywhere.
&lt;/aside&gt;
&lt;p&gt;DESFire supports DES (I’m sure most readers saw that one coming), 3DES (I
didn’t bother playing with 3DES at all) or AES-128 (AFAICT always use this?)
keying material. It’s worth noting that the DESFire only supports symmetric
keys and is not designed for public key cryptography, and operates exclusively
using shared symmetric key material. The DESFire EV series use those keys and
related authentication schemes to interact with “files” stored on the on-chip
EEPROM (2k, 4k, 8k, and 16k versions exist), or “applications” (groups of files
and authentication keys).&lt;/p&gt;
&lt;h1 id=&quot;talking-to-a-desfire-ev3&quot;&gt;Talking to a DESFire EV3&lt;/h1&gt;
&lt;p&gt;Interactions with the card are done over NFC (ISO/IEC 14443 Type A), and
commands to/from the card may be in the usual ISO/IEC 7816-4 APDU format, or
“unencapsulated” bytes sent to/from the card are sent using a fixed instruction
set and return code structure – saving a few bytes per message. I’ve opted to
use their undocumented and proprietary format – I found it easier to work
with and with a maximum message of 60 bytes, the savings matter a lot.&lt;/p&gt;
&lt;aside class=&quot;right&quot;&gt;
I keep calling the DESFire messages I implemented &quot;APDU messages&quot; since I have
to use a bunch of API surface saying it is -- but they&#39;re not.
&lt;/aside&gt;
&lt;p&gt;While powered via NFC, the card maintains a small amount of state about the
connection between the reader and the card in its RAM, including if the
session is authenticated or unauthenticated. I’ll dig into how authentication
happens later, but it’s worth knowing that sessions &lt;em&gt;can&lt;/em&gt; become authenticated
using one of the symmetric keys shared by the card and the reader. The vast
majority of the
&lt;a href=&quot;https://docs.rs/desox/0.5.1/desox/enum.Instruction.html&quot;&gt;DESFire commands&lt;/a&gt;
I know about tend to work while either authenticated or unauthenticated,
with a few exceptions (&lt;code&gt;GetUid&lt;/code&gt;, &lt;code&gt;ChangeKey&lt;/code&gt;, and &lt;code&gt;ChangeKeySettings&lt;/code&gt;
for example).&lt;/p&gt;
&lt;p&gt;In general, I found working with this card particularly pleasant. There is a
fair amount of backwards-compatible behavior and multiple methods of
communication that confuse things a bit, but overall, it was better than
average to integrate with. Kudos to the NXP team. If the docs on this chip
were public, things would be orders of magnitude easier – it’s not entirely
clear to my why they’re keeping so much of the interface documentation under
NDA, but it’s the largest knock against the chip, by far.&lt;/p&gt;
&lt;h2 id=&quot;authentication&quot;&gt;Authentication&lt;/h2&gt;
&lt;p&gt;I found a lot of really great resources outlining how the handshake and
protocol works for a DESFire EV3, especially from
&lt;a href=&quot;https://ridrix.wordpress.com/2009/09/19/mifare-desfire-communication-example/&quot;&gt;Ridrix&lt;/a&gt;,
some &lt;a href=&quot;https://www.cardlogix.com/wp-content/uploads/MIFARE-Application-Programming-Guide-for-DESFfire_rev.e.pdf&quot;&gt;public datasheets&lt;/a&gt;
&lt;a href=&quot;https://www.scribd.com/document/683260738/DESFire&quot;&gt;ThrRealRevK&lt;/a&gt;
and posts from &lt;a href=&quot;https://medium.com/@androidcrypto/mifare-desfire-ev3-a-beginner-tutorial-android-java-using-the-desfire-for-android-tools-00aaecb8fa93&quot;&gt;AndroidCrypto&lt;/a&gt;.&lt;/p&gt;
&lt;aside class=&quot;left&quot;&gt;
It&#39;s not super clear to me why all of this is under such heavy NDA, surely
a robust ecosystem is nothing but good?
&lt;/aside&gt;
&lt;p&gt;The gist here is that, because the DESFire only does symmetric key operations,
the key exchange (a type of SKA – Symmetric Key Agreement) uses symmetric keys
to establish a unique session key which is used to sign or encrypt data
exchanged between the reader and the card. I’m not going to get too in-depth
here, since there’s a ton of other resources out there to dig into – but I
will do a quick high-level description to keep this post mostly self-contained.&lt;/p&gt;
&lt;p&gt;The authentication protocol serves two main functions – to verify that both
parties know the same shared secret, as well as to act as a SKA to construct a
new session shared secret key. Here’s a quick overview of how a shared session
key is derived between the reader and the card using our symmetric keys
(&lt;code&gt;AES-128&lt;/code&gt; in the case below).&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the reader requests to start authentication with the card (something like
&lt;code&gt;AA 00&lt;/code&gt; to start an AES Authentication handshake with keyslot &lt;code&gt;0x00&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The card will then reply with &lt;code&gt;AF&lt;/code&gt; (a status code that indicates more data
is to follow), followed by 16 bytes (in the case of &lt;code&gt;AES-128&lt;/code&gt;) of encrypted
(using CBC) data.&lt;/li&gt;
&lt;li&gt;The hosts then decrypts this block with the symmetric key from keyslot 0,
returning the card’s session nonce.&lt;/li&gt;
&lt;li&gt;The host generates 16 bytes (usually random) for its session
nonce.&lt;/li&gt;
&lt;li&gt;The host sends an instruction of &lt;code&gt;AF&lt;/code&gt; (indicating a continuation of
the previous command), followed by 32 bytes of encrypted data. When decrypted,
the first 16 bytes are our nonce generated in step #4, followed by the 16 bytes
provided by the card, decrypted in step #3, except where every byte is shifted
to the left by one place (the 0th byte is copied to the end).&lt;/li&gt;
&lt;li&gt;The card will reply with &lt;code&gt;00&lt;/code&gt; indicating a successful operation, followed
by 16 bytes, which when decrypted, is our session nonce from step #4, shifted
to the left by one byte in the same way that we did in step #5 with the card’s
nonce.&lt;/li&gt;
&lt;li&gt;At this point, both the reader and card have confirmed the other party has
the same symmetric secret key. The session is now “authenticated” and a
“session key” is derived using the two nonce blocks. Two hashing keys (K1
and K2) are derived from this key, which is used to maintain an ongoing
&lt;a href=&quot;https://csrc.nist.gov/pubs/sp/800/38/b/upd1/final&quot;&gt;CMAC&lt;/a&gt; hash of the messages
coming and going to/from the card.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;From here on out, the session is “authenticated”, and responses from the card
which were previously “plain” will now contain a 8-byte CMAC signature,
which can be used to ensure that the replies in question come from the
active session.&lt;/p&gt;
&lt;p&gt;In my &lt;a href=&quot;https://github.com/paultag/desox-rs/tree/v0.5.4/src/handshake&quot;&gt;implementation of the handshake&lt;/a&gt;
I opted to encode the handshake state into rust types, just so I wouldn’t make
any mistakes. The &lt;code&gt;Handshake&lt;/code&gt; type contains the session internals (session
nonce values, keying state, to include IV, etc). This means the authentication
flow (from within my code) uses the &lt;code&gt;Handshake&lt;/code&gt; struct to generate the commands
to send to the card in order:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #e6db74;&quot;&gt;/// Create a new `Handshake`, and return the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #e6db74;&quot;&gt;/// start auth command (something like `AA 00`)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #66d9ef;&quot;&gt;fn&lt;/span&gt; &lt;span style=&quot;color: #a6e22e;&quot;&gt;Handshake&lt;/span&gt;::&lt;span style=&quot;color: #f92672;&quot;&gt;&amp;lt;&lt;/span&gt;Initial&lt;span style=&quot;color: #f92672;&quot;&gt;&amp;gt;&lt;/span&gt;::begin(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt; output: &lt;span style=&quot;color: #66d9ef;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #a6e22e;&quot;&gt;mut&lt;/span&gt; [&lt;span style=&quot;color: #66d9ef;&quot;&gt;u8&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt; key: [&lt;span style=&quot;color: #66d9ef;&quot;&gt;u8&lt;/span&gt;; &lt;span style=&quot;color: #ae81ff;&quot;&gt;16&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt; key_id: &lt;span style=&quot;color: #66d9ef;&quot;&gt;u8&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;) -&amp;gt; (Self, &lt;span style=&quot;color: #f92672;&quot;&gt;&amp;amp;&lt;/span&gt;[&lt;span style=&quot;color: #66d9ef;&quot;&gt;u8&lt;/span&gt;]);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After we get a reply back from the card (the encrypted version of the card’s
session nonce, sometimes called &lt;code&gt;Rnd_B&lt;/code&gt; in code I’ve seen), we transition
states from &lt;code&gt;Initial&lt;/code&gt; into &lt;code&gt;HalfOpen&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #e6db74;&quot;&gt;/// Given the card&#39;s encrypted response, generate
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #e6db74;&quot;&gt;/// our session nonce and generate a reply
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #e6db74;&quot;&gt;/// (something that starts with `AF` followed by
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #e6db74;&quot;&gt;/// 32 bytes of encrypted data).
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #66d9ef;&quot;&gt;fn&lt;/span&gt; &lt;span style=&quot;color: #a6e22e;&quot;&gt;Handshake&lt;/span&gt;::&lt;span style=&quot;color: #f92672;&quot;&gt;&amp;lt;&lt;/span&gt;Initial&lt;span style=&quot;color: #f92672;&quot;&gt;&amp;gt;&lt;/span&gt;::rnd_b(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt; self,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt; output: &lt;span style=&quot;color: #66d9ef;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #a6e22e;&quot;&gt;mut&lt;/span&gt; [&lt;span style=&quot;color: #66d9ef;&quot;&gt;u8&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt; input: &lt;span style=&quot;color: #66d9ef;&quot;&gt;&amp;amp;&lt;/span&gt;[&lt;span style=&quot;color: #66d9ef;&quot;&gt;u8&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;) -&amp;gt; (Handshake::&lt;span style=&quot;color: #f92672;&quot;&gt;&amp;lt;&lt;/span&gt;HalfOpen&lt;span style=&quot;color: #f92672;&quot;&gt;&amp;gt;&lt;/span&gt;, &lt;span style=&quot;color: #f92672;&quot;&gt;&amp;amp;&lt;/span&gt;[&lt;span style=&quot;color: #66d9ef;&quot;&gt;u8&lt;/span&gt;]);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now that we’re “&lt;code&gt;HalfOpen&lt;/code&gt;”, we’re waiting to hear back from the card to ensure
that it, too, can byte-shift our provided nonce. Once we have the card’s reply,
we can check it using our &lt;code&gt;complete&lt;/code&gt; helper, transitioning from &lt;code&gt;HalfOpen&lt;/code&gt; to
&lt;code&gt;Successful&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #e6db74;&quot;&gt;/// Check to ensure that the card replied with
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #e6db74;&quot;&gt;/// our nonce byte-shifted by one place, indicating
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #e6db74;&quot;&gt;/// that they know the symmetric secret in
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #e6db74;&quot;&gt;/// this key slot.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #66d9ef;&quot;&gt;fn&lt;/span&gt; &lt;span style=&quot;color: #a6e22e;&quot;&gt;Handshake&lt;/span&gt;::&lt;span style=&quot;color: #f92672;&quot;&gt;&amp;lt;&lt;/span&gt;HalfOpen&lt;span style=&quot;color: #f92672;&quot;&gt;&amp;gt;&lt;/span&gt;::complete(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt; self,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt; input: &lt;span style=&quot;color: #66d9ef;&quot;&gt;&amp;amp;&lt;/span&gt;[&lt;span style=&quot;color: #66d9ef;&quot;&gt;u8&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;) -&amp;gt; &lt;span style=&quot;color: #a6e22e;&quot;&gt;Handshake&lt;/span&gt;::&lt;span style=&quot;color: #f92672;&quot;&gt;&amp;lt;&lt;/span&gt;Successful&lt;span style=&quot;color: #f92672;&quot;&gt;&amp;gt;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Once the &lt;code&gt;Handshake&lt;/code&gt; is successful, the only thing left to do is consume
the &lt;code&gt;Handshake&lt;/code&gt; struct and turn it into the shared session key by running
it through the &lt;a href=&quot;https://github.com/paultag/desox-rs/blob/v0.5.4/src/crypto/kdf.rs&quot;&gt;key derivation function&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #e6db74;&quot;&gt;/// Consume the `Handshake` struct and return the
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #e6db74;&quot;&gt;/// new shared session secret key.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #66d9ef;&quot;&gt;fn&lt;/span&gt; &lt;span style=&quot;color: #a6e22e;&quot;&gt;Handshake&lt;/span&gt;::&lt;span style=&quot;color: #f92672;&quot;&gt;&amp;lt;&lt;/span&gt;Successful&lt;span style=&quot;color: #f92672;&quot;&gt;&amp;gt;&lt;/span&gt;::into_key(self) -&amp;gt; [&lt;span style=&quot;color: #66d9ef;&quot;&gt;u8&lt;/span&gt;; &lt;span style=&quot;color: #ae81ff;&quot;&gt;16&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;From here on out we can use this session key for the remainder of our
interactions with the card – signing messages from (and sometimes to!) the
card, or encrypted messages to and from the card. This key is used in CBC block
mode, where the session IV is updated with the last block of the encrypted
data.&lt;/p&gt;
&lt;h2 id=&quot;unit-testing&quot;&gt;Unit Testing&lt;/h2&gt;
&lt;p&gt;A nice proprietary of the SKA scheme we’re using as part of DESFire is that the
derived session key is actually deterministic if you control your nonce RNG
(ok, actually, pretty true for most key agreements, but anyway), which means it
is possible to capture traffic over the NFC interface, and “replay” the NFC I/O
with cooked RNGs and ensure byte-identical messages and keys are generated.
Within &lt;code&gt;desox-rs&lt;/code&gt; this is called &lt;code&gt;replay&lt;/code&gt; (I’m creative), and I’ve got a few
replay sessions checked into VCS, which exercise a signficant amount fo the API
surface. All were derived from an actual session with a real DESFire card, and
can be updated with a live card and a &lt;code&gt;--cfg&lt;/code&gt; flag.&lt;/p&gt;
&lt;aside class=&quot;left&quot;&gt;
This replay stuff wound up being super dope, it caught a ton of
almost-regressions during the heavy development phases. If I did this again
from scratch -- this would be the first thing I did.
&lt;/aside&gt;
&lt;p&gt;Each &lt;code&gt;replay&lt;/code&gt; file is a set of lines (request-response transactions), each
containing two space-delimited hex encoded NFC messages. For instance,
here’s an authentication handshake in &lt;code&gt;replay&lt;/code&gt; format:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-txt&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;1a00 afc7bbd82ff8fefae8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;afc6dab54df2278d2952d560821be7e4c3 007d9abe94a9b14748
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The code that generated that exchange came from the test stored adjacent
to that file – a handshake with the default DES key (all zeros), and
an &lt;code&gt;RndA&lt;/code&gt; value hardcoded to &lt;code&gt;32c28fdafd3960de&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #66d9ef;&quot;&gt;let&lt;/span&gt; &lt;span style=&quot;color: #66d9ef;&quot;&gt;mut&lt;/span&gt; card &lt;span style=&quot;color: #f92672;&quot;&gt;=&lt;/span&gt; card
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt; .authenticate_with_rnd_a(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt; &lt;span style=&quot;color: #ae81ff;&quot;&gt;0x00&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt; Key::Des([&lt;span style=&quot;color: #ae81ff;&quot;&gt;0&lt;/span&gt;; &lt;span style=&quot;color: #ae81ff;&quot;&gt;8&lt;/span&gt;]),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt; Key::Des(hex_literal::&lt;span style=&quot;color: #a6e22e;&quot;&gt;hex!&lt;/span&gt;(&lt;span style=&quot;color: #e6db74;&quot;&gt;&quot;32 c2 8f da fd 39 60 de&quot;&lt;/span&gt;)),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt; )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt; .&lt;span style=&quot;color: #66d9ef;&quot;&gt;await&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;display: flex;&quot;&gt;&lt;span&gt; .unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since the card’s &lt;code&gt;RndB&lt;/code&gt; is similarly unchanging (I’m replaying this file every
time), this will always derive the same session key, which means messages
(including encrypted ones or CMAC signed responses) will be identical, as well.
If you’re playing with the DESFire yourself, feel free to grab my &lt;a href=&quot;https://github.com/paultag/desox-rs/tree/main/src/replay&quot;&gt;replay
files&lt;/a&gt; if you need a
“known good” baseline.&lt;/p&gt;
&lt;p&gt;By default this will run using the
&lt;a href=&quot;https://docs.rs/desox/latest/desox/io/struct.MockBackend.html&quot;&gt;MockBackend&lt;/a&gt;,
replaying each file – expecting a byte-identical request, and responding with
the harcoded customary reply. If the code (or test!) needs to change, updating
the tests is done by swapping the &lt;code&gt;MockBackend&lt;/code&gt; out for a real one. Since I
had to do this a bunch during development, running &lt;code&gt;cargo test&lt;/code&gt;
with &lt;code&gt;RUSTFLAGS=&quot;--cfg desox_replay_rw&quot;&lt;/code&gt; will, on run, overwrite the replay
file(s) for the executed test(s), ensuring all line-protocol changes are
explicitly caught and reviewed.&lt;/p&gt;
&lt;h1 id=&quot;observations&quot;&gt;Observations&lt;/h1&gt;
&lt;p&gt;Most commands, even ones which require authentication, are transmitted without
CMAC signature(s) or encryption. &lt;code&gt;CMAC&lt;/code&gt; signatures from the reader to the card
are not really used (except for writes to a file which specifies communication
must be &lt;code&gt;CMAC&lt;/code&gt; signed), ditto for encryption (although that one is used for key
change operations, in addition to file writes on files that specify encrypted
communication must be used). The vast majority of commands take a “plain”
request from the reader, and return a CMAC signed response.&lt;/p&gt;
&lt;aside class=&quot;right&quot;&gt;
I really wish there was a mode or configuration flag I could flip that would
enforce CMAC signatures from the reader to the card.
&lt;/aside&gt;
&lt;p&gt;By my eye, this means that a malicious reader, or something otherwise capable
of holding the card online after communication with an authentic reader is
complete are able to execute privilaged commands (since one can simply ignore
the &lt;code&gt;CMAC&lt;/code&gt; signatures on responses), so long as the command doesn’t require the
reader to provide CMAC signatures (or encryption), or allow the card to power
down.&lt;/p&gt;
&lt;h1 id=&quot;fun-with-desfire&quot;&gt;Fun with DESFire&lt;/h1&gt;
&lt;p&gt;I’ve played around a bit with ways to use the DESFire cards in interesting
configurations, given what they’re capable of. Here’s some half-baked thoughts
I had while mucking around with the cards – these are all poorly thought out
sketches of some things we can do given the specific tradeoffs I see with the
DESFire card. It’s also worth noting that I don’t have any of the actual
documentation, and am not a cryptographic grown-up, so take these sketches with
a massive grain of salt.&lt;/p&gt;
&lt;aside class=&quot;left&quot;&gt;
This stuff is right around when I really miss having asymmetric cryptographic
operations handy.
&lt;/aside&gt;
&lt;p&gt;The first thing that came to mind when implementing this is how the
authentication scheme can shift the boundary of what is and is not trusted
(assuming good secure keying, and provided the key slots and card/application
permissions are configured correctly). Rather than push the key material out to
the machine connected to the NFC reader (“reader machine”), I instead tried
turning the NFC reader and computer into something psuedo-untrusted by “merely”
having it pass messages from the card to a trusted remote system (“remote
machine”). This means that the “reader machine” is exchanging NFC data with the
card, but that data is being decrypted, encrypted and processed by the trusted
“remote machine” – the reader is unable to derive the session key.&lt;/p&gt;
&lt;p&gt;For each of these, I wind up needing to authenticate – so there’s still a few
latent risks, but these can mostly be mitigated by asking for a readbacks of
any changed file(s), setting key permissions carefully, and requesting the
card’s UID via the encrypted channel – all of which would require the
symmetric secrets (which undermine the whole security model if comprimised).&lt;/p&gt;
&lt;aside class=&quot;right&quot;&gt;
This all feels a bit messy at times -- but I have to keep grounding myself
in the threat model -- &quot;if you have the key, you can clone the card (or snoop
the session key)&quot;
&lt;/aside&gt;
&lt;p&gt;This general construction is also subject to a hostile takeover of the
untrusted “reader machine”, since most commands (including destructive ones!)
are sent in “&lt;code&gt;PLAIN&lt;/code&gt;” mode – the reader machine can wait until authentication
is complete and then inject commands into the card and “simply” ignore the CMAC
signatures on responses, severing ties with the remote machine. As such, we
also need to take steps to ensure that the key being used is not one that
allows any access beyond what is allowed. Here were some ideas I sketched out
off the back of this theory.&lt;/p&gt;
&lt;h2 id=&quot;the-second-factor&quot;&gt;The “second-factor”&lt;/h2&gt;
&lt;p&gt;Given some established (and authenticated) connection, part of the initial
authentication flow may use the DESFire card to prove physical control over it
as part of a handshake. This can serve as a second factor during some
authentication flow, requiring physical card presence at a reader to fully
initialize a connection. This does have one glaring downside, however – it’s
phishable. To use this “for real”, we’d need to take some steps to prevent
obvious MITM flows (XOR the NFC messages with the URI as seen by the client?),
but maybe there’s something interesting there.&lt;/p&gt;
&lt;aside class=&quot;left&quot;&gt;
WebAuthN is objectively better in basically every way to this -- this scheme
has some heafty downsides, but also a few interesting properties.
&lt;/aside&gt;
&lt;p&gt;This also has a second interesting attribute – when used as part of a physical
system authentication flow, this becomes a logical place to inject access
control, being able to determine if some person is permitted to operate some
device at that particular time (Is “Joe” current on his Laser Cutter
certifications?) I think of the ideas I landed on, while conceptually
interesting (using an employee id card as a 2FA token, it’s very fast), this
one is the least likely to turn into something real.&lt;/p&gt;
&lt;h2 id=&quot;the-encrypted-cookie&quot;&gt;The “encrypted-cookie”&lt;/h2&gt;
&lt;p&gt;This construction, when paired with an encrypted DESFire file, allows the
“remote machine” to read/write an ’encrypted cookie’ to the card – storing
small amount of encrypted data that the “remote machine” can read/write, but
not the “reader machine”, since this uses an encrypted and authenticated
channel from the “remote machine” directly to the DESFire card, without any
intermediate hosts needing to be &lt;em&gt;fully&lt;/em&gt; trusted. I keep calling this the
“encrypted cookie” in my head because it feels conceptually similar to how Ruby
on Rails and Laravel handles cookies.&lt;/p&gt;
&lt;aside class=&quot;right&quot;&gt;
I never really liked encrypted cookies.
&lt;/aside&gt;
&lt;p&gt;We’d need to take a few extra steps here (for instance, ensure that you read
the cookie back over the encrypted channel after writing to prevent a malicious
reader from dropping writes) to secure the system, but it feels like the
structure of this is definitely decent.&lt;/p&gt;
&lt;h2 id=&quot;the-takeover&quot;&gt;The “takeover”&lt;/h2&gt;
&lt;p&gt;This time, let’s say the computer attached to the NFC reader (“reader machine”)
&lt;em&gt;is&lt;/em&gt; semi-trusted. For this scheme, our trusted “remote machine” and the
“reader machine” pass messages over the network to handle authentication to the
card (as above), where the handshake data is being decrypted, encrypted and
processed by the trusted “remote machine” as usual. However, once the
authentication handshake is complete and a session key has been derived, the
“remote system” return the session key to the “reader machine”, giving it a
one-time-use key and authenticated session to the card.&lt;/p&gt;
&lt;aside class=&quot;left&quot;&gt;
Like a hermit crab.
&lt;/aside&gt;
&lt;p&gt;We need to be careful about global/application permissions and key access
control to files – but in this construction, we can allow the “reader machine”
to take over privileged actions using a scope-limited DESFire key without
handing over the card’s true keying material (preventing cloning of the card).
This can be helpful to ensure messages to/from the card are &lt;em&gt;truely&lt;/em&gt; from the
card (verifying CMAC signatures), enables the “reader machine” to directly
read/write to/from encrypted file(s), but allows the symmetric key material to
remain in as few places as possible – which is critical given compromising
that secret will undermine the security of the entire system.&lt;/p&gt; </description> 
	<pubDate>Tue, 15 Sep 2026 13:25:00 +0000</pubDate>

</item> 
</channel>
</rss>
