<story><title>I translated a simple C program to x86_64 and it was slower</title><url>https://ecc-comp.blogspot.com/2020/04/i-translated-simple-c-program-to-x8664.html</url></story><parent_chain><item><author>jdsully</author><text>The assembly is not bad for a beginner but far from optimal. A few things that stand out from a quick glance:&lt;p&gt;1) Try to load things sequentially don’t load from offset 32, then 0, then 16.&lt;p&gt;2) Don’t use the loop instruction&lt;p&gt;3) this code:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  dec  n
  cmp  n, 0
  jne  1b
&lt;/code&gt;&lt;/pre&gt;
Can be replaced with:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  sub n, 1
  jnz 1b
&lt;/code&gt;&lt;/pre&gt;
Which will actually be executed by the processor as a single instruction (macro-op fusion).&lt;p&gt;4) Interleave your expensive instructions with less expensive ones. Try to interleave multiple dependency chains to let the processor see more of the parallelism.&lt;p&gt;Your two divisions one after another will be limited by available execution units capable of doing the divide.&lt;p&gt;5) Lastly align your loop labels to 16-byte offsets. The assembler will do this for you with the ALIGN directive.</text></item></parent_chain><comment><author>fallat</author><text>Doing most of your changes made essentially no difference X)&lt;p&gt;I suspect the assembly generated by the compiler is pretty fancy.&lt;p&gt;Edit: Just briefly looking at the objdump again, gcc is using a lot of scalar variants of instructions, instead of vector. Maybe this is giving the CPU better hints?&lt;p&gt;Maybe my code would run better on a more modern CPU (while still constraining the original C program to SSE3 only) ?</text></comment>
<story><title>I translated a simple C program to x86_64 and it was slower</title><url>https://ecc-comp.blogspot.com/2020/04/i-translated-simple-c-program-to-x8664.html</url></story><parent_chain><item><author>jdsully</author><text>The assembly is not bad for a beginner but far from optimal. A few things that stand out from a quick glance:&lt;p&gt;1) Try to load things sequentially don’t load from offset 32, then 0, then 16.&lt;p&gt;2) Don’t use the loop instruction&lt;p&gt;3) this code:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  dec  n
  cmp  n, 0
  jne  1b
&lt;/code&gt;&lt;/pre&gt;
Can be replaced with:&lt;p&gt;&lt;pre&gt;&lt;code&gt;  sub n, 1
  jnz 1b
&lt;/code&gt;&lt;/pre&gt;
Which will actually be executed by the processor as a single instruction (macro-op fusion).&lt;p&gt;4) Interleave your expensive instructions with less expensive ones. Try to interleave multiple dependency chains to let the processor see more of the parallelism.&lt;p&gt;Your two divisions one after another will be limited by available execution units capable of doing the divide.&lt;p&gt;5) Lastly align your loop labels to 16-byte offsets. The assembler will do this for you with the ALIGN directive.</text></item></parent_chain><comment><author>heeen2</author><text>Shouldn&amp;#x27;t a superscalar CPU figure out concurrent execution chains by itself with register renaming</text></comment>