<html><head><meta http-equiv="Content-Type" content="text/html charset=iso-8859-1"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On May 25, 2012, at 3:07 PM, Chandler Carruth <<a href="mailto:chandlerc@google.com">chandlerc@google.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div class="gmail_quote">On Fri, May 25, 2012 at 8:28 AM, Duncan Sands <span dir="ltr"><<a href="mailto:baldrick@free.fr" target="_blank">baldrick@free.fr</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex; position: static; z-index: auto; "># phi213.i is in %ebx<br>
<br>
+       leaq    1(%rdx), %rsi<br>
+       xorl    %esi, %ebx<br>
         xorl    (%rax,%rdx,4), %ebx<br>
-       incq    %rdx<br>
-       xorl    %edx, %ebx<br>
-       cmpl    $500001, %edx           # imm = 0x7A121<br>
+       cmpl    $500001, %esi           # imm = 0x7A121<br>
+       movq    %rsi, %rdx<br>
<br>
I'm not sure why this codegen difference arises.  Any suggestions?<br></blockquote><div><br></div><div>One, largely uninformed idea is the dependency chains (in addition to the leaq stuff mentioned by Jakob):</div><div>
<br></div><div>Old code, we execute the load+xor first, and while in flight we can increment rdx, and execute the comparison with edx. whenever the load+xor lands, we can execute the second xor.</div><div><br></div><div>New code, the leaq must execute before the first xor, and the first xor must execute before the second xor. That means we may not be able to overlap as much of the load delay.</div></div></blockquote><div><br></div><div>I can probably explain why the new code is slow.</div><div><br></div><div>You get these µops with the old code:</div><div><br></div><div>xorl -> (lea, load, xor1)</div><div>incq -> (add)</div><div>xorl -> (xor2)</div><div>cmpl -> (cmp)</div><div>jne -> (branch)</div><div><br></div><div>There are two loop-carried dependencies:</div><div><br></div><div>add -> add</div><div>xor1 -> xor2 ->xor1</div><div><br></div><div>The xor chain means the loop requires at least 2 cycles per iteration. Nehalem can execute 3 ALU µops per cycle, and we have 6 per iteration (lea, xor1, add, xor2, cmp, branch).</div><div><br></div><div>The extra movq brings us to 7 ALU ops per iteration, which can't happen in 2 cycles. (Ivy bridge doesn't need a pipeline slot for a move, so it probably won't see the regression). </div><div><br></div><div>There is also a scheduling issue:</div><div><br></div><div><div>        cmpl    $500001, %esi           # imm = 0x7A121</div><div>        movq    %rsi, %rdx</div><div>        jne     .LBB1_18</div><div><br></div><div>If we place the cmpl and jne next to each other, they should fuse into one µop, and we are down to 6 ALU µops per iteration again.</div><div><br></div><div>/jakob</div><div><br></div></div></div></body></html>