<div dir="ltr"><div><div><div>> Also, isn’t there the exact same register pressure concern in the 
DAG as well? Especially considering the fact that this is 
target-independent?<br><br></div>Now that the patch is reverted due to a spilling catastrophe, this seems obvious. :)<br><br></div>I also seem to have completely misjudged the potential compile-time hit. I did look at that using test-suite on x86, so I'd love to know if D9363 made any difference for your out-of-tree target and/or tests.<br><br><br><div>> By the way the name of the function is very generic 
(ReassociateBinops), do you plan to extend it to do perform 
transformations?<br>> Right now it does not carry what it does.</div><span><div><br></div></span></div>I had a vague feeling that someone, someday would extend it in some interesting way, but the truth is really just that I don't know what to name this:<br><br>//  (op N0: (op N00: (op z, w), N01: y), N1: x) -><br>
//  (op N00: (op z, w), (op N1: x, N01: y))<br>
<br><div><div><br><br><div><div><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Apr 29, 2015 at 10:03 PM, Mehdi Amini <span dir="ltr"><<a href="mailto:mehdi.amini@apple.com" target="_blank">mehdi.amini@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word">Hi Sanjay, <div><br></div><div>Thanks for your detailed answer.</div><div><br></div><div><br><div><span><blockquote type="cite"><div>On Apr 29, 2015, at 8:03 PM, Sanjay Patel <<a href="mailto:spatel@rotateright.com" target="_blank">spatel@rotateright.com</a>> wrote:</div><br><div>Hi Mehdi,<div><br></div><div>Let me answer the last question first: why not instcombine?</div><div>Because I noticed this pattern was created by another DAGCombine in:</div><div><font size="2"><span style="background-color:rgba(255,255,255,0)"><a href="http://reviews.llvm.org/D8941" target="_blank">http://reviews.llvm.org/D8941</a></span></font><br><br>So although doing the fold here does not preclude an instcombine, doing an instcombine alone would not be sufficient. </div></div></blockquote><div><br></div></span><div>Good point!</div><span><div><br></div><br><blockquote type="cite"><div><div>I'm also not sure that the transform should be done that early because it's not a completely free transform; I think there is a potential register pressure concern.</div></div></blockquote><div><br></div><div><br></div></span><div>How does the fact that we do it early would increase the register pressure? </div><div>Also, isn’t there the exact same register pressure concern in the DAG as well? Especially considering the fact that this is target-independent?</div><span><br><blockquote type="cite"><div><div><br></div><div>I agree that the fold should be applied more generally. Please see the follow up patch and post commit thread for r236171. I welcome any advice on how to do this better.</div></div></blockquote><div><br></div></span><div>I gave a try in <a href="http://reviews.llvm.org/D9363" target="_blank">http://reviews.llvm.org/D9363</a> ; let me know what you think.</div><div>By the way the name of the function is very generic (ReassociateBinops), do you plan to extend it to do perform transformations? Right now it does not carry what it does.</div><span><div><br></div><br><blockquote type="cite"><div><div><br></div><div>Regarding the canonicalization, I wasn't aware of any downside to commuting the operands, so yes, I added it to not have to duplicate the fold logic for all permutations of the operand order. I was also inf-looping in an early draft of the patch, and canonicalization was my solution to avoid that without multiplying the if checks. If these are not valid reasons for the canonicalization, I can fix it.</div></div></blockquote><div><br></div></span><div>This is introducing a strong canonicalization which is not very constrained. No target would be able to canonicalize on more specific conditions. </div><div>I don’t know people use to judge if a canonicalization is justified or not, I tend to at least look at a “cost/benefit” analysis: </div><div>- how does this enable/simplify other transformations?</div><div>- how does this constrains other transformations (infinite loop problem…)</div><div><br></div><div>The benefits are unclear to me right now, but that does not mean they don’t exist.</div><div><br></div><div><br></div><div>— </div><span><font color="#888888"><div>Mehdi</div></font></span><div><div><div><br></div><div><br></div><br><blockquote type="cite"><div><div><br><br>On Wednesday, April 29, 2015, Mehdi Amini <<a>mehdi.amini@apple.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hello Sanjay,<br>
<br>
In this commit you introduce a new canonicalization in the DAG:<br>
<br>
 (fadd (otherop, fadd)) -> (fadd (fadd, otherop))<br>
<br>
It is not clear to me why this canonicalization is desirable in general (other than to ease the implementation of your transformation, which does not seem to justify it alone IMO).<br>
<br>
Also, if such a canonicalization is needed, my feeling is that it shouldn’t be hidden deeply here, and should probably apply to a bunch of other binop.<br>
<br>
As a side question: I’m curious why isn’t this been performed in instcombine?<br>
<br>
Thanks,<br>
<br>
Mehdi<br>
<br>
<br>
<br>
> On Apr 28, 2015, at 2:03 PM, Sanjay Patel <<a>spatel@rotateright.com</a>> wrote:<br>
><br>
> Author: spatel<br>
> Date: Tue Apr 28 16:03:22 2015<br>
> New Revision: 236031<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=236031&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=236031&view=rev</a><br>
> Log:<br>
> transform fadd chains to increase parallelism<br>
><br>
> This is a compromise: with this simple patch, we should always handle a chain of exactly 3<br>
> operations optimally, but we're not generating the optimal balanced binary tree for a longer<br>
> sequence.<br>
><br>
> In general, this transform will reduce the dependency chain for a sequence of instructions<br>
> using N operands from a worst case N-1 dependent operations to N/2 dependent operations.<br>
> The optimal balanced binary tree would reduce the chain to log2(N).<br>
><br>
> The trade-off for not dealing with longer sequences is: (1) we have less complexity in the<br>
> compiler, (2) we avoid unknown compile-time blowup calculating a balanced tree, and (3) we<br>
> don't need to worry about the increased register pressure required to parallelize longer<br>
> sequences. It also seems unlikely that we would ever encounter really long strings of<br>
> dependent ops like that in the wild, but I'm not sure how to verify that speculation.<br>
> FWIW, I see no perf difference for test-suite running on btver2 (x86-64) with -ffast-math<br>
> and this patch.<br>
><br>
> We can extend this patch to cover other associative operations such as fmul, fmax, fmin,<br>
> integer add, integer mul.<br>
><br>
> This is a partial fix for:<br>
> <a href="https://llvm.org/bugs/show_bug.cgi?id=17305" target="_blank">https://llvm.org/bugs/show_bug.cgi?id=17305</a><br>
><br>
> and if extended:<br>
> <a href="https://llvm.org/bugs/show_bug.cgi?id=21768" target="_blank">https://llvm.org/bugs/show_bug.cgi?id=21768</a><br>
> <a href="https://llvm.org/bugs/show_bug.cgi?id=23116" target="_blank">https://llvm.org/bugs/show_bug.cgi?id=23116</a><br>
><br>
> The issue also came up in:<br>
> <a href="http://reviews.llvm.org/D8941" target="_blank">http://reviews.llvm.org/D8941</a><br>
><br>
> Differential Revision: <a href="http://reviews.llvm.org/D9232" target="_blank">http://reviews.llvm.org/D9232</a><br>
><br>
><br>
> Modified:<br>
>    llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp<br>
>    llvm/trunk/test/CodeGen/X86/fp-fast.ll<br>
><br>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=236031&r1=236030&r2=236031&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=236031&r1=236030&r2=236031&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)<br>
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Tue Apr 28 16:03:22 2015<br>
> @@ -7801,6 +7801,24 @@ SDValue DAGCombiner::visitFADD(SDNode *N<br>
>                            N0.getOperand(0), DAG.getConstantFP(4.0, DL, VT));<br>
>       }<br>
>     }<br>
> +<br>
> +    // Canonicalize chains of adds to LHS to simplify the following transform.<br>
> +    if (N0.getOpcode() != ISD::FADD && N1.getOpcode() == ISD::FADD)<br>
> +      return DAG.getNode(ISD::FADD, SDLoc(N), VT, N1, N0);<br>
> +<br>
> +    // Convert a chain of 3 dependent operations into 2 independent operations<br>
> +    // and 1 dependent operation:<br>
> +    //  (fadd N0: (fadd N00: (fadd z, w), N01: y), N1: x) -><br>
> +    //  (fadd N00: (fadd z, w), (fadd N1: x, N01: y))<br>
> +    if (N0.getOpcode() == ISD::FADD &&  N0.hasOneUse() &&<br>
> +        N1.getOpcode() != ISD::FADD) {<br>
> +      SDValue N00 = N0.getOperand(0);<br>
> +      if (N00.getOpcode() == ISD::FADD) {<br>
> +        SDValue N01 = N0.getOperand(1);<br>
> +        SDValue NewAdd = DAG.getNode(ISD::FADD, SDLoc(N), VT, N1, N01);<br>
> +        return DAG.getNode(ISD::FADD, SDLoc(N), VT, N00, NewAdd);<br>
> +      }<br>
> +    }<br>
>   } // enable-unsafe-fp-math<br>
><br>
>   // FADD -> FMA combines:<br>
><br>
> Modified: llvm/trunk/test/CodeGen/X86/fp-fast.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fp-fast.ll?rev=236031&r1=236030&r2=236031&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fp-fast.ll?rev=236031&r1=236030&r2=236031&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/test/CodeGen/X86/fp-fast.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/X86/fp-fast.ll Tue Apr 28 16:03:22 2015<br>
> @@ -113,3 +113,46 @@ define float @test11(float %a) {<br>
>   %t2 = fadd float %a, %t1<br>
>   ret float %t2<br>
> }<br>
> +<br>
> +; Verify that the first two adds are independent; the destination registers<br>
> +; are used as source registers for the third add.<br>
> +<br>
> +define float @reassociate_adds1(float %a, float %b, float %c, float %d) {<br>
> +; CHECK-LABEL: reassociate_adds1:<br>
> +; CHECK:       # BB#0:<br>
> +; CHECK-NEXT:    vaddss %xmm1, %xmm0, %xmm0<br>
> +; CHECK-NEXT:    vaddss %xmm2, %xmm3, %xmm1<br>
> +; CHECK-NEXT:    vaddss %xmm1, %xmm0, %xmm0<br>
> +; CHECK-NEXT:    retq<br>
> +  %add0 = fadd float %a, %b<br>
> +  %add1 = fadd float %add0, %c<br>
> +  %add2 = fadd float %add1, %d<br>
> +  ret float %add2<br>
> +}<br>
> +<br>
> +define float @reassociate_adds2(float %a, float %b, float %c, float %d) {<br>
> +; CHECK-LABEL: reassociate_adds2:<br>
> +; CHECK:       # BB#0:<br>
> +; CHECK-NEXT:    vaddss %xmm1, %xmm0, %xmm0<br>
> +; CHECK-NEXT:    vaddss %xmm2, %xmm3, %xmm1<br>
> +; CHECK-NEXT:    vaddss %xmm1, %xmm0, %xmm0<br>
> +; CHECK-NEXT:    retq<br>
> +  %add0 = fadd float %a, %b<br>
> +  %add1 = fadd float %c, %add0<br>
> +  %add2 = fadd float %add1, %d<br>
> +  ret float %add2<br>
> +}<br>
> +<br>
> +define float @reassociate_adds3(float %a, float %b, float %c, float %d) {<br>
> +; CHECK-LABEL: reassociate_adds3:<br>
> +; CHECK:       # BB#0:<br>
> +; CHECK-NEXT:    vaddss %xmm1, %xmm0, %xmm0<br>
> +; CHECK-NEXT:    vaddss %xmm2, %xmm3, %xmm1<br>
> +; CHECK-NEXT:    vaddss %xmm1, %xmm0, %xmm0<br>
> +; CHECK-NEXT:    retq<br>
> +  %add0 = fadd float %a, %b<br>
> +  %add1 = fadd float %add0, %c<br>
> +  %add2 = fadd float %d, %add1<br>
> +  ret float %add2<br>
> +}<br>
> +<br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a>llvm-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
<br>
</blockquote></div>
</div></blockquote></div></div></div><br></div></div></blockquote></div><br></div></div></div></div></div></div>