<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>KG&#39;s Blog – Welcome</title>
    <link>https://blog.kavin.me/blog/</link>
    <description>Recent content in Welcome on KG&#39;s Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Mon, 09 Jun 2025 18:02:29 -0400</lastBuildDate>
    
	  <atom:link href="https://blog.kavin.me/blog/index.xml" rel="self" type="application/rss+xml" />
    
    
      
        
      
    
    
    <item>
      <title>Tuning LLVM&#39;s SLP Vectorizer Cost Model</title>
      <link>https://blog.kavin.me/blog/tuning-llvms-slp-vectorizer-cost-model/</link>
      <pubDate>Sun, 24 May 2026 11:00:55 -0400</pubDate>
      
      <guid>https://blog.kavin.me/blog/tuning-llvms-slp-vectorizer-cost-model/</guid>
      <description>
        
        
        &lt;p&gt;Similar to my last post, this writeup covers how I solved a performance regression on LLVM by analyzing a benchmark from a RISCV target.&lt;/p&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:rounded-lg hx:border hx:py-2 hx:ltr:pr-4 hx:rtl:pl-4 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-blue-200 hx:bg-blue-100 hx:text-blue-900 hx:dark:border-blue-200/30 hx:dark:bg-blue-900/30 hx:dark:text-blue-200&#34;&gt;
  &lt;div class=&#34;hx:ltr:pl-3 hx:ltr:pr-2 hx:rtl:pr-3 hx:rtl:pl-2&#34;&gt;&lt;svg height=1.2em class=&#34;hx:inline-block hx:align-middle&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z&#34;/&gt;&lt;/svg&gt;&lt;/div&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;strong&gt;TLDR&lt;/strong&gt; &lt;/br&gt;
A recent LLVM patch introduced ordered vector reductions to replace a chain of scalar fadds, but it triggered a performance regression on a benchmark by failing to account for cost of building the initial vector &lt;em&gt;per iteration&lt;/em&gt;. This in turned caused unprofitable code to be deemed &amp;ldquo;profitable.&amp;rdquo;
&lt;/br&gt;&lt;a href=&#34;https://github.com/llvm/llvm-project/pull/199388&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;PR&lt;/a&gt;, &lt;a href=&#34;https://github.com/llvm/llvm-project/issues/199267&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Issue&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;The Regression&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;the-regression&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#the-regression&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Looking at Igalia&amp;rsquo;s LNT instance for the BPI-F3, I noticed this particular &lt;a href=&#34;https://cc-perf.igalia.com/db_default/v4/nts/profile/291/529/12&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;benchmark&lt;/a&gt; with a delta of 89%. Specifically, there was an increase in ~26% issued instructions and a ~48% increase in cycles.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/tuning-llvms-slp-vectorizer-cost-model/benchmark_detail_initial.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;I have attached two more pictures right below, with the first one being the assembly of a basic block from the older build and the corresponding assembly from the newer build.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/tuning-llvms-slp-vectorizer-cost-model/LLVM_old.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/tuning-llvms-slp-vectorizer-cost-model/LLVM_regr.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-green-200 hx:bg-green-100 hx:text-green-900 hx:dark:border-green-200/30 hx:dark:bg-green-900/30 hx:dark:text-green-200&#34;&gt;
  &lt;p class=&#34;hx:flex hx:items-center hx:font-medium&#34;&gt;&lt;svg height=16px class=&#34;hx:inline-block hx:align-middle hx:mr-2&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z&#34;/&gt;&lt;/svg&gt;Info&lt;/p&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;p&gt;&lt;strong&gt;Bn&lt;/strong&gt; here refers to &lt;em&gt;Billions&lt;/em&gt; of cycles. This basic block is basically taking twice as many cycles to execute.&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We can see that that newer build of LLVM is performing a sequence of &lt;code&gt;fsd&lt;/code&gt; instructions, also known as &lt;strong&gt;Float Store Double&lt;/strong&gt;. It&amp;rsquo;s essentially storing the floating point values from those registers onto the stack. Specifically, it&amp;rsquo;s storing the value at the address &lt;code&gt;s1 + 0x80&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;From a preceding basic block that I have not included here, I know that value of the register &lt;code&gt;a5&lt;/code&gt; to be equal to &lt;code&gt;s1 + 0x80&lt;/code&gt; from this instruction.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;addi&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a5&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;s1&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0x80&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;strong&gt;Vector Load Instruction&lt;/strong&gt; &lt;code&gt;vle64.v&lt;/code&gt;  is loading the values from memory at the address at &lt;code&gt;a5&lt;/code&gt; (&lt;code&gt;s1 + 0x80&lt;/code&gt;) into the vector register &lt;code&gt;v16&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;v16&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;M&lt;/span&gt;[&lt;span style=&#34;color:#f9e2af&#34;&gt;a5&lt;/span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Finally, it executes the &lt;code&gt;vfredosum.vs&lt;/code&gt; instruction (&lt;em&gt;Ordered floating-point sum&lt;/em&gt;), which performas the following for a vector register of size &lt;em&gt;VL&lt;/em&gt;.&lt;/p&gt;
\[
vd[0] = \left( \dots \left( \left( vs1[0] &amp;#43; vs2[0] \right) &amp;#43; vs2[1] \right) &amp;#43; \dots &amp;#43; vs2[VL-1] \right)
\]&lt;p&gt;The new codegen is basically trying to replace the ordered &lt;code&gt;fadd&lt;/code&gt; instructions in the first basic block with this vector sum reduction instruction. I hope this diagram may illustrate this better, with what was previously happening versus what is currently occurring. From the images above, it can be observed that the new code is significantly more expensive in terms of cycles.&lt;/p&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph LR
    %% Left-to-Right top level allows parallel tracks to scale height independently
    V_IN[&amp;#34;Original Source Data&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;(Residing in Scalar Registers)&amp;lt;/i&amp;gt;&amp;#34;]

    %% Link to Scalar Track
    V_IN --&amp;gt;|Old Execution| S1
    
    %% Link to Vector Track
    V_IN --&amp;gt;|New Execution| FSD1

    %% Left Side Track: Original Scalar Chain
    subgraph ScalarChain [&amp;#34;Original Intent: Ordered fadd Chain&amp;#34;]
        direction TB
        S1[&amp;#34;fadd (START_VAL + SCALAR_VAL_0)&amp;#34;] --&amp;gt; S2[&amp;#34;fadd (Result + SCALAR_VAL_1)&amp;#34;]
        S2 --&amp;gt; S3[&amp;#34;fadd (Result + SCALAR_VAL_2)&amp;#34;]
        S3 --&amp;gt; S4[&amp;#34;fadd (Result + SCALAR_VAL_3)&amp;lt;br/&amp;gt;&amp;lt;code&amp;gt;FINAL_SCALAR_SUM&amp;lt;/code&amp;gt;&amp;#34;]
    end

    %% Right Side Track Part 1: Memory Gather (Now cleanly scales to its actual contents)
    subgraph Gather [&amp;#34;Memory Gather (Stack Spilling Penalty)&amp;#34;]
        direction TB
        FSD1[&amp;#34;Store SCALAR_VAL_0 to s1 + 0x80&amp;#34;]
        FSD2[&amp;#34;Store SCALAR_VAL_1 to s1 + 0x88&amp;#34;]
        FSD3[&amp;#34;Store SCALAR_VAL_2 to s1 + 0x90&amp;#34;]
        FSD4[&amp;#34;Store SCALAR_VAL_3 to s1 + 0x98&amp;#34;]
    end

    subgraph VectorOps [&amp;#34;Vector Load &amp;amp; Reduction&amp;#34;]
        direction TB
        VLE[&amp;#34;Vector Load&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;(Loads from memory into vector register v16)&amp;lt;/i&amp;gt;&amp;#34;] --&amp;gt; VFRED[&amp;#34;Vector Ordered Sum Reduction&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;(vfredosum)&amp;lt;/i&amp;gt;&amp;#34;]
    end

    %% Connect the two vector halves sequentially
    FSD4 --&amp;gt;VLE

    %% --- STYLING BLOCK ---
    style ScalarChain fill:none,stroke:#888888,stroke-dasharray: 5 5
    
    %% Gather Penalty (Soft Red Glow)
    style Gather fill:#b71c1c18,stroke:#ef4444,stroke-width:2px,rx:8,ry:8
    
    %% Vector Operations (Soft Blue Glow)
    style VectorOps fill:#0d47a118,stroke:#3b82f6,stroke-width:2px,rx:8,ry:8
  &lt;/pre&gt;
&lt;/div&gt;&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-green-200 hx:bg-green-100 hx:text-green-900 hx:dark:border-green-200/30 hx:dark:bg-green-900/30 hx:dark:text-green-200&#34;&gt;
  &lt;p class=&#34;hx:flex hx:items-center hx:font-medium&#34;&gt;&lt;svg height=16px class=&#34;hx:inline-block hx:align-middle hx:mr-2&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z&#34;/&gt;&lt;/svg&gt;Info&lt;/p&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;p&gt;If you visit the link yourself, you may notice that there is also another basic block further down that also has a significant increase in cycles compared to its older counterpart. I chose not to include that as both of them are identical, so fixing one fixes the other.&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;The Where?&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;the-where&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#the-where&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;To narrow down where these new &lt;code&gt;fsd&lt;/code&gt; and &lt;code&gt;vfredosum.vs&lt;/code&gt; instructions are introduced, I ran the command below to get emit the LLVM IR. The output of this commend will give us the intermediate representation produced by the middle-end. If we can observe IR code that would result in those instructions, we can rule out the backend.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;$lbd&lt;/span&gt;/bin/clang -O3 &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  --target&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;riscv64-unknown-linux-gnu &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  -march&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;rva22u64_v &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  --gcc-toolchain&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;/usr &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  --sysroot&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;/usr/riscv64-linux-gnu &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  -I. &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  -DFP_ABSTOLERANCE&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;1e-5 &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  -S -emit-llvm seidel-2d.c &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  -o seidel-2d.ll&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-llvm&#34; data-lang=&#34;llvm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;for.body8.i:&lt;/span&gt;                                      &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;; preds = %for.body8.i, %for.cond5.preheader.i
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%18&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;phi&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; [ &lt;span style=&#34;color:#f5e0dc&#34;&gt;%.pre117.i&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.cond5.preheader.i&lt;/span&gt; ], [ &lt;span style=&#34;color:#f5e0dc&#34;&gt;%26&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.body8.i&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%19&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;phi&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; [ &lt;span style=&#34;color:#f5e0dc&#34;&gt;%.pre116.i&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.cond5.preheader.i&lt;/span&gt; ], [ &lt;span style=&#34;color:#f5e0dc&#34;&gt;%18&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.body8.i&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%20&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;phi&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; [ &lt;span style=&#34;color:#f5e0dc&#34;&gt;%.pre115.i&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.cond5.preheader.i&lt;/span&gt; ], [ &lt;span style=&#34;color:#f5e0dc&#34;&gt;%25&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.body8.i&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%21&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;phi&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; [ &lt;span style=&#34;color:#f5e0dc&#34;&gt;%.pre114.i&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.cond5.preheader.i&lt;/span&gt; ], [ &lt;span style=&#34;color:#f5e0dc&#34;&gt;%div.i40&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.body8.i&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%22&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;phi&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; [ &lt;span style=&#34;color:#f5e0dc&#34;&gt;%.pre113.i&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.cond5.preheader.i&lt;/span&gt; ], [ &lt;span style=&#34;color:#f5e0dc&#34;&gt;%24&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.body8.i&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%23&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;phi&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; [ &lt;span style=&#34;color:#f5e0dc&#34;&gt;%.pre.i&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.cond5.preheader.i&lt;/span&gt; ], [ &lt;span style=&#34;color:#f5e0dc&#34;&gt;%22&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.body8.i&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%indvars.iv.i38&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;phi&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; [ &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.cond5.preheader.i&lt;/span&gt; ], [ &lt;span style=&#34;color:#f5e0dc&#34;&gt;%indvars.iv.next.i39&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.body8.i&lt;/span&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%add.i&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;fadd&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%22&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;%23&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%indvars.iv.next.i39&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;add&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;nuw&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;nsw&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%indvars.iv.i38&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%arrayidx23.i&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;getelementptr&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;inbounds&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;nuw&lt;/span&gt; [&lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i8&lt;/span&gt;], &lt;span style=&#34;color:#f38ba8&#34;&gt;ptr&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%arrayidx.i37&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%indvars.iv.next.i39&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%24&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;load&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;ptr&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%arrayidx23.i&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;align&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;!tbaa&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;!14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%arrayidx34.i&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;getelementptr&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;inbounds&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;nuw&lt;/span&gt; [&lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i8&lt;/span&gt;], &lt;span style=&#34;color:#f38ba8&#34;&gt;ptr&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%17&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%indvars.iv.i38&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%arrayidx40.i&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;getelementptr&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;inbounds&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;nuw&lt;/span&gt; [&lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i8&lt;/span&gt;], &lt;span style=&#34;color:#f38ba8&#34;&gt;ptr&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%17&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%indvars.iv.next.i39&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%25&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;load&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;ptr&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%arrayidx40.i&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;align&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;!tbaa&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;!14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%arrayidx60.i&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;getelementptr&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;inbounds&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;nuw&lt;/span&gt; [&lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i8&lt;/span&gt;], &lt;span style=&#34;color:#f38ba8&#34;&gt;ptr&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%arrayidx44.i&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%indvars.iv.next.i39&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%26&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;load&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;ptr&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%arrayidx60.i&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;align&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;!tbaa&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;!14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%27&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;insertelement&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;poison&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%24&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;i32&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%28&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;insertelement&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%27&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%add.i&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;i32&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%29&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;insertelement&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%28&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%21&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;i32&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%30&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;insertelement&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%29&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%20&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;i32&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%31&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;insertelement&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%30&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%25&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;i32&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%32&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;insertelement&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%31&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%19&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;i32&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%33&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;insertelement&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%32&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%18&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;i32&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%34&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;insertelement&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%33&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%26&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;i32&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%35&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;call&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;@llvm.vector.reduce.fadd.v8f64&lt;/span&gt;(&lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;-0.000000e+00&lt;/span&gt;, &amp;lt;&lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;x&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%34&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%div.i40&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;fdiv&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%35&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;9.000000e+00&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;store&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%div.i40&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;ptr&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%arrayidx34.i&lt;/span&gt;, &lt;span style=&#34;color:#cba6f7&#34;&gt;align&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;!tbaa&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;!14&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%exitcond.not.i41&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;icmp&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;eq&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%indvars.iv.next.i39&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;1999&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;br&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i1&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%exitcond.not.i41&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;label&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.inc66.i&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;label&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%for.body8.i&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;!llvm.loop&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;!25&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We can observe here a chain of &lt;code&gt;insertelement&lt;/code&gt; instructions building an &lt;code&gt;&amp;lt;8 x double&amp;gt;&lt;/code&gt; vector. The instruction follows this format:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-llvm&#34; data-lang=&#34;llvm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%result&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;insertelement&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#f38ba8&#34;&gt;vector_&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;type&lt;/span&gt;&amp;gt; &amp;lt;&lt;span style=&#34;color:#f38ba8&#34;&gt;source_vect&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;or&lt;/span&gt;&amp;gt;, &amp;lt;&lt;span style=&#34;color:#f38ba8&#34;&gt;scalar_value&lt;/span&gt;&amp;gt;, &amp;lt;&lt;span style=&#34;color:#f38ba8&#34;&gt;inde&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;x&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Using the snippet above, we can see that &lt;code&gt;%27&lt;/code&gt; is the initial vector. Because there is no prior value, the source is marked as &lt;code&gt;poison&lt;/code&gt;, the scalar value it&amp;rsquo;s inserting is the value &lt;code&gt;%24&lt;/code&gt;, and the index is &lt;code&gt;0&lt;/code&gt;. From there, each subsequent instruction feeds the result of the previous line its &lt;em&gt;source vector&lt;/em&gt; operand.&lt;/p&gt;
&lt;p&gt;Once the vector is completely packed at &lt;code&gt;%34&lt;/code&gt;, it serves as an operand to the &lt;code&gt;vector.reduce.fadd&lt;/code&gt; intrinsic (maps to &lt;code&gt;vfredosum&lt;/code&gt;). The LLVM &lt;a href=&#34;https://llvm.org/docs/LangRef.html#llvm-vector-reduce-fadd-intrinsic&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;LangRef&lt;/a&gt; explains how this intrinsic sums up the elements in the second operand (&lt;code&gt;34%&lt;/code&gt;), and adds the first operand (&lt;code&gt;0.0&lt;/code&gt;), and stores the result (&lt;code&gt;%35&lt;/code&gt;). The pseudocode provided by the LangRef probably explains this better.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;sequential_fadd&lt;/span&gt;(start_value, input_vector)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  result &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; start_value &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// This is -0.00000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt; to &lt;span style=&#34;color:#89b4fa&#34;&gt;length&lt;/span&gt;(input_vector) &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Traverses every element in %34
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    result &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; result &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; input_vector[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; result&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-green-200 hx:bg-green-100 hx:text-green-900 hx:dark:border-green-200/30 hx:dark:bg-green-900/30 hx:dark:text-green-200&#34;&gt;
  &lt;p class=&#34;hx:flex hx:items-center hx:font-medium&#34;&gt;&lt;svg height=16px class=&#34;hx:inline-block hx:align-middle hx:mr-2&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z&#34;/&gt;&lt;/svg&gt;&lt;strong&gt;Intrinsic&lt;/strong&gt;&lt;/p&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;p&gt;LLVM intrinsics are built-in functions that map directly to low-level architecture instructions, but can be hard to express in normal LLVM IR semantics. They give the compiler a better understanding of a hardware operation, allowing it to generate more efficient assembly.&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Since the behaviour is already introduced by the middle-end, we can rule out the RISCV backend. I can confidently say that it was some middle-end pass causing this behaviour.&lt;/p&gt;
&lt;p&gt;This gives us a better idea of what to isolate. I ran &lt;code&gt;git log&lt;/code&gt; on the dates of when the builds were ran, and grepped for keywords. After hitting a couple of dead-ends, I found a promising lead when I filtered specifically for &lt;em&gt;reduction&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git log --since&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;2026-05-19 00:00:00 +0000&amp;#34;&lt;/span&gt; --until&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;2026-05-20 00:13:39 +0000&amp;#34;&lt;/span&gt; --oneline | grep reduc
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;e28e7ec30357 Reland &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;[&lt;/span&gt;VectorCombine&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;]&lt;/span&gt; foldShuffleChainsToReduce - add support &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; partial vector reductions &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#197659)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dfa05b675eee &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;[&lt;/span&gt;VectorCombine&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;]&lt;/span&gt; Fold reduce.add &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt; into reduce.&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;[&lt;/span&gt;or,umax&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;]&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#180001)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;230980947083&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;[&lt;/span&gt;SLP&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;]&lt;/span&gt; Support ordered fadd reduction via reduction intrinsics
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2d9407bb56b7 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;[&lt;/span&gt;X86&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;]&lt;/span&gt; Add handling &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; sub-128bit minmax reductions &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;(&lt;/span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#198319)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The third commit immediately stood out, as its description would perfectly explain the new codegen. After building LLVM locally before and with this commit, I was able to determine that the commit was the culprit.&lt;/p&gt;
&lt;h2&gt;The Why?&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;the-why&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#the-why&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;For some reason, the SLP Vectorizer thinks it more profitable to performed the fadd reduction here when we know from the benchmark that its not. The key things that author added in that commit were the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;matchOrderedReduction&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;Responsible for finding possible instructions for ordered reduction.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tryToReduceOrdered&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;This is the function that actually checks if its profitable, and commits to the ordered reduction if it is.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;SLP Vectorizer&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;slp-vectorizer&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#slp-vectorizer&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;I think the LLVM &lt;a href=&#34;https://llvm.org/docs/Vectorizers.html&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;docs&lt;/a&gt; does a decent job at a high-level overview of what the SLPVectorizer does. LLVM has two vectorizers, and the SLP Vectorizer is one of them. The pass&amp;rsquo; main goal  is to combine independent instructions into vector instructions. This is a pretty important in terms of performance. By vectorizing what was previously scalar instructions, you can perform the same operations on multiple values at once. This is especially beneficial when operations within a loop can be vectorized, as these tend to be the &lt;strong&gt;hotspots&lt;/strong&gt; within a program.&lt;/p&gt;
&lt;p&gt;In this case though, the SLP Vectorizer was vectorizing a sequence of ordered instructions. I think the commit message itself will elucidate the goal of this commit better.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Previously, the SLP vectorizer could only vectorize ordered reductions
by keeping the original scalar chain and emitting extractelement
instructions. The new path replaces the scalar chain with a vector
ordered reduction intrinsic (where profitable), which allows the backend to lower it
more efficiently.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The following test case from the PR further illustrates the goal of the commit.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;- ; CHECK-NEXT:    [[TMP28:%.*]] = extractelement &amp;lt;4 x float&amp;gt; [[TMP17]], i32 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;- ; CHECK-NEXT:    [[TMP32:%.*]] = extractelement &amp;lt;4 x float&amp;gt; [[TMP17]], i32 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;- ; CHECK-NEXT:    [[ADD30:%.*]] = fadd float [[TMP28]], [[TMP32]]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;- ; CHECK-NEXT:    [[TMP20:%.*]] = extractelement &amp;lt;4 x float&amp;gt; [[TMP17]], i32 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;- ; CHECK-NEXT:    [[ADD31:%.*]] = fadd float [[ADD30]], [[TMP20]]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;- ; CHECK-NEXT:    [[TMP30:%.*]] = extractelement &amp;lt;4 x float&amp;gt; [[TMP17]], i32 3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;- ; CHECK-NEXT:    [[ADD33:%.*]] = fadd float [[ADD31]], [[TMP30]]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+ ; CHECK-NEXT:    [[ADD33:%.*]] = call float @llvm.vector.reduce.fadd.v4f32(float -0.000000e+00, &amp;lt;4 x float&amp;gt; [[TMP17]])
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Before this commit, LLVM had to extract elements out of a vector to perform a chain of scalar &lt;code&gt;fadd&lt;/code&gt;. This commit notices that it&amp;rsquo;s cheaper to keep them in the vector, and use the reduction intrinsic (which maps to &lt;code&gt;vfredosum&lt;/code&gt; on RISCV).&lt;/p&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph TD
    %% Top Level Input
    V_IN[&amp;#34;Source Vector Input&amp;lt;br/&amp;gt;&amp;lt;code&amp;gt;VECTOR_INPUT&amp;lt;/code&amp;gt;&amp;#34;]

    %% Split Path
    V_IN --&amp;gt;|Old Code Generation| OldBehavior
    V_IN --&amp;gt;|Optimized SLP Rewrite| NewBehavior

    %% Left Side Path: Old Behavior (The Costly Extraction Chain)
    subgraph OldBehavior [&amp;#34;Before: Extraction Penalty&amp;#34;]
        direction TB
        
        %% Extraction Row
        subgraph Extractions [&amp;#34;Explicit Extractions&amp;#34;]
            E0[&amp;#34;extractelement (EL0)&amp;#34;]
            E1[&amp;#34;extractelement (EL1)&amp;#34;]
            E2[&amp;#34;extractelement (EL2)&amp;#34;]
            E3[&amp;#34;extractelement (EL3)&amp;#34;]
        end
        
        %% Chain
        A0[&amp;#34;fadd (EL0 + EL1)&amp;#34;]
        A1[&amp;#34;fadd (Result + EL2)&amp;#34;]
        A2[&amp;#34;fadd (Result + EL3)&amp;lt;br/&amp;gt;&amp;lt;code&amp;gt;FINAL_SCALAR_SUM&amp;lt;/code&amp;gt;&amp;#34;]
        
        %% Wire it up
        E0 &amp;amp; E1 --&amp;gt; A0
        A0 &amp;amp; E2 --&amp;gt; A1
        A1 &amp;amp; E3 --&amp;gt; A2
    end

    %% Right Side Path: New Behavior (The Native Intrinsic)
    subgraph NewBehavior [&amp;#34;Direct Reduction&amp;#34;]
        direction TB
        INTRINSIC[&amp;#34;&amp;lt;b&amp;gt;@llvm.vector.reduce.fadd&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;Executes natively inside the vector unit&amp;lt;/i&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;code&amp;gt;FINAL_SCALAR_SUM&amp;lt;/code&amp;gt;&amp;#34;]
    end

    %% --- STYLING BLOCK ---
    style OldBehavior fill:none,stroke:#888888,stroke-dasharray: 5 5
    style NewBehavior fill:none,stroke:#888888,stroke-dasharray: 5 5
    style Extractions fill:none,stroke:none
    
    %% Highlight the bad overhead path in red
    style E0 fill:#b71c1c18,stroke:#ef4444,stroke-width:1px
    style E1 fill:#b71c1c18,stroke:#ef4444,stroke-width:1px
    style E2 fill:#b71c1c18,stroke:#ef4444,stroke-width:1px
    style E3 fill:#b71c1c18,stroke:#ef4444,stroke-width:1px
    
    %% Highlight the clean vector intrinsic win in green
    style INTRINSIC fill:#1b5e2018,stroke:#4caf50,stroke-width:2px,rx:8,ry:8
  &lt;/pre&gt;
&lt;/div&gt;&lt;h4&gt;TreeEntry&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;treeentry&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#treeentry&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;The &lt;code&gt;TreeEntry&lt;/code&gt; is a datastructure used to hold relevant data to determine which scalar operations can be combined into vector operations. The log below was printed using &lt;code&gt;TE.dump()&lt;/code&gt; on the benchmark.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;==== [SLP Cost Loop] Examining TreeEntry (Idx: 0) ====
0.
Scalars: 
    %45 = load double, ptr %arrayidx23.i75, align 8, !tbaa !16
    %add.i73 = fadd double %43, %44
    %42 = phi double [ %.pre114.i65, %for.cond5.preheader.i58 ], [ %div.i86, %for.body8.i71 ]
    %41 = phi double [ %.pre115.i67, %for.cond5.preheader.i58 ], [ %46, %for.body8.i71 ]
    %46 = load double, ptr %arrayidx40.i80, align 8, !tbaa !16
    %40 = phi double [ %.pre116.i68, %for.cond5.preheader.i58 ], [ %39, %for.body8.i71 ]
    %39 = phi double [ %.pre117.i70, %for.cond5.preheader.i58 ], [ %47, %for.body8.i71 ]
    %47 = load double, ptr %arrayidx60.i84, align 8, !tbaa !16
State: NeedToGather
MainOp: NULL
AltOp: NULL
VectorizedValue: NULL
ReuseShuffleIndices: Empty
ReorderIndices: 
UserTreeIndex: &amp;lt;invalid&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I&amp;rsquo;m not a 100% sure why there are &lt;code&gt;phi&lt;/code&gt; instructions within Scalars, but I&amp;rsquo;m fairly sure it&amp;rsquo;s because the function &lt;code&gt;matchOrderedReduction&lt;/code&gt;, which is responsible for finding ordered operations, walks back to the root of the instructions. The comments on this function may explain this better.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;/// Analyze whether \p Root forms a linearized ordered reduction chain.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;/// If \p MatchLHS is true, analyzes LHS-associated (left-linearized) chains
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;/// where the chain recurses on the LHS and the RHS at each level is a leaf:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;///   ((((v0 op v1) op v2) op v3) op v4)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;/// If \p MatchLHS is false, analyzes RHS-associated (right-linearized) chains
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;/// where the chain recurses on the RHS and the LHS at each level is a leaf:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;///   (v0 op (v1 op (v2 op (v3 op v4))))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;/// Leaf values are stored in ReducedVals.back() in accumulation order
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;/// (innermost pair first, outermost last), e.g. [v0,v1,v2,v3,v4] for
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;/// LHS-associated and [v4,v3,v2,v1,v0] for RHS-associated chains.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;/// \returns true if the chain is a valid ordered reduction.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The key thing to notice is that the &lt;code&gt;UserTreeIndex&lt;/code&gt; is invalid. &lt;code&gt;tryToReduceOrdered&lt;/code&gt; builds an isolated tree by calling &lt;code&gt;V.buildTree(VL, IgnoreList)&lt;/code&gt; specifically for the ordered reduction candidates. Since this is the root, there is no parent, so &lt;code&gt;EI&lt;/code&gt; (&lt;em&gt;EdgeInfo&lt;/em&gt;) would be null.&lt;/p&gt;
&lt;h3&gt;Tracing the logs to the code&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;tracing-the-logs-to-the-code&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#tracing-the-logs-to-the-code&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;I first raised an issue and pinged the author of the commit with a kind of hacky solution. He suggested an inaccurate TTI (&lt;em&gt;Target Transform Info&lt;/em&gt;) for this particular target.&lt;/p&gt;
&lt;p&gt;Issue: &lt;a href=&#34;https://github.com/llvm/llvm-project/issues/199267&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://github.com/llvm/llvm-project/issues/199267&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-green-200 hx:bg-green-100 hx:text-green-900 hx:dark:border-green-200/30 hx:dark:bg-green-900/30 hx:dark:text-green-200&#34;&gt;
  &lt;p class=&#34;hx:flex hx:items-center hx:font-medium&#34;&gt;&lt;svg height=16px class=&#34;hx:inline-block hx:align-middle hx:mr-2&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z&#34;/&gt;&lt;/svg&gt;&lt;strong&gt;Target Transform Info (TTI)&lt;/strong&gt;&lt;/p&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;p&gt;LLVM middle-end tries to be target-agnostic. But it&amp;rsquo;s easy to imagine scenarios where we would need info on the target during the middle-end. For example, building the vector in this benchmark might be cheaper on other targets. &lt;strong&gt;Target Transform Info&lt;/strong&gt; provides hooks that can be overridden by backends to provide info to the middle-end.&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;With this in mind, I kept investigating the code alongside the logs. I noticed this piece of code from the diff.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+      LLVM_DEBUG(dbgs() &amp;lt;&amp;lt; &amp;#34;SLP: Vectorizing ordered reduction at cost:&amp;#34; &amp;lt;&amp;lt; Cost
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+                        &amp;lt;&amp;lt; &amp;#34;. (HorRdx)\n&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;When the SLPVectorizer commits to performing an ordered reduction, it prints that debug statement alongside the cost. Searching through the log for this debug message, I found two instances of &amp;ldquo;Vectorizing ordered&amp;hellip;&amp;rdquo;, which corresponds to the two basic blocks in this benchmark.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;SLP: Adding cost 15 for bundle Idx: 0, n=8 [  %24 = load double, ptr %arrayidx23.i, align 8, !tbaa !16, ..].
SLP: Current total cost = 15
SLP: Adding cost -4 for reduction of n=8 [  %24 = load double, ptr %arrayidx23.i, align 8, !tbaa !16, ..] (It is a splitting reduction)
Scale 1996002000 For entry 0
SLP: Spill Cost = 0.
SLP: Extract Cost = 0.
SLP:  Reduction Cost = -7984008000.
SLP: Total Cost = -7984007985.
SLP: Found cost = -7984007985 for ordered reduction
SLP: Vectorizing ordered reduction at cost:-7984007985. (HorRdx)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;From these logs, we can observe a couple of things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The value of &lt;code&gt;Scale&lt;/code&gt;, which is the number of iterations in a loop, is 1996002000.&lt;/li&gt;
&lt;li&gt;The Reduction Cost was -7984008000, which I deduce is from the -4 being multiplied by the &lt;code&gt;Scale&lt;/code&gt; value&lt;/li&gt;
&lt;li&gt;The TreeCost which encompasses the cost of the bundle in this case, which corresponds to the instructions building the vector to reduce it, is 15&lt;/li&gt;
&lt;li&gt;The total cost was -7894007895, the TreeCost subtracted by the ReductionCost&lt;/li&gt;
&lt;/ul&gt;
\[
\begin{aligned}
&amp;amp;\text{TreeCost} = 15 \\
&amp;amp;\text{ReductionCost} = -4 \\
&amp;amp;\text{Scale} = 1,996,002,000 \\[1em]
&amp;amp;\text{ReductionCost}&amp;#39; = \text{ReductionCost} \times \text{Scale} \\
&amp;amp;\text{Total Cost} = \text{TreeCost} &amp;#43; \text{ReductionCost}&amp;#39; \\
&amp;amp;\text{Total Cost} = 15 &amp;#43; (-7,984,008,000) \\
&amp;amp;\text{Total Cost} = -7,984,007,985
\end{aligned}
\]&lt;p&gt;I hope the problem is clearer now. In this benchmark, the &lt;code&gt;TreeCost&lt;/code&gt; - the cost to build the vector - is not scaled alongside the &lt;code&gt;ReductionCost&lt;/code&gt;. This results in really big negative value, leading the SLPVectorizer to think this ordered reduction is profitable.&lt;/p&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:rounded-lg hx:border hx:py-2 hx:ltr:pr-4 hx:rtl:pl-4 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-green-200 hx:bg-green-100 hx:text-green-900 hx:dark:border-green-200/30 hx:dark:bg-green-900/30 hx:dark:text-green-200&#34;&gt;
  &lt;div class=&#34;hx:ltr:pl-3 hx:ltr:pr-2 hx:rtl:pr-3 hx:rtl:pl-2&#34;&gt;&lt;svg height=1.2em class=&#34;hx:inline-block hx:align-middle&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z&#34;/&gt;&lt;/svg&gt;&lt;/div&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;p&gt;If you&amp;rsquo;re wondering where exactly the Scale came to be, this snippet from the source code can explain this.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// seidel-2d.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;/* Default to LARGE_DATASET. */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;# if !defined(MINI_DATASET) &amp;amp;&amp;amp; ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#  define LARGE_DATASET
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;# endif
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#  ifdef LARGE_DATASET
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#   define TSTEPS 500
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#   define N 2000
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#  endif
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// seidel-2d.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; (t &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;; t &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;=&lt;/span&gt; _PB_TSTEPS &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;; t&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; (i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;=&lt;/span&gt; _PB_N &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;; i&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; (j &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;; j &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;=&lt;/span&gt; _PB_N &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;; j&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
\[
\begin{aligned}
&amp;amp;\text{TSTEPS} = 500 \\
&amp;amp;\text{_PB_N} = 2000 \\[1em]
&amp;amp;\text{Total Iterations} = \text{TSTEPS} \times (\text{_PB_N} - 2) \times (\text{_PB_N} - 2) \\
&amp;amp;\text{Total Iterations} = 500 \times 1998 \times 1998 \\
&amp;amp;\text{Total Iterations} = 1,996,002,000
\end{aligned}
\]&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;If we look at the function &lt;code&gt;getTreeCost&lt;/code&gt;, we can see how &lt;code&gt;ReductionCost&lt;/code&gt; is scaled.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;InstructionCost BoUpSLP&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;getTreeCost(InstructionCost TreeCost,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                     ArrayRef&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;Value &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&amp;gt;&lt;/span&gt; VectorizedVals,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                     InstructionCost ReductionCost,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                     Instruction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;RdxRoot) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  InstructionCost Cost &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; TreeCost;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SmallDenseMap&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;std&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;tuple&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;const&lt;/span&gt; TreeEntry &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;, Value &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;, Instruction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&amp;gt;&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;uint64_t&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      EntryToScale;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;auto&lt;/span&gt; ScaleCost &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;](InstructionCost C, &lt;span style=&#34;color:#cba6f7&#34;&gt;const&lt;/span&gt; TreeEntry &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;TE,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                       Value &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;Scalar &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;nullptr&lt;/span&gt;, Instruction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;U &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;nullptr&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!&lt;/span&gt;C.isValid() &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;||&lt;/span&gt; C &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; C;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;uint64_t&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;Scale &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        EntryToScale.try_emplace(std&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;make_tuple(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;TE, Scalar, U), &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .first&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;getSecond();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!&lt;/span&gt;Scale)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      Scale &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; getScaleToLoopIterations(TE, Scalar, U);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    LLVM_DEBUG(dbgs() &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;Scale &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; Scale &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34; For entry &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; TE.Idx &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; C &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; Scale;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Instruction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;ReductionRoot &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; RdxRoot;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (UserIgnoreList) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Scale reduction cost to the factor of the loop nest trip count.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    ReductionCost &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ScaleCost(ReductionCost, &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;VectorizableTree.front().get(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                              &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;/*Scalar=*/&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;nullptr&lt;/span&gt;, ReductionRoot);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Add the cost for reduction.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  Cost &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+=&lt;/span&gt; ReductionCost;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;ReductionCost is being multiplied by the valued returned by &lt;code&gt;getScaleToLoopIterations&lt;/code&gt;. The function &lt;code&gt;getScaleToLoopIterations&lt;/code&gt; also has access to &lt;code&gt;*RdxRoot&lt;/code&gt;, which gives &lt;code&gt;getScaleToLoopIterations&lt;/code&gt; awareness of the parent block, and lets it figure out the number of iterations if the block is a loop.&lt;/p&gt;
&lt;p&gt;To figure out why the &lt;code&gt;TreeCost&lt;/code&gt; is not being scaled, lets again compare the logs to the code. By searching for &amp;ldquo;for bundle:&amp;rdquo;, I was able to find this snippet of the code in a function called &lt;code&gt;calculateTreeCostAndTrimNonProfitable&lt;/code&gt;. As the name suggests, this is the function responsible for calculating the cost of &lt;code&gt;TreeCost&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;InstructionCost
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BoUpSLP&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;calculateTreeCostAndTrimNonProfitable(ArrayRef&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;Value &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&amp;gt;&lt;/span&gt; VectorizedVals,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                               Instruction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;RdxRoot) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    InstructionCost C &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; getEntryCost(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;TE, VectorizedVals, CheckedExtracts);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;uint64_t&lt;/span&gt; Scale &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;bool&lt;/span&gt; CostIsFree &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; C &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!&lt;/span&gt;CostIsFree &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!&lt;/span&gt;Scale) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      Scale &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; IsGatherLike &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;?&lt;/span&gt; getGatherNodeEffectiveScale(TE)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                           &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&lt;/span&gt; getScaleToLoopIterations(TE);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      C &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*=&lt;/span&gt; Scale;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      EntryToScale.try_emplace(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;TE, Scale);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!&lt;/span&gt;TE.isGather() &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; TE.hasState()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        PrevVecParent &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; TE.getMainOp()&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;getParent();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        PrevScale &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; Scale;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Cost &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+=&lt;/span&gt; C;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    NodesCosts.try_emplace(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;TE, C);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    LLVM_DEBUG(dbgs() &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;SLP: Adding cost &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; C &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34; for bundle &amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; shortBundleName(TE.Scalars, TE.Idx) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;.&lt;/span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                      &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;SLP: Current total cost = &amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; Cost &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To get a better idea of what was happening, I added debug logs. From these logs, I determined that &lt;code&gt;getGatherNodeEffectiveScale&lt;/code&gt; is called to calculate the Scale value here. This function then calls &lt;code&gt;getScaleToLoopIterations&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;uint64_t&lt;/span&gt; BoUpSLP&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;getScaleToLoopIterations(&lt;span style=&#34;color:#cba6f7&#34;&gt;const&lt;/span&gt; TreeEntry &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;TE, Value &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;Scalar,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                           Instruction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;U) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  BasicBlock &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;Parent &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;nullptr&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ... 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;if&lt;/span&gt; (TE.isGather() &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;||&lt;/span&gt; TE.State &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; TreeEntry&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;SplitVectorize) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    EdgeInfo EI &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; TE.UserTreeIndex;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;while&lt;/span&gt; (EI.UserTE) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!&lt;/span&gt;Parent)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this case, &lt;code&gt;EI.UserTE&lt;/code&gt; is null, so the (!Parent) would return true and the function would just return 1.&lt;/p&gt;
&lt;h2&gt;Landing a fix&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;landing-a-fix&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#landing-a-fix&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;I&amp;rsquo;ll be upfront in that the author, &lt;code&gt;alexey-bataev&lt;/code&gt;, heavily guided me towards this fix. Take a look at the issue if you want to see my initial ideas on trying to solve this.&lt;/p&gt;
&lt;p&gt;Here is a link to the final PR as well as the precommit test:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/llvm/llvm-project/pull/199388&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://github.com/llvm/llvm-project/pull/199388&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/llvm/llvm-project/pull/199428&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://github.com/llvm/llvm-project/pull/199428&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The solution was to pass the &lt;code&gt;RdxRoot&lt;/code&gt; instruction to &lt;code&gt;calculateTreeCostAndTrimNonProfitable&lt;/code&gt;, and subsequently to &lt;code&gt;getGatherNodeEffectiveScale&lt;/code&gt; and &lt;code&gt;getScaleToLoopIterations&lt;/code&gt;, so that they have the loop context needed to correctly scale TreeCost.&lt;/p&gt;
&lt;p&gt;In simpler terms, Scale was previously being assigned the value of 1 because the pass did not have access to the parent block of the &lt;code&gt;insertelement&lt;/code&gt; instructions. This patch addresses that.&lt;/p&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph TD
    %% Main execution flow container
    subgraph Pipeline [&amp;#34;The Fix: Passing RdxRoot&amp;#34;]
        direction TB
        
        %% Step 1
        A[&amp;#34;&amp;lt;b&amp;gt;tryToReduceOrdered&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;Identifies reduction and holds reference to &amp;lt;code&amp;gt;RdxRootInst&amp;lt;/code&amp;gt;&amp;#34;]
        
        %% Step 2
        B[&amp;#34;&amp;lt;b&amp;gt;calculateTreeCostAndTrimNonProfitable&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;Accepts new parameter: &amp;lt;code&amp;gt;Instruction *RdxRoot&amp;lt;/code&amp;gt;&amp;#34;]
        
        %% Step 3 (The Ternary Switch)
        C{&amp;#34;Is the node&amp;lt;br/&amp;gt;Gather-Like?&amp;#34;}
        
        %% Step 4a
        D[&amp;#34;&amp;lt;b&amp;gt;getGatherNodeEffectiveScale(TE, RdxRoot)&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;(Applies to Root Node at TE.Idx == 0)&amp;lt;/i&amp;gt;&amp;#34;]
        
        %% Step 4b
        E[&amp;#34;&amp;lt;b&amp;gt;getScaleToLoopIterations(TE)&amp;lt;/b&amp;gt;&amp;#34;]
        
        %% Step 5
        F[&amp;#34;&amp;lt;b&amp;gt;getScaleToLoopIterations(TE, nullptr, U)&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;Bypasses missing tree parent by anchoring to &amp;lt;code&amp;gt;U&amp;lt;/code&amp;gt; (RdxRoot)&amp;#34;]

        %% Define flow connections
        A --&amp;gt;|Passes RdxRootInst| B
        B --&amp;gt; C
        C --&amp;gt;|Yes: Node is isolated| D
        C --&amp;gt;|No: Standard node| E
        D --&amp;gt;|Passes U to find loop context| F
    end

    %% --- STYLING BLOCK ---
    %% Neutral structural wrapper for the pipeline
    style Pipeline fill:none,stroke:#888888,stroke-dasharray: 5 5
    
    %% Standard nodes styling
    style A fill:none,stroke:#888888,stroke-width:1px
    style B fill:none,stroke:#888888,stroke-width:1px
    style C fill:none,stroke:#888888,stroke-width:1px
    style E fill:none,stroke:#888888,stroke-width:1px
    
    %% Highlights for where the fix actively changes behavior (Soft Green Glow)
    style D fill:#1b5e2018,stroke:#4caf50,stroke-width:2px,rx:8,ry:8
    style F fill:#1b5e2018,stroke:#4caf50,stroke-width:2px,rx:8,ry:8
  &lt;/pre&gt;
&lt;/div&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;index 54a4d6b68b2e..d90eba7118b3 100644
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;@@ -2176,7 +2176,8 @@ public:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;&lt;/span&gt;   /// Calculates the cost of the subtrees, trims non-profitable ones and returns
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   /// final cost.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   InstructionCost
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;-  calculateTreeCostAndTrimNonProfitable(ArrayRef&amp;lt;Value *&amp;gt; VectorizedVals = {});
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+  calculateTreeCostAndTrimNonProfitable(ArrayRef&amp;lt;Value *&amp;gt; VectorizedVals = {},
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+                                        Instruction *RdxRoot = nullptr);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   /// \returns the vectorization cost of the subtree that starts at \p VL.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   /// A negative number means that this is profitable.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;@@ -3996,7 +3997,8 @@ private:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;&lt;/span&gt;   /// LICM hoisting that optimizeGatherSequence() performs after vectorization
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   /// for inserts with loop-invariant operands. Falls back to the whole-entry
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   /// scale when per-lane information is unavailable or the feature is off.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;-  uint64_t getGatherNodeEffectiveScale(const TreeEntry &amp;amp;TE);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+  uint64_t getGatherNodeEffectiveScale(const TreeEntry &amp;amp;TE,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+                                       Instruction *U = nullptr);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   /// Get the loop nest for the given loop \p L.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ArrayRef&amp;lt;const Loop *&amp;gt; getLoopNest(const Loop *L);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;@@ -16455,14 +16457,15 @@ uint64_t BoUpSLP::getLoopNestScale(const Loop *L) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;&lt;/span&gt;   return std::max&amp;lt;uint64_t&amp;gt;(1, Scale);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;-uint64_t BoUpSLP::getGatherNodeEffectiveScale(const TreeEntry &amp;amp;TE) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+uint64_t BoUpSLP::getGatherNodeEffectiveScale(const TreeEntry &amp;amp;TE,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+                                              Instruction *U) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;&lt;/span&gt;   // Only meaningful for gather/buildvector-like entries; the per-lane
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   // insertelements that make up such an entry are LICM-hoistable by
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   // optimizeGatherSequence() when their operand is loop-invariant.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   assert((TE.isGather() || TE.State == TreeEntry::SplitVectorize) &amp;amp;&amp;amp;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &amp;#34;Expected gather/split tree entry.&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;-  uint64_t BaseScale = getScaleToLoopIterations(TE);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+  uint64_t BaseScale = getScaleToLoopIterations(TE, nullptr, U);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;&lt;/span&gt;   if (!PerLaneGatherScale || LoopAwareTripCount == 0 || BaseScale &amp;lt;= 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     return BaseScale;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;@@ -16487,7 +16490,8 @@ uint64_t BoUpSLP::getGatherNodeEffectiveScale(const TreeEntry &amp;amp;TE) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;&lt;/span&gt;     if (isConstant(V))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       continue;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     ++N;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;-    uint64_t LaneScale = std::min(getScaleToLoopIterations(TE, V), BaseScale);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+    uint64_t LaneScale =
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+        std::min(getScaleToLoopIterations(TE, V, U), BaseScale);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;&lt;/span&gt;     Sum = SaturatingAdd(Sum, LaneScale, &amp;amp;Overflow);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     if (Overflow)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       return BaseScale;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;@@ -18839,8 +18843,9 @@ static T *performExtractsShuffleAction(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;&lt;/span&gt;   return Prev;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;-InstructionCost BoUpSLP::calculateTreeCostAndTrimNonProfitable(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;-    ArrayRef&amp;lt;Value *&amp;gt; VectorizedVals) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+InstructionCost
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+BoUpSLP::calculateTreeCostAndTrimNonProfitable(ArrayRef&amp;lt;Value *&amp;gt; VectorizedVals,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+                                               Instruction *RdxRoot) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;&lt;/span&gt;   // FIXME: support buildvector of the gather nodes with struct types.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   if (any_of(VectorizableTree, [&amp;amp;](const std::unique_ptr&amp;lt;TreeEntry&amp;gt; &amp;amp;TE) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         return TE-&amp;gt;isGather() &amp;amp;&amp;amp;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;@@ -18960,8 +18965,10 @@ InstructionCost BoUpSLP::calculateTreeCostAndTrimNonProfitable(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;&lt;/span&gt;       }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     if (!CostIsFree &amp;amp;&amp;amp; !Scale) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;-      Scale = IsGatherLike ? getGatherNodeEffectiveScale(TE)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;-                           : getScaleToLoopIterations(TE);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+      Scale =
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+          IsGatherLike
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+              ? getGatherNodeEffectiveScale(TE, TE.Idx == 0 ? RdxRoot : nullptr)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+              : getScaleToLoopIterations(TE);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;&lt;/span&gt;       C *= Scale;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       EntryToScale.try_emplace(&amp;amp;TE, Scale);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       if (!TE.isGather() &amp;amp;&amp;amp; TE.hasState()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;@@ -29837,7 +29844,8 @@ public:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       V.transformNodes();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       V.computeMinimumValueSizes();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;-      InstructionCost TreeCost = V.calculateTreeCostAndTrimNonProfitable(VL);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+      InstructionCost TreeCost =
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+          V.calculateTreeCostAndTrimNonProfitable(VL, RdxRootInst);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;&lt;/span&gt;       V.buildExternalUses(LocalExternallyUsedValues);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       InstructionCost ReductionCost =
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;Performance&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;performance&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#performance&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The image below captures the post-patch performance &lt;a href=&#34;https://cc-perf.igalia.com/db_default/v4/nts/profile/291/545/541&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;improvement&lt;/a&gt;. Although, if we compare this to the original baseline I displayed at the beginning of this writeup, we can see an increase in issued instructions, and a slight decrease in vector instructions.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/tuning-llvms-slp-vectorizer-cost-model/benchmark_detail_final.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;However, the total cycles stays about the same to the baseline! 🥹&lt;/p&gt;
      </description>
    </item>
    
    <item>
      <title>Tracking down a 25% Regression on LLVM RISC-V</title>
      <link>https://blog.kavin.me/blog/tracking-down-a-25-regression-on-llvm-risc-v/</link>
      <pubDate>Thu, 09 Apr 2026 15:00:00 -0400</pubDate>
      
      <guid>https://blog.kavin.me/blog/tracking-down-a-25-regression-on-llvm-risc-v/</guid>
      <description>
        
        
        &lt;p&gt;Similar to the previous post, this post covers my analysis of a benchmark on RISC-V targets. Unlike the previous post, I was able to land a patch to eliminate the performance gap to GCC (for this benchmark)!&lt;/p&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:rounded-lg hx:border hx:py-2 hx:ltr:pr-4 hx:rtl:pl-4 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-blue-200 hx:bg-blue-100 hx:text-blue-900 hx:dark:border-blue-200/30 hx:dark:bg-blue-900/30 hx:dark:text-blue-200&#34;&gt;
  &lt;div class=&#34;hx:ltr:pl-3 hx:ltr:pr-2 hx:rtl:pr-3 hx:rtl:pl-2&#34;&gt;&lt;svg height=1.2em class=&#34;hx:inline-block hx:align-middle&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z&#34;/&gt;&lt;/svg&gt;&lt;/div&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;p&gt;&lt;strong&gt;TLDR&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A recent LLVM &lt;a href=&#34;https://github.com/llvm/llvm-project/pull/190235/changes&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;commit&lt;/a&gt; improved &lt;code&gt;isKnownExactCastIntToFP&lt;/code&gt; to fold &lt;code&gt;fpext(sitofp x to float) to double&lt;/code&gt; into a direct &lt;code&gt;uitofp x to double&lt;/code&gt; cast, but this inadvertently broke a downstream narrowing optimization in &lt;code&gt;visitFPTrunc&lt;/code&gt; that relied on the &lt;code&gt;fpext&lt;/code&gt; to narrow a double to float, causing a ~24% performance regression on RISC-V targets, where &lt;code&gt;fdiv.d&lt;/code&gt; (33 cycle latency) was emitted instead of &lt;code&gt;fdiv.s&lt;/code&gt; (19 cycle latency).&lt;/p&gt;
&lt;p&gt;My &lt;a href=&#34;https://github.com/llvm/llvm-project/pull/190550&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;fix&lt;/a&gt; extends &lt;code&gt;getMinimumFPType&lt;/code&gt; with range analysis to recognize that &lt;code&gt;fptrunc(uitofp x double) to float&lt;/code&gt; can be reduced to &lt;code&gt;uitofp x to float&lt;/code&gt;, restoring the narrowing optimization.&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Analysis&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;analysis&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#analysis&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;I was looking at Igalia&amp;rsquo;s site comparing the performance of LLVM to GCC on RISCV targets, and I noticed this particular &lt;a href=&#34;https://cc-perf.igalia.com/db_default/v4/nts/profile/260/410/409&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;benchmark&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/tracking-down-a-25-regression-on-llvm-risc-v/LLVM-vs-GCC.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;As shown in the image below, LLVM requires about ~8% more cycles than GCC for that specific benchmark on the &lt;strong&gt;SiFive P550&lt;/strong&gt; CPU.&lt;/p&gt;
&lt;p&gt;I have included snippets of the relevant basic block assembly. Practically all the cycles were spent on the assembly below.&lt;/p&gt;
&lt;h3&gt;LLVM&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;llvm&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#llvm&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/tracking-down-a-25-regression-on-llvm-risc-v/llvm-asm.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h3&gt;GCC&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;gcc&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#gcc&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/tracking-down-a-25-regression-on-llvm-risc-v/gcc-asm.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;From the two assembly, it wasn&amp;rsquo;t immediately obvious to me why GCC was doing better. They seemed almost identical, and if anything, LLVM was able to optimize the branch logic here. The big difference I did notice was that LLVM was emitting an &lt;code&gt;fdiv.d&lt;/code&gt;, a division with double precision floating point or an &lt;code&gt;f64&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This did seem promising so I decided to run &lt;code&gt;llvm-mca&lt;/code&gt; on the source code to get a better idea of what is happening. Note that I am using llvm-mca built from source that was a couple of days old from upstream. From the analysis done by llvm-mca, I noticed that the &lt;code&gt;fdiv.d&lt;/code&gt; instruction made no appearance in the loop. Although I did not show it above, both GCC and LLVM contained an &lt;code&gt;fdiv.d&lt;/code&gt; instruction in a later basic block but, this was outside the main loop and therefore not relevant to the performance difference.&lt;/p&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-green-200 hx:bg-green-100 hx:text-green-900 hx:dark:border-green-200/30 hx:dark:bg-green-900/30 hx:dark:text-green-200&#34;&gt;
  &lt;p class=&#34;hx:flex hx:items-center hx:font-medium&#34;&gt;&lt;svg height=16px class=&#34;hx:inline-block hx:align-middle hx:mr-2&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z&#34;/&gt;&lt;/svg&gt;Info&lt;/p&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;p&gt;llvm-mca is a tool within the llvm suite that can be used to statically measure the performance of machine code for a specific CPU.&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;$LLVM_BUILD_DIR&lt;/span&gt;/bin/llvm-mca -mtriple&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;riscv64 -mcpu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;sifive-p550 pi.s &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/tracking-down-a-25-regression-on-llvm-risc-v/llvm-mca-old-correct.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Around the area where there should have been an &lt;code&gt;fdiv.d&lt;/code&gt;, there were two &lt;code&gt;fdiv.s&lt;/code&gt; like GCC. From this,  I concluded that the &lt;code&gt;fdiv.d&lt;/code&gt; instruction in the loop must have been a recent regression. LLVM used to be able to narrow the double to a float, but the latest builds can no longer convert the double into a float.&lt;/p&gt;
&lt;p&gt;I confirmed this was indeed a regression by comparing LLVM to a prior build for the same CPU and benchmark.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://cc-perf.igalia.com/db_default/v4/nts/profile/260/406/4&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://cc-perf.igalia.com/db_default/v4/nts/profile/260/406/4&lt;/a&gt;
&lt;img src=&#34;https://blog.kavin.me/blog/tracking-down-a-25-regression-on-llvm-risc-v/benchmark.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;Below is the assembly generated by the prior build of LLVM.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/tracking-down-a-25-regression-on-llvm-risc-v/llvm-old-asm.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;No &lt;code&gt;fdiv.d&lt;/code&gt; instruction on the prior build. In its place, an &lt;code&gt;fdiv.s&lt;/code&gt; is used.&lt;/p&gt;
&lt;h4&gt;Out-of-Order Execution&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;out-of-order-execution&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#out-of-order-execution&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;If you are wondering as to why the ordering of the assembly above and the assembly from the new LLVM build look different, it&amp;rsquo;s because the target CPU, the SiFive P550, is an out of order CPU. Unlike the CPU in the Banana Pi mentioned in the previous post which was an in-order CPU, this target can execute instructions in an order that can produce a higher throughput.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not exactly sure why the fdiv.d is higher, but my suspicions would be that since the double division has a significantly higher latency, the CPU is trying to dispatch other instructions to &amp;lsquo;hide&amp;rsquo; this latency. The &lt;code&gt;fcvt.s.d&lt;/code&gt; instruction that consumes the value of the fdiv.d, &lt;code&gt;ft1&lt;/code&gt;, would need to wait for 33 cycles, so perhaps the CPU made the decision to schedule instructions between them.&lt;/p&gt;
&lt;h3&gt;Where is this happening?&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;where-is-this-happening&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#where-is-this-happening&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;At this point in time we don&amp;rsquo;t know why this happened but a step in the right direction would be to figure out where it happens. Perhaps it was some change in the RISCV backend? The command below gives us the commits related to RISC-V.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git log --after&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;2026-04-01 00:11&amp;#34;&lt;/span&gt; --before&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;2026-04-04 00:10&amp;#34;&lt;/span&gt; | grep -E &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;RISC&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;[RISCV] Select add(vec, splat(scalar)) to PADD_*S for P extension (#190303)
[RISCV] Allow coalesceVSETVLIs to move an LI if it allows a vsetvli to be mutated. (#190287)
[RISCV][TTI] Update cost and prevent exceed m8 for vector.extract.last.active (#188160)
[RISCV] Check EnsureWholeVectorRegisterMoveValidVTYPE in RISCVInsertVSETVLI::transferBefore. (#190022)
[RISCV] Remove codegen for vp_ctlz, vp_cttz, vp_ctpop (#189904)
Part of the work to remove trivial VP intrinsics from the RISC-V
[RISCV] Move unpaired instruction back in RISCVLoadStoreOptimizer (#189912)
`RISCVLoadStoreOptimizer` moves the instruction adjacent to the other
[RISCV] Fix stackmap shadow trimming NOP size for compressed targets (#189774)
[RISCV] Relax VL constraint in convertSameMaskVMergeToVMv (#189797)
[RISCV] Add SATI_RV64/USATI_RV64 to RISCVOptWInstrs. (#190030)
and the RISCVISD::SATI encoding uses the type width minus one.
[RISCV][MCA] Update sifive-p670 tests to consume input files instead (#189785)
[RISCV] Remove codegen for vp_minnum, vp_maxnum (#189899)
Part of the work to remove trivial VP intrinsics from the RISC-V
[RISCV] Add RISCVISD::USATI/SATI to computeKnownBitsForTargetNode/ComputeNumSignBitsForTargetNode. (#189702)
[RISCV] Add assertions to VSETVLIInfo::hasSEWLMULRatioOnly(). NFC (#189799)
[RISCV] combine-is_fpclass.ll - add initial tests showing failure to constant fold ISD::IS_FPCLASS nodes (#189940)
[RISCV] Remove codegen for VP float rounding intrinsics (#189896)
Part of the work to remove trivial VP intrinsics from the RISC-V
[RISCV] Remove codegen for vp_lrint, vp_llrint (#189714)
Part of the work to remove trivial VP intrinsics from the RISC-V
[RISCV] Add codegen support for SATI and USATI. (#189532)&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;None of these commits immediately stood out to me, so I put them off. Investigating the middle-end, I decided to look at the final LLVM IR produced by &lt;code&gt;opt&lt;/code&gt; with my local LLVM version that was a few days old. Remember that my build is the &amp;lsquo;working&amp;rsquo; build. Here is the LLVM IR produced at the beginning of the pipeline (right after clang), and at the end.&lt;/p&gt;
&lt;p&gt;Gets the LLVM IR right after the pipeline:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;$LLVM_BUILD_DIR&lt;/span&gt;/bin/clang -O3 &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;--target&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;riscv64-unknown-linux-gnu &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;-march&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;rv64gc_zba_zbb &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;--sysroot&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;/usr/riscv64-linux-gnu &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;-Xclang -disable-llvm-passes &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;-S -emit-llvm pi.c -o pi_raw_old.ll&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Gets the LLVM IR at the end of the optimization pipeline:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;$LLVM_BUILD_DIR&lt;/span&gt;/bin/clang -O3 &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  --target&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;riscv64-unknown-linux-gnu &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  -march&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;rv64gc_zba_zbb &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  --sysroot&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;/usr/riscv64-linux-gnu &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  -S -emit-llvm pi.c -o pi.ll&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph LR
    %% Main Compiler Flow
    Source[Source Code&amp;lt;br/&amp;gt;&amp;lt;b&amp;gt;pi.c&amp;lt;/b&amp;gt;] --&amp;gt; FE[&amp;lt;b&amp;gt;Front-End&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;Clang/Lexer/Parser&amp;lt;/i&amp;gt;]
    
    subgraph MiddleEnd [&amp;#34;&amp;lt;b&amp;gt;Middle-End&amp;lt;/b&amp;gt; (Optimization Pipeline)&amp;#34;]
        direction LR
        ME_Start(&amp;lt;b&amp;gt;Beginning of Middle-End&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;Unoptimized IR&amp;lt;/i&amp;gt;) --&amp;gt; Opts[&amp;lt;i&amp;gt;InstCombine, LoopUnroll, GVN, etc.&amp;lt;/i&amp;gt;]
        Opts --&amp;gt; ME_End(&amp;lt;b&amp;gt;End of Middle-End&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;Optimized IR&amp;lt;/i&amp;gt;)
    end
    
    FE --&amp;gt; ME_Start
    ME_End --&amp;gt; BE[&amp;lt;b&amp;gt;Backend&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;Code Generator/Instruction Selection&amp;lt;/i&amp;gt;]
    BE --&amp;gt; Asm(&amp;lt;b&amp;gt;Assembly&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;RISC-V&amp;lt;/i&amp;gt;)

    %% Styling Main Pipeline
    style Source fill:none,stroke:#888,stroke-width:1px
    style FE fill:none,stroke:#888,stroke-width:1px
    style ME_Start fill:none,stroke:#1e88e5,stroke-width:2px
    style ME_End fill:none,stroke:#1e88e5,stroke-width:2px
    style Opts fill:none,stroke:#888,stroke-width:1px,stroke-dasharray: 5 5
    style BE fill:none,stroke:#888,stroke-width:1px
    style Asm fill:none,stroke:#888,stroke-width:1px
    style MiddleEnd fill:none,stroke:#444,stroke-width:1px,stroke-dasharray: 3 3

    %% Compact Command Boxes
    %% We use &amp;lt;div&amp;gt; and &amp;lt;code&amp;gt; to keep things tight and prevent block-level gaps
    Cmd_Raw[&amp;#34;&amp;lt;div style=&amp;#39;line-height:1.2;&amp;#39;&amp;gt;&amp;lt;b&amp;gt;Command 1: Raw IR&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;code style=&amp;#39;background:none;color:inherit;&amp;#39;&amp;gt;-Xclang -disable-llvm-passes&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;small&amp;gt;Produces &amp;lt;b&amp;gt;pi_raw_old.ll&amp;lt;/b&amp;gt;&amp;lt;/small&amp;gt;&amp;lt;/div&amp;gt;&amp;#34;]
    
    Cmd_Opt[&amp;#34;&amp;lt;div style=&amp;#39;line-height:1.2;&amp;#39;&amp;gt;&amp;lt;b&amp;gt;Command 2: Optimized IR&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;code style=&amp;#39;background:none;color:inherit;&amp;#39;&amp;gt;-O3 -S -emit-llvm&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;small&amp;gt;Produces &amp;lt;b&amp;gt;pi.ll&amp;lt;/b&amp;gt;&amp;lt;/small&amp;gt;&amp;lt;/div&amp;gt;&amp;#34;]

    %% Connections
    Cmd_Raw -.-&amp;gt; ME_Start
    Cmd_Opt -.-&amp;gt; ME_End

    %% Style Command Notes
    style Cmd_Raw fill:#fff3e011,stroke:#f57c00,stroke-width:1px,rx:10,ry:10
    style Cmd_Opt fill:#fff3e011,stroke:#f57c00,stroke-width:1px,rx:10,ry:10
  &lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If you are confused as to what I am doing, hopefully the diagram above illustrates this better. If the middle-end is responsible for narrowing the double to a float, I am trying to get an idea of what optimizations are happening to the IR that causes this.&lt;/p&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:rounded-lg hx:border hx:py-2 hx:ltr:pr-4 hx:rtl:pl-4 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-green-200 hx:bg-green-100 hx:text-green-900 hx:dark:border-green-200/30 hx:dark:bg-green-900/30 hx:dark:text-green-200&#34;&gt;
  &lt;div class=&#34;hx:ltr:pl-3 hx:ltr:pr-2 hx:rtl:pr-3 hx:rtl:pl-2&#34;&gt;&lt;svg height=1.2em class=&#34;hx:inline-block hx:align-middle&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z&#34;/&gt;&lt;/svg&gt;&lt;/div&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;Instead of doing this, you could also use the &lt;code&gt;print-before&lt;/code&gt; and &lt;code&gt;print-after&lt;/code&gt; on a specific pass to see what the pass is doing to the IR.&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;This is the relevant snippet of the IR from the beginning of the optimization pipeline.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;conv  &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; sitofp i64 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;5&lt;/span&gt; to &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt;        ; &lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;conv2 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; fpext &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;conv to &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;   ; &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;div3  &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; fdiv &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;conv2, &lt;span style=&#34;color:#fab387&#34;&gt;7.438300e+04&lt;/span&gt;  ; fdiv.d 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;conv4 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; fptrunc &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;div3 to &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt; ; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Which was converted into the following by the end of the pipeline.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;conv  &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; uitofp nneg i64 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt; to &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt;   ; &lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;conv4 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; fdiv &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;conv, &lt;span style=&#34;color:#fab387&#34;&gt;7.438300e+04&lt;/span&gt; ; fdiv.s 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We can see that by the end of the middle-end, the double was narrowed to a float. I hope it&amp;rsquo;s clear from these snippets that it was the middle-end responsible for narrowing this initial double value to a float.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re confused as to why these seemingly redundant cast operations are produced in the first place, taking a cursory glance at the source code can help.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/llvm/llvm-test-suite/blob/main/SingleSource/Benchmarks/Misc/pi.c&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;main&lt;/span&gt;(&lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; argc, &lt;span style=&#34;color:#f38ba8&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;argv[]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt; ztot, yran, ymult, ymod, x, y, z, pi, prod;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;long&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; low, ixran, itot, j, iprod;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt;(j&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;; j&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;=&lt;/span&gt;itot; j&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    iprod &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;27611&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; ixran;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ixran &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; iprod &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;74383&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;(&lt;span style=&#34;color:#f38ba8&#34;&gt;long&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt;)(iprod&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;74383&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt;)ixran &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;74383.0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This specific line shows that 74383.0 is a double in the source code.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt;)ixran &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;74383.0&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This is why the LLVM IR has an &lt;code&gt;fpext&lt;/code&gt; converting a float to a double, and then a &lt;code&gt;fptrunc&lt;/code&gt; of the double back to a float.&lt;/p&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:rounded-lg hx:border hx:py-2 hx:ltr:pr-4 hx:rtl:pl-4 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-green-200 hx:bg-green-100 hx:text-green-900 hx:dark:border-green-200/30 hx:dark:bg-green-900/30 hx:dark:text-green-200&#34;&gt;
  &lt;div class=&#34;hx:ltr:pl-3 hx:ltr:pr-2 hx:rtl:pr-3 hx:rtl:pl-2&#34;&gt;&lt;svg height=1.2em class=&#34;hx:inline-block hx:align-middle&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z&#34;/&gt;&lt;/svg&gt;&lt;/div&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;p&gt;This may be obvious, but I&amp;rsquo;ll state it regardless. If the literal above had an initially been a float like below, the &lt;code&gt;fdiv.d&lt;/code&gt; would have never been produced.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt;)ixran &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;74383.0f&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Given a sufficient optimization level, the compiler should still be able to catch something like this, but it&amp;rsquo;s still cool seeing how such a little change in code can have such a huge difference. In this case, over +19% in cycles!&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;The table below shows the mapping of LLVM IR to the C source code, as well as a brief note on what the specified IR does.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;LLVM IR&lt;/th&gt;
          &lt;th&gt;C Source&lt;/th&gt;
          &lt;th&gt;Notes&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;%mul = mul nuw nsw i64 %ixran.053, 27611&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;iprod = 27611 * ixran&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;integer multiply&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;%0 = urem i64 %mul, 74383&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;ixran = iprod - 74383*(long int)(iprod/74383)&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;compiler optimized modulo via &lt;code&gt;urem&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;%conv2 = uitofp nneg i64 %0 to double&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;(float)ixran&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;cast to double first due to &lt;code&gt;74383.0&lt;/code&gt; being a double literal&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;%div3 = fdiv double %conv2, 7.438300e+04&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;/ 74383.0&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;division in double precision because &lt;code&gt;74383.0&lt;/code&gt; is a double literal in C&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;%conv4 = fptrunc double %div3 to float&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;x = (float)...&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;explicit &lt;code&gt;(float)&lt;/code&gt; cast truncates result back to float&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The LLVM build at the time was producing the following.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-llvm&#34; data-lang=&#34;llvm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%mul&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;mul&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;nuw&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;nsw&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%ixran.053&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;27611&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%0&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;urem&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%mul&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;74383&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv2&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;uitofp&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;nneg&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%0&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%div3&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;fdiv&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv2&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;7.438300e+04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv4&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;fptrunc&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%div3&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We can see that the operands of the &lt;code&gt;div3&lt;/code&gt; operations is &lt;code&gt;%conv2&lt;/code&gt;, and a decimal value. &lt;code&gt;%conv2&lt;/code&gt; is the result of a cast operation converting &lt;code&gt;%0&lt;/code&gt; into a double, but the maximum value of &lt;code&gt;%0&lt;/code&gt;, &lt;code&gt;74383&lt;/code&gt;, can fit within a float.&lt;/p&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:rounded-lg hx:border hx:py-2 hx:ltr:pr-4 hx:rtl:pl-4 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-green-200 hx:bg-green-100 hx:text-green-900 hx:dark:border-green-200/30 hx:dark:bg-green-900/30 hx:dark:text-green-200&#34;&gt;
  &lt;div class=&#34;hx:ltr:pl-3 hx:ltr:pr-2 hx:rtl:pr-3 hx:rtl:pl-2&#34;&gt;&lt;svg height=1.2em class=&#34;hx:inline-block hx:align-middle&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z&#34;/&gt;&lt;/svg&gt;&lt;/div&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;p&gt;Looking at the result from &lt;code&gt;llvm-mca&lt;/code&gt;, we can see the following for &lt;code&gt;fdiv.d&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt; 1      33    32.00                       fdiv.d	ft1, ft1, fa3&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This shows that &lt;code&gt;fdiv.d&lt;/code&gt; has a latency of 33 cycles, significantly longer than &lt;code&gt;fdiv.s&lt;/code&gt;&amp;rsquo;s 19 cycles. In our performance comparison, the older LLVM build reported a &lt;strong&gt;Reciprocal Throughput&lt;/strong&gt; (RThroughput) of 86.0, whereas the newer build has increased to 100.0. RThroughput represents the number of clock cycles the processor must wait before it can start executing another instruction of the same type. So the lower, the better.&lt;/p&gt;
&lt;p&gt;This shows how a double division is pretty expensive compared to a float division.&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;From the list of commits in those past few days, the one below immediately stood out to me.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;[InstCombine] Use ComputeNumSignBits in isKnownExactCastIntToFP (#190235)

For signed int-to-FP casts, ComputeNumSignBits can prove exactness where
computeKnownBits cannot -- e.g. through ashr(shl x, a), b where sign propagation is
tracked precisely but individual known bits are all unknown.&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:rounded-lg hx:border hx:py-2 hx:ltr:pr-4 hx:rtl:pl-4 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-blue-200 hx:bg-blue-100 hx:text-blue-900 hx:dark:border-blue-200/30 hx:dark:bg-blue-900/30 hx:dark:text-blue-200&#34;&gt;
  &lt;div class=&#34;hx:ltr:pl-3 hx:ltr:pr-2 hx:rtl:pr-3 hx:rtl:pl-2&#34;&gt;&lt;svg height=1.2em class=&#34;hx:inline-block hx:align-middle&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z&#34;/&gt;&lt;/svg&gt;&lt;/div&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;strong&gt;InstCombine&lt;/strong&gt; is an LLVM middle-end optimization pass that combines adjacent or related instructions into single, more efficient operations. It&amp;rsquo;s broad in its duties, so examples of InstCombine optimizations can vary. For example, InstCombine can reduce &lt;code&gt;x = x * 2&lt;/code&gt; to &lt;code&gt;x = x &amp;lt;&amp;lt; 1&lt;/code&gt;;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Given that the newest build can no longer cast that integer to a float, this commit message with the &lt;code&gt;int-to-FP casts (sitofp/uitofp)&lt;/code&gt; immediately roused my suspicions, and they were confirmed when I built LLVM before and after that commit. Before this change, everything worked and afterward, &lt;code&gt;fdiv.d&lt;/code&gt; instructions appeared in the assembly.&lt;/p&gt;
&lt;p&gt;I should also note that this patch &lt;em&gt;is&lt;/em&gt; an improvement - the InstCombiner pass has &lt;em&gt;more&lt;/em&gt; information available to it - but sometimes improvements can cause regression(s) elsewhere in unforeseeable ways. I would posit this gives opportunities for folks like me to contribute &amp;#x1f605;&lt;/p&gt;
&lt;h3&gt;Why is this happening?&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;why-is-this-happening&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#why-is-this-happening&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Looking at the diff on this commit, I can see that that the author of the patch added known bit analysis to the function &lt;code&gt;isKnownExactCastIntToFP&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;isKnownExactCastIntToFP&lt;/span&gt;(CastInst &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;I, InstCombinerImpl &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;IC) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// For sitofp, the sign maps to the FP sign bit, so only magnitude bits
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// (BitWidth - NumSignBits) consume mantissa.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (IsSigned) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    SigBits &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt;)SrcTy&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;getScalarSizeInBits() &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; IC.ComputeNumSignBits(Src, &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;I);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (SigBits &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;=&lt;/span&gt; DestNumSigBits)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#89dceb&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#89dceb&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;You don&amp;rsquo;t need an in-depth understanding of what this changed did, but we can infer that this change is causing &lt;code&gt;isKnownExactCastIntToFP&lt;/code&gt; to return &lt;em&gt;true&lt;/em&gt;, when it was returning &lt;em&gt;false&lt;/em&gt; before. So I decided to look at all the call sites of &lt;code&gt;isKnownExactCastIntToFP&lt;/code&gt; to gain a better understanding of how this could lead to a regression.&lt;/p&gt;
&lt;p&gt;The following function calls &lt;code&gt;isKnownExactCastIntToFP&lt;/code&gt;. It is called to reduce an &lt;code&gt;fpext&lt;/code&gt; instruction if a preceding instruction casts an integer to FP like so: &lt;code&gt;itofp i64 x to float&lt;/code&gt; -&amp;gt; &lt;code&gt;fpext float x to double&lt;/code&gt;. This can just be reduced to a &lt;code&gt;itofp i64 x to double&lt;/code&gt; instead.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Instruction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;InstCombinerImpl&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;visitFPExt(CastInst &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;FPExt) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// If the source operand is a cast from integer to FP and known exact, then
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// cast the integer operand directly to the destination type.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  Type &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;Ty &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; FPExt.getType();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Value &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;Src &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; FPExt.getOperand(&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (isa&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;SIToFPInst&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;(Src) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;||&lt;/span&gt; isa&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;UIToFPInst&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;(Src)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;FPCast &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; cast&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;CastInst&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;(Src);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (isKnownExactCastIntToFP(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;FPCast))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; CastInst&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;Create(FPCast&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;getOpcode(), FPCast&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;getOperand(&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;), Ty);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;commonCastTransforms&lt;/span&gt;(FPExt);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And this puts it together.&lt;/p&gt;
&lt;p&gt;Referring the LLVM IR that was generated at the beginning of the pipeline.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-llvm&#34; data-lang=&#34;llvm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv&lt;/span&gt;  = &lt;span style=&#34;color:#cba6f7&#34;&gt;sitofp&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%5&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;; int -&amp;gt; float
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv2&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;fpext&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;   &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;; float -&amp;gt; double 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%div3&lt;/span&gt;  = &lt;span style=&#34;color:#cba6f7&#34;&gt;fdiv&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv2&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;7.438300e+04&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;; fdiv.d 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv4&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;fptrunc&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%div3&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;;&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;-&lt;/span&gt;&amp;gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And the LLVM IR at the end of the pipeline.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-llvm&#34; data-lang=&#34;llvm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv2&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;uitofp&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;nneg&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%0&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%div3&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;fdiv&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv2&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;7.438300e+04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv4&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;fptrunc&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%div3&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph TD
    %% Node Definitions
    N1[&amp;#34;%conv = sitofp i64 %5 to float&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;int -&amp;gt; float&amp;lt;/i&amp;gt;&amp;#34;]
    N2[&amp;#34;%conv2 = fpext float %conv to double&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;float -&amp;gt; double&amp;lt;/i&amp;gt;&amp;#34;]
    N3[&amp;#34;%div3 = fdiv double %conv2, 7.438300e+04&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;fdiv.d&amp;lt;/i&amp;gt;&amp;#34;]
    N4[&amp;#34;%conv4 = fptrunc double %div3 to float&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;double -&amp;gt; float&amp;lt;/i&amp;gt;&amp;#34;]

    %% Data Flow
    N1 --&amp;gt; N2
    N2 --&amp;gt; N3
    N3 --&amp;gt; N4

    %% Subgraph
    subgraph CastGroup [&amp;#34;Initial Casts&amp;#34;]
        direction TB
        N1
        N2
    end

    %% Annotation Node
    AnnotateNode[&amp;#34;&amp;lt;b&amp;gt;InstCombinerCast&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;Reduces this pattern to %conv2 = uitofp nneg i64 %0 to double&amp;#34;]
    
    %% Styling - Using neutral strokes that work in both modes
    style AnnotateNode fill:#0288d122,stroke:#0288d1,stroke-width:2px,rx:10,ry:10
    style CastGroup fill:none,stroke:#888,stroke-dasharray: 5 5

    %% Invisible edges for layout
    AnnotateNode -.-&amp;gt; N1
    AnnotateNode -.-&amp;gt; N2
  &lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The InstCombiner pass after that patch is able to optimize the &lt;code&gt;sitofp i64 to float&lt;/code&gt;, followed by &lt;code&gt;fpext float to double&lt;/code&gt; by reducing it a single &lt;code&gt;uitofp nneg i64 %0 to double&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, &lt;code&gt;visitFPTrunc&lt;/code&gt; optimized the following pattern as commented in the code:&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;// If we have fptrunc(OpI (fpextend x), (fpextend y)), we would like to&lt;/p&gt;
&lt;p&gt;// simplify this expression to avoid one or more of the trunc/extend&lt;/p&gt;
&lt;p&gt;// operations if we can do so without changing the numerical results.&lt;/p&gt;
&lt;p&gt;//&lt;/p&gt;
&lt;p&gt;// The exact manner in which the widths of the operands interact to limit&lt;/p&gt;
&lt;p&gt;// what we can and cannot do safely varies from operation to operation, and&lt;/p&gt;
&lt;p&gt;// is explained below in the various case statements.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The optimized LLVM IR now no longer has that &lt;code&gt;fpext&lt;/code&gt; instruction, so the InstCombiner pass and specifically &lt;code&gt;visitFPTrunc&lt;/code&gt; can no longer narrow the double to a float.&lt;/p&gt;
&lt;h2&gt;Landing a solution&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;landing-a-solution&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#landing-a-solution&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;So we diagnosed the issue - the recent patch to InstCombine, which improved the logic, causes the pass to no longer be able to perform another optimization. We need to teach the InstCombiner to narrow an operation earlier with the &lt;code&gt;uitofp&lt;/code&gt;/&lt;code&gt;sitofp&lt;/code&gt; if there&amp;rsquo;s an &lt;code&gt;fptrunc&lt;/code&gt; later anyways.&lt;/p&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph TD
    %% Define the Instruction Spine
    subgraph Flow [&amp;#34;LLVM Data Flow&amp;#34;]
        direction TB
        N0[&amp;#34;%0 = urem i64 %mul, 74383&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;Range Provider: 0 to 74,382&amp;lt;/i&amp;gt;&amp;#34;]
        N1[&amp;#34;%conv2 = uitofp nneg i64 %0 to double&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;Integer to Double&amp;lt;/i&amp;gt;&amp;#34;]
        N2[&amp;#34;%div3 = fdiv double %conv2, 7.438300e+04&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;Double Division&amp;lt;/i&amp;gt;&amp;#34;]
        N3[&amp;#34;%conv4 = fptrunc double %div3 to float&amp;lt;br/&amp;gt;&amp;lt;i&amp;gt;Double to Float&amp;lt;/i&amp;gt;&amp;#34;]

        %% Define the vertical chain
        N0 --&amp;gt; N1
        N1 --&amp;gt; N2
        N2 --&amp;gt; N3
    end

    %% Define the Optimizer Node on the side
    IC[&amp;#34;&amp;lt;b&amp;gt;InstCombiner&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;Reduces to float-precision&amp;lt;br/&amp;gt;math if inputs fit.&amp;#34;]
    
    %% Styling: Using #AARRGGBB or #RRGGBBAA logic for Hextra
    %% fill:#1b5e2022 is a very transparent green (approx 13% opacity)
    style IC fill:#1b5e2022,stroke:#4caf50,stroke-width:2px,rx:10,ry:10
    
    %% Subgraph styling to keep it neutral
    style Flow fill:none,stroke:#888888,stroke-dasharray: 5 5

    %% Dotted arrow connections
    IC -.-&amp;gt; N0
    IC -.-&amp;gt; N1
    IC -.-&amp;gt; N3
  &lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;I first raised an issue on Github. While I was confident that this was a valid issue, I wanted to double check that this warranted a fix. I do want to thank the author of that patch I mentioned earlier, &lt;code&gt;@SavchenkoValeriy&lt;/code&gt;, as he was able to offer me guidance on solving this issue, as well as providing reviews to my PR. My very initial solution would&amp;rsquo;ve been pretty convoluted but he was able to offer me a much simpler approach.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GitHub Issue:&lt;/strong&gt;
&lt;a href=&#34;https://github.com/llvm/llvm-project/issues/190503&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://github.com/llvm/llvm-project/issues/190503&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;PR:&lt;/strong&gt;
&lt;a href=&#34;https://github.com/llvm/llvm-project/pull/190550&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://github.com/llvm/llvm-project/pull/190550&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As pointed out by my reviewer, the current issue with &lt;code&gt;isKnownExactCastIntToFP&lt;/code&gt; currently only checks if the casting instruction &lt;code&gt;CastInst&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-llvm&#34; data-lang=&#34;llvm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%0&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;urem&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%mul&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;74383&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv2&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;uitofp&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;nneg&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%0&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%div3&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;fdiv&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv2&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;7.438300e+04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv4&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;fptrunc&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%div3&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The code below is the &lt;code&gt;visitFPTrunc&lt;/code&gt; function You can see the switch statement with the different operations, including the FDiv, and this corresponds to the &lt;code&gt;fdiv.d&lt;/code&gt;/&lt;code&gt;fdiv.s&lt;/code&gt;. &lt;code&gt;FPT&lt;/code&gt; corresponds to the &lt;code&gt;fptrunc&lt;/code&gt; instruction, &lt;code&gt;BO&lt;/code&gt; corresponds to &lt;code&gt;FPT.getOperand(0)&lt;/code&gt;, so it would refer to &lt;code&gt;%conv2&lt;/code&gt;. We need to see if we can instead convert this uitofp into a float, so we need to modify &lt;code&gt;getMinimumFPType&lt;/code&gt; to check for cast operations as well as &lt;code&gt;fpext&lt;/code&gt; instructions.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Instruction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;InstCombinerImpl&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;visitFPTrunc(FPTruncInst &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;FPT) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (Instruction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;I &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; commonCastTransforms(FPT))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; I;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Type &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;Ty &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; FPT.getType();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;auto&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;BO &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; dyn_cast&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;BinaryOperator&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;(FPT.getOperand(&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (BO &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; BO&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;hasOneUse()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Type &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;LHSMinType &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; getMinimumFPType(BO&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;getOperand(&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;), PreferBFloat);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Type &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;RHSMinType &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; getMinimumFPType(BO&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;getOperand(&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;), PreferBFloat);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;switch&lt;/span&gt; (BO&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;getOpcode()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;default&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;case&lt;/span&gt; Instruction&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;FAdd&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;case&lt;/span&gt; Instruction&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;FSub&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;One of my initial idea was to modify &lt;code&gt;isKnownExactCastIntToFP&lt;/code&gt; to accept a parameter with a different &lt;em&gt;Type&lt;/em&gt; (&lt;code&gt;f32&lt;/code&gt; in my case) but with a default &lt;em&gt;nullptr&lt;/em&gt; value. This would allow us to modify just the header definition and its implementation. My reviewer instead proposed the idea of making a variant of &lt;code&gt;isKnownExactCastIntToFP&lt;/code&gt;, &lt;code&gt;canBeCastedExactlyIntToFP&lt;/code&gt;. This will do the actual analysis with the type given to it, and &lt;code&gt;isKnownExactCastIntToFP&lt;/code&gt; can call it. I mention this to show that it&amp;rsquo;s good to interact with the community and seek ideas from others. They can come up with ideas which for a variety of reasons could be better.&lt;/p&gt;
&lt;p&gt;Below is the final git diff. We split &lt;code&gt;isKnownExactCastIntToFP&lt;/code&gt; and created &lt;code&gt;canBeCastedExactlyIntToFP&lt;/code&gt; to perform the actual analysis, and &lt;code&gt;isKnownExactCastIntToFP&lt;/code&gt; call it. Then, we have &lt;code&gt;getMinimumFPType&lt;/code&gt; call &lt;code&gt;canBeCastedExactlyIntToFP&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;index bc52bf1168d4..2688891c1509 100644
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;--- a/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+++ b/llvm/include/llvm/Transforms/InstCombine/InstCombiner.h
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;@@ -481,6 +481,8 @@ public:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;&lt;/span&gt;   /// Return true if the cast from integer to FP can be proven to be exact
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   /// for all possible inputs (the conversion does not lose any precision).
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   bool isKnownExactCastIntToFP(CastInst &amp;amp;I) const;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+  bool canBeCastedExactlyIntToFP(Value *V, Type *FPTy, bool IsSigned,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+                                 const Instruction *CxtI = nullptr) const;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   OverflowResult computeOverflowForUnsignedMul(const Value *LHS,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                                const Value *RHS,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;index e3c39a3c193e..0cd035bd1413 100644
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;@@ -2039,10 +2039,17 @@ static Type *shrinkFPConstantVector(Value *V, bool PreferBFloat) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#fab387;font-weight:bold&#34;&gt;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; /// Find the minimum FP type we can safely truncate to.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;-static Type *getMinimumFPType(Value *V, bool PreferBFloat) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8;background-color:#313244&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+static Type *getMinimumFPType(Value *V, Type *PreferredTy, InstCombiner &amp;amp;IC) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;&lt;/span&gt;   if (auto *FPExt = dyn_cast&amp;lt;FPExtInst&amp;gt;(V))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     return FPExt-&amp;gt;getOperand(0)-&amp;gt;getType();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+  Value *Src;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+  if (match(V, m_IToFP(m_Value(Src))) &amp;amp;&amp;amp;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+      IC.canBeCastedExactlyIntToFP(Src, PreferredTy, isa&amp;lt;SIToFPInst&amp;gt;(V),
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+                                   cast&amp;lt;Instruction&amp;gt;(V)))
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+    return PreferredTy;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e3a1;background-color:#313244&#34;&gt;+  bool PreferBFloat = PreferredTy-&amp;gt;getScalarType()-&amp;gt;isBFloatTy();
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Notice how we now call &lt;code&gt;canBeCastedExactlyIntToFP&lt;/code&gt; with the Type of the &lt;code&gt;fptrunc&lt;/code&gt; instruction being passed in. &lt;code&gt;Src&lt;/code&gt; in this case is the input to &lt;code&gt;BO-&amp;gt;getOperand(0)&lt;/code&gt;, and &lt;code&gt;BO&lt;/code&gt; is the &lt;em&gt;0th&lt;/em&gt; operand of the fptrunc instruction. Remember the llvm ir earlier:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-llvm&#34; data-lang=&#34;llvm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%0&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;urem&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%mul&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;74383&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv2&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;uitofp&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;nneg&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%0&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%div3&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;fdiv&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv2&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;7.438300e+04&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv4&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;fptrunc&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;double&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%div3&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The fptrunc is converting the input into a float, so the type &lt;code&gt;Ty&lt;/code&gt; is f32. &lt;code&gt;BO&lt;/code&gt; is &lt;code&gt;%div3&lt;/code&gt;, &lt;code&gt;BO-&amp;gt;getOperand(0)&lt;/code&gt; is &lt;code&gt;%conv2&lt;/code&gt; and the &lt;code&gt;m_IToFP(m_Value(Src))&lt;/code&gt; puts the input of &lt;code&gt;BO-&amp;gt;getOperand(0)&lt;/code&gt; into &lt;code&gt;Src&lt;/code&gt;. The table below shows the mapping of the &lt;code&gt;visitFPTrunc&lt;/code&gt; code to the &lt;code&gt;LLVM IR&lt;/code&gt; variables.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;&lt;code&gt;visitFPTrunc&lt;/code&gt; Variables&lt;/th&gt;
          &lt;th&gt;LLVM IR Variables&lt;/th&gt;
          &lt;th&gt;Value&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;BO&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;%div3&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;fdiv double %conv2, 7.438300e+04&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;BO-&amp;gt;getOperand(0)&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;%conv2&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;uitofp nneg i64 %0 to double&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;BO-&amp;gt;getOperand(1)&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;7.438300e+04&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;double constant&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;Src&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;%0&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;urem i64 %mul, 74383&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Result&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;result&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#result&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Did this work? By running the command below we can see the LLVM IR after my patch.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;$LLVM_BUILD_DIR&lt;/span&gt;/bin/clang -O3 &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  --target&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;riscv64-unknown-linux-gnu &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  -march&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;rv64gc_zba_zbb &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  --sysroot&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;/usr/riscv64-linux-gnu &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;  -S -emit-llvm pi.c -o pi_fixed.ll&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And this is the relevant LLVM IR.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-llvm&#34; data-lang=&#34;llvm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%mul&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;mul&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;nuw&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;nsw&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%ixran.053&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;27611&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%0&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;urem&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%mul&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;74383&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%1&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;uitofp&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;nneg&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;i64&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%0&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;to&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f5e0dc&#34;&gt;%conv4&lt;/span&gt; = &lt;span style=&#34;color:#cba6f7&#34;&gt;fdiv&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;float&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;%1&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;7.438300e+04&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;It worked! &amp;#x1f979;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;fptrunc&lt;/code&gt; is gone, and the cast operation &lt;code&gt;uitofp&lt;/code&gt; now converts it into a float.&lt;/p&gt;
&lt;p&gt;Shown below are the results after my patch was merged. We can see that the target can execute the benchmark in 1.67 Bn cycles, about a 25% improvement.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://cc-perf.igalia.com/db_default/v4/nts/profile/260/426/422&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://cc-perf.igalia.com/db_default/v4/nts/profile/260/426/422&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/tracking-down-a-25-regression-on-llvm-risc-v/improvement.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;
&lt;img src=&#34;https://blog.kavin.me/blog/tracking-down-a-25-regression-on-llvm-risc-v/improvement_cycle.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
      </description>
    </item>
    
    <item>
      <title>Analysing a Benchmark on LLVM RISCV</title>
      <link>https://blog.kavin.me/blog/analysing-a-benchmark-on-llvm-riscv/</link>
      <pubDate>Sun, 05 Apr 2026 18:14:45 -0400</pubDate>
      
      <guid>https://blog.kavin.me/blog/analysing-a-benchmark-on-llvm-riscv/</guid>
      <description>
        
        
        &lt;p&gt;This was my attempt at improving a benchmark on LLVM RISCV. Unfortunately, the solution to this problem is kind of out of my league. But the attempt does make for a good blog post.&lt;/p&gt;
&lt;h2&gt;Introduction&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;introduction&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#introduction&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Recently, I found this &lt;a href=&#34;https://lukelau.me/2025/12/10/closing-the-gap-pt1.html&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;blog&lt;/a&gt; post by Luke Lau, in which he shows how he was able to make improvements to the middle-end (and ultimately the generated code) in LLVM, resulting in better performance for RISC-V targets on LLVM. He does this by comparing the assembly of LLVM and GCC with the llvm test suite and analysing the cases where LLVM falls behind.&lt;/p&gt;
&lt;p&gt;I found this whole process of looking at assembly and figuring out where the root issue to be very interesting, and this blog goes over my first thorough attempt at this.&lt;/p&gt;
&lt;p&gt;I should also note that the company Igalia hosts these benchmarks, and runs periodic updates. You can take a &lt;a href=&#34;https://cc-perf.igalia.com/db_default/v4/nts/recent_activity&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;look&lt;/a&gt; and see how LLVM compares to GCC on certain RISCV targets.&lt;/p&gt;
&lt;h2&gt;Code Analysis&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;code-analysis&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#code-analysis&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;This &lt;a href=&#34;https://cc-perf.igalia.com/db_default/v4/nts/profile/312/320/319&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;link&lt;/a&gt; will take you to the benchmark, but I have pasted the relevant assembly in the sections below, as well as the relevant source code. Another thing to note is that the CPU used in this benchmark is the Banana Pi F3, a 64-bit &lt;strong&gt;in-order&lt;/strong&gt; CPU with RISCV&amp;rsquo;s vector extension, &lt;em&gt;RVV&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I will go into a level of detail that&amp;rsquo;s probably not necessary, but as I&amp;rsquo;m still new to assembly, I found understanding what each instruction to be helpful. If you&amp;rsquo;re already familiar with assembly or not really interested in the nitty gritty, feel free to skim over this section.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/llvm/llvm-test-suite/blob/main/SingleSource/Benchmarks/Shootout/ary3.c&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; (k&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;; k&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;1000&lt;/span&gt;; k&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; (i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; n&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;; i&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;--&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    y[i] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+=&lt;/span&gt; x[i];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-blue-200 hx:bg-blue-100 hx:text-blue-900 hx:dark:border-blue-200/30 hx:dark:bg-blue-900/30 hx:dark:text-blue-200&#34;&gt;
  &lt;p class=&#34;hx:flex hx:items-center hx:font-medium&#34;&gt;&lt;svg height=16px class=&#34;hx:inline-block hx:align-middle hx:mr-2&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z&#34;/&gt;&lt;/svg&gt;Note&lt;/p&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;p&gt;The inner loop here does not have any dependency on the outer loop (as in k is not use as a subscript
in the inner loop).&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This is the results of the benchmark.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/analysing-a-benchmark-on-llvm-riscv/benchmark_result.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h3&gt;LLVM&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;llvm&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#llvm&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;BB1:&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;li&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a3&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0x0&lt;/span&gt;      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;mv&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a4&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;s0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;BB2:&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;vsetvli&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a5&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a4&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;e32&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;m2&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;ta&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;ma&lt;/span&gt;      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;not&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a2&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a3&lt;/span&gt;      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;add&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a2&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a2&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;s0&lt;/span&gt;      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;sub&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;t0&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a5&lt;/span&gt;      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;sh2add&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a2&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;s2&lt;/span&gt;      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;sh2add&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a2&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a2&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;s1&lt;/span&gt;      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;sh2add&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt;      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;sh2add&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a2&lt;/span&gt;      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;vle32.v&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;v8&lt;/span&gt;, (&lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt;)      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;vle32.v&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;v10&lt;/span&gt;, (&lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;)      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;sub&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a4&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a4&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a5&lt;/span&gt;      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;vadd.vv&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;v8&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;v10&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;v8&lt;/span&gt;      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;vse32.v&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;v8&lt;/span&gt;, (&lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;)      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;add&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a3&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a3&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a5&lt;/span&gt;      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;bnez&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a4&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0x7b2&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#f9e2af&#34;&gt;main&lt;/span&gt;+&lt;span style=&#34;color:#fab387&#34;&gt;0x7a&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;BB3:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;addiw&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a7&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a7&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0x1&lt;/span&gt;      	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;bne&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a7&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a6&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0x7ae&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#f9e2af&#34;&gt;main&lt;/span&gt;+&lt;span style=&#34;color:#fab387&#34;&gt;0x76&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph TD
    BB1 --&amp;gt; BB2
    BB2 --&amp;gt; BB3
    BB3 --&amp;gt; BB2
    BB2 --&amp;gt; BB2
  &lt;/pre&gt;
&lt;/div&gt;&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:flex-col hx:rounded-lg hx:border hx:py-4 hx:px-4 hx:border-gray-200 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-green-200 hx:bg-green-100 hx:text-green-900 hx:dark:border-green-200/30 hx:dark:bg-green-900/30 hx:dark:text-green-200&#34;&gt;
  &lt;p class=&#34;hx:flex hx:items-center hx:font-medium&#34;&gt;&lt;svg height=16px class=&#34;hx:inline-block hx:align-middle hx:mr-2&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z&#34;/&gt;&lt;/svg&gt;Info&lt;/p&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;p&gt;A Basic Block is a sequence of instructions in a program that executes linearly, meaning it has exactly one entry point at the start and one exit point at the end. Because there are no internal jumps or branches, once the first instruction is triggered, the entire block is guaranteed to execute in order.&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This is a bit of a doozy, but it&amp;rsquo;s not too bad when you match it with the source code. The middle basic block is basically doing the third line of the code snippet provided.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;y[i] &amp;#43;= x[i];&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The four &lt;code&gt;sh2add&lt;/code&gt; instructions are getting the location of the addresses of &lt;code&gt;y[i]&lt;/code&gt; and &lt;code&gt;x[i]&lt;/code&gt;. They perform the following logic:
&lt;/p&gt;
\[
Op0 = Op1 \times 4 &amp;#43; Op2
\]&lt;p&gt;In this case, Op2 is the base address and Op1 is the index &lt;code&gt;i&lt;/code&gt; or &lt;em&gt;induction variable&lt;/em&gt;, and multiplying by four (an integer is 4 bytes), will get us the correct address. We see four of these instructions since there&amp;rsquo;s two arrays and the inner for loop is decrementing in value.&lt;/p&gt;
&lt;p&gt;Notice how third &lt;code&gt;sh2add&lt;/code&gt; is writing it&amp;rsquo;s result into &lt;code&gt;a0&lt;/code&gt;, and how the result of the second &lt;code&gt;sh2add&lt;/code&gt; is just needed as an operand for the fourth &lt;code&gt;sh2add&lt;/code&gt;. Essentially, the registers to take note of are &lt;code&gt;a0&lt;/code&gt;, and &lt;code&gt;a1&lt;/code&gt;, as these are where the addresses were stored in.&lt;/p&gt;
&lt;p&gt;After that, we can see the two &lt;em&gt;vector&lt;/em&gt; load instructions &lt;code&gt;vle32.v&lt;/code&gt;, and a vector store instruction later &lt;code&gt;vse32.v&lt;/code&gt;.
At this point, you may be able to surmise that LLVM was able to vectorize this loop, as in was able to use the RVV extension of the BPI-F3 cpu to operate on multiple elements per iteration. Pretty cool!&lt;/p&gt;
&lt;h3&gt;GCC&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;gcc&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#gcc&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;BB1:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;lw&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a3&lt;/span&gt;,&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;(&lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;)	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;lw&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a4&lt;/span&gt;,&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;(&lt;span style=&#34;color:#f9e2af&#34;&gt;a2&lt;/span&gt;)	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;li&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a5&lt;/span&gt;,&lt;span style=&#34;color:#fab387&#34;&gt;500&lt;/span&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;slliw&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a3&lt;/span&gt;,&lt;span style=&#34;color:#f9e2af&#34;&gt;a3&lt;/span&gt;,&lt;span style=&#34;color:#fab387&#34;&gt;0x1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;BB2:&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;addiw&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a5&lt;/span&gt;,&lt;span style=&#34;color:#f9e2af&#34;&gt;a5&lt;/span&gt;,-&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;addw&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a4&lt;/span&gt;,&lt;span style=&#34;color:#f9e2af&#34;&gt;a4&lt;/span&gt;,&lt;span style=&#34;color:#f9e2af&#34;&gt;a3&lt;/span&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;bnez&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a5&lt;/span&gt;,&lt;span style=&#34;color:#fab387&#34;&gt;1064&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;e&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;main&lt;/span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;+&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;0x8e&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;BB3:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;sw&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a4&lt;/span&gt;,&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;(&lt;span style=&#34;color:#f9e2af&#34;&gt;a2&lt;/span&gt;)	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;addi&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a2&lt;/span&gt;,&lt;span style=&#34;color:#f9e2af&#34;&gt;a2&lt;/span&gt;,-&lt;span style=&#34;color:#fab387&#34;&gt;4&lt;/span&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;addi&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;,&lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;,-&lt;span style=&#34;color:#fab387&#34;&gt;4&lt;/span&gt;	
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;bne&lt;/span&gt;	&lt;span style=&#34;color:#f9e2af&#34;&gt;a2&lt;/span&gt;,&lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt;,&lt;span style=&#34;color:#fab387&#34;&gt;10642&lt;/span&gt; &amp;lt;&lt;span style=&#34;color:#f9e2af&#34;&gt;main&lt;/span&gt;+&lt;span style=&#34;color:#fab387&#34;&gt;0x82&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph TD
    BB1 --&amp;gt; BB2
    BB2 --&amp;gt; BB3
    BB3 --&amp;gt; BB2
    BB2 --&amp;gt; BB2
  &lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;What GCC did here was very clever. Essentially, GCC&amp;rsquo;s middle-end performed what&amp;rsquo;s called a &lt;em&gt;Loop Interchange&lt;/em&gt;. It swapped the inner loop for the outer loop, resulting in something would look like the following in code.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; (i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; n&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;; i&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;--&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; (k&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;; k&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;1000&lt;/span&gt;; k&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    y[i] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+=&lt;/span&gt; x[i];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Why is this better? Take a look at the &lt;em&gt;CFG&lt;/em&gt; and assembly and notice how the second basic block, BB2, in both the GCC assembly and LLVM points to itself. It&amp;rsquo;s more obvious if you look at the website, as it clearly shows those basic blocks as &lt;em&gt;hotspots&lt;/em&gt;, in which the program spends most of its cycles on these basic blocks. In this case, both programs spend 99% of their cycles on BB2.&lt;/p&gt;
&lt;p&gt;By doing the interchange, GCC has only add operations in BB2, while LLVM has two loads and a store. Meaning that when Banana Pi runs the code produced by clang, it will get a lot of &lt;em&gt;cache misses&lt;/em&gt; and &lt;em&gt;stalls&lt;/em&gt;. If you look at the image of the benchmark results, you can see that despite LLVM issuing less instructions, it still takes several more cycles. This is because the CPU has a limited size cache, and if the memory it&amp;rsquo;s looking for is not in cache, it has to go down the cache hierarchy to look for it, and each tier of memory is significantly slower.&lt;/p&gt;
&lt;p&gt;I found it pretty cool to visually see the direct impact your code can have on the performance, and how compilers can significantly improve performance. In this case, just reordering the loop can significantly increase the performance.&lt;/p&gt;
&lt;h2&gt;Loop Interchange&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;loop-interchange&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#loop-interchange&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Ok great, the solution is to simply run loop interchange on LLVM as well. Unfortunately, the loop interchange is not enabled by default. I won&amp;rsquo;t even bother to summarize why as it seems quite complicated, but take a look at the &lt;a href=&#34;https://discourse.llvm.org/t/enabling-loop-interchange/82589&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;discourse&lt;/a&gt; if you&amp;rsquo;re curious. Suffice to say, it seems like there&amp;rsquo;s still work be done on the pass.&lt;/p&gt;
&lt;p&gt;But I was curious - I wanted to take a look at the &lt;em&gt;LLVM IR&lt;/em&gt; of the interchanged loop. I ran the following command to get emit the LLVM IR before the Loop Vectorizer pass.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;../bin/clang --target&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;riscv64-linux-gnu &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;    -march&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;rva22u64_v -mcpu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;spacemit-x60 -O3 &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;    --sysroot&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;/usr/riscv64-linux-gnu &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;    -mllvm -print-before&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;loop-vectorize &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;    -mllvm -print-module-scope &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;    -S -emit-llvm ary3.c -o ary3_prevec.ll&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then I ran the following command to get the LLVM IR, as well as the debug output, of the loop interchange pass and &lt;em&gt;DependenceAnalysis&lt;/em&gt;, which supports the Loop interchange pass.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;../bin/opt -passes&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#39;loop-interchange&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;    -mtriple&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;riscv64 -mattr&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;+v &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;    -debug-only&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;loop-interchange,da &lt;span style=&#34;color:#89b4fa&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;&lt;/span&gt;    -S ary3_prevec.ll -o ary3_interchange.ll 2&amp;gt; interchange_log.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This ultimately did not change the LLVM IR, indicating that loop interchange did not occur.&lt;/p&gt;
&lt;h3&gt;Troubleshooting&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;troubleshooting&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#troubleshooting&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Taking a look at the debug message, I noticed this excerpt which proved to be key in understanding why it did not work. By the way, &lt;code&gt;for.bod14.us&lt;/code&gt; is the name of the basic block for the inner for loop, equivalent to BB2 above.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;Dependency matrix before interchange:
* =
... 
Failed interchange InnerLoopId = 1 and OuterLoopId = 0 due to dependence
Cannot prove legality, not interchanging loops &amp;#39;for.cond11.preheader.us&amp;#39; and &amp;#39;for.body14.us&amp;#39;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I&amp;rsquo;ve listed some code from &lt;code&gt;LoopInterchange.cpp&lt;/code&gt; that should explain why the pass failed to run.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#f38ba8&#34;&gt;unsigned&lt;/span&gt; II &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;; II &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;=&lt;/span&gt; Levels; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;II) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// `DVEntry::LE` is converted to `*`. This is because `LE` means `&amp;lt;`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// or `=`, for which we don&amp;#39;t have an equivalent representation, so
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// that the conservative approximation is necessary. The same goes for
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// `DVEntry::GE`.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// TODO: Use of fine-grained expressions allows for more accurate
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// analysis.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;unsigned&lt;/span&gt; Dir &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; D&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;getDirection(II);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (Dir &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; Dependence&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;DVEntry&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;LT)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Direction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#39;&amp;lt;&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;if&lt;/span&gt; (Dir &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; Dependence&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;DVEntry&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;GT)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Direction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#39;&amp;gt;&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;if&lt;/span&gt; (Dir &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; Dependence&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;DVEntry&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;EQ)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Direction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#39;=&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Direction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Dep.push_back(Direction);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;And this code, which is called during the &lt;em&gt;legality&lt;/em&gt; check.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;static&lt;/span&gt; std&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;optional&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;bool&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;isLexicographicallyPositive(ArrayRef&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;char&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; DV, &lt;span style=&#34;color:#f38ba8&#34;&gt;unsigned&lt;/span&gt; Begin, &lt;span style=&#34;color:#f38ba8&#34;&gt;unsigned&lt;/span&gt; End) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#f38ba8&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;char&lt;/span&gt; &lt;span style=&#34;color:#89dceb&#34;&gt;Direction&lt;/span&gt; : DV.slice(Begin, End &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; Begin)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (Direction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#39;&amp;lt;&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#89dceb&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (Direction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#39;&amp;gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;||&lt;/span&gt; Direction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#89dceb&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; std&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;nullopt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Basically, the nested for loop in the source code was designated with a dependency matrix of &lt;code&gt;* =&lt;/code&gt;, which each character representing the dependency direction of each loop level. So the outer loop has a dependency direction of &lt;code&gt;*&lt;/code&gt; and the inner loop has a dependency direction of &lt;code&gt;=&lt;/code&gt;. I&amp;rsquo;m still don&amp;rsquo;t fully understand all the terminology used in this pass. Take a look at my &lt;a href=&#34;https://discourse.llvm.org/t/loopinterchange-some-questions-and-a-potential-missing-case/90270&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;discourse post&lt;/a&gt; where a user, @kasuga-fj, was kind enough to break this down for me.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;I’ve not checked the details, but at a glance, I think the dependency direction for the outer loop should be DVEntry::ALL. The direction represents the possible relationships between the values of k when the same memory location is accessed. More precisely, in this case, it answers this question: when regarding the access to y as a function f(k, i), what are the possible relations between k0 and k1 when f(k0, i) = f(k1, i) for some i?&lt;/p&gt;
&lt;p&gt;Here, f(k, i) = i. So, for example, f(0, 0) = f(1, 0) = &amp;hellip; = f(999, 0). Thus the outer loop has a dependency with all directions.&lt;/p&gt;
&lt;p&gt;&amp;hellip;&lt;/p&gt;
&lt;p&gt;I believe the right direction is to allow swapping the adjacent loops if the direction vector is * = or = *. But this is also non-trivial in terms of soundness, and we need to think this through a bit more…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;His proposed solution is to allow the swapping of the dependency matrix given it&amp;rsquo;s &lt;code&gt;*=&lt;/code&gt;. As shown in &lt;code&gt;isLexicographicallyPositive&lt;/code&gt;, this check fails since it&amp;rsquo;s specifically looks for &lt;code&gt;&amp;lt;&lt;/code&gt; character as the leftmost character. I&amp;rsquo;m guessing this hasn&amp;rsquo;t been implemented yet since it would probably cause a lot of regressions and/or would require more discussion among the community.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;conclusion&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#conclusion&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;All in all, this process was pretty rewarding. I couldn&amp;rsquo;t land a change to improve or fix this, nor did I did discover a missing case, but I do think this project was still worth it.&lt;/p&gt;
      </description>
    </item>
    
    <item>
      <title>My intro to the RISCV LLVM Backend: modifying an existing LLVM pass to merge GPRPair moves</title>
      <link>https://blog.kavin.me/blog/my-intro-to-riscv-backend/</link>
      <pubDate>Fri, 27 Feb 2026 18:02:45 -0500</pubDate>
      
      <guid>https://blog.kavin.me/blog/my-intro-to-riscv-backend/</guid>
      <description>
        
        
        &lt;p&gt;For a while now I&amp;rsquo;ve been interested in the RISCV architecture, and recently I had the opportunity to indulge this interest by working on a pass improving code gen on the RISCV backend for LLVM.&lt;/p&gt;
&lt;p&gt;Credits to @lenary to raising this issue.&lt;/p&gt;
&lt;p&gt;Relevant PRs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/llvm/llvm-project/pull/182416&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://github.com/llvm/llvm-project/pull/182416&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/llvm/llvm-project/pull/183657&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://github.com/llvm/llvm-project/pull/183657&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/llvm/llvm-project/pull/186600&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://github.com/llvm/llvm-project/pull/186600&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Some context&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;some-context&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#some-context&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;There exists a pass known as the RISCVMoveMerger. Prior to my work this pass was solely intended to merge particular instructions on RISCV targets with the &lt;code&gt;zcmp&lt;/code&gt; or &lt;code&gt;xqccmp&lt;/code&gt; extension. An extension can be thought of as an addition to the existing RISCV ISA.&lt;/p&gt;
&lt;p&gt;In assembly, we have instructions that move values between registers, referred to as &lt;em&gt;move&lt;/em&gt; or &lt;em&gt;copy&lt;/em&gt; instructions. In a 64-bit CPU, the registers would be 64 bits wide, and correspondingly, the registers would be 32-bits in a 32-bit CPU. A good chunk of variables in C/C++ are interpreted as 32-bits unless specified (int, float, etc.). So what happens when a code specifies a 64-bit integer on a 32-bit CPU? Well, something akin to the following. &lt;code&gt;mv&lt;/code&gt; indicates this is a &lt;em&gt;move&lt;/em&gt; instruction, the first operand is the destination, and the second operand is the source.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Copy the lower 32 bits
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;t0&lt;/span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Copy the upper 32 bits
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;t1&lt;/span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In the context of the RISCVMoveMerger, the &lt;code&gt;zcmp&lt;/code&gt; extension has two instructions of concern. They are &lt;code&gt;CM.MVSA01&lt;/code&gt; and &lt;code&gt;CM.MVA01S&lt;/code&gt;. They use the following syntax.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;r1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;r2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Statement below is equivalent.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// We are moving values in register r1 and r2 into a0 and a1 respectively.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;cm.mvsa01&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;r1&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;r2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;r1&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;r2&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Statement below is equivalent.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// We are moving values in register a0 and a1 into r1 and r2 respectively.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;cm.mva01s&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;r1&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;r2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;a0&lt;/code&gt; is designated as the first argument register. Whenever a function is called, it&amp;rsquo;s input parameters will be placed in &lt;code&gt;a0&lt;/code&gt;. For example, when calling &lt;code&gt;foo(int x)&lt;/code&gt;i, &lt;code&gt;x&lt;/code&gt; would be stored in &lt;code&gt;a0&lt;/code&gt;. These &lt;em&gt;compressed&lt;/em&gt; instructions take advantage of this by making the source and destination implicit. The &lt;code&gt;cm*&lt;/code&gt; don&amp;rsquo;t &lt;em&gt;implicitly&lt;/em&gt; define the source or destination registers, and instead implicitly use &lt;code&gt;a0&lt;/code&gt;/&lt;code&gt;a1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To get back to &lt;code&gt;RISCVMoveMerger&lt;/code&gt;, the goal of this pass was to find instructions like these two 32-bit moves:&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;r1&lt;/span&gt;         &lt;span style=&#34;color:#f9e2af&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;r1&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;r2&lt;/span&gt;         &lt;span style=&#34;color:#f9e2af&#34;&gt;mb&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;r2&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;and merge them to make use of &lt;code&gt;zcmp&lt;/code&gt;&amp;rsquo;s &lt;code&gt;cm.mv*&lt;/code&gt; instructions. It can be thought of as providing a &amp;ldquo;macro&amp;rdquo; to handle 64-bit logic in a single step.&lt;/p&gt;
&lt;h2&gt;My PR(s)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;my-prs&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#my-prs&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Hopefully that laid the ground work for what the &lt;code&gt;RISCVMoveMerger&lt;/code&gt; was doing prior to my work. I added onto this pass by extending to other types of possible 32-bit to 64-bit pairs for other targets. This was a task raised by @&lt;strong&gt;lenary&lt;/strong&gt;, who allowed me to pursue an implementation.&lt;/p&gt;
&lt;p&gt;RISCV supports quite a lot of different extension, and two extensions that concerns this pass is the &lt;code&gt;experimental-p&lt;/code&gt; and &lt;code&gt;zdinx&lt;/code&gt; target. They respectively support the instructions &lt;code&gt;addd&lt;/code&gt;, and &lt;code&gt;fsgnj.d&lt;/code&gt; which both can support &lt;code&gt;GPRPair&lt;/code&gt;s as operands. A GPRPair is a pair of registers which can be treated as one unit. We can take a look at &lt;code&gt;RISCVRegisterInfo.td&lt;/code&gt; - a tablegen file that describes the register info the RISCV architecture - to find out the exact details of GPRPairs.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-td&#34; data-lang=&#34;td&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#f5e0dc&#34;&gt;GPRPair&lt;/span&gt; : &lt;span style=&#34;color:#f5e0dc&#34;&gt;RISCVRegisterClass&lt;/span&gt;&amp;lt;[&lt;span style=&#34;color:#f5e0dc&#34;&gt;XLenPairVT&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;XLenPairFVT&lt;/span&gt;], &lt;span style=&#34;color:#fab387&#34;&gt;64&lt;/span&gt;, (&lt;span style=&#34;color:#f5e0dc&#34;&gt;add&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5e0dc&#34;&gt;X10_X11&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;X12_X13&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;X14_X15&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;X16_X17&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5e0dc&#34;&gt;X6_X7&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5e0dc&#34;&gt;X28_X29&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;X30_X31&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5e0dc&#34;&gt;X8_X9&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5e0dc&#34;&gt;X18_X19&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;X20_X21&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;X22_X23&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;X24_X25&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;X26_X27&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f5e0dc&#34;&gt;X0_Pair&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;X2_X3&lt;/span&gt;, &lt;span style=&#34;color:#f5e0dc&#34;&gt;X4_X5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)&amp;gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I hope this is starting to come together. RISCVMoveMerger can be additionally used to find two move instructions such that they can be merged into one instruction.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;s0&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;s1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// or 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;s1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;s0&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// This is the equivalent for zdinx.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;fmv.d&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;s0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// This is the equivalent for experimental-p. Note that a third operand is 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// used but this just adds zero to s0, so it&amp;#39;s still a move.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;addd&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;s0&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;zero&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Honestly at this point, I basically recounted the major points of my work. Reading further will go into some more minute details which I found interesting.&lt;/p&gt;
&lt;h3&gt;Current structure &amp;amp; New Functions&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;current-structure--new-functions&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#current-structure--new-functions&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;This was structure of the pass, and it can be noticed that the current function signatures are tied with finding and merging &lt;code&gt;cm.mv*&lt;/code&gt; instructions. For example, &lt;code&gt;MoveFromSToA&lt;/code&gt; is a helpful boolean parameter useful for &lt;code&gt;cm.mv*&lt;/code&gt; instructions, but useless for GPRPairs.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;isCandidateToMergeMVA01S&lt;/span&gt;(&lt;span style=&#34;color:#cba6f7&#34;&gt;const&lt;/span&gt; DestSourcePair &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;RegPair);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;isCandidateToMergeMVSA01&lt;/span&gt;(&lt;span style=&#34;color:#cba6f7&#34;&gt;const&lt;/span&gt; DestSourcePair &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;RegPair);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Merge the two instructions indicated into a single pair instruction.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  MachineBasicBlock&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;iterator
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  mergePairedInsns(MachineBasicBlock&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;iterator I,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   MachineBasicBlock&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;iterator Paired, &lt;span style=&#34;color:#f38ba8&#34;&gt;bool&lt;/span&gt; MoveFromSToA);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Look for C.MV instruction that can be combined with
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// the given instruction into CM.MVA01S or CM.MVSA01. Return the matching
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// instruction if one exists.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  MachineBasicBlock&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;iterator
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  findMatchingInst(MachineBasicBlock&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;iterator &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;MBBI, &lt;span style=&#34;color:#f38ba8&#34;&gt;bool&lt;/span&gt; MoveFromSToA,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#cba6f7&#34;&gt;const&lt;/span&gt; DestSourcePair &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;RegPair);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;mergeMoveSARegPair&lt;/span&gt;(MachineBasicBlock &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;MBB);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;bool&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;runOnMachineFunction&lt;/span&gt;(MachineFunction &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;Fn) &lt;span style=&#34;color:#cba6f7&#34;&gt;override&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The first two &lt;code&gt;isCandidate*&lt;/code&gt; bool helpers are used to indicate whether an instruction can be merged into a possible &lt;em&gt;cm.mv&lt;/em&gt; instruction. &lt;code&gt;mergePairedInsns&lt;/code&gt; is used when two potential instructions are found and the merged. &lt;code&gt;findMatchingInst&lt;/code&gt; is used when the first instruction is already found, and it looks for the second pair. &lt;code&gt;mergeMoveSARegPair&lt;/code&gt; is used to iterate through instructions in a basic block to initially find the instructions, and call the &lt;em&gt;find&lt;/em&gt; and &lt;em&gt;merge&lt;/em&gt; functions.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;mergeMoveSARegPair&lt;/em&gt; can definitely be reused, since it&amp;rsquo;s goal is to iterate through instructions. However, &lt;em&gt;findMatchingInst&lt;/em&gt; and &lt;em&gt;mergeMoveSARegPair&lt;/em&gt; are inherently tied to the &lt;em&gt;cm.mv&lt;/em&gt; instructions. For GPRPair, there needs to be very similar functions but with a different boolean parameter, &lt;code&gt;EvenRegPair&lt;/code&gt;, to indicate if a GPRPair is even or odd, since the logic to make the pair would be slightly different if the pair is even or odd. The snippet below from &lt;em&gt;mergeRegPairInsns&lt;/em&gt; may illuminate what I&amp;rsquo;m trying to convey.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;unsigned&lt;/span&gt; GPRPairIdx &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      RegPairIsEven &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;?&lt;/span&gt; RISCV&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;sub_gpr_even&lt;/span&gt; : RISCV&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;sub_gpr_odd;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SrcReg1 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; TRI&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;getMatchingSuperReg(FirstPair.Source&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;getReg(), GPRPairIdx,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                     &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;RISCV&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;GPRPairRegClass);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SrcReg2 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ST&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;hasStdExtZdinx() &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;?&lt;/span&gt; &lt;span style=&#34;color:#89dceb&#34;&gt;SrcReg1&lt;/span&gt; : Register(RISCV&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;X0_Pair);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  DestReg &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; TRI&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;getMatchingSuperReg(FirstPair.Destination&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;getReg(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                     GPRPairIdx, &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;RISCV&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;GPRPairRegClass);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Some DFA&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;some-dfa&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#some-dfa&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Dataflow analysis allows compilers to determine how data flows through the program. It allows compilers to make effective and safe decisions about optimizations. It&amp;rsquo;s essential to understand DFA to work with middle-end and back-end optimizations, and we get to see DFA in action at least within a basic block in this pass. Keep in mind that I did not write the code you&amp;rsquo;ll see in this section.&lt;/p&gt;
&lt;p&gt;Lets think up of a scenario where we found the first potential instruction pair, and the findMatchingInst/Pair is called to iterate through the rest of the basic block to find the second.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;s0&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;ld&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a2&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;s1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;We can see from the snippet above that there &lt;em&gt;could&lt;/em&gt; be a potential match here with a0, a1 and s0, s1. However, notice that before the second mv instruction is a &lt;em&gt;ld&lt;/em&gt; instruction. This instruction loads the value of a1 into a2. If we were to merge the two move instructions, a1 would get &lt;em&gt;overwritten&lt;/em&gt; and the data loaded into &lt;code&gt;a2&lt;/code&gt; would be invalid!&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-asm&#34; data-lang=&#34;asm&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Say we did merge it so now it&amp;#39;s mv a0_a1, s0_s1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;mv&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a0&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;s0&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// a2 would get the value of s1 instead of the previous (correct) value of a1!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;ld&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;a2&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;a1&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;em&gt;if statement&lt;/em&gt; with early return has a pretty good comment explaining it&amp;rsquo;s purpose and it solves this problem. If there are any instructions between the first instruction, and the second instruction which modifies or uses the destination register of the second instruction, return early.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; (MachineBasicBlock&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;iterator I &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; next_nodbg(MBBI, E); I &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!=&lt;/span&gt; E;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       I &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; next_nodbg(I, E)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    MachineInstr &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;MI &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;I;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#cba6f7&#34;&gt;auto&lt;/span&gt; SecondPair &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; TII&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;isCopyInstrImpl(MI)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      Register SourceReg &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; SecondPair&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;Source&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;getReg();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      Register DestReg &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; SecondPair&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;Destination&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;getReg();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f38ba8&#34;&gt;bool&lt;/span&gt; IsCandidate &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; MoveFromSToA &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;?&lt;/span&gt; isCandidateToMergeMVA01S(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;SecondPair)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                      &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&lt;/span&gt; isCandidateToMergeMVSA01(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;SecondPair);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (IsCandidate) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// If paired destination register was modified or used, the source reg
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// was modified, there is no possibility of finding matching
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// instruction so exit early.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!&lt;/span&gt;ModifiedRegUnits.available(DestReg) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;||&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!&lt;/span&gt;UsedRegUnits.available(DestReg) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;||&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!&lt;/span&gt;ModifiedRegUnits.available(SourceReg))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; E;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; I;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Update modified / used register units.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    LiveRegUnits&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Another DFA we can observe is ensuring the liveness or kill status of registers when moving the second register pair to the first pair&amp;rsquo;s location. The snippet below demonstrates the problem if the kill status is not considered. Note that the snippet below is an &lt;strong&gt;mir&lt;/strong&gt; file, a lower-level intermediate representation right before the final assembly.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;$x10 = COPY $x12               ; (I) The &amp;#34;Target&amp;#34; location for the merge
$x5  = ADD $x13, $x3           ; (It) Middle instruction READS $x13!
$x11 = COPY killed $x13        ; (Paired) The move we want to bring up to Line 1&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The third instruction, a &lt;em&gt;move&lt;/em&gt;/&lt;em&gt;copy&lt;/em&gt; instruction, can be merged with the first instruction. But note that the there is a keyword, &lt;em&gt;killed&lt;/em&gt; $x13. It indicates that this register, &lt;code&gt;$x13&lt;/code&gt; is not used after that instruction. If the compiler just moves this to the location of the first instruction and merges it, this would cause an error because it&amp;rsquo;s still &lt;em&gt;killed&lt;/em&gt; but the second instruction reads the value from $x13.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// PairSource is a copy of the second pair. 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// This for loop iterates from the first istruction to the second instruction.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// It checks if any other register reads the register of the second instruction.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// If it does, it sets the kill status to false.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#cba6f7&#34;&gt;auto&lt;/span&gt; It &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; std&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;next(I); It &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!=&lt;/span&gt; Paired &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; PairedSource.isKill(); &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;It)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (It&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;readsRegister(PairedSource.getReg(), TRI))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PairedSource.setIsKill(&lt;span style=&#34;color:#89dceb&#34;&gt;false&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Conclusion&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;conclusion&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#conclusion&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Overall, this was a pretty fun PR. It was pretty exciting to work on a PR that was not labelled a &amp;lsquo;Good First Issue&amp;rsquo;. Some things I want to keep pursuing are issues that in some manner require DFA.&lt;/p&gt;
      </description>
    </item>
    
    <item>
      <title>My First LLVM PR</title>
      <link>https://blog.kavin.me/blog/my-first-llvm-pr/</link>
      <pubDate>Fri, 21 Nov 2025 13:48:43 -0500</pubDate>
      
      <guid>https://blog.kavin.me/blog/my-first-llvm-pr/</guid>
      <description>
        
        
        &lt;p&gt;Honestly, it&amp;rsquo;s actually my second upstreamed PR, but I think it&amp;rsquo;s worth writing a blog about and the title sounds better
then &amp;lsquo;&lt;em&gt;My Second LLVM PR&lt;/em&gt;&amp;rsquo;.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also a revival of the work done by @huhu233, who implemented the feature of this PR for the ARM backend. I also received a lot of help from the PR reviewer, @RKSimon, to ensure the code is up to LLVM&amp;rsquo;s standards.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/llvm/llvm-project/pull/166839&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Link To PR&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;What &amp;amp; Why LLVM?&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;what--why-llvm&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#what--why-llvm&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;It&amp;rsquo;s essentially a modular compiler infrastructure that can be used to develop a compiler. It&amp;rsquo;s the backbone for Clang (C/C++), Rust, Zig (I think they&amp;rsquo;re migrating though). It&amp;rsquo;s also the industry standard GPU computing software, like CUDA and HIP. It&amp;rsquo;s fair to say it&amp;rsquo;s quite commonplace now in the compiler world.&lt;/p&gt;
&lt;p&gt;At a very high level birds-eye overview, LLVM converts the front-end language (C++, rust, CUDA, etc.) into &lt;em&gt;LLVM IR&lt;/em&gt; (Intermediate Representation). LLVM IR is sort of its own language, but understanding LLVM IR isn&amp;rsquo;t necessary to understand the work I have done, so I won&amp;rsquo;t try to explain it here. The magic of having the intermediate representation is it allows for &lt;strong&gt;language-agnostic&lt;/strong&gt; optimizations that can benefit every front-end.&lt;/p&gt;
&lt;p&gt;And the great thing about the llvm community is that they&amp;rsquo;re quite friendly to newcomers. Most importantly, there&amp;rsquo;s is a regular supply of &lt;code&gt;Good first issue&lt;/code&gt; on the llvm-project, making it easy for me to start contributing.&lt;/p&gt;
&lt;h2&gt;Brief SelectionDAG Overview&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;brief-selectiondag-overview&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#brief-selectiondag-overview&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;I think this &lt;a href=&#34;https://www.youtube.com/watch?v=nNQ6AF6i5FI&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;video&lt;/a&gt; is a great for beginners to understand how SelectionDAG works. I&amp;rsquo;ll try my best give a 1 minute crash course below to get a better grasp on what my PR does.&lt;/p&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph LR
    B[Frontend] --&amp;gt;|LLVM IR| D[opt]
    D --&amp;gt;|LLVM IR| F[llc]
    F --&amp;gt; G[Assembly]
    H[SelectionDAG] -.-&amp;gt; F
  &lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;From the diagram above, you can see that SelectionDAG is used when converting LLVM IR to the final assembly. It ensures the LLVM IR generated from &lt;code&gt;opt&lt;/code&gt; is suitable for the target used. For example, SelectionDAG will perform &lt;em&gt;Type Legalization&lt;/em&gt;, where it ensures the type used in the LLVM IR is actually supported on the target such as an &lt;code&gt;i24&lt;/code&gt;being promoted to an &lt;code&gt;i32&lt;/code&gt; for X86. This is just an example, and the video linked before goes much into details of the other things SelectionDAG does to ensure legal instructions are generated for the target.&lt;/p&gt;
&lt;h4&gt;SDValue&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;sdvalue&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#sdvalue&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;The SelectionDAG datastructure is composed of &lt;em&gt;nodes&lt;/em&gt; which can represent the actual operations in the IR, such as ADD, LOAD, OR STORE. SDValue represents the &lt;em&gt;output&lt;/em&gt; and &lt;em&gt;inputs&lt;/em&gt; of these nodes.&lt;/p&gt;
&lt;h4&gt;MVT&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;mvt&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#mvt&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;MVT is the union of tpyes that are supported by each targets that uses SelectionDAG. So an MVT could be an &lt;code&gt;i32&lt;/code&gt;, &lt;code&gt;f16&lt;/code&gt;, &lt;code&gt;v2f32&lt;/code&gt;, and the list goes on. You may also encounter an &lt;strong&gt;EVT&lt;/strong&gt;, which is union of the MVT types and all integer, float, and vector types supported by LLVM IR.&lt;/p&gt;
&lt;h2&gt;FLDEXP &amp;amp; SCALEF&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;fldexp--scalef&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#fldexp--scalef&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;ldexp&lt;/code&gt; is a function in C++ which multiplies a floating-point number by an integral power of two.&lt;/p&gt;
\[
ldexp(x, n) = x \times 2 ^ n 
\]&lt;p&gt;It allows for the precise manipulation of floating-point numbers by directly changing the &lt;code&gt;exponent&lt;/code&gt; without touching the &lt;code&gt;mantissa&lt;/code&gt;. This avoids rounding errors from repeated multiplication by 2, and ensures exact powers-of-two scaling in binary floating-point&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#94e2d5&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;math&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;math&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;.&lt;/span&gt;ldexp(&lt;span style=&#34;color:#fab387&#34;&gt;0.75&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;)  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;# 0.75 * 2^2 = 3.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;details class=&#34;hx:last-of-type:mb-0 hx:rounded-lg hx:bg-neutral-50 hx:dark:bg-neutral-800 hx:p-2 hx:mt-4 hx:group&#34; &gt;
  &lt;summary class=&#34;hx:flex hx:items-center hx:cursor-pointer hx:select-none hx:list-none hx:p-1 hx:rounded-sm hx:transition-colors hx:hover:bg-gray-100 hx:dark:hover:bg-neutral-800 hx:before:mr-1 hx:before:inline-block hx:before:transition-transform hx:before:content-[&#39;&#39;] hx:dark:before:invert hx:rtl:before:rotate-180 hx:group-open:before:rotate-90&#34;&gt;
    &lt;strong class=&#34;hx:text-lg&#34;&gt;Mantissa &amp;amp; Exponent&lt;/strong&gt;
  &lt;/summary&gt;
  &lt;div class=&#34;hx:p-2 hx:overflow-hidden&#34;&gt;
    &lt;p&gt;A floating-point number represents a value as:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;value = mantissa × 2^exponent&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mantissa (significand):&lt;/strong&gt; holds the significant digits&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exponent:&lt;/strong&gt; scales the mantissa by a power of 2&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
Decimal 6.5 → Binary &lt;code&gt;110.1₂&lt;/code&gt; → &lt;code&gt;1.101 × 2²&lt;/code&gt;&lt;br&gt;
Mantissa: &lt;code&gt;1.101&lt;/code&gt;, Exponent: &lt;code&gt;2&lt;/code&gt;&lt;/p&gt;
\[
Exponent: 2 &amp;#43; 127 = 129_{10} -&amp;gt; {10000001}_2 
\]&lt;p&gt;
&lt;/p&gt;
\[
Mantissa: 101
\]&lt;div style=&#34;font-family: monospace; display: flex; gap: 2px; margin-top: 5px;&#34;&gt;
  &lt;!-- Sign bit --&gt;
  &lt;div style=&#34;background:#ff5555; color:#000; padding:2px 4px; border-radius:2px;&#34;&gt;0&lt;/div&gt;
  &lt;!-- Exponent bits --&gt;
  &lt;div style=&#34;background:#55aaff; color:#000; padding:2px 4px; border-radius:2px;&#34;&gt;10000001&lt;/div&gt;
  &lt;!-- Mantissa bits --&gt;
  &lt;div style=&#34;background:#ffdd55; color:#000; padding:2px 4px; border-radius:2px;&#34;&gt;10100000000000000000000&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&#34;margin-top:4px; font-size:0.9em;&#34;&gt;
&lt;span style=&#34;color:#ff5555;&#34;&gt;Sign&lt;/span&gt; | 
&lt;span style=&#34;color:#55aaff;&#34;&gt;Exponent&lt;/span&gt; | 
&lt;span style=&#34;color:#ffdd55;&#34;&gt;Mantissa&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Basically. this allow for efficient representation of very large or very small numbers.&lt;br&gt;
Functions like &lt;code&gt;ldexp(x, n)&lt;/code&gt; scale the number precisely by powers of 2.&lt;/p&gt;
  &lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;Normally, when such a function gets &lt;em&gt;lowered&lt;/em&gt; into assembly, it would generate a lot of assembly since there is no direct mapping. However, the latest X86 CPU have an extension for vector &lt;em&gt;SIMD&lt;/em&gt; operations, called &lt;strong&gt;AVX-512&lt;/strong&gt;. Within the AVX-512 extension, is an instruction called &lt;strong&gt;VSCALEF&lt;/strong&gt; that essentially performs ldexp on multiple floating point values with a single instruction.
As the name implies, the extension comes with &lt;em&gt;512-bit&lt;/em&gt; registers, allowing the CPU to perform instructions on  multiple 64/32-bit elements at once.&lt;/p&gt;
&lt;details class=&#34;hx:last-of-type:mb-0 hx:rounded-lg hx:bg-neutral-50 hx:dark:bg-neutral-800 hx:p-2 hx:mt-4 hx:group&#34; &gt;
  &lt;summary class=&#34;hx:flex hx:items-center hx:cursor-pointer hx:select-none hx:list-none hx:p-1 hx:rounded-sm hx:transition-colors hx:hover:bg-gray-100 hx:dark:hover:bg-neutral-800 hx:before:mr-1 hx:before:inline-block hx:before:transition-transform hx:before:content-[&#39;&#39;] hx:dark:before:invert hx:rtl:before:rotate-180 hx:group-open:before:rotate-90&#34;&gt;
    &lt;strong class=&#34;hx:text-lg&#34;&gt;AVX512 Feature Subsets&lt;/strong&gt;
  &lt;/summary&gt;
  &lt;div class=&#34;hx:p-2 hx:overflow-hidden&#34;&gt;
    &lt;p&gt;AVX-512 includes a collections of features that a target can include.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AVX512F (Foundation):&lt;/strong&gt; The base AVX-512 instruction set. Includes 512-bit operations for 32-bit and 64-bit floats/integers, mask registers (k0-k7), and basic operations like VSCALEFPS/VSCALEFPD for 512-bit vectors.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AVX512VL (Vector Length Extensions):&lt;/strong&gt; Enables AVX-512 instructions on smaller vector sizes (128-bit and 256-bit). Without VLX, AVX-512 instructions only work on 512-bit (&lt;code&gt;ZMM&lt;/code&gt;) registers. With VLX, you can use AVX-512 features on &lt;code&gt;XMM&lt;/code&gt; (128-bit) and `YMM`` (256-bit) registers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;AVX512FP16 (Half Precision):&lt;/strong&gt; Adds native support for 16-bit floating-point operations, including VSCALEFPH/VSCALEFSH for half-precision SCALEF operations.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Without VLX, 128-bit and 256-bit vector operations must be widened to 512-bit before using VSCALEF and without FP16, vectors must be widened to &lt;strong&gt;f32&lt;/strong&gt;.&lt;/p&gt;
  &lt;/div&gt;
&lt;/details&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Instruction&lt;/th&gt;
          &lt;th&gt;Packed/Scalar&lt;/th&gt;
          &lt;th&gt;Element Type&lt;/th&gt;
          &lt;th&gt;Widths Supported&lt;/th&gt;
          &lt;th&gt;Required Features&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;VSCALEFPD&lt;/td&gt;
          &lt;td&gt;Packed&lt;/td&gt;
          &lt;td&gt;FP64&lt;/td&gt;
          &lt;td&gt;128 / 256 / 512&lt;/td&gt;
          &lt;td&gt;AVX512F, AVX512VL (for 128/256)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;VSCALEFPH&lt;/td&gt;
          &lt;td&gt;Packed&lt;/td&gt;
          &lt;td&gt;FP16&lt;/td&gt;
          &lt;td&gt;128 / 256 / 512&lt;/td&gt;
          &lt;td&gt;AVX512FP16, AVX512VL (for 128/256)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;VSCALEFPS&lt;/td&gt;
          &lt;td&gt;Packed&lt;/td&gt;
          &lt;td&gt;FP32&lt;/td&gt;
          &lt;td&gt;128 / 256 / 512&lt;/td&gt;
          &lt;td&gt;AVX512F, AVX512VL (for 128/256)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;VSCALEFSD&lt;/td&gt;
          &lt;td&gt;Scalar&lt;/td&gt;
          &lt;td&gt;FP64&lt;/td&gt;
          &lt;td&gt;128&lt;/td&gt;
          &lt;td&gt;AVX512F&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;VSCALEFSH&lt;/td&gt;
          &lt;td&gt;Scalar&lt;/td&gt;
          &lt;td&gt;FP16&lt;/td&gt;
          &lt;td&gt;128&lt;/td&gt;
          &lt;td&gt;AVX512FP16&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;VSCALEFSS&lt;/td&gt;
          &lt;td&gt;Scalar&lt;/td&gt;
          &lt;td&gt;FP32&lt;/td&gt;
          &lt;td&gt;128&lt;/td&gt;
          &lt;td&gt;AVX512F&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;LowerFLDEXP&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;lowerfldexp&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#lowerfldexp&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Now to get onto what my PR actually does. On the X86 backend, when the target has the AVX-512 extension, &lt;em&gt;ldexp&lt;/em&gt; should get lowered to &lt;em&gt;VSCALEF&lt;/em&gt;. As mentioned before, AVX-512 adds 512-bit SIMD registers and vector instructions, but there are also subsets or extensions to AVX-512. The ones relevant to this PR are AVX-512VL and AVX-512FP16. With AVX-512VL, instructions can operate on 128-bit and 256-bit vectors instead of &lt;em&gt;just&lt;/em&gt; 512-bit vectors, and AVX-512FP16 allows for instructions to operate on 16-bit floating pointer vectors. The table below displays the vectors this function will lower and the requirements.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Types&lt;/th&gt;
          &lt;th&gt;Bit Width&lt;/th&gt;
          &lt;th&gt;Requirements / Notes&lt;/th&gt;
          &lt;th&gt;Instruction&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;v16f32&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;512-bit&lt;/td&gt;
          &lt;td&gt;- Full 512-bit native vector&lt;br&gt;- No extensions required&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;VSCALEFPS&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;v8f64&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;512-bit&lt;/td&gt;
          &lt;td&gt;- Full 512-bit native vector&lt;br&gt;- No extensions required&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;VSCALEFPD&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;v8f32 / v4f64&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;256-bit&lt;/td&gt;
          &lt;td&gt;- Requires &lt;strong&gt;AVX512VL&lt;/strong&gt; (VLX), &lt;strong&gt;or&lt;/strong&gt;&lt;br&gt;- Widening to 512-bit&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;VSCALEFPS / VSCALEFPD&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;v4f32 / v2f64&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;128-bit&lt;/td&gt;
          &lt;td&gt;- Requires &lt;strong&gt;AVX512VL&lt;/strong&gt; (VLX), &lt;strong&gt;or&lt;/strong&gt;&lt;br&gt;- Widening to 512-bit&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;VSCALEFPS / VSCALEFPD&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;v32f16&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;512-bit&lt;/td&gt;
          &lt;td&gt;- Requires &lt;strong&gt;AVX512FP16&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;VSCALEFPH&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;v16f16 / v8f16&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;128–256-bit&lt;/td&gt;
          &lt;td&gt;- Requires &lt;strong&gt;FP16 + VLX&lt;/strong&gt;&lt;br&gt;- Requires &lt;strong&gt;FP16 + widening&lt;/strong&gt; to 512-bit (no VLX)&lt;br&gt;- Requires &lt;strong&gt;extend f16→f32 and i16→i32&lt;/strong&gt; + widening (no FP16 &amp;amp; no VLX)&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;VSCALEFPH&lt;/strong&gt; (if FP16)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Scalar f64&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;64-bit&lt;/td&gt;
          &lt;td&gt;- Insert into 128-bit vector&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;VSCALEFSD&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Scalar f32&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;32-bit&lt;/td&gt;
          &lt;td&gt;- Insert into 128-bit vector&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;VSCALEFSS&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;strong&gt;Scalar f16&lt;/strong&gt;&lt;/td&gt;
          &lt;td&gt;16-bit&lt;/td&gt;
          &lt;td&gt;- Requires &lt;strong&gt;AVX512FP16&lt;/strong&gt;, or&lt;br&gt;- Extend f16→f32 and use scalar f32 path&lt;/td&gt;
          &lt;td&gt;&lt;strong&gt;VSCALEFSH&lt;/strong&gt; (if FP16)&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;How to call vscalef*&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;how-to-call-vscalef&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#how-to-call-vscalef&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;LLVM’s X86 backend uses SelectionDAG nodes to represent target-specific operations during instruction selection. &lt;code&gt;X86ISD::SCALEF&lt;/code&gt; and &lt;code&gt;X86ISD::SCALEFS&lt;/code&gt; is the X86 backend&amp;rsquo;s internal opcode for the vscalef and vscalefs (scalar) instruction.&lt;/p&gt;
&lt;p&gt;In the code below you will see occurrences of &lt;code&gt;ISD::*&lt;/code&gt; and these represent generic
DAG opcodes, such as &lt;code&gt;ISD::ADD&lt;/code&gt;. &lt;code&gt;X86ISD::*&lt;/code&gt; represent DAG nodes specific to the X86 backend.&lt;/p&gt;
&lt;h3&gt;Difficulties&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;difficulties&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#difficulties&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The biggest hurdle I faced implementing this PR was correctly handling &lt;em&gt;FP16&lt;/em&gt; vectors (v8f16, v16f16) when the &lt;strong&gt;AVX512FP16&lt;/strong&gt; extension is not available.&lt;/p&gt;
&lt;p&gt;The operation requires converting the integer exponent vector (&lt;code&gt;vNi16&lt;/code&gt;) into a floating-point exponent vector (&lt;code&gt;vNf16&lt;/code&gt;). If the FP16 instruction set isn&amp;rsquo;t supported, LLVM literally cannot convert an &lt;code&gt;i16&lt;/code&gt; integer into an f16 floating-point number.&lt;/p&gt;
&lt;p&gt;Honestly, the solution was pretty simple. Instead of converting the &lt;code&gt;vNi16&lt;/code&gt; to an &lt;code&gt;vNf16&lt;/code&gt;, I would &lt;em&gt;sign-extend&lt;/em&gt; the Exp vector to an &lt;code&gt;i32&lt;/code&gt; vector.&lt;/p&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph TD
    subgraph &amp;#34;Before&amp;#34;
        A[v8f16 / v16f16&amp;lt;br/&amp;gt;FP16 Vector] --&amp;gt; B[Extract i16 Exp]
        B --&amp;gt; C[Convert i16 → fp16&amp;lt;br/&amp;gt;❌ NOT SUPPORTED]
        C --&amp;gt; D[fp16 Exponent]
        D --&amp;gt; E[ldexp operation]
    end
    
  &lt;/pre&gt;
&lt;/div&gt;&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph TD
    subgraph &amp;#34;After&amp;#34;
        A[v8f16 / v16f16&amp;lt;br/&amp;gt;FP16 Vector] --&amp;gt; B[Widen to v8f32 / v16f32]
        A --&amp;gt; D[Widen to i32 Exp]
        
        B --&amp;gt; E[Widen v8f32 → v16f32]
        D --&amp;gt; F[Widen i32 Exp → v16i32&amp;lt;br/&amp;gt;512-bit vector]
        
        E --&amp;gt; G[ldexp operation&amp;lt;br/&amp;gt;✓ FP32 supported]
        F --&amp;gt; G
    end
    
  &lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;As shown below, when the target has VLX and FP16 support, SCALEF can be directly called on &lt;code&gt;v8f16&lt;/code&gt;/&lt;code&gt;v16f16&lt;/code&gt; vectors. Without VLX (but with FP16), LowerFLDEXP will widen the vectors to 512-bits (v32f16). Without either, I have to extend both X and Exp to 32 bits, then widen to 512-bits (v16f32).&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;case&lt;/span&gt; MVT&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;v8f16&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;case&lt;/span&gt; MVT&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;v16f16&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (Subtarget.hasFP16()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (Subtarget.hasVLX()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Exp &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; DAG.getNode(ISD&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;SINT_TO_FP, DL, XTy, Exp);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; DAG.getNode(X86ISD&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;SCALEF, DL, XTy, X, Exp);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    X &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; DAG.getFPExtendOrRound(X, DL, XTy.changeVectorElementType(MVT&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;f32));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Exp &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; DAG.getSExtOrTrunc(Exp, DL,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                             X.getSimpleValueType().changeTypeToInteger());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;For v32f16, no prep is needed if it has FP16 support. Otherwise, I would have to split the v32f16 vector into two v16f16 vectors, and recursively call LoewerFLDEXP on the two, concatenating their results.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;case&lt;/span&gt; MVT&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;v32f16&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (Subtarget.hasFP16()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Exp &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; DAG.getNode(ISD&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;SINT_TO_FP, DL, XTy, Exp);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; DAG.getNode(X86ISD&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;SCALEF, DL, XTy, X, Exp);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SDValue Low &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; DAG.getExtractSubvector(DL, MVT&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;v16f16, X, &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SDValue High &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; DAG.getExtractSubvector(DL, MVT&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;v16f16, X, &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SDValue ExpLow &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; DAG.getExtractSubvector(DL, MVT&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;v16i16, Exp, &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SDValue ExpHigh &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; DAG.getExtractSubvector(DL, MVT&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;v16i16, Exp, &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SDValue OpLow &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; DAG.getNode(ISD&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;FLDEXP, DL, MVT&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;v16f16, Low, ExpLow);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SDValue OpHigh &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; DAG.getNode(ISD&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;FLDEXP, DL, MVT&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;v16f16, High, ExpHigh);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SDValue ScaledLow &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; LowerFLDEXP(OpLow, Subtarget, DAG);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SDValue ScaledHigh &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; LowerFLDEXP(OpHigh, Subtarget, DAG);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; DAG.getNode(ISD&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;CONCAT_VECTORS, DL, MVT&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;v32f16, ScaledLow,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                       ScaledHigh);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Which after being pointed out by the PR&amp;rsquo;s reviewer, I found out the splitting/concatenating can be simply reduced to the helper function below.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;splitVectorOp&lt;/span&gt;(Op, DAG, DL);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The code below handles the cases where VLX is not supported, in which the vectors need to be widened to 512-bits.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c++&#34; data-lang=&#34;c++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SDValue WideX &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; widenSubVector(X, &lt;span style=&#34;color:#89dceb&#34;&gt;true&lt;/span&gt;, Subtarget, DAG, DL, &lt;span style=&#34;color:#fab387&#34;&gt;512&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SDValue WideExp &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; widenSubVector(Exp, &lt;span style=&#34;color:#89dceb&#34;&gt;true&lt;/span&gt;, Subtarget, DAG, DL, &lt;span style=&#34;color:#fab387&#34;&gt;512&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Exp &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; DAG.getNode(ISD&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;SINT_TO_FP, DL, WideExp.getSimpleValueType(), Exp);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SDValue Scalef &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      DAG.getNode(X86ISD&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;::&lt;/span&gt;SCALEF, DL, WideX.getValueType(), WideX, WideExp);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  SDValue Final &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      DAG.getExtractSubvector(DL, X.getSimpleValueType(), Scalef, &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; DAG.getFPExtendOrRound(Final, DL, XTy);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Conclusion&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;conclusion&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#conclusion&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Overall, that was a pretty fun PR. I&amp;rsquo;m very grateful to my reviewer for his patience. If at any point this blog gave the impression that I got this PR done easily, please take a look at the PR link to see the many iterations of code reviews. It definitely pushed me to write code in a more optimal manner. It was also satisfying trying to find ways to reduce the number of lines I introduce, and is something I&amp;rsquo;ll focus on as I keep contributing. Looking forward to my next PR.&lt;/p&gt;
&lt;h3&gt;Resources&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;resources&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#resources&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://cdrdv2.intel.com/v1/dl/getContent/671200&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://cdrdv2.intel.com/v1/dl/getContent/671200&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Intel&amp;rsquo;s manual which contains documentation on the AVX-512 instructions, including VSCALE&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://llvm.org/doxygen/classllvm_1_1SelectionDAG.html&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://llvm.org/doxygen/classllvm_1_1SelectionDAG.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://www.youtube.com/watch?v=nNQ6AF6i5FI&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;https://www.youtube.com/watch?v=nNQ6AF6i5FI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
      </description>
    </item>
    
    <item>
      <title>Nes Emulator</title>
      <link>https://blog.kavin.me/blog/nes-emulator/</link>
      <pubDate>Mon, 09 Jun 2025 19:06:00 -0400</pubDate>
      
      <guid>https://blog.kavin.me/blog/nes-emulator/</guid>
      <description>
        
        
        &lt;p&gt;This blog covers my journey of emulating the NES, a popular console from the 1980s made by Nintendo.&lt;/p&gt;
&lt;h1&gt;Yet Another NES Emulator&lt;/h1&gt;&lt;p&gt;Why write an emulator for the NES, a project that can be considered well-trodden at this point? For those pursuing low level programming, an emulation project can serve as an excellent appetizer to the field. It gets you familiarized with CPU architecture and the interactions of different components within a computer. It&amp;rsquo;s a project big enough that authors have to concern themselves with profiling, and unit testing, concepts that may not be well taught in university. With a sufficiently complex computer to emulate, authors will actually have to think about how to structure their project, else be ridden with spaghetti code that can be a nightmare to debug. And why not the NES, which at this point is well documented and has a lot of support from communities such as r/EmuDev.&lt;/p&gt;
&lt;p&gt;The intentions of this blog are to document my process in writing this emulator, as well as write about the flow of execution of the PPU, and the APU. I will not go into the specifics, as the nesdev wiki already provides the necessary technical details of the NES. I hope that my blog can serve as a guide to what each component does on a higher level.
&lt;br&gt;
&lt;br&gt;&lt;/p&gt;
&lt;h1&gt;Core Emulation Logic&lt;/h1&gt;&lt;h2&gt;CPU - 6502&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;cpu---6502&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#cpu---6502&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;h3&gt;CPU Components&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;cpu-components&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#cpu-components&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;I would like to preface this by saying that when I refer to CPU components, I am talking about the elements of the 6502 relevant to emulation. A good starting point would be to list the &lt;em&gt;registers&lt;/em&gt; of the 6502 CPU.&lt;/p&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:rounded-lg hx:border hx:py-2 hx:ltr:pr-4 hx:rtl:pl-4 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-blue-200 hx:bg-blue-100 hx:text-blue-900 hx:dark:border-blue-200/30 hx:dark:bg-blue-900/30 hx:dark:text-blue-200&#34;&gt;
  &lt;div class=&#34;hx:ltr:pl-3 hx:ltr:pr-2 hx:rtl:pr-3 hx:rtl:pl-2&#34;&gt;&lt;svg height=1.2em class=&#34;hx:inline-block hx:align-middle&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z&#34;/&gt;&lt;/svg&gt;&lt;/div&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;A register is simply a piece of hardware that contains bits of data. For the sake of emulation, registers can be represented as unsigned integers.&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h4&gt;PC (Program Counter)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;pc-program-counter&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#pc-program-counter&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;The PC is a 16 bit register that tracks where the program is at in memory. It can be thought of as an index of an array, with the array being memory.&lt;/p&gt;
&lt;h4&gt;A (Accumulator)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;a-accumulator&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#a-accumulator&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;This is an 8 bit register that is typically used to hold the result of operations performed by instructions.&lt;/p&gt;
&lt;h4&gt;X, Y&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;x-y&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#x-y&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;These are 8 bit registers, and typically used as operands for operations.&lt;/p&gt;
&lt;h4&gt;S&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;s&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#s&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;This 8 bit register serves as a stack pointer, letting the CPU know where the top (or bottom in the case of the NES) of the &lt;a href=&#34;#stack&#34;&gt;stack&lt;/a&gt; is at.&lt;/p&gt;
&lt;h4&gt;P&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;p&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#p&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;This is the status register. It&amp;rsquo;s not really a register, but can be thought of as one. Each bit in this &amp;lsquo;register&amp;rsquo; represents a state after an instruction is performed. Decimal mode can be ignored, as this is not a feature on the NES.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;&lt;strong&gt;Bit&lt;/strong&gt;&lt;/th&gt;
          &lt;th&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/th&gt;
          &lt;th&gt;&lt;strong&gt;Flag&lt;/strong&gt;&lt;/th&gt;
          &lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;7&lt;/td&gt;
          &lt;td&gt;Negative&lt;/td&gt;
          &lt;td&gt;N&lt;/td&gt;
          &lt;td&gt;Set if the result of an operation is negative (bit 7 set)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;6&lt;/td&gt;
          &lt;td&gt;Overflow&lt;/td&gt;
          &lt;td&gt;V&lt;/td&gt;
          &lt;td&gt;Set if signed overflow occurred&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;5&lt;/td&gt;
          &lt;td&gt;Unused&lt;/td&gt;
          &lt;td&gt;—&lt;/td&gt;
          &lt;td&gt;Always set to 1 when pushed to the stack, ignored otherwise&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;4&lt;/td&gt;
          &lt;td&gt;Break&lt;/td&gt;
          &lt;td&gt;B&lt;/td&gt;
          &lt;td&gt;Set when a BRK instruction was executed&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;3&lt;/td&gt;
          &lt;td&gt;Decimal&lt;/td&gt;
          &lt;td&gt;D&lt;/td&gt;
          &lt;td&gt;Decimal mode (ignored on NES)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2&lt;/td&gt;
          &lt;td&gt;Interrupt Disable&lt;/td&gt;
          &lt;td&gt;I&lt;/td&gt;
          &lt;td&gt;If set, disables IRQ interrupts&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;Zero&lt;/td&gt;
          &lt;td&gt;Z&lt;/td&gt;
          &lt;td&gt;Set if the result of an operation is zero&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;0&lt;/td&gt;
          &lt;td&gt;Carry&lt;/td&gt;
          &lt;td&gt;C&lt;/td&gt;
          &lt;td&gt;Set if the last addition or shift resulted in a carry or borrow&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Memory&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;memory&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#memory&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The CPU also has access to 64KB of memory, with each element of this memory being able to store an 8 bit value.
The table below is the CPU&amp;rsquo;s memory layout. Take a careful look at this map, particularly region $8000 to $FFFF, as this is where the games discussed in this blog will be stored.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;&lt;strong&gt;Address Range&lt;/strong&gt;&lt;/th&gt;
          &lt;th&gt;&lt;strong&gt;Size&lt;/strong&gt;&lt;/th&gt;
          &lt;th&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;$0000–$07FF&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;$0800&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;2 KB internal RAM&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;$0800–$0FFF&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;$0800&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Mirrors of &lt;code&gt;$0000–$07FF&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;$1000–$17FF&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;$0800&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Mirrors of &lt;code&gt;$0000–$07FF&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;$1800–$1FFF&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;$0800&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Mirrors of &lt;code&gt;$0000–$07FF&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;$2000–$2007&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;$0008&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;PPU MMIO registers&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;$2008–$3FFF&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;$1FF8&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Mirrors of &lt;code&gt;$2000–$2007&lt;/code&gt; (repeats every 8 bytes)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;$4000–$4017&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;$0018&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;NES APU and I/O registers&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;$4018–$401F&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;$0008&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;APU and I/O functionality (normally disabled — see CPU Test Mode)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;$4020–$FFFF&lt;/code&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;code&gt;$6000–$7FFF&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;Usually cartridge RAM, when present&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;$8000–$FFFF&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;$BFE0&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Usually cartridge ROM and mapper registers&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The code below is a representation of the information relayed so far as a struct in C. There are some values that weren&amp;rsquo;t covered yet and they can be ignored for now as they do not pertain to the core cpu functionality.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;struct&lt;/span&gt; Cpu6502 {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; cycles;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; instr;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Accumulator
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; A;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// X and Y register
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; X;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; Y;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Program Counter
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;uint16_t&lt;/span&gt; PC;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Stack pointer
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Initialize it to the top
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; S;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;char&lt;/span&gt; P[&lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  PPU &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;ppu;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; ctrl_latch_state;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; ctrl_bit_index;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;char&lt;/span&gt; nmi_state;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;char&lt;/span&gt; strobe;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} Cpu6502;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;Stack&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;stack&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#stack&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The stack is a part of the memory used to temporarily hold values assigned by the CPU. It&amp;rsquo;s used to save values when the CPU needs to change to a different context. Certain instructions, such as the &lt;strong&gt;Jump to Subroutine&lt;/strong&gt; (JSR) instructs the CPU to change the &lt;em&gt;program counter&lt;/em&gt; value to another value. The current PC will be saved by &lt;em&gt;pushing&lt;/em&gt; its value to the stack.&lt;/p&gt;
&lt;h3&gt;CPU Instructions&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;cpu-instructions&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#cpu-instructions&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The CPU executes instructions and these instructions can vary in function. The simplest instructions implement are the &lt;strong&gt;read/write&lt;/strong&gt;and the register operations. The &lt;em&gt;LDA&lt;/em&gt;, &lt;em&gt;LDX&lt;/em&gt;, &lt;em&gt;LDY&lt;/em&gt;, &lt;em&gt;STA, STX, STY&lt;/em&gt; are the read &amp;amp; write instructions of the 6502 ISA. The last letter (A, X, or Y) indicates the register that will be used in the instruction. &lt;strong&gt;LD&lt;/strong&gt; retrieves a value from memory, and the location of this value is determined by the &lt;a href=&#34;#addressing-mode&#34;&gt;Addressing Mode&lt;/a&gt;. The retrieved value is stored in the specified register. For example, LDA # gets a value from the immediate address and stored it in the accumulator register. Most of the CPU&amp;rsquo;s instructions are quite simple functionality-wise so I won&amp;rsquo;t cover them. This &lt;a href=&#34;https://www.masswerk.at/6502/6502_instruction_set.html&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;site&lt;/a&gt;, as well the NesDev Wiki fully documents the 6502 ISA.&lt;/p&gt;
&lt;h4&gt;Addressing Mode&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;addressing-mode&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#addressing-mode&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Certain instructions need operand(s) to execute. For example, a load instruction needs an address to specify where to load the value from memory.&lt;/p&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:rounded-lg hx:border hx:py-2 hx:ltr:pr-4 hx:rtl:pl-4 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-blue-200 hx:bg-blue-100 hx:text-blue-900 hx:dark:border-blue-200/30 hx:dark:bg-blue-900/30 hx:dark:text-blue-200&#34;&gt;
  &lt;div class=&#34;hx:ltr:pl-3 hx:ltr:pr-2 hx:rtl:pr-3 hx:rtl:pl-2&#34;&gt;&lt;svg height=1.2em class=&#34;hx:inline-block hx:align-middle&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z&#34;/&gt;&lt;/svg&gt;&lt;/div&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;In the code implementation in this section, you will notice that I increment &lt;code&gt;PC&lt;/code&gt; within the addressing mode logic. This is not  entirely accurate but it serves my purposes, since I do not increment &lt;code&gt;PC&lt;/code&gt; in the previous instruction.&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h5&gt;&lt;strong&gt;Immediate Addressing&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;immediate-addressing&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#immediate-addressing&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h5&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PC&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;address &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; PC; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;details class=&#34;hx:last-of-type:mb-0 hx:rounded-lg hx:bg-neutral-50 hx:dark:bg-neutral-800 hx:p-2 hx:mt-4 hx:group&#34; &gt;
  &lt;summary class=&#34;hx:flex hx:items-center hx:cursor-pointer hx:select-none hx:list-none hx:p-1 hx:rounded-sm hx:transition-colors hx:hover:bg-gray-100 hx:dark:hover:bg-neutral-800 hx:before:mr-1 hx:before:inline-block hx:before:transition-transform hx:before:content-[&#39;&#39;] hx:dark:before:invert hx:rtl:before:rotate-180 hx:group-open:before:rotate-90&#34;&gt;
    &lt;strong class=&#34;hx:text-lg&#34;&gt;Immediate Addressing&lt;/strong&gt;
  &lt;/summary&gt;
  &lt;div class=&#34;hx:p-2 hx:overflow-hidden&#34;&gt;
    The immediate address is the value itself, located at &lt;code&gt;PC + 1&lt;/code&gt;. This addressing mode fetches the operand directly following the opcode.
  &lt;/div&gt;
&lt;/details&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph TD
    A[&amp;#34;Mnemonic: LDA #$42&amp;#34;]
    B[&amp;#34;$A9 $42&amp;#34;] 
    C[&amp;#34;A ← $42&amp;#34;]
    B --&amp;gt; C
  &lt;/pre&gt;
&lt;/div&gt;&lt;h5&gt;&lt;strong&gt;Zero Page Addressing&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;zero-page-addressing&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#zero-page-addressing&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h5&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PC&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;address &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; memory[PC];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;details class=&#34;hx:last-of-type:mb-0 hx:rounded-lg hx:bg-neutral-50 hx:dark:bg-neutral-800 hx:p-2 hx:mt-4 hx:group&#34; &gt;
  &lt;summary class=&#34;hx:flex hx:items-center hx:cursor-pointer hx:select-none hx:list-none hx:p-1 hx:rounded-sm hx:transition-colors hx:hover:bg-gray-100 hx:dark:hover:bg-neutral-800 hx:before:mr-1 hx:before:inline-block hx:before:transition-transform hx:before:content-[&#39;&#39;] hx:dark:before:invert hx:rtl:before:rotate-180 hx:group-open:before:rotate-90&#34;&gt;
    &lt;strong class=&#34;hx:text-lg&#34;&gt;Zero Page Addressing&lt;/strong&gt;
  &lt;/summary&gt;
  &lt;div class=&#34;hx:p-2 hx:overflow-hidden&#34;&gt;
    Zero page refers to memory addresses from &lt;code&gt;$0000&lt;/code&gt; to &lt;code&gt;$00FF&lt;/code&gt;. This region is faster for the CPU to access. The instruction uses a single-byte operand (from &lt;code&gt;PC + 1&lt;/code&gt;) as the full address.
  &lt;/div&gt;
&lt;/details&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph TD 
    A[&amp;#34;Mnemonic: LDA $42&amp;#34;]
    B[&amp;#34;$A5 $42&amp;#34;] 
    C[&amp;#34;Address [$42] → $10&amp;#34;]
    D[&amp;#34;A ← $10&amp;#34;]

    B --&amp;gt; C --&amp;gt; D
  &lt;/pre&gt;
&lt;/div&gt;&lt;h6&gt;&lt;strong&gt;Zero Page,X&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;zero-pagex&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#zero-pagex&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h6&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PC&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;address &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (memory[PC] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; X) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0xFF&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;details class=&#34;hx:last-of-type:mb-0 hx:rounded-lg hx:bg-neutral-50 hx:dark:bg-neutral-800 hx:p-2 hx:mt-4 hx:group&#34; &gt;
  &lt;summary class=&#34;hx:flex hx:items-center hx:cursor-pointer hx:select-none hx:list-none hx:p-1 hx:rounded-sm hx:transition-colors hx:hover:bg-gray-100 hx:dark:hover:bg-neutral-800 hx:before:mr-1 hx:before:inline-block hx:before:transition-transform hx:before:content-[&#39;&#39;] hx:dark:before:invert hx:rtl:before:rotate-180 hx:group-open:before:rotate-90&#34;&gt;
    &lt;strong class=&#34;hx:text-lg&#34;&gt;Zero Page,X Addressing&lt;/strong&gt;
  &lt;/summary&gt;
  &lt;div class=&#34;hx:p-2 hx:overflow-hidden&#34;&gt;
    This uses the value stored in memory at the address of &lt;code&gt;(PC + 1)&lt;/code&gt; incremented by the value in register X. It wraps around within the zero page using &lt;code&gt;&amp;amp; 0xFF&lt;/code&gt;.
  &lt;/div&gt;
&lt;/details&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph TD 
    M[&amp;#34;Mnemonic: LDA $42,X&amp;#34;]
    I[&amp;#34;$B5 $42&amp;#34;] 
    Xreg[&amp;#34;X → $04&amp;#34;] 
    AddrCalc[&amp;#34;Effective address = ($42 + $04) &amp;amp; 0xFF = $46&amp;#34;]
    MemRead[&amp;#34;Address [$46] → $99&amp;#34;]
    Result[&amp;#34;A ← $99&amp;#34;]

    I --&amp;gt; AddrCalc --&amp;gt; MemRead --&amp;gt; Result
  &lt;/pre&gt;
&lt;/div&gt;&lt;h6&gt;&lt;strong&gt;Zero Page,Y&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;zero-pagey&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#zero-pagey&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h6&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PC&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;address &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (memory[PC] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; Y) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0xFF&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;details class=&#34;hx:last-of-type:mb-0 hx:rounded-lg hx:bg-neutral-50 hx:dark:bg-neutral-800 hx:p-2 hx:mt-4 hx:group&#34; &gt;
  &lt;summary class=&#34;hx:flex hx:items-center hx:cursor-pointer hx:select-none hx:list-none hx:p-1 hx:rounded-sm hx:transition-colors hx:hover:bg-gray-100 hx:dark:hover:bg-neutral-800 hx:before:mr-1 hx:before:inline-block hx:before:transition-transform hx:before:content-[&#39;&#39;] hx:dark:before:invert hx:rtl:before:rotate-180 hx:group-open:before:rotate-90&#34;&gt;
    &lt;strong class=&#34;hx:text-lg&#34;&gt;Zero Page,Y Addressing&lt;/strong&gt;
  &lt;/summary&gt;
  &lt;div class=&#34;hx:p-2 hx:overflow-hidden&#34;&gt;
    Works the same way as Zero Page,X, but adds the Y register instead. Rarely used in 6502.
  &lt;/div&gt;
&lt;/details&gt;
&lt;h5&gt;&lt;strong&gt;Absolute Addressing&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;absolute-addressing&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#absolute-addressing&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h5&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lsb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; memory[&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;PC];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;msb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; memory[&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;PC];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;address &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (msb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; lsb;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;details class=&#34;hx:last-of-type:mb-0 hx:rounded-lg hx:bg-neutral-50 hx:dark:bg-neutral-800 hx:p-2 hx:mt-4 hx:group&#34; &gt;
  &lt;summary class=&#34;hx:flex hx:items-center hx:cursor-pointer hx:select-none hx:list-none hx:p-1 hx:rounded-sm hx:transition-colors hx:hover:bg-gray-100 hx:dark:hover:bg-neutral-800 hx:before:mr-1 hx:before:inline-block hx:before:transition-transform hx:before:content-[&#39;&#39;] hx:dark:before:invert hx:rtl:before:rotate-180 hx:group-open:before:rotate-90&#34;&gt;
    &lt;strong class=&#34;hx:text-lg&#34;&gt;Absolute Addressing&lt;/strong&gt;
  &lt;/summary&gt;
  &lt;div class=&#34;hx:p-2 hx:overflow-hidden&#34;&gt;
    Absolute addressing requires &lt;em&gt;two&lt;/em&gt; operands (bytes) from memory to form a full 16-bit address. The low byte (LSB) comes first, then the high byte (MSB). These are combined using bit shifting and bitwise OR.
  &lt;/div&gt;
&lt;/details&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph TD 
    M[&amp;#34;Mnemonic: LDA $1234&amp;#34;]
    I[&amp;#34;$AD $34 $12&amp;#34;] 
    Addr[&amp;#34;Effective address = $1234&amp;#34;]
    MemRead[&amp;#34;Address [$1234] → $56&amp;#34;]
    Result[&amp;#34;A ← $56&amp;#34;]

    I --&amp;gt; Addr --&amp;gt; MemRead --&amp;gt; Result
  &lt;/pre&gt;
&lt;/div&gt;&lt;h6&gt;&lt;strong&gt;Absolute,X&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;absolutex&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#absolutex&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h6&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lsb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; memory[&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;PC];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;msb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; memory[&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;PC];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;address &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ((msb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; lsb) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; X;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h6&gt;&lt;strong&gt;Absolute,Y&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;absolutey&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#absolutey&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h6&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lsb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; memory[&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;PC];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;msb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; memory[&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;PC];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;address &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ((msb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; lsb) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; Y;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h5&gt;&lt;strong&gt;(Indirect,X)&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;indirectx&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#indirectx&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h5&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PC&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;base &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (memory[PC] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; X) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0xFF&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lo &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; memory[base];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hi &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; memory[(base &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0xFF&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;address &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (hi &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; lo;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;details class=&#34;hx:last-of-type:mb-0 hx:rounded-lg hx:bg-neutral-50 hx:dark:bg-neutral-800 hx:p-2 hx:mt-4 hx:group&#34; &gt;
  &lt;summary class=&#34;hx:flex hx:items-center hx:cursor-pointer hx:select-none hx:list-none hx:p-1 hx:rounded-sm hx:transition-colors hx:hover:bg-gray-100 hx:dark:hover:bg-neutral-800 hx:before:mr-1 hx:before:inline-block hx:before:transition-transform hx:before:content-[&#39;&#39;] hx:dark:before:invert hx:rtl:before:rotate-180 hx:group-open:before:rotate-90&#34;&gt;
    &lt;strong class=&#34;hx:text-lg&#34;&gt;(Indirect,X) Addressing&lt;/strong&gt;
  &lt;/summary&gt;
  &lt;div class=&#34;hx:p-2 hx:overflow-hidden&#34;&gt;
    First adds X to the operand (from zero page), then uses the result as a pointer to a 16-bit address. The pointer wraps in zero page.
  &lt;/div&gt;
&lt;/details&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph TD
    M[&amp;#34;Mnemonic: LDA ($20,X)&amp;#34;]
    I[&amp;#34;$A1 $20&amp;#34;]
    Xreg[&amp;#34;X → $04&amp;#34;]
    AddrCalc[&amp;#34;$20 + $04 = $24&amp;#34;]
    PtrLow[&amp;#34;Address [$24] → $78 (low byte)&amp;#34;]
    PtrHigh[&amp;#34;Address [$24 + $1] → $56 (high byte)&amp;#34;]
    EffAddrLow[&amp;#34;Effective address low byte: $78&amp;#34;]
    EffAddrHigh[&amp;#34;Effective address high byte: $56&amp;#34;]
    EffAddr[&amp;#34;Effective address = $5678&amp;#34;]
    MemRead[&amp;#34;Address [$5678] → $9A&amp;#34;]
    Result[&amp;#34;Load A ← $9A&amp;#34;]

    M --&amp;gt; I --&amp;gt; Xreg --&amp;gt; AddrCalc
    AddrCalc --&amp;gt; PtrLow --&amp;gt; PtrHigh
    PtrLow --&amp;gt; EffAddrLow
    PtrHigh --&amp;gt; EffAddrHigh
    EffAddrLow --&amp;gt; EffAddr
    EffAddrHigh --&amp;gt; EffAddr
    EffAddr --&amp;gt; MemRead --&amp;gt; Result
  &lt;/pre&gt;
&lt;/div&gt;&lt;h5&gt;&lt;strong&gt;(Indirect),Y&lt;/strong&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;indirecty&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#indirecty&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h5&gt;&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;PC&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ptr &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; memory[PC];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;lo &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; memory[ptr];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;hi &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; memory[(ptr &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0xFF&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;address &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ((hi &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; lo) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; Y;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;details class=&#34;hx:last-of-type:mb-0 hx:rounded-lg hx:bg-neutral-50 hx:dark:bg-neutral-800 hx:p-2 hx:mt-4 hx:group&#34; &gt;
  &lt;summary class=&#34;hx:flex hx:items-center hx:cursor-pointer hx:select-none hx:list-none hx:p-1 hx:rounded-sm hx:transition-colors hx:hover:bg-gray-100 hx:dark:hover:bg-neutral-800 hx:before:mr-1 hx:before:inline-block hx:before:transition-transform hx:before:content-[&#39;&#39;] hx:dark:before:invert hx:rtl:before:rotate-180 hx:group-open:before:rotate-90&#34;&gt;
    &lt;strong class=&#34;hx:text-lg&#34;&gt;(Indirect),Y Addressing&lt;/strong&gt;
  &lt;/summary&gt;
  &lt;div class=&#34;hx:p-2 hx:overflow-hidden&#34;&gt;
    Reads a pointer from zero page, builds a base address from it, then adds the Y register to get the effective address.
  &lt;/div&gt;
&lt;/details&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    graph TD
    M[&amp;#34;Mnemonic: LDA ($20),Y&amp;#34;]
    I[&amp;#34;$B1 $20&amp;#34;]
    PtrLow[&amp;#34;Read low byte at Address [$20]: $34&amp;#34;]
    PtrHigh[&amp;#34;Read high byte at Address [$20 + 1]: $12&amp;#34;]
    Yreg[&amp;#34;Y register → $05&amp;#34;]
    AddrCombine[&amp;#34;Combine bytes: $1234&amp;#34;]
    EffAddrCalc[&amp;#34;Add Y: $1234 + $05 = $1239&amp;#34;]
    MemRead[&amp;#34;Address [$1239] → $BC&amp;#34;]
    Result[&amp;#34;A ← $BC&amp;#34;]

    M --&amp;gt; I --&amp;gt; PtrLow --&amp;gt; AddrCombine 
    I --&amp;gt; PtrHigh --&amp;gt; AddrCombine 
    AddrCombine --&amp;gt; EffAddrCalc --&amp;gt; MemRead --&amp;gt; Result
    Yreg --&amp;gt; EffAddrCalc
  &lt;/pre&gt;
&lt;/div&gt;&lt;h2&gt;PPU - The Picture Processing Unit&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;ppu---the-picture-processing-unit&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#ppu---the-picture-processing-unit&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;This component of the NES is what generates the graphics. The PPU was definitely the most confusing and time consuming part of this emulation process. The documentation I was able to find was in-depth on the individual components of the PPU, but I was confused as to what the PPU was doing at a high level. If you&amp;rsquo;re having a hard time understanding what the PPU is doing, I hope this initial high-level overview helps.&lt;/p&gt;
&lt;p&gt;The main goal of the PPU is to draw a frame, pixel by pixel. The visible frame is the actual display, 256 by 240 pixels. This can also be thought of as 32 by 30 tiles, with each tile being 8 by 8 pixels. To draw each pixel, the PPU will have to know what colour each pixel is. The PPU does 4 memory fetches every 8 cycles to get the colour of a pixel. The first memory fetch is from the &lt;strong&gt;Nametable&lt;/strong&gt; using the value in the PPU&amp;rsquo;s &lt;em&gt;v&lt;/em&gt; register. The Nametable contains the &lt;em&gt;tile ID&lt;/em&gt;. For example, let&amp;rsquo;s say the Nametable returns $13 (19 in base 10), this means we have to use the 19th tile from the CHR, which is stored in the &lt;strong&gt;Pattern Table&lt;/strong&gt;. The next two cycles are spent on a memory fetch from the &lt;strong&gt;Attribute Table&lt;/strong&gt;. The Attribute Table determines which &lt;strong&gt;Palette&lt;/strong&gt; out of the four palettes to use for a 4x4 tile region. The next 4 cycles are spent on the &lt;strong&gt;Pattern Table&lt;/strong&gt;. A palette is composed of four possible colours to use. The Pattern Table will determine which of the four colours in a palette to use. All these memory fetches will let us build an address that reveals which colour from the &lt;strong&gt;Palette&lt;/strong&gt; memory to use.&lt;/p&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    flowchart TD
    A[&amp;#34;PPU Begins Rendering Pixel&amp;#34;] --&amp;gt; V([&amp;#34;v = $2000&amp;#34;])

    V --&amp;gt; B[&amp;#34;Fetch Tile ID from Nametable&amp;#34;]
    B --&amp;gt; C([&amp;#34;Tile ID = $13&amp;#34;])

    V --&amp;gt; AT[&amp;#34;Fetch Palette Index from Attribute Table&amp;#34;]
    AT --&amp;gt; G([&amp;#34;Palette Index = 3&amp;#34;])

    C --&amp;gt; D[&amp;#34;Fetch Pattern from Pattern Table&amp;#34;]
    D --&amp;gt; E([&amp;#34;Tile #19 Pixel Data&amp;#34;])

    E --&amp;gt; F[&amp;#34;Combine Pattern Data + Palette Index&amp;#34;]
    G --&amp;gt; F

    F --&amp;gt; H[&amp;#34;Fetch Color from Palette Memory&amp;#34;]
    H --&amp;gt; I([&amp;#34;Final Pixel Color = #12&amp;#34;])
  &lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This diagram simplifies the flow a bit too much. There are some crucial nuances that the Wiki will cover, and some that I&amp;rsquo;ll try to cover below.&lt;/p&gt;
&lt;h3&gt;PPU Memory Mapped &amp;amp; Internal Registers&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;ppu-memory-mapped--internal-registers&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#ppu-memory-mapped--internal-registers&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Memory mapped registers are essentially the channels of communication between the CPU and PPU. These two components have seperate memory space. For these two components to communicate with each other, the PPU has eight registers which are mapped to certain addresses of the CPU in its memory space. For example, the PPU has a register called &lt;strong&gt;PPUCTRL&lt;/strong&gt;. The CPU is writing to this register when it writes to the address $2000 in its memory space. I won&amp;rsquo;t cover in detail the purpose of each memory mapped register as the NesDev Wiki details this extensively.&lt;/p&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    flowchart LR
    A[&amp;#34;A → $80&amp;#34;] 
CPU[&amp;#34;STA $2000&amp;#34;]
    CPU --&amp;gt; Write[&amp;#34;Stores $80 in CPU&amp;#39;s memory address $2000&amp;#34;]
    Map[&amp;#34;$2000 is Memory-Mapped to PPUCTRL Register&amp;#34;] --&amp;gt; PPUCTRL[&amp;#34;PPUCTRL Register ← $80&amp;#34;]
    PPUCTRL --&amp;gt; PPU[&amp;#34;PPU Updates Control Flags&amp;#34;]
  &lt;/pre&gt;
&lt;/div&gt;&lt;h3&gt;Frames, Scanlines, &amp;amp; Cycles&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;frames-scanlines--cycles&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#frames-scanlines--cycles&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;A frame is an instance of the screen. Each frame is composed of 262 scanlines, which can be thought of as rows. Earlier, I mentioned the visible frame, which can also be referred to as the picture region. But I also said there were 240 rows. This discrepancy is due to something called the &lt;strong&gt;Vertical Blanking Lines&lt;/strong&gt; (VBlank). The PPU has essentially finished drawing the frame by scanline 239, but there are additional scanlines, (241 to 260) where the PPU is idle. During this period of time, the CPU can commit operations that can alter PPU&amp;rsquo;s behaviour, such as changing which sprites to appear on the next frame, or change the palette colours. Scanline 0 to scanline 239 are referred to as the &lt;strong&gt;Visible Scanlines&lt;/strong&gt;. Scanline 240 is the &lt;strong&gt;Post-render&lt;/strong&gt; scanline, where the PPU is idle. The VBlank flag isn&amp;rsquo;t yet so this is &lt;strong&gt;not&lt;/strong&gt; VBlank. At scanline 241, if enabled in &lt;em&gt;PPUCTRL&lt;/em&gt; the PPU triggers an &lt;strong&gt;NMI&lt;/strong&gt;, which notifies the CPU that the PPU is in VBlank.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Scanline #&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;0–239&lt;/td&gt;
          &lt;td&gt;Visible Scanlines&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;240&lt;/td&gt;
          &lt;td&gt;Post-render (idle)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;241–260&lt;/td&gt;
          &lt;td&gt;VBlank (Vertical Blanking)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;261&lt;/td&gt;
          &lt;td&gt;Pre-render scanline&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Each scanline requires 341 PPU clock cycles, with each clock cycle producing one pixel. You may notices the additional 86 cycles to draw the 256 pixels per row. Cycle 0 is idle, it does nothing. Cycle 1 to Cycle 256 is where the 4 memory fetches I mentioned above are executed. Cycle 257-320 are pre-fetching the first two tiles of the next scanline. Cycle 337-340 also does memory fetches, but their purpose are unknown and for the sake of emulation can be ignored.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Cycle Range&lt;/th&gt;
          &lt;th&gt;Purpose / Memory Fetch Pattern&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;0&lt;/td&gt;
          &lt;td&gt;Idle (no operation)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;1–256&lt;/td&gt;
          &lt;td&gt;Pixel rendering (4 memory fetches every 8 cycles)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;257–320&lt;/td&gt;
          &lt;td&gt;Prefetch tiles for next scanline&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;321–336&lt;/td&gt;
          &lt;td&gt;Pipeline warm-up / dummy fetches&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;337–340&lt;/td&gt;
          &lt;td&gt;Unused or unknown-purpose fetches (safe to ignore)&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Cycle % 8&lt;/th&gt;
          &lt;th&gt;Memory Fetch Target&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;Nametable byte&lt;/td&gt;
          &lt;td&gt;Tile ID for the current tile&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;3&lt;/td&gt;
          &lt;td&gt;Attribute table byte&lt;/td&gt;
          &lt;td&gt;Palette attribute for 4×4 tile region&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;5&lt;/td&gt;
          &lt;td&gt;Pattern table low byte&lt;/td&gt;
          &lt;td&gt;LSB of tile graphics from CHR&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;7&lt;/td&gt;
          &lt;td&gt;Pattern table high byte&lt;/td&gt;
          &lt;td&gt;MSB of tile graphics from CHR&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Memory Reads&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;memory-reads&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#memory-reads&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;h4&gt;Nametable&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;nametable&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#nametable&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;A nametable dictates how the background is laid out. Each nametable is composed of 1024 bytes, each byte storing the tile ID of each of the 30x32 tiles. So 960 bytes (30 * 32) are used to indicate which tile to use from the pattern table, the remaining 64 bytes are used by each nametable&amp;rsquo;s &lt;a href=&#34;#Attribute-Table&#34;&gt;Attribute Table&lt;/a&gt;. The CPU will write to this memory area ($2000 - $2FFF) as instructed by the PRG data, so the CPU (indirectly) directed by the PRG data determines how the background is laid out.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;read_mem&lt;/span&gt;(PPU &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;ppu, &lt;span style=&#34;color:#f38ba8&#34;&gt;uint16_t&lt;/span&gt; addr) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ... 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (addr &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x3F00&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Nametable region with mirroring
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    addr &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x2FFF&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;uint16_t&lt;/span&gt; offset &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; addr &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0xFFF&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (nametable_mirror_flag) { &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// vertical
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; ppu_memory[offset &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x800&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; { &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// horizontal
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (offset &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x800&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// NT0 or NT1 (2000 or 2400)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; ppu_memory[(&lt;span style=&#34;color:#fab387&#34;&gt;0x2000&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; (offset &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x400&lt;/span&gt;))];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (offset &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0xC00&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; ppu_memory[addr];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; ppu_memory[&lt;span style=&#34;color:#fab387&#34;&gt;0x2000&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; (offset &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x400&lt;/span&gt;)];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The function above is how I fetch the nametable byte using the value in register v. The code handles PPU memory reads in the nametable region ($2000–$2FFF), applying mirroring rules. For vertical mirroring, it mirrors every 2 KB. For horizontal, it redirects specific 1 KB chunks to simulate NT0 and NT1 sharing. The goal is to map the 4 nametable address ranges into the 2 KB of physical VRAM available in the NES.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;background_ppu_render&lt;/span&gt;(PPU &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;ppu) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;switch&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;current_scanline_cycle &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Fetch Nametable byte
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;bg_pipeline.name_table_byte &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;fetch_name_table_byte&lt;/span&gt;(ppu);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The code above is how the function (fetch_name_table_byte just calls read_mem) is used in the actual background rendering pipeline. The modulo switch statement lets us know which cycle we are on in the 8 cycle pipeline of rendering a tile.&lt;/p&gt;
&lt;h4&gt;Attribute Table&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;attribute-table&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#attribute-table&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;As mentioned before, the last 64 bytes of each nametable is used as the Attribute table of the corresponding nametable. Each byte controls the palette of a 4x4 tile region of the nametable. Each 2 bits of the byte controls a 2x2 tile region.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Bits&lt;/th&gt;
          &lt;th&gt;Bit Position&lt;/th&gt;
          &lt;th&gt;Affected Quadrant&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;1 0&lt;/td&gt;
          &lt;td&gt;Bits 0–1&lt;/td&gt;
          &lt;td&gt;Bottom Right (BR)&lt;/td&gt;
          &lt;td&gt;Palette index for bottom-right&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;3 2&lt;/td&gt;
          &lt;td&gt;Bits 2–3&lt;/td&gt;
          &lt;td&gt;Bottom Left (BL)&lt;/td&gt;
          &lt;td&gt;Palette index for bottom-left&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;5 4&lt;/td&gt;
          &lt;td&gt;Bits 4–5&lt;/td&gt;
          &lt;td&gt;Top Right (TR)&lt;/td&gt;
          &lt;td&gt;Palette index for top-right&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;7 6&lt;/td&gt;
          &lt;td&gt;Bits 6–7&lt;/td&gt;
          &lt;td&gt;Top Left (TL)&lt;/td&gt;
          &lt;td&gt;Palette index for top-left&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;background_ppu_render&lt;/span&gt;(PPU &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;ppu) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;bg_pipeline.attribute_byte &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;fetch_attr_table_byte&lt;/span&gt;(ppu);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Determines which of the four areas of the attribute byte to use
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Each attribute byte covers 4x4 tiles → each quadrant is 2x2 tiles
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; quadrant_x &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ((ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;v &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x1F&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;; &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// 0 = left, 1 = right
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; quadrant_y &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (((ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;v &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;5&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x1F&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;; &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// 0 = top,  1 = bottom
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; shift &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (quadrant_y &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; quadrant_x) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;; &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// 0, 2, 4, or 6
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;bg_pipeline.palette_index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;bg_pipeline.attribute_byte &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; shift) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The code above is the logic I use to extract the relevant part of the attribute byte depending on the register v pointer.&lt;/p&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:rounded-lg hx:border hx:py-2 hx:ltr:pr-4 hx:rtl:pl-4 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-blue-200 hx:bg-blue-100 hx:text-blue-900 hx:dark:border-blue-200/30 hx:dark:bg-blue-900/30 hx:dark:text-blue-200&#34;&gt;
  &lt;div class=&#34;hx:ltr:pl-3 hx:ltr:pr-2 hx:rtl:pr-3 hx:rtl:pl-2&#34;&gt;&lt;svg height=1.2em class=&#34;hx:inline-block hx:align-middle&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z&#34;/&gt;&lt;/svg&gt;&lt;/div&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;p&gt;It&amp;rsquo;s crucial that the logic used here is sound. Previously, I was using if statements to get parse out the attribute byte shown below.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; tile_area_horizontal &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;v &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x00F&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;4&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; tile_area_vertical &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ((ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;v &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x0F0&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x20&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;4&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (tile_area_vertical &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; tile_area_horizontal &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Top left quadrant (bit 1 &amp;amp; 0)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;      ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;palette_index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;attribute_byte &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x03&lt;/span&gt;; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&amp;gt;&lt;/span&gt; [&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!&lt;/span&gt;WARNING]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (tile_area_vertical &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; tile_area_horizontal &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Top right quadrant (bit 3 &amp;amp; 2)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;      ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;palette_index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;attribute_byte &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x0C&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (tile_area_vertical &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; tile_area_horizontal &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Bottom left quadrant (bit 5 &amp;amp; 4)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;      ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;palette_index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;attribute_byte &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x30&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;4&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (tile_area_vertical &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; tile_area_horizontal &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Bottom right quadrant (bit 7 6 6)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;      ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;palette_index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;attribute_byte &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0xC0&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;6&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The code wasn&amp;rsquo;t computing the tile&amp;rsquo;s quadrant within the 4-tile attribute area correctly. As a result, the following occurred.
&lt;img src=&#34;donkey_kong_almost.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;
There was a bag of other issues with my implementation at the time, but the incorrect colours were mainly due to how I was parsing the attribute byte.&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h4&gt;Pattern Table (CHR)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;pattern-table-chr&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#pattern-table-chr&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Each tile is consists of 16 bytes, made up of two &lt;em&gt;planes&lt;/em&gt;. The first plane controls bit 0 of pixel&amp;rsquo;s palette index, and the corresponding bit in the second plane controls bit 1. The diagram below will hopefully clear up any confusion. In the example below, PPUCTRL sets the base address of the pattern table to 0x1000, and the nametable byte is 0x3A.&lt;/p&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    flowchart TD
    NTB[&amp;#34;Nametable Byte: 0x2000:0x3A&amp;#34;]
    PTAddr[&amp;#34;Pattern Table Addr: 0x1000 + 0x3A×16 + scanline&amp;#34;]
    PTByte1[&amp;#34;Pattern Table Byte Lo: 0x13A0:0x5C&amp;#34;]
    PTByte2[&amp;#34;Pattern Table Byte Hi: 0x13A1:0xA3&amp;#34;]

    NTB --&amp;gt; PTAddr --&amp;gt; PTByte1
    PTAddr --&amp;gt; PTByte2
  &lt;/pre&gt;
&lt;/div&gt;&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Pixel #&lt;/th&gt;
          &lt;th&gt;PT Hi Bit&lt;/th&gt;
          &lt;th&gt;PT Lo Bit&lt;/th&gt;
          &lt;th&gt;Palette Index (binary)&lt;/th&gt;
          &lt;th&gt;Palette Index (decimal)&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;7&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
          &lt;td&gt;10&lt;/td&gt;
          &lt;td&gt;2&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;6&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;01&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;5&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
          &lt;td&gt;10&lt;/td&gt;
          &lt;td&gt;2&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;4&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;01&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;3&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;01&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;01&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
          &lt;td&gt;10&lt;/td&gt;
          &lt;td&gt;2&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;0&lt;/td&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;0&lt;/td&gt;
          &lt;td&gt;10&lt;/td&gt;
          &lt;td&gt;2&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;background_ppu_render&lt;/span&gt;(PPU &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;ppu) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;bg_pipeline.pattern_table_lsb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89b4fa&#34;&gt;read_mem&lt;/span&gt;(ppu, (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;bg_pipeline.name_table_byte &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; fine_y);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Fetch high byte
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;7&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;bg_pipeline.pattern_table_msb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89b4fa&#34;&gt;read_mem&lt;/span&gt;(ppu, (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;bg_pipeline.name_table_byte &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; fine_y);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;read_mem&lt;/span&gt;(PPU &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;ppu, &lt;span style=&#34;color:#f38ba8&#34;&gt;uint16_t&lt;/span&gt; addr) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (addr &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x2000&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Pattern tables
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;uint16_t&lt;/span&gt; pt_base_addr &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// if (ppu-&amp;gt;drawing_bg_flag) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    pt_base_addr &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;PPUCTRL &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x10&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;?&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x1000&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x0000&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//} else {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//  // TODO: Handle 8x16 sprites separately in sprite code
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//  pt_base_addr = (ppu-&amp;gt;PPUCTRL &amp;amp; 0x08) ? 0x1000 : 0x0000;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; ppu_memory[pt_base_addr &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; (addr &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x0FFF&lt;/span&gt;)];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:rounded-lg hx:border hx:py-2 hx:ltr:pr-4 hx:rtl:pl-4 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-blue-200 hx:bg-blue-100 hx:text-blue-900 hx:dark:border-blue-200/30 hx:dark:bg-blue-900/30 hx:dark:text-blue-200&#34;&gt;
  &lt;div class=&#34;hx:ltr:pl-3 hx:ltr:pr-2 hx:rtl:pr-3 hx:rtl:pl-2&#34;&gt;&lt;svg height=1.2em class=&#34;hx:inline-block hx:align-middle&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z&#34;/&gt;&lt;/svg&gt;&lt;/div&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;p&gt;For the longest time, my emulator was outputting garbage visuals and it was due to how I was fetching my pattern table data. Currently, my implementation is fine (with the limited testing I have done so far, so this statement is subject to change). But initially, I wrote the code as below.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (drawing_bg_flag) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;pattern_table_lsb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;read_mem&lt;/span&gt;(ppu, (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;name_table_byte &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;scanline);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;pattern_table_msb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;read_mem&lt;/span&gt;(ppu, (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;name_table_byte &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;scanline &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// byte 1 is tile number
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;pattern_table_lsb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;read_mem&lt;/span&gt;(ppu, (oam_buffer_latches[sprite_index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;scanline);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;pattern_table_msb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;read_mem&lt;/span&gt;(ppu, (oam_buffer_latches[sprite_index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;scanline &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;break&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The crucial error is in the address I&amp;rsquo;m reading from.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;pattern_table_lsb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;read_mem&lt;/span&gt;(ppu, (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;name_table_byte &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;scanline);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;pattern_table_msb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;read_mem&lt;/span&gt;(ppu, (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;name_table_byte &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;scanline &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I was using the incorrect address here! My goal was to increment the &lt;code&gt;name_table_byte&lt;/code&gt; by the current row being rendered in a tile, which can range in value from 0 to 8. However, I was increasing by the total number of scanlines! This outputted some interesting visuals when I tried to run the Donkey Kong rom.
&lt;img src=&#34;initial_donkey_kong.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h4&gt;Palette&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;palette&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#palette&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;The PPU memory (0x3F00 - 0x3F1F) contains four palettes, with each palette containing four colours. Memory address $3F00 to $3F0F contains the colours that background will use, while memory address $3F10 to $3F1F contains the colours used by sprites. The table below illustrates this.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Address Range&lt;/th&gt;
          &lt;th&gt;Purpose&lt;/th&gt;
          &lt;th&gt;Notes&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;$3F00&lt;/td&gt;
          &lt;td&gt;Universal background color&lt;/td&gt;
          &lt;td&gt;Shared by all background palettes&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;$3F01–$3F03&lt;/td&gt;
          &lt;td&gt;Background palette 0&lt;/td&gt;
          &lt;td&gt;3 colors (color 0 is $3F00)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;$3F04–$3F06&lt;/td&gt;
          &lt;td&gt;Background palette 1&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;$3F07–$3F09&lt;/td&gt;
          &lt;td&gt;Background palette 2&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;$3F0A–$3F0C&lt;/td&gt;
          &lt;td&gt;Background palette 3&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;$3F0D–$3F0F&lt;/td&gt;
          &lt;td&gt;Sprite palette 0&lt;/td&gt;
          &lt;td&gt;$3F0F may mirror $3F10&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;$3F10–$3F12&lt;/td&gt;
          &lt;td&gt;Sprite palette 1&lt;/td&gt;
          &lt;td&gt;$3F10 often mirrors $3F00&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;$3F13–$3F15&lt;/td&gt;
          &lt;td&gt;Sprite palette 2&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;$3F16–$3F18&lt;/td&gt;
          &lt;td&gt;Sprite palette 3&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;$3F19–$3F1F&lt;/td&gt;
          &lt;td&gt;Mirrors&lt;/td&gt;
          &lt;td&gt;Mirrors previous palette entries&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As I mentioned before, each memory fetch plays a part in computing the address used to fetch a pixel&amp;rsquo;s colour.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Bit&lt;/th&gt;
          &lt;th&gt;Meaning&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;3&lt;/td&gt;
          &lt;td&gt;Sprite (1) or Background (0)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2-1&lt;/td&gt;
          &lt;td&gt;Attribute bits (palette selection: 0–3)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;0&lt;/td&gt;
          &lt;td&gt;Pixel value from pattern table (0 or 1)&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Hopefully everything comes together with this. It took me a while of reading through the NesDev Wiki forums and documentation to piece it together myself.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;background_ppu_render&lt;/span&gt;(PPU &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;ppu) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;unsigned&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;char&lt;/span&gt; is_pre_fetch &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;current_scanline_cycle &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;321&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;current_scanline_cycle &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;336&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;?&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; row &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; is_pre_fetch &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;?&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;scanline &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;scanline;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; column_base &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; is_pre_fetch &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;?&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;current_scanline_cycle &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;328&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                   &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;current_scanline_cycle &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; TILE_SIZE; i&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; bit &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;7&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; i;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; bg_lo &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;bg_pipeline.pattern_table_lsb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; bit) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; bg_hi &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;bg_pipeline.pattern_table_msb &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; bit) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;bg_pipeline.tile_pixel_value[i] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (bg_hi &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; bg_lo;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; palette_index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;bg_pipeline.palette_index;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f38ba8&#34;&gt;uint16_t&lt;/span&gt; pal_addr &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#fab387&#34;&gt;0x3F00&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; (palette_index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;bg_pipeline.tile_pixel_value[i];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; palette_data &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;read_mem&lt;/span&gt;(ppu, pal_addr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; alpha &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;bg_pipeline.tile_pixel_value[i] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;?&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x00&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0xFF&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;color &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;ppu_palette[palette_data &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; r &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; color[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;], g &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; color[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;], b &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; color[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; column &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; column_base &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; i;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (column &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;256&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;||&lt;/span&gt; row &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;240&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;frame_buffer[row][column] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (r &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;24&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; (g &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; (b &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; alpha;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    sequenceDiagram
    participant PPU
    participant PPU_Memory
    participant FrameBuffer
    participant Frontend 

    loop 8-cycle fetch
        PPU-&amp;gt;&amp;gt;PPU_Memory: Fetch nametable byte
        PPU-&amp;gt;&amp;gt;PPU_Memory: Fetch attribute byte
        PPU-&amp;gt;&amp;gt;PPU_Memory: Fetch pattern LSB
        PPU-&amp;gt;&amp;gt;PPU_Memory: Fetch pattern MSB
        PPU-&amp;gt;&amp;gt;FrameBuffer: Fill up framebuffer with 8 pixels
    end

    FrameBuffer-&amp;gt;&amp;gt;Frontend: Present frame buffer to render
  &lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The Nes outputs a pixel cycle by cycle. I&amp;rsquo;m doing it a little differently. At every 8 cycle from cycle 1 - 256 (as well as the prefetch cycle 321 - 336), I use the information I have fetched the past 8 cycles rendering the past 8 pixels. Once I have a frame&amp;rsquo;s worth of pixels filled up in the buffer, I pass it off to &lt;strong&gt;Frontend&lt;/strong&gt;, which is an abstraction I made that does all the user interactions, including rendering the graphics.&lt;/p&gt;
&lt;h3&gt;OAM (Sprites)&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;oam-sprites&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#oam-sprites&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The OAM is another internal memory of the PPU that contains up to 64 sprites, with each sprite taking up 4 bytes. The table below can summarize what each of the 4 bytes determine.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Byte&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
          &lt;th&gt;Details&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;0&lt;/td&gt;
          &lt;td&gt;Y Position&lt;/td&gt;
          &lt;td&gt;Y coordinate of top of sprite minus 1 (due to 1-scanline delay). Values #$EF–#$FF hide the sprite offscreen.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;1&lt;/td&gt;
          &lt;td&gt;Tile Index Number&lt;/td&gt;
          &lt;td&gt;Tile number in pattern table. For 8x16 sprites, bit 0 selects tile bank ($0000 or $1000).&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;Bit 0: Bank ($0000 or $1000); Bits 1-7: Tile number top of sprite (0–254).&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2&lt;/td&gt;
          &lt;td&gt;Attributes&lt;/td&gt;
          &lt;td&gt;Bit 0-1: Palette (4–7) of sprite&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;Bit 2-4: Unimplemented (always read 0)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;Bit 5: Priority (0=front of BG, 1=behind BG)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;Bit 6: Flip sprite horizontally&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;Bit 7: Flip sprite vertically&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;3&lt;/td&gt;
          &lt;td&gt;X Position&lt;/td&gt;
          &lt;td&gt;X coordinate of left side of sprite&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;From this table, it can be discerned that the same rendering process done for the background pipeline cannot be used for the sprite. At least that was my conclusion. Instead I made a different function to render and &lt;em&gt;detect&lt;/em&gt; the sprites. To be honest, I&amp;rsquo;m still not fully confident in my sprite rendering implementation. It works with the games I&amp;rsquo;ve tried so far but I suggest you take this section with a grain of salt, as its most likely subject to change when I realize I did something wrong. Still, I believe my understanding should be able to help somewhat if you&amp;rsquo;re absolutely lost.&lt;/p&gt;
&lt;p&gt;To start with, each scanline from cycle 65-256 skims through the OAM memory to fill up a buffer with any sprite that will appear on the &lt;em&gt;next&lt;/em&gt; scanline. At HBlank, after cycle 256, this buffer is transferred to the appropriate shift and rendering registers to be rendered on the next scanline. To represent this, I employ two arrays. One will fill up the sprites of the next scanline, and at HBlank, will transfer its content to the second array so that it can be used to render the sprites on the next scanline.&lt;/p&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    flowchart TD
    Start([Start: n=0, m=0])

    ReadY[&amp;#34;Read sprite Y-coordinate OAM[n][0]&amp;#34;]
    CheckInRange{&amp;#34;Y in range?&amp;#34;}
    CopySprite[&amp;#34;Copy sprite data to secondary OAM if &amp;lt; 8 sprites found&amp;#34;]
    WriteIgnore[&amp;#34;Ignore write if secondary OAM full&amp;#34;]
    IncrementN[&amp;#34;Increment n&amp;#34;]
    CheckNZero{&amp;#34;All 64 sprites checked (n=0)?&amp;#34;}
    CheckSpriteCount{&amp;#34;&amp;lt; 8 sprites found?&amp;#34;}
    EvaluateSprites[&amp;#34;Evaluate sprites for overflow&amp;#34;]
    SetOverflow[&amp;#34;Set sprite overflow flag if &amp;gt; 8 sprites&amp;#34;]
    IncrementM[&amp;#34;Increment m (hardware bug)&amp;#34;]
    ContinueEval[&amp;#34;Continue evaluation&amp;#34;]
    CopyFail[&amp;#34;Fail to copy sprite to secondary OAM&amp;#34;]
    IncrementNUntilHBLANK[&amp;#34;Increment n until HBLANK&amp;#34;]
    End([End at HBLANK])

    Start --&amp;gt; ReadY
    ReadY --&amp;gt; CheckInRange

    CheckInRange -- Yes --&amp;gt; CopySprite
    CopySprite --&amp;gt; IncrementN
    CheckInRange -- No --&amp;gt; IncrementN

    IncrementN --&amp;gt; CheckNZero
    CheckNZero -- No --&amp;gt; CheckSpriteCount
    CheckNZero -- Yes --&amp;gt; CopyFail

    CheckSpriteCount -- Yes --&amp;gt; ReadY
    CheckSpriteCount -- No --&amp;gt; EvaluateSprites

    EvaluateSprites --&amp;gt; SetOverflow
    SetOverflow --&amp;gt; IncrementM
    IncrementM --&amp;gt; ContinueEval
    ContinueEval --&amp;gt; EvaluateSprites

    CopyFail --&amp;gt; IncrementNUntilHBLANK --&amp;gt; End
  &lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If this confuses you, don&amp;rsquo;t worry cause it confused me too. Just take your time reading through the &lt;a href=&#34;https://www.nesdev.org/wiki/PPU_sprite_evaluation&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;wiki&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This is the code I was able to come up with my current understanding.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;sprite_detect&lt;/span&gt;(PPU &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;ppu) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Reset secondary OAM memory at cycle 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;current_scanline_cycle &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#89b4fa&#34;&gt;memset&lt;/span&gt;(oam_memory_secondary, &lt;span style=&#34;color:#fab387&#34;&gt;0xFF&lt;/span&gt;, OAM_SECONDARY_SIZE);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;current_scanline_cycle &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;336&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;copy_sprite_flag &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;index_of_sprite &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;sprite_evaluation_index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;oam_memory_top &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Bit 5 of PPUCTRL determines sprite size
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; sprite_height &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;PPUCTRL &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x20&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;?&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;current_scanline_cycle &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;65&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;current_scanline_cycle &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;256&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// int index = ppu-&amp;gt;sprite_evaluation_index * 4 + ppu-&amp;gt;index_of_sprite;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;sprite_evaluation_index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;4&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; OAM_SIZE &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Odd cycle; read OAM
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;current_scanline_cycle &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;scanline &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;=&lt;/span&gt; oam_memory[index] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;scanline &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; oam_memory[index] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; sprite_height) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;copy_sprite_flag &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;copy_sprite_flag &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;oam_memory_top &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;31&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        oam_memory_secondary[ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;oam_memory_top&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; oam_memory[index];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        oam_memory_secondary[ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;oam_memory_top&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; oam_memory[index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        oam_memory_secondary[ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;oam_memory_top&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; oam_memory[index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        oam_memory_secondary[ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;oam_memory_top&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; oam_memory[index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;sprite_evaluation_index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;64&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;sprite_evaluation_index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;PPUSTATUS &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x20&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;sprite_evaluation_index&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;copy_sprite_flag &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;ppu_exec_visible_scanline&lt;/span&gt;(PPU &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;ppu) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  oam_buffer_latches[(ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;current_scanline_cycle &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;257&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;32&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    oam_memory_secondary[(ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;current_scanline_cycle &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;257&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;32&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The actual rendering code is basically identical to the background rendering. It just uses data from the &lt;code&gt;oam_buffer_latches&lt;/code&gt; instead of&lt;code&gt;ppu_memory&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Loop v&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;loop-v&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#loop-v&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;v&lt;/code&gt; is the current VRAM address used by the PPU to fetch the nametable, and attribute data. It&amp;rsquo;s a 15-bit register that changes during the rendering process, and each bit of this register has a significance to which tile to retrieve.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Bit(s)&lt;/th&gt;
          &lt;th&gt;Name&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;14–12&lt;/td&gt;
          &lt;td&gt;fine Y&lt;/td&gt;
          &lt;td&gt;Row offset within a tile (0–7)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;11&lt;/td&gt;
          &lt;td&gt;nametable Y&lt;/td&gt;
          &lt;td&gt;Selects vertical nametable (0 or 1)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;10&lt;/td&gt;
          &lt;td&gt;nametable X&lt;/td&gt;
          &lt;td&gt;Selects horizontal nametable (0 or 1)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;9–5&lt;/td&gt;
          &lt;td&gt;coarse Y&lt;/td&gt;
          &lt;td&gt;Tile row index on the screen (0–29)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;4–0&lt;/td&gt;
          &lt;td&gt;coarse X&lt;/td&gt;
          &lt;td&gt;Tile column index on the screen (0–31)&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;&amp;ndash;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;heading&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#heading&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;To get to this point took me quite a long time, mostly a lot of painful debugging. But after getting some coherent gameplay, it was all worth it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/nes-emulator/donkey_kong_menu.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;
&lt;img src=&#34;https://blog.kavin.me/blog/nes-emulator/donkey_kong_a1.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;
&lt;img src=&#34;https://blog.kavin.me/blog/nes-emulator/donkey_kong_a2.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;
&lt;img src=&#34;https://blog.kavin.me/blog/nes-emulator/ice_picker.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;APU - Audio Processing Unit&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;apu---audio-processing-unit&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#apu---audio-processing-unit&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Now it&amp;rsquo;s time to add audio. I found this part to be not too hard compared to the PPU, but the theory behind it can be quite confusing. How does a digital signal get converted to audio? Some basic understanding of digital signal processing will help, but basically sound is just a vibration in the air. The APU generates samples of this &lt;em&gt;vibration&lt;/em&gt; as a digital representation. My job is to simply collect these samples and use an existing library, &lt;code&gt;SDL2&lt;/code&gt; in my case, to generate the actual audio. The APU is comprised of five channels, 2 pulse channels, 1 triangle channel, 1 noise channel, and a delta modulation channel. The output of each of these channels is sent to a mixer. Currently, I&amp;rsquo;m using a simple averaging mixer, but I do plan on exploring other formulas in the future.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;apu_output&lt;/span&gt;(APU &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;apu) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; p1 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;apu_pulse_output&lt;/span&gt;(apu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;pulse1);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; p2 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;apu_pulse_output&lt;/span&gt;(apu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;pulse2);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; tri &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;apu_triangle_output&lt;/span&gt;(apu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;triangle);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;uint8_t&lt;/span&gt; noise &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;apu_noise_output&lt;/span&gt;(apu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;noise);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// At this point, I still have not implemented the Delta modulation channel.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;  
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; (p1 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; p2 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; tri &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; noise) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;Frame Counter&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;frame-counter&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#frame-counter&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The frame counter basically acts like a clock generator. Similar to how everything acts on the PPU cycle in the PPU, certain components act on the clock signal generated by the frame counter. The frame counter itself derives its generated clock signals by the APU cycle. For example, the frame counter will generate a clock signal at 3728 APU cycles. This would clock the &lt;code&gt;Envelopes&lt;/code&gt; and &lt;code&gt;Triangle&#39;s linear counter&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Length Counter, Envelope, Sweep&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;length-counter-envelope-sweep&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#length-counter-envelope-sweep&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Before I cover the actual channels, I&amp;rsquo;ll start off with the components they&amp;rsquo;re comprised. Namely, the length counter, envelope generator and the sweep unit.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;length counter&lt;/strong&gt; acts like a timer. Once it counts down to zero, the sound will stop. The CPU writes a 5 bit values to one of the APU&amp;rsquo;s memory mapped register, and this value serves as an index to a duration. For example, lets say the value is $1F. The corresponding duration would be 30, which is clocked by the &lt;code&gt;Frame Counter&lt;/code&gt;.&lt;/p&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    flowchart LR 
    CPU[&amp;#34;CPU writes 5-bit value (e.g. $1F) to APU register&amp;#34;] --&amp;gt; IDX[&amp;#34;Value used as index into length table&amp;#34;]
    IDX --&amp;gt; DUR[&amp;#34;Length counter initialized (e.g. 30)&amp;#34;]
    DUR --&amp;gt; FC[&amp;#34;Frame Counter ticks at 240Hz&amp;#34;]
    FC --&amp;gt; DEC[&amp;#34;Length counter decrements each tick&amp;#34;]
    DEC --&amp;gt; CHECK{&amp;#34;Length counter == 0?&amp;#34;}
    CHECK -- Yes --&amp;gt; STOP[&amp;#34;Sound channel muted&amp;#34;]
    CHECK -- No --&amp;gt; DEC
  &lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;The &lt;strong&gt;Envelope&lt;/strong&gt; controls the volume output. Depending on certain flags, the volume can either decay with an optional looping to repeat the decay, or it can be a constant volume.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;Sweep&lt;/strong&gt; unit can adjust a channel&amp;rsquo;s period up or down. Shorter period creates a higher pitch, while longer period creates a lower pitch.&lt;/p&gt;
&lt;h3&gt;Pulse Channels&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;pulse-channels&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#pulse-channels&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;This is a simple square wave generator with an adjustable &lt;code&gt;duty cycle&lt;/code&gt;, &lt;code&gt;volume&lt;/code&gt;  and &lt;code&gt;sweep&lt;/code&gt;. A period is the length of the smallest unrepeatable values in a signal. Duty cycle determines during the period when a value is 0, or when the signal is 1. Volume can either be constant, or have a decay. It is composed of a length counter, envelope, and a sweep unit.&lt;/p&gt;
&lt;div class=&#34;hx:overflow-x-auto hx:mt-6 hx:flex hx:rounded-lg hx:border hx:py-2 hx:ltr:pr-4 hx:rtl:pl-4 hx:contrast-more:border-current hx:contrast-more:dark:border-current hx:border-blue-200 hx:bg-blue-100 hx:text-blue-900 hx:dark:border-blue-200/30 hx:dark:bg-blue-900/30 hx:dark:text-blue-200&#34;&gt;
  &lt;div class=&#34;hx:ltr:pl-3 hx:ltr:pr-2 hx:rtl:pr-3 hx:rtl:pl-2&#34;&gt;&lt;svg height=1.2em class=&#34;hx:inline-block hx:align-middle&#34; xmlns=&#34;http://www.w3.org/2000/svg&#34; fill=&#34;none&#34; viewBox=&#34;0 0 24 24&#34; stroke-width=&#34;2&#34; stroke=&#34;currentColor&#34; aria-hidden=&#34;true&#34;&gt;&lt;path stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34; d=&#34;M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z&#34;/&gt;&lt;/svg&gt;&lt;/div&gt;

  &lt;div class=&#34;hx:w-full hx:min-w-0 hx:leading-7&#34;&gt;
    &lt;div class=&#34;hx:mt-6 hx:leading-7 hx:first:mt-0&#34;&gt;&lt;p&gt;I have included a little clip to show how important it is to nail the logic of each component. Have a listen!&lt;/p&gt;
&lt;video controls width=&#34;640&#34;&gt;
  &lt;source src=&#34;https://blog.kavin.me/video/unfixed_audio.mp 4&#34; type=&#34;video/mp4&#34;&gt;
  Your browser does not support the video tag.
&lt;/video&gt;
&lt;p&gt;It took me a long time to pinpoint this issue, as it was due to just a single line.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (envelope&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;constant_volume_flag) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    envelope&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;volume &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; envelope&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;divider&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;P;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    envelope&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;volume &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; envelope&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;divider&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;counter;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;If the constant volume flag was not set, I was resetting the volume to the value of the divider. This is why each note sounds choppy, as if the volume restarts! The corrected code is as shown below.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (envelope&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;constant_volume_flag) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    envelope&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;volume &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; envelope&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;divider&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;P;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    envelope&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;volume &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; envelope&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;envelope_decay_level_counter;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This results in the following.&lt;/p&gt;
&lt;video controls width=&#34;640&#34;&gt;
  &lt;source src=&#34;https://blog.kavin.me/video/fixed_audio.mp4&#34; type=&#34;video/mp4&#34;&gt;
  Your browser does not support the video tag.
&lt;/video&gt;
&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;h3&gt;Triangle Channel&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;triangle-channel&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#triangle-channel&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The Triangle channel is composed of a timer, a length counter, a linear counter, and some flags. A linear counter is basically a length counter, but its value is directly used, unlike a length counter which uses an index to get its duration.&lt;/p&gt;
&lt;p&gt;Unlike the pulse, the triangle channel has no envelope. Instead, when the timer is clocked, it traverses through a 32 step sequence of values to output to the mixer.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0
 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;Noise&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;noise&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#noise&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The Noise channel is composed of an envelope generator, a timer, a &lt;code&gt;Linear Feedback Shift Register&lt;/code&gt;, and a length counter. When clocked by the timer, a 1 bit &lt;em&gt;feedback&lt;/em&gt; value is calculated, the shift register gets shifted to the right by 1 bit, and the leftmost bit is set to the feedback. The mixer will get the value generated by the envelope if bit 0 if the shift register is 1. It will get zero otherwise.&lt;/p&gt;
&lt;div role=&#34;img&#34; aria-label=&#34;Diagram&#34;&gt;
  &lt;pre class=&#34;mermaid hx:mt-6&#34;&gt;
    flowchart TD
    R[&amp;#34;Shift Register (R): 100000000000001&amp;#34;]

    Timer[&amp;#34;Timer clocks shift register&amp;#34;] --&amp;gt; Feedback[&amp;#34;XOR bit 0 (1) and bit 6 (0) equals 1&amp;#34;]

    Feedback --&amp;gt; ShiftAfter[&amp;#34;After shift right by 1 bit: 010000000000000&amp;#34;]

    ShiftAfter --&amp;gt; SetBit14[&amp;#34;Set bit 14 = feedback (1)&amp;#34;]

    SetBit14 --&amp;gt; Result[&amp;#34;New register value: 1100000000000001&amp;#34;]

    R
  &lt;/pre&gt;
&lt;/div&gt;&lt;h3&gt;DMC&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;dmc&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#dmc&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;To be implemented.&lt;/p&gt;
&lt;br&gt;                                                                                                                           
&lt;br&gt;                                                                                                                                                                                                                                                                
&lt;h2&gt;The Frontend - SDL2&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;the-frontend---sdl2&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#the-frontend---sdl2&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Frontend&lt;/code&gt; is just the name of my abstraction for &lt;strong&gt;SDL2&lt;/strong&gt;. This is the library that handles all the rendering, control inputs, and audio. It&amp;rsquo;s a very popular library with a lot of examples, so it shouldn&amp;rsquo;t be too difficult getting something up and running using this library.&lt;/p&gt;
&lt;h3&gt;Visuals&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;visuals&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#visuals&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;I employ a flag to let the renderer know if the buffer is ready. When scanline 260 is reached, the PPU will set this flag.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;ppu_execute_cycle&lt;/span&gt;(PPU &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;ppu) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;scanline &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;260&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;scanline &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      ppu&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;update_graphics &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Once the flag is set, the &lt;code&gt;Frontend&lt;/code&gt; library will update SDL2 with the PPU&amp;rsquo;s frame buffer and reset the flag.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#89b4fa&#34;&gt;ppu_graphics_flag_set&lt;/span&gt;(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;ppu)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#89b4fa&#34;&gt;ppu_graphics_flag_reset&lt;/span&gt;(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;ppu);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#89b4fa&#34;&gt;Frontend_DrawFrame&lt;/span&gt;(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;frontend, ppu.frame_buffer);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#89b4fa&#34;&gt;Frontend_SetFrameTickStart&lt;/span&gt;(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;frontend);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;Controls&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;controls&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#controls&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The CPU sets a flag, &lt;code&gt;strobe&lt;/code&gt;, to indicate when its ready to poll the user inputs. When the user presses a button on the NES controller, the corresponding bit on a register is set, which is fed to the CPU. This register essentially holds the state of the controller per frame.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#89b4fa&#34;&gt;cpu_strobe_set&lt;/span&gt;(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;cpu)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#89b4fa&#34;&gt;Frontend_HandleInput&lt;/span&gt;(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;frontend) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// cpu.ctrl_latch_state = frontend.controller;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#89b4fa&#34;&gt;Frontend_SetController&lt;/span&gt;(&lt;span style=&#34;color:#89b4fa&#34;&gt;cpu_ctrl_latch_state&lt;/span&gt;(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;cpu));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The following code shows what keys I use for control.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; keyboard[&lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    SDL_SCANCODE_Z,  SDL_SCANCODE_X,    SDL_SCANCODE_C,    SDL_SCANCODE_V,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;Frontend_HandleInput&lt;/span&gt;(Frontend &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;frontend) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#89b4fa&#34;&gt;SDL_PumpEvents&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;const&lt;/span&gt; Uint8 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;keystate &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;SDL_GetKeyboardState&lt;/span&gt;(&lt;span style=&#34;color:#89dceb&#34;&gt;NULL&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  frontend&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;controller &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (keystate[SDL_SCANCODE_Q])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (keystate[keyboard[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;]])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    frontend&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;controller &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|=&lt;/span&gt; NES_A;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (keystate[keyboard[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;]])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    frontend&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;controller &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|=&lt;/span&gt; NES_B;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (keystate[keyboard[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;]])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    frontend&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;controller &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|=&lt;/span&gt; NES_SELECT;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (keystate[keyboard[&lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;]])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    frontend&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;controller &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|=&lt;/span&gt; NES_START;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (keystate[keyboard[&lt;span style=&#34;color:#fab387&#34;&gt;4&lt;/span&gt;]])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    frontend&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;controller &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|=&lt;/span&gt; NES_UP;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (keystate[keyboard[&lt;span style=&#34;color:#fab387&#34;&gt;5&lt;/span&gt;]])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    frontend&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;controller &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|=&lt;/span&gt; NES_DOWN;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (keystate[keyboard[&lt;span style=&#34;color:#fab387&#34;&gt;6&lt;/span&gt;]])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    frontend&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;controller &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|=&lt;/span&gt; NES_LEFT;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (keystate[keyboard[&lt;span style=&#34;color:#fab387&#34;&gt;7&lt;/span&gt;]])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    frontend&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&amp;gt;&lt;/span&gt;controller &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|=&lt;/span&gt; NES_RIGHT;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;Audio&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;audio&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#audio&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The standard frequency used for sampling is 44.1 kHz. With that in mind, we need to collect enough samples to generate audio at 44.1 kHz. However, the CPU frequency is 1.79 MHz. This would generate too many samples, at a frequency that would be inaudible to human ears. As such, I had to downsample this high-frequency signal to the standard 44.1 kHz audio rates, which will still preserve the shape of the NES sound waves while remaining audible. The calculation below illustrates how many samples I would need to get per frame.&lt;/p&gt;
\[
\begin{aligned}
\text{Audio Sample Rate} &amp;amp;= 44{,}100 \, \text{samples/sec} \\
\text{Video Frame Rate (NTSC)} &amp;amp;= 60 \, \text{frames/sec} \\
\\
\text{Samples per Frame} &amp;amp;= \frac{44{,}100}{60} = 735 \, \text{samples/frame}
\end{aligned}
\]&lt;p&gt;The calculation below illustrates how many times I&amp;rsquo;d have to downsample the NES APU signal to get the audio sample rate of 44.1 kHz. What this means is that I have to call my apu mixer function once approximately every 40 CPU cycles.&lt;/p&gt;
\[
\begin{aligned}
\text{CPU Clock Frequency} &amp;amp;= 1{,}789{,}773 \text{ Hz} \\
\text{Audio Sample Rate} &amp;amp;= 44{,}100 \text{ Hz} \\
\\
\text{Downsampling Factor} &amp;amp;= \frac{\text{CPU Clock Frequency}}{\text{Audio Sample Rate}} \\
&amp;amp;= \frac{1{,}789{,}773}{44{,}100} \\
&amp;amp;\approx 40.57
\end{aligned}
\]&lt;p&gt;My implementation of the calculation presented above is shown in the code below. I still call the apu mixer output (&lt;code&gt;apu_output&lt;/code&gt;) every CPU cycle, but I average it out over every ~40 CPU cycles. I could simply just disregard the other samples and call it every 40 cycles, but the sound quality improves drastically with this simple technique. The &lt;code&gt;audio_buffer_add&lt;/code&gt; is a function in the Frontend abstraction that adds the samples to a ring buffer.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; cpu.cycles; i&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#89b4fa&#34;&gt;apu_execute&lt;/span&gt;(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;apu);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      sample_accumulator &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;apu_output&lt;/span&gt;(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;apu);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      apu_accumulator &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1.0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (apu_accumulator &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;=&lt;/span&gt; apu_ticks_per_sample) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        apu_accumulator &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-=&lt;/span&gt; apu_ticks_per_sample;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;int16_t&lt;/span&gt; sample &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ((&lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt;)(sample_accumulator &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; apu_ticks_per_sample) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;4096&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89b4fa&#34;&gt;audio_buffer_add&lt;/span&gt;(sample);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        sample_accumulator &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0.0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The code below shows how SDL2 initializes the audio. It sets a frequency of 44100 Hz, expects 735 samples per buffer, repeatedly calls &lt;code&gt;audio_callback&lt;/code&gt; (the function the parses through the samples in the ring buffer), and uses signed 16 bit.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SDL_AudioSpec spec &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      .freq &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;44100&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      .format &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; AUDIO_S16SYS,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      .channels &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      .samples &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;735&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      .callback &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; audio_callback,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      .userdata &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89dceb&#34;&gt;NULL&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;audio_callback&lt;/span&gt;(&lt;span style=&#34;color:#f38ba8&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;userdata, Uint8 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;stream, &lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; len) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;int16_t&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;out &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (&lt;span style=&#34;color:#f38ba8&#34;&gt;int16_t&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;)stream;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; samples &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; len &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;sizeof&lt;/span&gt;(&lt;span style=&#34;color:#f38ba8&#34;&gt;int16_t&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#f38ba8&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; samples; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;++&lt;/span&gt;i) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; (read_pos &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!=&lt;/span&gt; write_pos) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      out[i] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; audio_buffer[read_pos];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      read_pos &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (read_pos &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt; AUDIO_BUFFER_SIZE;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      out[i] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Wrap up&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;wrap-up&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#wrap-up&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;That&amp;rsquo;s about it. I still have some stuff to do, like finishing up the &lt;code&gt;DMC&lt;/code&gt;, trying out different apu mixer formulas, implementing other NROM mappers. But as to the core functionality, I&amp;rsquo;m basically done. Of course, I still want to test other NROM0 ROMs, and I&amp;rsquo;m sure I&amp;rsquo;ll find something wrong about my code down the line. Overall, this was a pretty fun project. If you want to try something that will get you familiarized with how a computer works, building any emulator will definitely do it.&lt;/p&gt;
      </description>
    </item>
    
    <item>
      <title>Rust-based Quadcopter Part 1</title>
      <link>https://blog.kavin.me/blog/rust-based-flight-controller/</link>
      <pubDate>Sat, 08 Jun 2024 22:59:08 +0000</pubDate>
      
      <guid>https://blog.kavin.me/blog/rust-based-flight-controller/</guid>
      <description>
        
        
        &lt;p&gt;This post covers the details of how I made a flight controller for a quadcopter using Rust and an STM32.&lt;/p&gt;
&lt;h2&gt;Introduction&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;introduction&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#introduction&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;This project began as a desire to familiarize myself with embedded development. I wanted to challenge myself by using technology I was not familiar with or had no prior knowledge of. This led me to the idea of making a Rust-based quadcopter. I will walk through the different components and software I used to realize this project.&lt;/p&gt;
&lt;h2&gt;Components&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;components&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#components&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;To simplify things on my end, I decided to buy a drone kit that came with the following items:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Chassis&lt;/li&gt;
&lt;li&gt;4 30A Electronic Speed Controllers&lt;/li&gt;
&lt;li&gt;4 BLDC Motors&lt;/li&gt;
&lt;li&gt;4 Propellers&lt;/li&gt;
&lt;li&gt;Screws &amp;amp; Bolts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Other components needed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;STM32F411CEU6&lt;/li&gt;
&lt;li&gt;FlySky Transmitter &amp;amp; Receiver&lt;/li&gt;
&lt;li&gt;LiPO Battery&lt;/li&gt;
&lt;li&gt;IMU (LSM6DSOX)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Rust&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;rust&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#rust&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;Rust is a systems programming language with an emphasis on performance and stability. Writing a quadcopter flight controller in C is cool, but it&amp;rsquo;s been done before. I wanted to walk the less-trodden path and take this as an opportunity to learn a new language as well.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also helpful that Rust has extensive community support for microcontrollers. There are HALs for many microcontrollers provided by STM32. In fact there is even a crate, &lt;a href=&#34;https://docs.rs/svd2rust/latest/svd2rust/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;svd2rust&lt;/a&gt;, that allows users to transform SVD files into crates that expose APIs to access the peripherals of the microcontrollers.&lt;/p&gt;
&lt;p&gt;I am using the STM32F411CEU6 for my flight controller, so I will be using the &lt;a href=&#34;https://github.com/stm32-rs/stm32f4xx-hal&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;stm32f4xx-hal&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Real-Time Interrupt-Driven Concurrency&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;real-time-interrupt-driven-concurrency&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#real-time-interrupt-driven-concurrency&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;a href=&#34;https://rtic.rs/2/book/en/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;RTIC&lt;/a&gt; is a Rust-based framework that allows real-time interrupt-driven concurrency for ARM Cortex-M microcontrollers. It is similar to an RTOS in that they both perform scheduling. Where they differ is that RTIC uses the hardware on the Cortex-M MCUs to perform the scheduling instead of a scheduling kernel.&lt;/p&gt;
&lt;h2&gt;IMU &amp;amp; Kalman Filter&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;imu--kalman-filter&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#imu--kalman-filter&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;IMU, short for inertial measurement unit, measures the angular rate and acceleration of our quadcopter&amp;rsquo;s roll, pitch, and yaw. These measurements can be used to determine the &lt;code&gt;attitude&lt;/code&gt; (roll, pitch, and yaw) of my flight controller.&lt;/p&gt;
&lt;p&gt;The IMU I will be using, the LSM6DSOX, consists of a gyroscope and accelerometer. The gyroscope allows for the measurement of the angular rates of the IMU&amp;rsquo;s roll, pitch, and yaw axes. The accelerometer allows for the measurement of the acceleration of the IMU&amp;rsquo;s roll, pitch, and yaw axes.&lt;/p&gt;
&lt;p&gt;This IMU also supports I2C and SPI communication protocols. These protocols allow for communication with other devices. In my case, I need to send the reported measurements from my IMU to the STM32. While the list of I2C and SPI drivers written in Rust may be extensive, there was not one yet for the LSM6DSOX as of the date of this project, so I wrote my own I2C driver.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&#34;https://github.com/KavinTheG/LSM6DSOX-Embedded-Rust-Driver/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;I2C Driver&lt;/a&gt;&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;i2c-driver&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#i2c-driver&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;Before writing an I2C driver in Rust, I first took a look at how other drivers were created in Rust. &lt;a href=&#34;https://github.com/rust-embedded/awesome-embedded-rust&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;This&lt;/a&gt; is a pretty good list to look at. It even contains a few drivers for other IMUs.&lt;/p&gt;
&lt;p&gt;Most of them were built on top of the &lt;a href=&#34;https://github.com/rust-embedded/embedded-hal&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;&lt;em&gt;embedded-hal&lt;/em&gt;&lt;/a&gt; crate. This crate serves as a foundation for building platform-agnostic drivers, allowing a driver to work on a microcontroller regardless of its platform.&lt;/p&gt;
&lt;p&gt;Before I go further into details about my I2C driver, a basic understanding of the I2C protocol might be helpful. The I2C protocol uses two wires for serial communication between a &lt;em&gt;Master&lt;/em&gt; and a &lt;em&gt;Slave&lt;/em&gt;. These wires are labeled the serial data line (SDA) and the serial clock line (SCL). The first line is for data transfer and the second line is for communication. When attempting to read data through the SDA bus, it is first necessary for the Master (or the STM32 in my case) to write the address of the slave onto the bus it wants to read from. This is necessary so that any slave can respond if they have the corresponding address.&lt;/p&gt;
&lt;p&gt;This was a very basic overview of the I2C protocol, and a lot of the underlying mechanisms of how it works were not covered, mainly because the &lt;em&gt;embedded-hal&lt;/em&gt; crate does a great job at abstracting away the underlying details.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/rust-based-flight-controller/I2C-layout.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;p&gt;With that basic understanding of the protocol, my driver will make more sense. In order to get the gyroscope and accelerometer values, I just have to write the address of my IMU on the I2C bus, and then read from the address of the register that stores the desired data. To find the IMU slave address, and the address of the registers where the data is stored, I had to read the LSM6DSOX datasheet. I have created two files, &lt;em&gt;gyro.rs&lt;/em&gt; and &lt;em&gt;accel.rs&lt;/em&gt;, to contain the registers necessary to read their values.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Rust&#34; data-lang=&#34;Rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#[allow(non_camel_case_types)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#[allow(dead_code)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#[derive(Copy, Clone)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;Register&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Gyro Configuration Register
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f9e2af&#34;&gt;CTRL2_G&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x11&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Angular rate pitch axis (X) output
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f9e2af&#34;&gt;OUTX_L_G&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x22&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f9e2af&#34;&gt;OUTX_H_G&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x23&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Angular rate roll axis (Y) output
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f9e2af&#34;&gt;OUTY_L_G&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x24&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f9e2af&#34;&gt;OUTY_H_G&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x25&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Angular rate yaw axis (Z) output
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f9e2af&#34;&gt;OUTZ_L_G&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x26&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f9e2af&#34;&gt;OUTZ_H_G&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x27&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;impl&lt;/span&gt; Register {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;addr&lt;/span&gt;(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;self&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u8&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;self&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#[allow(non_camel_case_types)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#[allow(dead_code)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#[derive(Copy, Clone)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;Register&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// ACCELEROMETER CONFIG REG
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f9e2af&#34;&gt;CTRL1_XL&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x10&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Accel rate X axis (X) output
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f9e2af&#34;&gt;OUTX_L_A&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x28&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f9e2af&#34;&gt;OUTX_H_A&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x29&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Accel rate Y axis (Y) output
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f9e2af&#34;&gt;OUTY_L_A&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x2A&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f9e2af&#34;&gt;OUTY_H_A&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x2B&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Accel rate Z axis (Z) output
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f9e2af&#34;&gt;OUTZ_L_A&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x2C&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f9e2af&#34;&gt;OUTZ_H_A&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x2D&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;impl&lt;/span&gt; Register {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;addr&lt;/span&gt;(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;self&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u8&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;self&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;I then defined the class/instance of my i2c driver with the paramter &lt;em&gt;I2C&lt;/em&gt;. Users will be required to define an I2C object to use this library.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// lsm6dsox driver
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;Lsm6dsox&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;I2C&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    i2c: &lt;span style=&#34;color:#f9e2af&#34;&gt;I2C&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt; endcodeblock &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt; codeblock lang:&lt;span style=&#34;color:#f9e2af&#34;&gt;rust&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;I2C&lt;/span&gt;, E&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; Lsm6dsox&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;I2C&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;where&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f9e2af&#34;&gt;I2C&lt;/span&gt;: &lt;span style=&#34;color:#f9e2af&#34;&gt;WriteRead&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;Error &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; E&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; Write&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;Error &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; E&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {       
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;new&lt;/span&gt;(i2c: &lt;span style=&#34;color:#f9e2af&#34;&gt;I2C&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#89dceb&#34;&gt;Result&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;Self&lt;/span&gt;, E&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; lsm6dsox &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; Lsm6dsox { i2c };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89dceb&#34;&gt;Ok&lt;/span&gt;(lsm6dsox)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;..&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The code above serves to implement a struct Lsm6dsox with a parameter I2C such that I2C has the methods &lt;em&gt;WriteRead&lt;/em&gt; and &lt;em&gt;Write&lt;/em&gt;.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;configure_accel&lt;/span&gt;(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;self&lt;/span&gt;, i2c: &lt;span style=&#34;color:#cba6f7&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;mut&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;I2C&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#89dceb&#34;&gt;Result&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;(), E&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// ODR_XL[7:4] = 0100; sets accelerometer to work at 200 Hz
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// FS[3:2] = 10; sets accelerometer full-scale selection to 4g
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// LPF2_XL_EN[1] = 1; output from first stage digital filtering
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// 0100 10 1 0
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; configuration: &lt;span style=&#34;color:#f38ba8&#34;&gt;u8&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0x48&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;match&lt;/span&gt; i2c.write(&lt;span style=&#34;color:#f9e2af&#34;&gt;SLAVE_ADDRESS&lt;/span&gt;, &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;[&lt;span style=&#34;color:#f9e2af&#34;&gt;CTRL1_XL&lt;/span&gt;, configuration]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89dceb&#34;&gt;Ok&lt;/span&gt;(_) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#89dceb&#34;&gt;Ok&lt;/span&gt;(()),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89dceb&#34;&gt;Err&lt;/span&gt;(e) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#89dceb&#34;&gt;Err&lt;/span&gt;(e),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In the function above, I configure the accelerometer in my IMU. Referring to the datasheet, I observe that each bit in the configuration register influences aspects such as the frequency of readings. I utilize the write method to transmit the 8 bit value &lt;em&gt;configuration&lt;/em&gt; to the &lt;code&gt;CTRL1_XL&lt;/code&gt; register of the device, specifying the slave address as &lt;em&gt;SLAVE_ADDRESS&lt;/em&gt;. The process of configuring the gyroscope mirrors that of the accelerometer, albeit with different configuration values and register addresses.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Read Accelerometer Data
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;read_accel&lt;/span&gt;(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; &lt;span style=&#34;color:#89dceb&#34;&gt;self&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#89dceb&#34;&gt;Result&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;[&lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;], E&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; accel_data: [&lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#fab387&#34;&gt;0.0&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0.0&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0.0&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; buffer: &lt;span style=&#34;color:#f9e2af&#34;&gt;GenericArray&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;u8&lt;/span&gt;, U6&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;unsafe&lt;/span&gt; { MaybeUninit::uninit().assume_init() };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    { 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; buffer: &lt;span style=&#34;color:#cba6f7&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;mut&lt;/span&gt; [&lt;span style=&#34;color:#f38ba8&#34;&gt;u8&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; buffer;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89dceb&#34;&gt;self&lt;/span&gt;.i2c.write_read(&lt;span style=&#34;color:#f9e2af&#34;&gt;SLAVE_ADDRESS&lt;/span&gt;, &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;[accel::Register::&lt;span style=&#34;color:#f9e2af&#34;&gt;OUTX_L_A&lt;/span&gt;.addr()], buffer)&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;?&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ((buffer[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;i16&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; (buffer[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;i16&lt;/span&gt;)) &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;4.0&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;32768.0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ((buffer[&lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;] &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;i16&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; (buffer[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;] &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;i16&lt;/span&gt;)) &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;4.0&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;32768.0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ((buffer[&lt;span style=&#34;color:#fab387&#34;&gt;5&lt;/span&gt;] &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;i16&lt;/span&gt;) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; (buffer[&lt;span style=&#34;color:#fab387&#34;&gt;4&lt;/span&gt;] &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;i16&lt;/span&gt;)) &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;4.0&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;32768.0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#89dceb&#34;&gt;Ok&lt;/span&gt;(accel_data)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In the function above, I read accelerometer data. Each axis&amp;rsquo;s data is 16 bits, spread across 2 8-bit registers. To get each axis&amp;rsquo;s value, I read from 6 consecutive registers (3 axis multiplied by 2 register per axis). The &lt;code&gt;write_read&lt;/code&gt; method writes &lt;code&gt;SLAVE_ADDRESS&lt;/code&gt; to the I2C bus and reads enough bytes from the device with the address of &lt;code&gt;SLAVE_ADDRESS&lt;/code&gt; to fill &lt;code&gt;buffer&lt;/code&gt; in one go. This reads all accelerometer registers if &lt;code&gt;buffer&lt;/code&gt; has 6 bytes. The IMU is configured by default to automatically increment a register address during a multiple byte access with a serial interface.&lt;/p&gt;
&lt;p&gt;Accelerometer data for each axis is 16-bit. The IMU stores the 8 most significant bits in one register and the 8 least significant bits in another. For the accelerometer, &lt;code&gt;OUTX_H_A&lt;/code&gt; is the MSB for the X-axis, and &lt;code&gt;OUTX_L_A&lt;/code&gt; is the LSB. I left shift &lt;code&gt;buffer[1]&lt;/code&gt;, &lt;code&gt;buffer[3]&lt;/code&gt;, and &lt;code&gt;buffer[5]&lt;/code&gt; by 8 bits, and bitwise &lt;em&gt;OR&lt;/em&gt; these values with their corresponding LSBs to reconstruct each axis&amp;rsquo;s value.&lt;/p&gt;
&lt;h3&gt;Deriving the Attitude&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;deriving-the-attitude&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#deriving-the-attitude&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;So I&amp;rsquo;m able to get the angular rates and acceleration of each axis using my IMU. But how can this be used to get the angles of roll, pitch, and yaw axis? I&amp;rsquo;ll discuss two ways of obtaining the attitude from the gyrscope and accelerometer.&lt;/p&gt;
&lt;p&gt;Angular rate is just the rate at which the angle changes in a moment of time. By integrating this value, we can get the the angle of each axis. Integration in the context of a microcontroller would have to be discretized. This simplifies the calculations a lot. To get the angle of an axis, you would do a summation of the corresponding angular rate multiplied by the &lt;code&gt;delta time&lt;/code&gt;. In our case, the delta time would be the amount of time elapsed between the previous and current loop.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; mono_timer &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; MonoTimer::new(cp.&lt;span style=&#34;color:#f9e2af&#34;&gt;DWT&lt;/span&gt;, cp.&lt;span style=&#34;color:#f9e2af&#34;&gt;DCB&lt;/span&gt;, &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;clocks);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; start_time &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; mono_timer.now();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;loop&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; time &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; start_time.elapsed();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; delta_time &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; time &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; prev_time;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; delta_sec &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; delta_time &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; clocks.sysclk().raw() &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;2.0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gyro_data &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; imu.read_gyro().unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    x_gyro &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+=&lt;/span&gt; delta_sec &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; gyro_data[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;]; &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Angle of flight controller in the x-axis
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    y_gyro &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+=&lt;/span&gt; delta_sec &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; gyro_data[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;]; &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Angle of the flight controller in the y-axis
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    z_gyro &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+=&lt;/span&gt; delta_sec &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; gyro_data[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    prev_time &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; time;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;While this method works in the short term, you will notice that the angles derived from the gyrscope drastically loses any accuracy as time progresses. This is due to the fact the there is an uncertainty in the readings of the angular rate, and as we integrate these uncertainties, the error will accumulate.&lt;/p&gt;
&lt;p&gt;The second method is using the accelerometer. As previously mentioned the accelerometer measures the acceleration of each of its axis (X, Y, and Z). At rest, the Z axis will report a value of around ~ 1 (measured in g&amp;rsquo;s). If the IMU is in a different orientation, each of its axis will experience a different portion of gravity. Plugging these values into trigonometric equations can give us the orientation of the IMU in terms of degrees of each of its axis except for the z-axis. The z-axis cannot be calculated as this is inherent limitation to an accelerometer.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;accel_data &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; imu.read_accel(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; i2c).unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;y_accel &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; atanf(accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; sqrtf(accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;]) ) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;180.0&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;PI&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;x_accel &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; atanf(accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; sqrtf(accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;]) ) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;180.0&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;PI&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;While the results from an accelerometer are mostly accurate, in moments of high vibrations the values are basically useless as there is too much noise.&lt;/p&gt;
&lt;p&gt;So we have a scenario in which the gyrscope&amp;rsquo;s data is useful in the short-term, but useless in the long-term and the vice-versa for the accelerometer&amp;rsquo;s data. A &lt;code&gt;Kalman Filter&lt;/code&gt; is perfect for this scenario.&lt;/p&gt;
&lt;h3&gt;What is a Kalman Filter?&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;what-is-a-kalman-filter&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#what-is-a-kalman-filter&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;The Kalman filter is an algorithm used for estimating the state of a system in the presence of noisy measurements. It works by iteratively predicting the next state based on a dynamic model and comparing it with actual measurements. The filter optimally combines predictions and measurements, dynamically adjusting their contributions based on their uncertainties. This allows the Kalman filter to provide a more accurate and stable estimate of the system&amp;rsquo;s true state, making it widely used in applications like sensor fusion for robotics, navigation, and control systems.&lt;/p&gt;
&lt;p&gt;In my case, I can use it to fuse the data from the accelerometer and gyroscope that can minimize their respective downfalls to produce a more accurate result. I found &lt;a href=&#34;https://blog.tkjelectronics.dk/2012/09/a-practical-approach-to-kalman-filter-and-how-to-implement-it/&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;this blog&lt;/a&gt; by TKJ Electornics to be very helpful in understanding how a Kalman Filter can be applied to a 6-axis IMU.&lt;/p&gt;
&lt;h2&gt;ESC&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;esc&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#esc&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;The electronic speed controller is a simple piece of circuit that controls the speed of the motors. There are a few methods to communicate with the ESC from my microcontroller to dictate the speed of the controllers. I will be using the simplest method, PWM signals.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;What is PWM?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Pulse-width-modulation is essentially rectangular wave signal with a &lt;code&gt;duty cycle&lt;/code&gt; and &lt;code&gt;period&lt;/code&gt;. A duty signal is the percentage of the signal that is active. A period is the time between each succesive occurence.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/rust-based-flight-controller/pwm.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For my ESC, I can dictate the desired speed of my motors by sending a 50Hz PWM signal. When the active portion is 1ms, the ESC interprets that as zero throttle. When the active portion is 2ms, the ESC interprets that as full throttle. Any signal with an active portion between 1ms to 2ms will set the speed proportionately. For example, a PWM signal with an active portion of 1.5ms will set the throttle to half the max speed.&lt;/p&gt;
&lt;p&gt;For my ESC to work, it needs to initially register a zero throttle signal before it can receive any other signal&lt;/p&gt;
&lt;h3&gt;PWM Implementation&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;pwm-implementation&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#pwm-implementation&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;I first needed to setup the timer channels. Each timer in the STM32 has two channels assosiated to itself. Thus, each timer can generate two differnt PWM signals. For your microcontroller, you must check the pinout sheet to see which pins to use.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; gpioa &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; dp.&lt;span style=&#34;color:#f9e2af&#34;&gt;GPIOA&lt;/span&gt;.split();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; channels &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (Channel1::new(gpioa.pa8), Channel2::new(gpioa.pa9));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt; endcodeblock &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;In the codeblock below, I am setting up the channel &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; a &lt;span style=&#34;color:#f9e2af&#34;&gt;PWM&lt;/span&gt; singal with a frequency of &lt;span style=&#34;color:#fab387&#34;&gt;50&lt;/span&gt; Hz. 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt; codeblock lang:&lt;span style=&#34;color:#f9e2af&#34;&gt;rust&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; pwm &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; dp.&lt;span style=&#34;color:#f9e2af&#34;&gt;TIM1&lt;/span&gt;.pwm_hz(channels, &lt;span style=&#34;color:#fab387&#34;&gt;50.&lt;/span&gt;Hz(), &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;clocks).split();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; (&lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; ch1, _ch2) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; pwm;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; max_duty &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ch1.get_max_duty() &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u32&lt;/span&gt;; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ch1.enable();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In the &lt;code&gt;stm32f4xx-hal&lt;/code&gt;, the &lt;code&gt;set_duty&lt;/code&gt; method requires a value rather than a percentage. To send a zero throttle signal, I need to determine the duty cycle with an active portion of 1ms.&lt;/p&gt;
&lt;p&gt;Given that a 50 Hz signal has a period of 20ms, the duty cycle for a zero throttle signal would be 1ms / 20ms, which equals 0.05. Therefore, to achieve a zero throttle signal, I multiply the maximum duty cycle by 5 / 1000, or equivalently, divide it by 20.&lt;/p&gt;
&lt;p&gt;For the maximum throttle signal, the duty cycle would be 2ms / 20ms, which equals 0.1. Thus, the corresponding maximum throttle signal would be the maximum duty cycle divided by 10.&lt;/p&gt;
&lt;p&gt;Additionally, I introduce a slight delay to allow the ESC to register the zero throttle signal. I can confirm this works because I hear specific beeps in a distinct melody.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;Zero signal&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ch1.set_duty(ch1.get_max_duty() &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;20&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;Slight delay&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;delay.delay_ms(&lt;span style=&#34;color:#fab387&#34;&gt;10000_&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;u32&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; min_limit &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; max_duty &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;5&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1000&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; max_limit &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; max_duty &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;100&lt;/span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt; codeblock lang:&lt;span style=&#34;color:#f9e2af&#34;&gt;rust&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; value &lt;span style=&#34;color:#cba6f7&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;..&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;50&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//ch1.set_duty(map(value, 0, 100, min_limit, max_limit));
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; throttle &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; map(value, &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;100&lt;/span&gt;, min_limit, max_limit);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ch1.set_duty(throttle &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u16&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    delay.delay_ms(&lt;span style=&#34;color:#fab387&#34;&gt;12_&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;u32&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;..&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;map&lt;/span&gt;(x: &lt;span style=&#34;color:#f38ba8&#34;&gt;u32&lt;/span&gt;, in_min: &lt;span style=&#34;color:#f38ba8&#34;&gt;u32&lt;/span&gt;, in_max: &lt;span style=&#34;color:#f38ba8&#34;&gt;u32&lt;/span&gt;, out_min: &lt;span style=&#34;color:#f38ba8&#34;&gt;u32&lt;/span&gt;, out_max: &lt;span style=&#34;color:#f38ba8&#34;&gt;u32&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (x &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; in_min) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; (out_max &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; out_min) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; (in_max &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; in_min) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; out_min
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt; endcodeblock &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;%&lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Remote Controller&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;remote-controller&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#remote-controller&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;For my remote controller, I am using the FlySky FS-IA6B. It comes with the transmitter and a receiver. All I had to do is read any bytes from the receiver. FlySky has something called the IBus protocol, which essentially allows it to send the data of all the channels in 32 byte packets through the UART hardware.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Note
A channel in this context refers to each inputs on the transmitter, such as the joysticsk and switches.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To my luck, the stm32f4xx-hal repository already contains an &lt;a href=&#34;https://github.com/stm32-rs/stm32f4xx-hal/blob/master/examples/rtic-serial-dma-rx-idle.rs&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;example&lt;/a&gt; with UART and RTIC. This example uses a UART interrupt to immediately notify the CPU when the UART has new information.&lt;/p&gt;
&lt;p&gt;Unfortunately, getting this to work for my usecase proved to be quite difficult. The UART would constantly get new data so it would starve the other tasks. Instead, I switched to &lt;code&gt;polling&lt;/code&gt; the UART for new info and implemented a checksum verification to discard erroneous packets.&lt;/p&gt;
&lt;blockquote&gt;
  &lt;p&gt;Note
Interrupts allow hardware to notify the CPU of a specific event. &lt;code&gt;Polling&lt;/code&gt; is when the CPU checks on the hardware for any new events. This comes at the cost of additional CPU clock cycles.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#[task(binds = TIM3, priority = 1, local=[rc_timer, prod_flysky, rx])]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;process_received_bytes&lt;/span&gt;(ctx: &lt;span style=&#34;color:#f9e2af&#34;&gt;process_received_bytes&lt;/span&gt;::Context) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ctx.local.rc_timer.clear_all_flags();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ctx.local.rc_timer.start(&lt;span style=&#34;color:#fab387&#34;&gt;15.&lt;/span&gt;millis()).unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; rx &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ctx.local.rx;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;process received bytes&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; bytes &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;u8&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;32&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; checksum: &lt;span style=&#34;color:#f38ba8&#34;&gt;u16&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;while&lt;/span&gt; index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#89dceb&#34;&gt;Ok&lt;/span&gt;(byte) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; rx.read() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; byte &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Ignore bytes until the first byte is 32 (space character)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                    &lt;span style=&#34;color:#cba6f7&#34;&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                bytes[index] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; byte;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//rprintln!(&amp;#34;bytes: {:?}&amp;#34;, bytes);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; channel_values: [&lt;span style=&#34;color:#f38ba8&#34;&gt;u16&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#cba6f7&#34;&gt;in&lt;/span&gt; (&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;..&lt;/span&gt;bytes.len()).step_by(&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; bytes.len() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Extract two bytes from the pair
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; byte1 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u16&lt;/span&gt;::from(bytes[i]);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; byte2 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u16&lt;/span&gt;::from(bytes[i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;]);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;30&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    checksum &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+=&lt;/span&gt; byte1 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; byte2;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Combine the bytes by multiplying the second number by 256
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//let combined_value = u16::from(byte1) + u16::from(byte2) * 256;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; combined_value &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; byte1 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; byte2 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; channel_index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//rprintln!(&amp;#34;index: {:?}&amp;#34;, channel_index);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Do something with the combined value (e.g., print or use it)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                channel_values[channel_index] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; combined_value;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//rprintln!(&amp;#34;Combined Value: {}&amp;#34;, combined_value);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;            } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#cba6f7&#34;&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;65535&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; channel_values[&lt;span style=&#34;color:#fab387&#34;&gt;15&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u16&lt;/span&gt;::from(checksum) {             
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;{:?} != {:?}&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;65535&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; channel_values[&lt;span style=&#34;color:#fab387&#34;&gt;15&lt;/span&gt;], checksum);                            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//rprintln!(&amp;#34;Channels: {:?}&amp;#34;, channel_values);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; _throttle &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; channel_values[&lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;] &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; _desired_roll &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; map(channel_values[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;1000.&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;2000.&lt;/span&gt;, &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;15.&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;15.&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; _desired_pitch &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; map(channel_values[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;] &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;1000.&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;2000.&lt;/span&gt;, &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;15.&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;15.&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#cba6f7&#34;&gt;match&lt;/span&gt; ctx.local.prod_flysky.enqueue([_throttle, _desired_roll, _desired_pitch]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#89dceb&#34;&gt;Ok&lt;/span&gt;(()) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//rprintln!(&amp;#34;Data sent&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#89dceb&#34;&gt;Err&lt;/span&gt;(_err) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Other errors occurred, handle them appropriately
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Example: println!(&amp;#34;Error occurred while enqueueing data: {:?}&amp;#34;, err);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                    &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;Flysky failed to enqueue&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;PID&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;pid&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#pid&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;A pid is a control loop concept that can use feedback to adjust the inputs to drive the system towards a desired state. I will be simplifing how PIDs work &lt;strong&gt;a lot&lt;/strong&gt; as I probably won&amp;rsquo;t do a good job at explaining its complexities.&lt;/p&gt;
&lt;p&gt;For my drone, I am able to get the attitude of my drone, and I can set the desired attitude with my remote controller. I need some sort of mechanism to force the drone to match the attitude set by the remote controller. A PID controller can do so by constantly adjusting the speed of each motor to match the desired angle. A PID must be configured to work properly by tuning its three parameters; proportional, controller, and integral.&lt;/p&gt;
&lt;h4&gt;Proportion&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;proportion&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#proportion&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;The porportional or P-controller takes a fraction of the error. For example, the pitch of my drone may be 15 degrees, but my desired pitch could be 0 degrees. The error would be 15 degrees. The proportion would multiply this error by a factor to adjust the input throttle to each motor.&lt;/p&gt;
&lt;h4&gt;Integral&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;integral&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#integral&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;The integral or I-controller helps with small errors by taking a fraction of the integral of the error.&lt;/p&gt;
&lt;h4&gt;Derivative&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;derivative&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#derivative&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;This controller takes into account on how rapidly the error is changing by taking a fraction of the error&amp;rsquo;s derivative.&lt;/p&gt;
&lt;h2&gt;RTIC&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;rtic&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#rtic&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;RTIC, as mentioned previously, is a real-time framework. In the context of embedded software, a real-time system is defined as one that is &lt;code&gt;deterministic&lt;/code&gt; and meets specific timing requirements. This is in contrast to systems like Arduinos, which rely on one large loop. While Arduino-based quadcopters have been developed before, using a real-time framework like RTIC can provide greater reliability in certain scenarios. Determining which approach is better depends on the use case.&lt;/p&gt;
&lt;p&gt;RTIC includes a scheduler that determines which &lt;code&gt;task&lt;/code&gt; to run by programming the MCU&amp;rsquo;s hardware. In my project, I have three tasks. The first task polls the UART for new data. The second task employs the Kalman Filter to determine the drone&amp;rsquo;s attitude from the IMU data. The third task is the flight controller task, where I use a PID controller to generate the appropriate throttle signals for each motor. Each task operates as an &lt;em&gt;interrupt service routine&lt;/em&gt; of a timer, allowing them to run approximately every 15ms with high accuracy. RTIC also includes an &lt;em&gt;init&lt;/em&gt; task, responsible for configuring all the hardware and setting initial values.&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#![no_main]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#![no_std]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#![feature(type_alias_impl_trait)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;use&lt;/span&gt; panic_halt &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; _;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;mod&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;kalman&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;mod&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;pid&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;use&lt;/span&gt; rtic::app;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#[app(device = stm32f4xx_hal::pac, dispatchers = [SPI1, SPI2])]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;mod&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;app&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;use&lt;/span&gt; core::&lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;::consts::&lt;span style=&#34;color:#f9e2af&#34;&gt;PI&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;use&lt;/span&gt; heapless::spsc::{Consumer, Producer, Queue};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;use&lt;/span&gt; rtic_monotonics::{create_systick_token, systick::Systick};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;use&lt;/span&gt; stm32f4xx_hal::{&lt;span style=&#34;color:#89dceb&#34;&gt;self&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; hal};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;use&lt;/span&gt; hal::{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        i2c::{I2c1, Mode}, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        pac::{&lt;span style=&#34;color:#f9e2af&#34;&gt;TIM1&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;TIM2&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;TIM3&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;TIM4&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;TIM5&lt;/span&gt;, &lt;span style=&#34;color:#f9e2af&#34;&gt;USART1&lt;/span&gt;}, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        prelude::&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt;, rcc::RccExt, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        serial::{Config, Rx, Serial}, 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        timer::{&lt;span style=&#34;color:#89dceb&#34;&gt;self&lt;/span&gt;, Channel1, Channel2, Event, PwmChannel}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;use&lt;/span&gt; rtt_target::{rprintln, rtt_init_print};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086&#34;&gt;/** Kalman Filter Libraries **/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;use&lt;/span&gt; libm::{atanf, sqrtf};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;use&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;crate&lt;/span&gt;::kalman::KalmanFilter;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;use&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;crate&lt;/span&gt;::pid::Pid;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;use&lt;/span&gt; lsm6dsox_driver::Lsm6dsox;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;FC_DELTA&lt;/span&gt;: &lt;span style=&#34;color:#f38ba8&#34;&gt;u32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;15&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;KALMAN_DELTA&lt;/span&gt;: &lt;span style=&#34;color:#f38ba8&#34;&gt;u32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;15&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#[shared]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;Shared&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#[local]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;Local&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086&#34;&gt;/** FlySky Buffer **/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        rx: &lt;span style=&#34;color:#f9e2af&#34;&gt;Rx&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;USART1&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;u8&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        prod_flysky: &lt;span style=&#34;color:#f9e2af&#34;&gt;Producer&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;&amp;#39;static&lt;/span&gt;, [&lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;], &lt;span style=&#34;color:#fab387&#34;&gt;10&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        con_flysky: &lt;span style=&#34;color:#f9e2af&#34;&gt;Consumer&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;&amp;#39;static&lt;/span&gt;, [&lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;], &lt;span style=&#34;color:#fab387&#34;&gt;10&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        rc_timer: &lt;span style=&#34;color:#f9e2af&#34;&gt;timer&lt;/span&gt;::CounterMs&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;TIM3&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086&#34;&gt;/** Kalman Filter Variables **/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        kalman_timer: &lt;span style=&#34;color:#f9e2af&#34;&gt;timer&lt;/span&gt;::CounterMs&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;TIM4&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        imu: &lt;span style=&#34;color:#f9e2af&#34;&gt;Lsm6dsox&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;I2c1&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        x_kalman: &lt;span style=&#34;color:#f9e2af&#34;&gt;KalmanFilter&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        y_kalman: &lt;span style=&#34;color:#f9e2af&#34;&gt;KalmanFilter&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        prod_kalman: &lt;span style=&#34;color:#f9e2af&#34;&gt;Producer&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;&amp;#39;static&lt;/span&gt;, [&lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;], &lt;span style=&#34;color:#fab387&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        con_kalman: &lt;span style=&#34;color:#f9e2af&#34;&gt;Consumer&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#89dceb&#34;&gt;&amp;#39;static&lt;/span&gt;, [&lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;], &lt;span style=&#34;color:#fab387&#34;&gt;5&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086&#34;&gt;/** Flight Controller variables **/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fc_timer: &lt;span style=&#34;color:#f9e2af&#34;&gt;timer&lt;/span&gt;::CounterMs&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;TIM5&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086&#34;&gt;/** ESC **/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m1: &lt;span style=&#34;color:#f9e2af&#34;&gt;PwmChannel&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;TIM1&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m2: &lt;span style=&#34;color:#f9e2af&#34;&gt;PwmChannel&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;TIM1&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m3: &lt;span style=&#34;color:#f9e2af&#34;&gt;PwmChannel&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;TIM2&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m4: &lt;span style=&#34;color:#f9e2af&#34;&gt;PwmChannel&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;TIM2&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        pitch_pid: &lt;span style=&#34;color:#f9e2af&#34;&gt;Pid&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        roll_pid: &lt;span style=&#34;color:#f9e2af&#34;&gt;Pid&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#[init(local = [
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;        rx_pool_memory: [u8; 400] = [0; 400],
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;        queue_kalman: Queue&amp;lt;[f32; 2], 5&amp;gt; = Queue::new(),
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;        queue_flysky: Queue&amp;lt;[f32; 3], 10&amp;gt; = Queue::new(),
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;    ])]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;init&lt;/span&gt;(cx: &lt;span style=&#34;color:#f9e2af&#34;&gt;init&lt;/span&gt;::Context) -&amp;gt; (Shared, Local) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89b4fa&#34;&gt;rtt_init_print!&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;Init&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; (prod_kalman, con_kalman) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; cx.local.queue_kalman.split();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; (prod_flysky, con_flysky) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; cx.local.queue_flysky.split();        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; token &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;create_systick_token!&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Systick::start(cx.core.&lt;span style=&#34;color:#f9e2af&#34;&gt;SYST&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;100_000_000&lt;/span&gt;, token);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; dp: &lt;span style=&#34;color:#f9e2af&#34;&gt;hal&lt;/span&gt;::pac::Peripherals &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; cx.device;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; rcc &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; dp.&lt;span style=&#34;color:#f9e2af&#34;&gt;RCC&lt;/span&gt;.constrain();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//let clocks = rcc.cfgr.freeze();
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//let clocks = rcc.cfgr.hclk(8.MHz()).freeze();
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; clocks &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; rcc.cfgr.use_hse(&lt;span style=&#34;color:#fab387&#34;&gt;25.&lt;/span&gt;MHz()).sysclk(&lt;span style=&#34;color:#fab387&#34;&gt;36.&lt;/span&gt;MHz()).hclk(&lt;span style=&#34;color:#fab387&#34;&gt;25.&lt;/span&gt;MHz()).freeze();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// let clocks = rcc.cfgr
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//     .use_hse(8.MHz())
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//     .sysclk(36.MHz())
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//     .pclk1(36.MHz())
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//     .freeze();
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; gpioa &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; dp.&lt;span style=&#34;color:#f9e2af&#34;&gt;GPIOA&lt;/span&gt;.split();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; rx_pin &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; gpioa.pa10; &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// RX
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Configure USART1 with a baud rate of 115200
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; rx: &lt;span style=&#34;color:#f9e2af&#34;&gt;Rx&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&#34;color:#f9e2af&#34;&gt;USART1&lt;/span&gt;, &lt;span style=&#34;color:#f38ba8&#34;&gt;u8&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Serial::rx(dp.&lt;span style=&#34;color:#f9e2af&#34;&gt;USART1&lt;/span&gt;, rx_pin, Config::default().baudrate(&lt;span style=&#34;color:#fab387&#34;&gt;115200.&lt;/span&gt;bps()), &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;clocks).unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; rc_timer &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; dp.&lt;span style=&#34;color:#f9e2af&#34;&gt;TIM3&lt;/span&gt;.counter_ms(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;clocks);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        rc_timer.start(&lt;span style=&#34;color:#fab387&#34;&gt;10000.&lt;/span&gt;millis()).unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        rc_timer.listen(Event::Update);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; gpiob &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; dp.&lt;span style=&#34;color:#f9e2af&#34;&gt;GPIOB&lt;/span&gt;.split();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//// LSM6DSOX IMU \\\\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; scl &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; gpiob.pb6.into_open_drain_output();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; sda &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; gpiob.pb7.into_open_drain_output();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; i2c &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; dp.&lt;span style=&#34;color:#f9e2af&#34;&gt;I2C1&lt;/span&gt;.i2c(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (scl, sda),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Mode::Standard {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                frequency: &lt;span style=&#34;color:#fab387&#34;&gt;104.&lt;/span&gt;kHz(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;clocks,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; imu &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; Lsm6dsox::new(i2c).unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;LSM6DSOX IMU initialized&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; id &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; imu.read_id().unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;id is {:#b}: &amp;#34;&lt;/span&gt;, id);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        imu.configure_accel().unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        imu.configure_gyro().unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Kalman Filter
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; x_kalman &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; KalmanFilter::new();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; y_kalman &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; KalmanFilter::new();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Kalman Filter Timer
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; kalman_timer &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; dp.&lt;span style=&#34;color:#f9e2af&#34;&gt;TIM4&lt;/span&gt;.counter_ms(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;clocks);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        kalman_timer.start(&lt;span style=&#34;color:#fab387&#34;&gt;10000.&lt;/span&gt;millis()).unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        kalman_timer.listen(Event::Update);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Motor Timer Setup
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; channels &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (Channel1::new(gpioa.pa8), Channel2::new(gpioa.pa9));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; channels_1 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; (Channel1::new(gpioa.pa0), Channel2::new(gpioa.pa1));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; pwm &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; dp.&lt;span style=&#34;color:#f9e2af&#34;&gt;TIM1&lt;/span&gt;.pwm_hz(channels, &lt;span style=&#34;color:#fab387&#34;&gt;50.&lt;/span&gt;Hz(), &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;clocks).split();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; pwm_1 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; dp.&lt;span style=&#34;color:#f9e2af&#34;&gt;TIM2&lt;/span&gt;.pwm_hz(channels_1, &lt;span style=&#34;color:#fab387&#34;&gt;50.&lt;/span&gt;Hz(), &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;clocks).split();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; (&lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; m1, &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; m2) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; pwm;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; (&lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; m3, &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; m4) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; pwm_1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m1.enable();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m2.enable();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m3.enable();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m4.enable();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;Zero signal&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m1.set_duty(m1.get_max_duty() &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;20&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m2.set_duty(m2.get_max_duty() &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;20&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m3.set_duty(m3.get_max_duty() &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;20&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m4.set_duty(m4.get_max_duty() &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;20&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//rprintln!(&amp;#34;m1 Value: {:?}&amp;#34;, [m1.get_max_duty() / 20, m1.get_max_duty() / 10]);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// PID
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; pitch_pid &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; Pid::new(&lt;span style=&#34;color:#fab387&#34;&gt;2.0&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0.1&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0.1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; roll_pid &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; Pid::new(&lt;span style=&#34;color:#fab387&#34;&gt;2.0&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0.1&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0.1&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Flight Controller Timer
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; fc_timer &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; dp.&lt;span style=&#34;color:#f9e2af&#34;&gt;TIM5&lt;/span&gt;.counter_ms(&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&lt;/span&gt;clocks);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fc_timer.start(&lt;span style=&#34;color:#fab387&#34;&gt;10000.&lt;/span&gt;millis()).unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        fc_timer.listen(Event::Update);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//process_received_bytes::spawn().ok();
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Shared {  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Local {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                rx,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                prod_flysky,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                con_flysky,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                rc_timer,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                imu,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                x_kalman,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                y_kalman,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                prod_kalman,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                con_kalman,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                kalman_timer,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                fc_timer,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                m1, m2, m3, m4,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                pitch_pid,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                roll_pid,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#[task(binds = TIM3, priority = 1, local=[rc_timer, prod_flysky, rx])]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;process_received_bytes&lt;/span&gt;(ctx: &lt;span style=&#34;color:#f9e2af&#34;&gt;process_received_bytes&lt;/span&gt;::Context) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ctx.local.rc_timer.clear_all_flags();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ctx.local.rc_timer.start(&lt;span style=&#34;color:#fab387&#34;&gt;15.&lt;/span&gt;millis()).unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; rx &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ctx.local.rx;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;process received bytes&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; bytes &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#cba6f7&#34;&gt;u8&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;32&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; checksum: &lt;span style=&#34;color:#f38ba8&#34;&gt;u16&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;while&lt;/span&gt; index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#89dceb&#34;&gt;Ok&lt;/span&gt;(byte) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; rx.read() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; byte &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Ignore bytes until the first byte is 32 (space character)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                    &lt;span style=&#34;color:#cba6f7&#34;&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                bytes[index] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; byte;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//rprintln!(&amp;#34;bytes: {:?}&amp;#34;, bytes);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; channel_values: [&lt;span style=&#34;color:#f38ba8&#34;&gt;u16&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;16&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#cba6f7&#34;&gt;in&lt;/span&gt; (&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;..&lt;/span&gt;bytes.len()).step_by(&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; bytes.len() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Extract two bytes from the pair
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; byte1 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u16&lt;/span&gt;::from(bytes[i]);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; byte2 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u16&lt;/span&gt;::from(bytes[i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;]);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;30&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    checksum &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+=&lt;/span&gt; byte1 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; byte2;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Combine the bytes by multiplying the second number by 256
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//let combined_value = u16::from(byte1) + u16::from(byte2) * 256;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; combined_value &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; byte1 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;|&lt;/span&gt; byte2 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;8&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; channel_index &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; i &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//rprintln!(&amp;#34;index: {:?}&amp;#34;, channel_index);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Do something with the combined value (e.g., print or use it)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                channel_values[channel_index] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; combined_value;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//rprintln!(&amp;#34;Combined Value: {}&amp;#34;, combined_value);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;            } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#cba6f7&#34;&gt;break&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;65535&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; channel_values[&lt;span style=&#34;color:#fab387&#34;&gt;15&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u16&lt;/span&gt;::from(checksum) {             
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;{:?} != {:?}&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;65535&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; channel_values[&lt;span style=&#34;color:#fab387&#34;&gt;15&lt;/span&gt;], checksum);                            
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;color:#cba6f7&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//rprintln!(&amp;#34;Channels: {:?}&amp;#34;, channel_values);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; _throttle &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; channel_values[&lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;] &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; _desired_roll &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; map(channel_values[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;1000.&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;2000.&lt;/span&gt;, &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;15.&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;15.&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; _desired_pitch &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; map(channel_values[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;] &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;1000.&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;2000.&lt;/span&gt;, &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;15.&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;15.&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#cba6f7&#34;&gt;match&lt;/span&gt; ctx.local.prod_flysky.enqueue([_throttle, _desired_roll, _desired_pitch]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#89dceb&#34;&gt;Ok&lt;/span&gt;(()) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//rprintln!(&amp;#34;Data sent&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#89dceb&#34;&gt;Err&lt;/span&gt;(_err) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Other errors occurred, handle them appropriately
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Example: println!(&amp;#34;Error occurred while enqueueing data: {:?}&amp;#34;, err);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                    &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;Flysky failed to enqueue&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086&#34;&gt;/** Mapping Function **/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;map&lt;/span&gt;(x: &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;, in_min: &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;, in_max: &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;, out_min: &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;, out_max: &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;) -&amp;gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (x &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; in_min) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; (out_max &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; out_min) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; (in_max &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; in_min) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; out_min
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#[task(binds = TIM4, local=[kalman_timer, imu, x_kalman, y_kalman, prod_kalman], priority = 1)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;sensor_fusion&lt;/span&gt;(ctx: &lt;span style=&#34;color:#f9e2af&#34;&gt;sensor_fusion&lt;/span&gt;::Context) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ctx.local.kalman_timer.clear_all_flags();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ctx.local.kalman_timer.start(&lt;span style=&#34;color:#fab387&#34;&gt;15.&lt;/span&gt;millis()).unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;Sensor fusion&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; delta_sec &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0.015&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; accel_data: [&lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; gyro_data: [&lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; x_accel: &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; y_accel: &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; imu &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ctx.local.imu;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        accel_data &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; imu.read_accel().unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        gyro_data &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; imu.read_gyro().unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        y_accel &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; atanf(accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; sqrtf(accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;])) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;180.0&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;PI&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        x_accel &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; atanf(accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; sqrtf(accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; accel_data[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;])) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;*&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;180.0&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#f9e2af&#34;&gt;PI&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ctx.local.x_kalman.process_posterior_state(gyro_data[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;], x_accel, delta_sec);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ctx.local.y_kalman.process_posterior_state(gyro_data[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;], y_accel, delta_sec);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// [roll, pitch]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;match&lt;/span&gt; ctx.local.prod_kalman.enqueue([ctx.local.y_kalman.get_angle(), ctx.local.x_kalman.get_angle()]) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#89dceb&#34;&gt;Ok&lt;/span&gt;(()) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//rprintln!(&amp;#34;Data sent&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#89dceb&#34;&gt;Err&lt;/span&gt;(_err) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Other errors occurred, handle them appropriately
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Example: println!(&amp;#34;Error occurred while enqueueing data: {:?}&amp;#34;, err);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;                &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;IMU Data failed to send&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;#[task(binds = TIM5, 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;           local = [fc_timer, con_kalman, con_flysky, 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;                    m1, m2, m3, m4,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;                    pitch_pid, roll_pid], 
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;            priority = 1)]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#cba6f7&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#89b4fa&#34;&gt;flight_controller&lt;/span&gt;(ctx: &lt;span style=&#34;color:#f9e2af&#34;&gt;flight_controller&lt;/span&gt;::Context) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ctx.local.fc_timer.clear_all_flags();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ctx.local.fc_timer.start(&lt;span style=&#34;color:#f9e2af&#34;&gt;FC_DELTA&lt;/span&gt;.millis()).unwrap();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; m1 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ctx.local.m1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; m2 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ctx.local.m2;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; m3 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ctx.local.m3;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; m4 &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ctx.local.m4;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; pitch_pid &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ctx.local.pitch_pid;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; roll_pid &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ctx.local.roll_pid;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; kalman_data: [&lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#fab387&#34;&gt;0.&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0.&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; fly_sky_data: [&lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#fab387&#34;&gt;0.&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0.&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;0.&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;FC&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#89dceb&#34;&gt;Some&lt;/span&gt;(data) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ctx.local.con_kalman.dequeue() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            kalman_data &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; data;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;Kalman Data: {:?}&amp;#34;&lt;/span&gt;, data);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#89dceb&#34;&gt;Some&lt;/span&gt;(data) &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; ctx.local.con_flysky.dequeue() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            fly_sky_data &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; data;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;Flysky Data: {:?}&amp;#34;&lt;/span&gt;, data);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// Error
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; _error_roll &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt;  kalman_data[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; _error_pitch &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; kalman_data[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// PID
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; _pitch_pid_value &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; pitch_pid.compute(_error_pitch, &lt;span style=&#34;color:#f9e2af&#34;&gt;FC_DELTA&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1000.&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; _roll_pid_value &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; roll_pid.compute(_error_roll, &lt;span style=&#34;color:#f9e2af&#34;&gt;FC_DELTA&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1000.&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f38ba8&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;color:#cba6f7&#34;&gt;mut&lt;/span&gt; throttle: [&lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;4&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#fab387&#34;&gt;0.&lt;/span&gt;; &lt;span style=&#34;color:#fab387&#34;&gt;4&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        throttle[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; fly_sky_data[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; _pitch_pid_value &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; _roll_pid_value; &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// front left
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        throttle[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; fly_sky_data[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; _pitch_pid_value &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; _roll_pid_value; &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// front right
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;//throttle[1] = 1000.;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        throttle[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; fly_sky_data[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; _pitch_pid_value &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;-&lt;/span&gt; _roll_pid_value; &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// rear left
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;        throttle[&lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; fly_sky_data[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; _pitch_pid_value &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;+&lt;/span&gt; _roll_pid_value; &lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;// rear right
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6c7086;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#cba6f7&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#cba6f7&#34;&gt;in&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;&lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;..&lt;/span&gt;&lt;span style=&#34;color:#fab387&#34;&gt;4&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; throttle[i] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1000.&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                throttle[i] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;1000.&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#cba6f7&#34;&gt;if&lt;/span&gt; throttle[i] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;2000.&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                throttle[i] &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;2000.&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }   
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;Pitch PID: {:?}, Roll PID: {:?}&amp;#34;&lt;/span&gt;, _pitch_pid_value, _roll_pid_value);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#89b4fa&#34;&gt;rprintln!&lt;/span&gt;(&lt;span style=&#34;color:#a6e3a1&#34;&gt;&amp;#34;Throttle: {:?}&amp;#34;&lt;/span&gt;, throttle);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m1.set_duty(map(throttle[&lt;span style=&#34;color:#fab387&#34;&gt;0&lt;/span&gt;], &lt;span style=&#34;color:#fab387&#34;&gt;1000.&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;2000.&lt;/span&gt;, m1.get_max_duty() &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;20.&lt;/span&gt;, m1.get_max_duty() &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;10.&lt;/span&gt;) &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u16&lt;/span&gt;); 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m2.set_duty(map(throttle[&lt;span style=&#34;color:#fab387&#34;&gt;1&lt;/span&gt;], &lt;span style=&#34;color:#fab387&#34;&gt;1000.&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;2000.&lt;/span&gt;, m2.get_max_duty() &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;20.&lt;/span&gt;, m2.get_max_duty() &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;10.&lt;/span&gt;) &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u16&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m3.set_duty(map(throttle[&lt;span style=&#34;color:#fab387&#34;&gt;2&lt;/span&gt;], &lt;span style=&#34;color:#fab387&#34;&gt;1000.&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;2000.&lt;/span&gt;, m3.get_max_duty() &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;20.&lt;/span&gt;, m3.get_max_duty() &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;10.&lt;/span&gt;) &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u16&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        m4.set_duty(map(throttle[&lt;span style=&#34;color:#fab387&#34;&gt;3&lt;/span&gt;], &lt;span style=&#34;color:#fab387&#34;&gt;1000.&lt;/span&gt;, &lt;span style=&#34;color:#fab387&#34;&gt;2000.&lt;/span&gt;, m4.get_max_duty() &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;20.&lt;/span&gt;, m4.get_max_duty() &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;f32&lt;/span&gt; &lt;span style=&#34;color:#89dceb;font-weight:bold&#34;&gt;/&lt;/span&gt; &lt;span style=&#34;color:#fab387&#34;&gt;10.&lt;/span&gt;) &lt;span style=&#34;color:#cba6f7&#34;&gt;as&lt;/span&gt; &lt;span style=&#34;color:#f38ba8&#34;&gt;u16&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;PCB&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;pcb&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#pcb&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;I initially used a breadboard for prototyping and testing each component. Afterwards I got each component working together, I designed a PCB to make connections for the ESC, IMU, FlySky Receiver, and the microcontroller on one board.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/rust-based-flight-controller/kicad_pcb.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;
&lt;img src=&#34;https://blog.kavin.me/blog/rust-based-flight-controller/kicad_schem.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;
&lt;img src=&#34;https://blog.kavin.me/blog/rust-based-flight-controller/drone.png&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;h2&gt;Current Issues&lt;span class=&#34;hx:absolute hx:-mt-20&#34; id=&#34;current-issues&#34;&gt;&lt;/span&gt;
    &lt;a href=&#34;#current-issues&#34; class=&#34;subheading-anchor&#34; aria-label=&#34;Permalink for this section&#34;&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;While the drone is assembled, stable flight has not yet been achieved. I suspect the root cause is the sporadic values from the IMU due to the vibrations from the motor messing with the accelerometer values. As a result of the IMU&amp;rsquo;s messy values, the PID is unable to get a reliable error to correct on. I&amp;rsquo;m not yet sure if this is due to my Kalman Filter implementation, if it can yet be improved with some tweaks on the R or Q values, or if I may have to switch to a different Kalman Filter crate such as &lt;a href=&#34;https://github.com/wangxiaochuTHU/yakf&#34;target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;yakf&lt;/a&gt;. This issue can be observed in the video below and the program&amp;rsquo;s output.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://blog.kavin.me/blog/rust-based-flight-controller/drone.gif&#34; alt=&#34;&#34;  loading=&#34;lazy&#34; /&gt;&lt;/p&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;FC
Kalman Data: [-0.90039134, 0.12164825]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: -6.5124507, Roll PID: -10.382492
Throttle: [1239.8949, 1219.13, 1226.87, 1206.1051]
Sensor fusion
process received bytes
FC
Kalman Data: [-2.0230548, 0.48110035]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: 3.458548, Roll PID: -11.619747
Throttle: [1231.1613, 1207.9218, 1238.0782, 1214.8387]
Sensor fusion
process received bytes
FC
Kalman Data: [1.2617773, 1.6009094]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: 10.767213, Roll PID: 24.335114
Sensor fusion
FC
Sensor fusion
FC
FC
Kalman Data: [-2.1917682, 0.08220053]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: -1.3731648, Roll PID: -14.535976
Throttle: [1238.9092, 1209.8372, 1236.1628, 1207.0908]
Sensor fusion
process received bytes
FC
Kalman Data: [1.738786, 1.4941175]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: 12.501015, Roll PID: 29.591108
Throttle: [1180.908, 1240.0901, 1205.9099, 1265.092]
Sensor fusion
process received bytes
FC
Kalman Data: [-2.5784974, 0.37395483]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: -6.6198416, Roll PID: -34.032913
Throttle: [1263.6528, 1195.5869, 1250.4131, 1182.3472]
Sensor fusion
process received bytes
FC
Kalman Data: [0.20860016, 1.2831023]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: 8.727188, Roll PID: 18.904137
Throttle: [1195.3687, 1233.177, 1212.823, 1250.6313]
Sensor fusion
process received bytes
FC
Kalman Data: [-0.7358496, 0.118415]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: -7.427752, Roll PID: -7.862849
Sensor fusion
process received bytes
FC
Kalman Data: [1.1448559, 1.5381482]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: 7.8262134, Roll PID: 19.894714
Throttle: [1195.279, 1235.0686, 1210.9314, 1250.721]
Sensor fusion
process received bytes
FC
Kalman Data: [-2.4780583, 0.006271422]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: -10.099969, Roll PID: -29.20888
Throttle: [1262.3088, 1203.8911, 1242.1089, 1183.6912]
Sensor fusion
process received bytes
FC
Kalman Data: [-1.4668975, 0.97744393]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: 8.529371, Roll PID: 3.7072783
Throttle: [1210.7633, 1218.1779, 1227.8221, 1235.2367]
Sensor fusion
process received bytes
FC
Kalman Data: [-0.10233903, 0.5720601]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: -1.4584388, Roll PID: 8.792378
Throttle: [1215.6661, 1233.2509, 1212.7491, 1230.3339]
Sensor fusion
process received bytes
FC
Kalman Data: [0.4794494, 1.6821591]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: 10.864978, Roll PID: 4.738208
Sensor fusion
FC
Sensor fusion
FC
FC
Kalman Data: [-2.4574478, 0.19115067]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: -9.944306, Roll PID: -28.328514
Throttle: [1261.2728, 1204.6158, 1241.3842, 1184.7272]
Sensor fusion
process received bytes
FC
Kalman Data: [1.0313929, 1.3718957]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: 10.7154255, Roll PID: 25.22327
Throttle: [1187.0613, 1237.5078, 1208.4922, 1258.9387]
Sensor fusion
process received bytes
FC
Kalman Data: [-0.7749517, 0.5282671]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: -4.4676566, Roll PID: -13.691817
Throttle: [1241.1594, 1213.7759, 1232.2241, 1204.8406]
Sensor fusion
process received bytes
FC
Kalman Data: [-0.1934669, 0.8849101]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: 4.2474403, Roll PID: 3.3897264
Throttle: [1215.3628, 1222.1423, 1223.8577, 1230.6372]
Sensor fusion
process received bytes
FC
Kalman Data: [-1.54417, 0.5238842]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: -1.2590712, Roll PID: -12.1930275
Sensor fusion
FC
Sensor fusion
FC
Kalman Data: [0.26610875, 1.2130305]
Flysky Data: [1223.0, -0.72000027, -5.16]
Pitch PID: 6.4048543, Roll PID: 10.804463
Throttle: [1205.7906, 1227.3995, 1218.6005, 1240.2094]
Sensor fusion
process received bytes&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&#34;hextra-code-block hx:relative hx:mt-6 hx:first:mt-0 hx:group/code&#34;&gt;

&lt;div&gt;&lt;pre&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;hextra-code-copy-btn-container hx:opacity-0 hx:transition hx:group-hover/code:opacity-100 hx:flex hx:gap-1 hx:absolute hx:m-[11px] hx:right-0 hx:top-0&#34;&gt;
  &lt;button
    class=&#34;hextra-code-copy-btn hx:group/copybtn hx:cursor-pointer hx:transition-all hx:active:opacity-50 hx:bg-primary-700/5 hx:border hx:border-black/5 hx:text-gray-600 hx:hover:text-gray-900 hx:rounded-md hx:p-1.5 hx:dark:bg-primary-300/10 hx:dark:border-white/10 hx:dark:text-gray-400 hx:dark:hover:text-gray-50&#34;
    title=&#34;Copy code&#34;
    aria-label=&#34;Copy code&#34;
    data-copied-label=&#34;Copied!&#34;
  &gt;
    &lt;div class=&#34;hextra-copy-icon hx:group-[.copied]/copybtn:hidden hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
&lt;div class=&#34;hextra-success-icon hx:hidden hx:group-[.copied]/copybtn:block hx:pointer-events-none hx:h-4 hx:w-4&#34;&gt;&lt;/div&gt;
  &lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
      </description>
    </item>
    
  </channel>
</rss>
