<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div><blockquote type="cite" class=""><div class=""><div class=""><br class="">I realize this is a micro-op saving a single cycle.  But this reduces the instruction count, one less<br class="">instr to decode in a potentially hot path. If this all makes sense, and seems like a reasonable addition<br class="">to llvm, would it make sense to implement this as a supplemental LSR formula, or as a separate pass?</div></div></blockquote><br class=""></div><div>This seems reasonable to me so long as rbx has no other uses that would complicate the problem; I’m not sure how much this occurs in hot code (a loop with an induction variable that isn’t used in the loop), but if it does, I don’t see why not.</div><div><br class=""></div><div>As a side note, in a past life, when I used to do x86 SIMD optimization for a living, I did similar tricks pretty much everywhere in DSP functions. It’d be pretty nice if the compiler could do it too.</div><div><br class=""></div><div>There is one alternate approach that I recall, which looks like this:</div><div><br class=""></div><div><b class="">Original code (example, pseudocode):</b></div><div><br class=""></div><div>int add_delta_256(uint8 *in1, uint8 *in2) {</div><div>  int accum = 0;</div><div>  for (int i = 0; i < 16; ++i) {</div><div>   uint8x16 a = load16(in1 + i *16); // NOTE: takes an extra addressing op because x86</div><div>   uint8x16 b = load16(in2 + i *16); // NOTE: takes an extra addressing op because x86</div><div>   accum += psadbw(a, b);</div><div>  }</div><div>  return accum;</div><div>}</div><div><br class=""></div><div>end of loop:</div><div>inc i</div><div>cmp i, 16</div><div>jl loop</div><div><br class=""></div><div><div><b class="">LSR’d code:</b></div><div><br class=""></div><div>int add_delta_256(uint8 *in1, uint8 *in2) {</div><div>  int accum = 0;</div><div>  for (int i = 0; i < 16; ++i, in1 += 16, in2 += 16) {</div><div>   uint8x16 a = load16(in1);</div><div>   uint8x16 b = load16(in2);</div><div>   accum += psadbw(a, b);</div><div>  }</div><div>  return accum;</div><div>}</div><div><br class=""></div><div><div>end of loop:</div><div>add in1, 16</div><div>add in2, 16</div><div>inc i</div><div>cmp i, 16</div><div>jl loop</div></div><div><br class=""></div><div><b class="">your code:</b></div><div><br class=""></div><div><div>int add_delta_256(uint8 *in1, uint8 *in2) {</div><div>  int accum = 0;</div><div>  for (int i = -16; i < 0; ++i, in1 += 16, in2 += 16) {</div><div>   uint8x16 a = load16(in1);</div><div>   uint8x16 b = load16(in2);</div><div>   accum += psadbw(a, b);</div><div>  }</div><div>  return accum;</div><div>}</div><div><br class=""></div><div><div>end of loop:</div><div>add in1, 16</div><div>add in2, 16</div><div>inc i</div><div>jl loop</div><div><br class=""></div><div><div><b class="">ideal code:</b></div><div><br class=""></div><div><div>int add_delta_256(uint8 *in1, uint8 *in2) {</div><div>  int accum = 0;</div><div>  in1 += 256;</div><div>  in2 += 256;</div><div>  for (int i = -256; i < 0; ++i) {</div><div>   uint8x16 a = load16(in1 + i);</div><div>   uint8x16 b = load16(in2 + i);</div><div>   accum += psadbw(a, b);</div><div>  }</div><div>  return accum;</div><div>}</div><div><br class=""></div><div><div>end of loop:</div><div>inc i</div><div>jl loop</div><div><br class=""></div><div>I don’t know, however, if it’s reasonable to teach the compiler to do the clever nonsense necessary to do the last one (requires enough understanding of x86 addressing modes, for one).</div></div></div></div></div></div></div><div><br class=""></div><div>—escha</div></body></html>