<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Mar 17, 2016, at 10:34 PM, Patrick Pijnappel via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">Currently, bit shifting with an amount greater than or equal to the size of the type traps:<div class=""><br class=""></div><div class=""><font face="monospace, monospace" class="">func foo(x: Int32) {</font></div><div class=""><font face="monospace, monospace" class="">&nbsp; let y = x &lt;&lt; 32 // Runtime trap (for any &lt;&lt; or &gt;&gt; with amount &gt;= 32)</font></div><div class=""><font face="monospace, monospace" class="">}</font></div><div class=""><font face="monospace, monospace" class=""><br class=""></font></div><div class=""><font face="arial, helvetica, sans-serif" class="">I propose to make this not trap, and just end up with 0 (or ~0 in case of right-shifting a negative number):</font></div><div class=""><ul class=""><li class=""><font face="arial, helvetica, sans-serif" class="">Unlike the traps for integer arithmetic and casts, it is obvious what a bitshift past the end does as fundamentally the behavior stays the same.</font></li><li class=""><font face="arial, helvetica, sans-serif" class="">If the intention is to make it&nbsp;analogous&nbsp;with multiplication/division by 2**n, the checks don't really change anything. Right shift are still identical to divisions by 2**n. Left shifts are like multiplication by 2**n but with different overflow behavior, which is already the case with the current rules (e.g. </font><font face="monospace, monospace" class="">Int.max &lt;&lt; 1</font><font face="arial, helvetica, sans-serif" class=""> doesn't trap)</font></li><li class=""><font face="arial, helvetica, sans-serif" class="">It could lead to bugs where users expect this to work, e.g. the following crashes when the entire buffer is consumed: </font><font face="monospace, monospace" class="">buffer = buffer &lt;&lt; bitsConsumed</font></li><li class=""><font face="arial, helvetica, sans-serif" class="">Bitshift are often used in performance-sensitive code, and with the current behavior any non-constant bit shift introduces a branch.</font></li></ul></div></div></div></blockquote><br class=""></div><div>Defining large shifts to 0 or ~0 does not improve performance on some architectures. The result of the i386 and x86_64 shift instruction is undefined for shift equal to or larger than the data size. The arm64 shift instruction shifts by (shift_value % data_size). If you want large shifts to return zero on architectures like these then you still need a branch.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">--&nbsp;</div><div class="">Greg Parker &nbsp; &nbsp; <a href="mailto:gparker@apple.com" class="">gparker@apple.com</a>&nbsp; &nbsp; &nbsp;Runtime Wrangler</div><div class=""><br class=""></div><div class=""><br class=""></div></body></html>