<div dir="ltr">Hmm... it would appear that the behaviour on that original test case changes with ToT. However, this test case will still allocate a CSR in the entry block even though it really does not need to. And adjusting the CSR first-time-use cost does not seem to have any effect on it.<br><br><span style="font-family:monospace,monospace">int *a;<br>int callVoid();<br>int callNonVoid(int*);<br>int test(int *b) {<br>  if (b == a) {<br>    callVoid();<br>    return callNonVoid(b);<br>  }<br>  return 0;<br>}</span><br><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Feb 9, 2017 at 5:15 AM, Wei Mi <span dir="ltr"><<a href="mailto:wmi@google.com" target="_blank">wmi@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Wed, Feb 8, 2017 at 6:21 PM, Wei Mi <<a href="mailto:wmi@google.com">wmi@google.com</a>> wrote:<br>
> I have an issue that I've been wrestling with for quite some time and I'm<br>
> hoping that someone with a deeper understanding of the register allocator<br>
> can help me with.<br>
><br>
> Namely, I am trying to teach RA to split a live range rather than<br>
> allocating a CSR. I've attempted a very large number of tweaks to the costs<br>
> (both existing and experimental ones that I've added). However, despite all<br>
> of that, I can't seem to get RA to split the following:<br>
><br>
>   1 BB#0: derived from LLVM BB %entry<br>
>   2     Live Ins: %X3<br>
>   3         %vreg15<def> = COPY %X3; G8RC:%vreg15<br>
>   4         %vreg4<def> = CMPLDI %vreg15, 0; CRRC:%vreg4 G8RC:%vreg15<br>
>   5         %vreg11:sub_32<def,read-undef> = LI 0; G8RC:%vreg11<br>
>   6         BCC 68, %vreg4, <BB#1>; CRRC:%vreg4<br>
>   7     Successors according to CFG: BB#4(0x30000000 / 0x80000000 = 37.50%)<br>
> BB#1(0x50000000 / 0x80000000 = 62.50%)<br>
>   8<br>
>   9 BB#4:<br>
>  10     Predecessors according to CFG: BB#0<br>
>  11         B <BB#3><br>
>  12     Successors according to CFG: BB#3(?%)<br>
>  13<br>
>  14 BB#1: derived from LLVM BB %if.end<br>
>  15     Predecessors according to CFG: BB#0<br>
>  16         %vreg6<def> = ADDIStocHA %X2, <ga:@a>; G8RC_and_G8RC_NOX0:%vreg6<br>
>  17         %vreg7<def> = LDtocL <ga:@a>, %vreg6, %X2<imp-use>;<br>
> mem:LD8[GOT] G8RC_and_G8RC_NOX0:%vreg7,%<wbr>vreg6<br>
>  18         %vreg8<def> = LWA 0, %vreg7;<br>
> mem:LD4[@a](tbaa=!3)(<wbr>dereferenceable) G8RC:%vreg8 G8RC_and_G8RC_NOX0:%vreg7<br>
>  19         %vreg9<def> = CMPLD %vreg8, %vreg15; CRRC:%vreg9<br>
> G8RC:%vreg8,%vreg15<br>
>  20         BCC 68, %vreg9, <BB#3>; CRRC:%vreg9<br>
>  21         B <BB#2><br>
>  22     Successors according to CFG: BB#2(0x30000000 / 0x80000000 = 37.50%)<br>
> BB#3(0x50000000 / 0x80000000 = 62.50%)<br>
>  23<br>
>  24 BB#2: derived from LLVM BB %if.then2<br>
>  25     Predecessors according to CFG: BB#1<br>
>  26         ADJCALLSTACKDOWN 96, %R1<imp-def,dead>, %R1<imp-use><br>
>  27         %vreg16<def> = COPY %vreg15; G8RC:%vreg16,%vreg15<br>
>  28         BL8_NOP <ga:@callVoid>, <regmask **LONG LIST**>,<br>
> %X3<imp-def,dead><br>
>  29         ADJCALLSTACKUP 96, 0, %R1<imp-def,dead>, %R1<imp-use><br>
>  30         ADJCALLSTACKDOWN 96, %R1<imp-def,dead>, %R1<imp-use> 31<br>
> %X3<def> = COPY %vreg16; G8RC:%vreg16<br>
>  32         BL8_NOP <ga:@callNonVoid>, <regmask **LONG LIST**>,<br>
> %X3<imp-use>, %X2<imp-use>, %R1<imp-def>, %X3<imp-def><br>
>  33         ADJCALLSTACKUP 96, 0, %R1<imp-def,dead>, %R1<imp-use><br>
>  34         %vreg11<def> = COPY %X3; G8RC:%vreg11 35     Successors<br>
> according to CFG: BB#3(?%)<br>
>  36<br>
>  37 BB#3: derived from LLVM BB %return<br>
>  38     Predecessors according to CFG: BB#1 BB#2 BB#4<br>
>  39         %vreg12<def> = EXTSW_32_64 %vreg11:sub_32; G8RC:%vreg12,%vreg11<br>
>  40         %X3<def> = COPY %vreg12; G8RC:%vreg12<br>
>  41         BLR8 %LR8<imp-use>, %RM<imp-use>, %X3<imp-use><br>
><br>
> No matter what I do, vreg15 will get a Callee-Saved Register assigned to<br>
> it. However, this is suboptimal. So what I am trying to accomplish is to<br>
> split the live range of vreg15 into the paths without the call and the path<br>
> with the call (BL8_NOP is a call). Then the physical register X3 can be<br>
> used in the paths BB#0 -> BB#1 -> BB#3 and BB#0 -> BB#4 -> BB#3 and it can<br>
> be copied to a Callee-Saved Register in BB#2.<br>
><br>
<br>
</div></div>Hi Nemanja,<br>
<br>
vreg15's live range is not across call. It is weird that it is always<br>
getting CSR. Maybe because of the hint of vreg16, i.e., the<br>
contribution of hint outweigh the cost of CSR first use?<br>
<br>
Is it possible to send out the testcase? I can try if there is anyway<br>
to allocate vreg15 to CSR.<br>
<br>
Thanks,<br>
Wei.<br>
<div class="HOEnZb"><div class="h5"><br>
> Without such a split, vreg15 is assigned a CSR for the entire live range<br>
> and there is no way to avoid having to save/restore the CSR in the<br>
> prologue/epilogue. If one of the two paths that did not actually have the<br>
> call turn out to be the hottest path through the function, there is a lot<br>
> of wasted cycles in the save/restore because we weren't able to shrink-wrap<br>
> this function due to the choice RA made.<br>
><br>
> If anyone can offer some ideas on what I should do here, I would truly<br>
> appreciate it.<br>
><br>
> Nemanja<br>
</div></div></blockquote></div><br></div>