<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><br></div><div><br class="Apple-interchange-newline">On Dec 16, 2008, at 7:57 PM, Eli Friedman wrote:</div><blockquote type="cite"><div>On Tue, Dec 16, 2008 at 3:36 PM, Daniel M Gessel <<a href="mailto:gessel@apple.com">gessel@apple.com</a>> wrote:<br><blockquote type="cite">I'm working on a Target that only uses the 5 lsbs of the shift amount.<br></blockquote><br>Okay, that's quite common... x86 is the same.<br><br></div></blockquote><div><br></div>Thanks - yes, I'd heard rumors that x86 operates the same way.<div><br></div><blockquote type="cite"><div><blockquote type="cite">I only have 32 bit registers, no 64 bit, so 64 bit math is emulated,<br></blockquote><blockquote type="cite">LLVM doing the transformations whenever I can get it to.<br></blockquote><br>x86 is the same.</div></blockquote><div><br></div><div>Ah, maybe I should try my test below on x86, and see what happens. It'll take me a bit as I'm not familiar with x86 assembly code.</div><blockquote type="cite"><div><br><blockquote type="cite">I think I'm seeing a case where it ultimately looks like a standard<br></blockquote><blockquote type="cite">multiword shift (from e.g. Hacker's Delight) is being inline expanded<br></blockquote><blockquote type="cite">that assumes at least 6 bits of the shift is paid attention to (i.e.<br></blockquote><blockquote type="cite">it looks like it assumes x >> 32 == 0 if x is 32 bits, but for me x >><br></blockquote><blockquote type="cite">32 == x).<br></blockquote><blockquote type="cite"><br></blockquote><blockquote type="cite">(A) What does LLVM assume about "shift width"?<br></blockquote><br>"If op2 is (statically or dynamically) negative or equal to or larger<br>than the number of bits in op1, the result is undefined."  See<br><a href="http://llvm.org/docs/LangRef.html#i_shl.">http://llvm.org/docs/LangRef.html#i_shl.</a>  Roughly, that means that<br>"lshr i32 %x, 32" is allowed to return any arbitrary value.  If you<br>need consistent behavior, you should explicitly mask the shift amount<br>in the front-end.</div></blockquote><div><br></div><div>The problem here is that it looks like LLVM is introducing an expansion that assumes 32 bit shifts use more than 5 bits of the shift value.</div><div><br></div><div>I created a simple test function:</div><div><div><br></div><div>u64 mebbe_shift( u64 x, int test )</div><div>{</div><div><span class="Apple-tab-span" style="white-space: pre; ">       </span>if( test )<br></div><div><span class="Apple-tab-span" style="white-space: pre; ">              </span>x <<= 2;<br></div><div><span class="Apple-tab-span" style="white-space: pre; ">  </span>return x;</div><div>}</div><div><br></div><div>I compile using clang, opt, and llc.</div><div><br></div><div>I get something that, converted from my assembler to hasty psuedo-C:</div><div><br></div><div>u64 mebbe_shift( u64 x, int test )</div><div>{</div><div><span class="Apple-tab-span" style="white-space: pre; ">       </span>int amt = test ? 2 : 0;</div><div><br></div><div><div><span class="Apple-tab-span" style="white-space: pre; ">       </span>x.hi = x.hi << amt  |  x.lo >> (32 - amt);</div></div><div><span class="Apple-tab-span" style="white-space: pre; ">      </span>x.lo <<= amt;<br></div><div><br></div><div><span class="Apple-tab-span" style="white-space: pre; ">    </span>return x;<br></div><div>}</div><div><br></div><div>My Target doesn't explicitly do any of these kinds of expansions or transformations, so it seems to me it's somewhere in LLVM that this is happening.</div><div><br></div><div>I'll investigate further.</div><div><br></div><div>Thanks,</div><div><br></div><div>Dan</div><div><br></div><div>P.S. what i'd like to get, for performance on my target, is something like:</div><div><br></div><div><br></div><div><div>u64 mebbe_shift( u64 x, int test )</div><div>{</div><div><span class="Apple-tab-span" style="white-space: pre; ">      </span>y.hi = x.hi << 2  |  x.lo >> 30;</div><div><span class="Apple-tab-span" style="white-space: pre; ">       </span>y.lo = x.lo << 2;<br></div><div><br></div><div><span class="Apple-tab-span" style="white-space: pre; ">        </span>x.hi = test ? y.hi : x.hi;<br></div><div><span class="Apple-tab-span" style="white-space: pre; ">      </span>x.lo = test ? y.lo : x.lo;</div><div><br></div><div><span class="Apple-tab-span" style="white-space: pre; ">       </span>return x;<br></div><div>}</div><div><br></div><div>Shifts are expensive but selects are cheap.</div><div><br></div><div>But I'd be happy to just understand where things are going wrong for now.</div><div><br></div><div><br></div></div><div><blockquote type="cite"><div><font class="Apple-style-span" color="#000000"><br></font><br>-Eli<br>_______________________________________________<br>LLVM Developers mailing list<br><a href="mailto:LLVMdev@cs.uiuc.edu">LLVMdev@cs.uiuc.edu</a>         <a href="http://llvm.cs.uiuc.edu">http://llvm.cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev">http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev</a><br></div></blockquote></div><br></div></body></html>