<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Youíre right. Mixed it up with is_oop().<div><br></div><div>igor<br><div><div><br></div><div>On Mar 11, 2014, at 4:26 PM, Krystal Mok <<a href="mailto:rednaxelafx@gmail.com">rednaxelafx@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div dir="ltr">Hi Igor,<div><br></div><div>I guess is_pointer() has been a confusing name: it's not about whether the semantic type is a pointer type or not, but rather if the contents of this LIR_Opr is allocated in an instance, in which case is_pointer() is true; or if the contents are actually packed in the LIR_Opr* pointer, in which case it's a fake pointer and is_pointer() is false.</div>
<div><br></div><div>When LIR_Opr::is_register() is true, LIR_is_pointer() is always false. So I believe the !is_pointer() check is redundant.</div><div>Does that sound reasonable?</div><div><br></div><div>Thanks,</div><div>
Kris</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Mar 11, 2014 at 4:22 PM, Igor Veresov <span dir="ltr"><<a href="mailto:igor.veresov@oracle.com" target="_blank">igor.veresov@oracle.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">I donít know. The only idea is that it could be for the case when we do pointer arithmetic in GC barriers and change the type from T_OBJECT to T_LONG/T_INT, at which point the register if it is the same should disappear from the oopmaps. But Iím probably wrong.<div>
<span class="HOEnZb"><font color="#888888"><br></font></span><div><span class="HOEnZb"><font color="#888888">igor</font></span><div><div class="h5"><br><div><br><div><div>On Mar 11, 2014, at 2:53 PM, Krystal Mok <<a href="mailto:rednaxelafx@gmail.com" target="_blank">rednaxelafx@gmail.com</a>> wrote:</div>
<br><blockquote type="cite"><div dir="ltr">Hi Igor,<div><br></div><div>Alrighty, thanks again for your reply! I've got it straight now.</div><div><br></div><div>Any ideas on the second question that I asked, about the check on !is_pointer() in LinearScan?</div>

<div><br></div><div>Thanks,</div><div>Kris</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Mar 11, 2014 at 9:36 AM, Igor Veresov <span dir="ltr"><<a href="mailto:igor.veresov@oracle.com" target="_blank">igor.veresov@oracle.com</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>In theory you need i2l, because the index can be negative. If you just used it as-is in addressing with the conversion that would be incorrect (addressing wants a 64-bit register). However, in this case youíre right, and weíre pretty sure itís never negative and using it directly would be just as fine, except the type of the virtual register would be T_INT and we really want T_LONG. So, yes, you could have a conversion, say, ďui2l" that essentially does nothing. But, sign-extending is not wrong either.</div>

<span><font color="#888888"><div><br></div>igor</font></span><div><br><div><div>On Mar 11, 2014, at 12:34 AM, Krystal Mok <<a href="mailto:rednaxelafx@gmail.com" target="_blank">rednaxelafx@gmail.com</a>> wrote:</div>

<br><blockquote type="cite">Hi Igor,<div><br></div><div>Thanks again for your reply.</div><div><br></div><div>I started out to believe that I should be able to trust the upper 32 bits being clean, but then I realized C1 did that i2l explicitly in array addressing. So I'm somehow confused about the assumptions in C1.<span></span></div>


<div><br></div><div>If the upper 32 bits are guaranteed to be clean, why is there a need for a i2l anyway? Can't we just receive an int argument in esi and then use rsi directly in array addressing?</div><div><br></div>


<div>What I really wanted to know is what could go wrong if we didn't have that i2l.</div><div><br></div><div>If we're passing an int argument in a register, there should have been a move or a constant load, and that would have cleared the upper 32 bits already. I'm missing what the failing scenarios are...</div>


<div><br></div><div>Thanks,</div><div>Kris<br><br>On Tuesday, March 11, 2014, Igor Veresov <<a href="mailto:igor.veresov@oracle.com" target="_blank">igor.veresov@oracle.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


<div style="word-wrap:break-word">No, itís quite the opposite. Upper 32bits should be clear (zeros) for 32bit values on x64. Moreover, C2 relies on the fact the on x64 32bit ints have upper word with zeros. So if you plan to call C2-compiled methods this must hold. Addressing requires that you use full 64-bit registers for the base and index, so if your index is 32bit, you must make it 64-bit one way on another.<div>


<div><div><br></div><div>On SPARC however itís another story, so you canít rely on this in platform-independent way.<br><div><br></div><div>igor</div><div><br><div><div>On Mar 10, 2014, at 11:38 PM, Krystal Mok <<a>rednaxelafx@gmail.com</a>> wrote:</div>


<br><blockquote type="cite"><div dir="ltr">Hi Igor and Christian,<div><br></div><div>Thanks a lot for your replies. I think my first question about the invariant boils down to these:</div><div><br></div><div>1. I can't trust any 64-bit register used as a 32-bit int to have its high 32 bits cleared, so: I have to always use 32-bit ops when possible; when having to use it in addressing, explicitly clear the high 32 bits.</div>



<div><br></div><div>2. The only special case of having to explicitly clear the high 32 bits is array addressing.</div><div><br></div><div>Are these statements correct?</div><div><br></div><div>Also, any thoughts on the second question on removing useless moves?</div>



<div><br></div><div>Thanks,</div><div>Kris</div></div><div><br><br><div>On Mon, Mar 10, 2014 at 8:56 PM, Christian Thalinger <span dir="ltr"><<a>christian.thalinger@oracle.com</a>></span> wrote:<br>
<blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><br><div><div><div>On Mar 10, 2014, at 7:52 PM, Igor Veresov <<a>igor.veresov@oracle.com</a>> wrote:</div>



<br><blockquote type="cite"><div style="word-wrap:break-word">I think everything should be zero-extended by default on x64. The invariant should be supported by using only 32bit ops on 32bit arguments and using zero-extending loads. Not sure why we do sign extension in the element address formation, zero-extending would seem to be enough (which should be a no-op on x64).</div>



</blockquote><div><br></div></div>I think the main reason C1 does a sign-extend on 64-bit is because pointers have the type T_LONG and we need the index register to be a T_LONG as well.  Additionally to be able to reuse existing machinery we just do an I2L:</div>



<div><br></div><div><div style="margin:0px;font-size:11px;font-family:Monaco"><span style="color:#931a68">#ifdef</span> _LP64</div><div style="margin:0px;font-size:11px;font-family:Monaco">    <span style="color:#931a68">if</span> (index_opr->type() == <span style="color:#0326cc">T_INT</span>) {</div>



<div style="margin:0px;font-size:11px;font-family:Monaco">      <span style="color:#006141">LIR_Opr</span> tmp = new_register(<span style="color:#0326cc">T_LONG</span>);</div><div style="margin:0px;font-size:11px;font-family:Monaco">



      __ convert(<span style="color:#006141">Bytecodes</span>::<span style="color:#0326cc">_i2l</span>, index_opr, tmp);</div><div style="margin:0px;font-size:11px;font-family:Monaco">      index_opr = tmp;</div><div style="margin:0px;font-size:11px;font-family:Monaco">



    }</div><div style="margin:0px;font-size:11px;font-family:Monaco;color:rgb(147,26,104)">#endif</div><div><div><br></div><blockquote type="cite"><div style="word-wrap:break-word"><div><br></div><div>igor<br>
<div><br><div><div>On Mar 10, 2014, at 5:06 PM, Krystal Mok <<a>rednaxelafx@gmail.com</a>> wrote:</div><br><blockquote type="cite"><div dir="ltr">Hi all,<div><br></div>
<div>I'd like to ask a couple of questions on C1's usage of 32-bit registers on amd64, when they're a part of the corresponding 64-bit register (e.g. ESI vs RSI).</div><div>



<br></div><div>1. Does C1 ensure the high 32 bits of a 64-bit register is cleared when using it as a 32-bit register? If so, where does C1 enforce that?</div><div><br></div><div>I see that for array indexing, C1 generates code that uses 64-bit register whose actual value is only stored in the low 32-bit part, e.g.</div>





<div><br></div><div>static int foo(int[] a, int i) {</div><div>  return a[i];</div><div>}</div><div><br></div><div>the actual load in C1 generated code would be (in AT&T syntax):</div><div><br></div><div>mov    0x10(%rsi,%rax,4),%eax<br>




</div><div><br>
</div><div>and there's an instruction prior to it that explicitly clears the high 32 bits,</div><div><br></div><div>movslq %edx,%rax<br></div><div><br></div><div>generated by LIRGenerator::emit_array_address().</div>




<div><br></div><div>So it's an invariant property enforced throughout C1, right?</div><div><br></div><div>2. There a piece of code in C1's linear scan register allocator that removes useless moves:</div>
<div><br></div><div><a href="http://hg.openjdk.java.net/jdk9/hs-comp/hotspot/file/480b0109db65/src/share/vm/c1/c1_LinearScan.cpp#l2996" target="_blank">http://hg.openjdk.java.net/jdk9/hs-comp/hotspot/file/480b0109db65/src/share/vm/c1/c1_LinearScan.cpp#l2996</a><br>





</div><div><br></div><div><div>    // remove useless moves</div><div>    if (op-</div></div></div></blockquote></div></div></div></div></blockquote></div></div></div></blockquote></div></div></blockquote></div>
</div></div></div></div></div></blockquote></div>
</blockquote></div><br></div></div></blockquote></div><br></div>
</blockquote></div><br></div></div></div></div></div></div></blockquote></div><br></div>
</blockquote></div><br></div></body></html>