<div dir="ltr">Hi Ahmed,<br><br><div>Thanks for your comments. I've re-looked at the code, and I completely misunderstood what an FTRUNC node was - I confused it with FP_ROUND.</div><div><br></div><div>So yes, FTRUNC should just use the generic unary op splitting, and wide FP truncations should not have an FTRUNC node planted but an (FP_ROUND $x, 0).</div><div><br></div><div>I also agree with the HalfVT problem. Thanks for noticing  both of these! I attach a patch which I think fixes all the issues, could you please review it?</div><div><br></div><div>I've added tests for v4{f,i}64->v4{i,f}16 to exercise this logic.</div><div><br></div><div>Cheers,</div><div><br></div><div>James</div><br><div class="gmail_quote">On Thu, 16 Apr 2015 at 02:51 Ahmed Bougacha <<a href="mailto:ahmed.bougacha@gmail.com">ahmed.bougacha@gmail.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi James,<br>
<br>
I got around to looking at this, and I have two concerns.<br>
<br>
First, is FTRUNC really a truncating conversion, and isn't it just a<br>
unary op?  It returns the exact same type, but removes the fractional<br>
part.<br>
The code should never fire currently, as I don't think we generate<br>
FTRUNCs with different in/out types.  It might make sense for<br>
"(FP_ROUND x, 1)" though, where it's fine to do the double-rounding.<br>
<br>
Second, for INT_TO_FP, the current logic (this is fixable I think)<br>
explicitly creates an integer type as HalfElementVT, but it should<br>
really be an FP type (if not, you should get stuff like "uitofp int -> int").<br>
The code should only fire when there's a 4x size difference;  the only<br>
case I can think of is f64/i64 -> f16, or i128 -> f32, if that's<br>
actually legal somewhere.<br>
<br>
-Ahmed<br>
<br>
<br>
On Tue, Mar 31, 2015 at 3:20 AM, James Molloy <<a href="mailto:james.molloy@arm.com" target="_blank">james.molloy@arm.com</a>> wrote:<br>
> Author: jamesm<br>
> Date: Tue Mar 31 05:20:58 2015<br>
> New Revision: 233681<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=233681&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=233681&view=rev</a><br>
> Log:<br>
> [SDAG] Move TRUNCATE splitting logic into a helper, and use<br>
>  it more liberally.<br>
><br>
> SplitVecOp_TRUNCATE has logic for recursively splitting oversize vectors<br>
> that need more than one round of splitting to become legal. There are many<br>
> other ISD nodes that could benefit from this logic, so factor it out and<br>
> use it for FP_TO_UINT,FP_TO_SINT,SINT_TO_FP,UINT_TO_FP and FTRUNC.<br>
><br>
> Added:<br>
>     llvm/trunk/test/CodeGen/AArch64/vcvt-oversize.ll<br>
> Modified:<br>
>     llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h<br>
>     llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp<br>
>     llvm/trunk/test/CodeGen/AArch64/arm64-convert-v4f64.ll<br>
>     llvm/trunk/test/CodeGen/ARM/vcvt.ll<br>
><br>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h?rev=233681&r1=233680&r2=233681&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h?rev=233681&r1=233680&r2=233681&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h (original)<br>
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h Tue Mar 31 05:20:58 2015<br>
> @@ -593,6 +593,7 @@ private:<br>
>    bool SplitVectorOperand(SDNode *N, unsigned OpNo);<br>
>    SDValue SplitVecOp_VSELECT(SDNode *N, unsigned OpNo);<br>
>    SDValue SplitVecOp_UnaryOp(SDNode *N);<br>
> +  SDValue SplitVecOp_TruncateHelper(SDNode *N, unsigned TruncateOp);<br>
><br>
>    SDValue SplitVecOp_BITCAST(SDNode *N);<br>
>    SDValue SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N);<br>
> @@ -600,7 +601,6 @@ private:<br>
>    SDValue SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo);<br>
>    SDValue SplitVecOp_MSTORE(MaskedStoreSDNode *N, unsigned OpNo);<br>
>    SDValue SplitVecOp_CONCAT_VECTORS(SDNode *N);<br>
> -  SDValue SplitVecOp_TRUNCATE(SDNode *N);<br>
>    SDValue SplitVecOp_VSETCC(SDNode *N);<br>
>    SDValue SplitVecOp_FP_ROUND(SDNode *N);<br>
><br>
><br>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp?rev=233681&r1=233680&r2=233681&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp?rev=233681&r1=233680&r2=233681&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp (original)<br>
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp Tue Mar 31 05:20:58 2015<br>
> @@ -1293,7 +1293,9 @@ bool DAGTypeLegalizer::SplitVectorOperan<br>
>      case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break;<br>
>      case ISD::EXTRACT_VECTOR_ELT:Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break;<br>
>      case ISD::CONCAT_VECTORS:    Res = SplitVecOp_CONCAT_VECTORS(N); break;<br>
> -    case ISD::TRUNCATE:          Res = SplitVecOp_TRUNCATE(N); break;<br>
> +    case ISD::TRUNCATE:<br>
> +      Res = SplitVecOp_TruncateHelper(N, ISD::TRUNCATE);<br>
> +      break;<br>
>      case ISD::FP_ROUND:          Res = SplitVecOp_FP_ROUND(N); break;<br>
>      case ISD::STORE:<br>
>        Res = SplitVecOp_STORE(cast<StoreSDNode>(N), OpNo);<br>
> @@ -1304,20 +1306,32 @@ bool DAGTypeLegalizer::SplitVectorOperan<br>
>      case ISD::VSELECT:<br>
>        Res = SplitVecOp_VSELECT(N, OpNo);<br>
>        break;<br>
> -    case ISD::CTTZ:<br>
> -    case ISD::CTLZ:<br>
> -    case ISD::CTPOP:<br>
> -    case ISD::FP_EXTEND:<br>
>      case ISD::FP_TO_SINT:<br>
>      case ISD::FP_TO_UINT:<br>
> +      if (N->getValueType(0).bitsLT(N->getOperand(0)->getValueType(0)))<br>
> +        Res = SplitVecOp_TruncateHelper(N, ISD::TRUNCATE);<br>
> +      else<br>
> +        Res = SplitVecOp_UnaryOp(N);<br>
> +      break;<br>
>      case ISD::SINT_TO_FP:<br>
>      case ISD::UINT_TO_FP:<br>
> -    case ISD::FTRUNC:<br>
> +      if (N->getValueType(0).bitsLT(N->getOperand(0)->getValueType(0)))<br>
> +        Res = SplitVecOp_TruncateHelper(N, ISD::FTRUNC);<br>
> +      else<br>
> +        Res = SplitVecOp_UnaryOp(N);<br>
> +      break;<br>
> +    case ISD::CTTZ:<br>
> +    case ISD::CTLZ:<br>
> +    case ISD::CTPOP:<br>
> +    case ISD::FP_EXTEND:<br>
>      case ISD::SIGN_EXTEND:<br>
>      case ISD::ZERO_EXTEND:<br>
>      case ISD::ANY_EXTEND:<br>
>        Res = SplitVecOp_UnaryOp(N);<br>
>        break;<br>
> +    case ISD::FTRUNC:<br>
> +      Res = SplitVecOp_TruncateHelper(N, ISD::FTRUNC);<br>
> +      break;<br>
>      }<br>
>    }<br>
><br>
> @@ -1581,7 +1595,8 @@ SDValue DAGTypeLegalizer::SplitVecOp_CON<br>
>    return DAG.getNode(ISD::BUILD_VECTOR, DL, N->getValueType(0), Elts);<br>
>  }<br>
><br>
> -SDValue DAGTypeLegalizer::SplitVecOp_TRUNCATE(SDNode *N) {<br>
> +SDValue DAGTypeLegalizer::SplitVecOp_TruncateHelper(SDNode *N,<br>
> +                                                    unsigned TruncateOp) {<br>
>    // The result type is legal, but the input type is illegal.  If splitting<br>
>    // ends up with the result type of each half still being legal, just<br>
>    // do that.  If, however, that would result in an illegal result type,<br>
> @@ -1624,8 +1639,8 @@ SDValue DAGTypeLegalizer::SplitVecOp_TRU<br>
>    EVT HalfElementVT = EVT::getIntegerVT(*DAG.getContext(), InElementSize/2);<br>
>    EVT HalfVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT,<br>
>                                  NumElements/2);<br>
> -  SDValue HalfLo = DAG.getNode(ISD::TRUNCATE, DL, HalfVT, InLoVec);<br>
> -  SDValue HalfHi = DAG.getNode(ISD::TRUNCATE, DL, HalfVT, InHiVec);<br>
> +  SDValue HalfLo = DAG.getNode(N->getOpcode(), DL, HalfVT, InLoVec);<br>
> +  SDValue HalfHi = DAG.getNode(N->getOpcode(), DL, HalfVT, InHiVec);<br>
>    // Concatenate them to get the full intermediate truncation result.<br>
>    EVT InterVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT, NumElements);<br>
>    SDValue InterVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InterVT, HalfLo,<br>
> @@ -1634,7 +1649,7 @@ SDValue DAGTypeLegalizer::SplitVecOp_TRU<br>
>    // type. This should normally be something that ends up being legal directly,<br>
>    // but in theory if a target has very wide vectors and an annoyingly<br>
>    // restricted set of legal types, this split can chain to build things up.<br>
> -  return DAG.getNode(ISD::TRUNCATE, DL, OutVT, InterVec);<br>
> +  return DAG.getNode(TruncateOp, DL, OutVT, InterVec);<br>
>  }<br>
><br>
>  SDValue DAGTypeLegalizer::SplitVecOp_VSETCC(SDNode *N) {<br>
><br>
> Modified: llvm/trunk/test/CodeGen/AArch64/arm64-convert-v4f64.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-convert-v4f64.ll?rev=233681&r1=233680&r2=233681&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/arm64-convert-v4f64.ll?rev=233681&r1=233680&r2=233681&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/test/CodeGen/AArch64/arm64-convert-v4f64.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/AArch64/arm64-convert-v4f64.ll Tue Mar 31 05:20:58 2015<br>
> @@ -3,11 +3,11 @@<br>
><br>
>  define <4 x i16> @fptosi_v4f64_to_v4i16(<4 x double>* %ptr) {<br>
>  ; CHECK: fptosi_v4f64_to_v4i16<br>
> -; CHECK-DAG: fcvtzs  v[[LHS:[0-9]+]].2d, v1.2d<br>
> -; CHECK-DAG: fcvtzs  v[[RHS:[0-9]+]].2d, v0.2d<br>
> -; CHECK-DAG: xtn  v[[LHS_NA:[0-9]+]].2s, v[[LHS]].2d<br>
> -; CHECK-DAG: xtn  v[[RHS_NA:[0-9]+]].2s, v[[RHS]].2d<br>
> -; CHECK:     uzp1  v0.4h, v[[RHS_NA]].4h, v[[LHS_NA]].4h<br>
> +; CHECK-DAG: fcvtzs  v[[LHS:[0-9]+]].2d, v0.2d<br>
> +; CHECK-DAG: fcvtzs  v[[RHS:[0-9]+]].2d, v1.2d<br>
> +; CHECK-DAG: xtn  v[[MID:[0-9]+]].2s, v[[LHS]].2d<br>
> +; CHECK-DAG: xtn2  v[[MID]].4s, v[[RHS]].2d<br>
> +; CHECK:     xtn  v0.4h, v[[MID]].4s<br>
>    %tmp1 = load <4 x double>, <4 x double>* %ptr<br>
>    %tmp2 = fptosi <4 x double> %tmp1 to <4 x i16><br>
>    ret <4 x i16> %tmp2<br>
> @@ -19,13 +19,13 @@ define <8 x i8> @fptosi_v4f64_to_v4i8(<8<br>
>  ; CHECK-DAG:  fcvtzs  v[[CONV1:[0-9]+]].2d, v1.2d<br>
>  ; CHECK-DAG:  fcvtzs  v[[CONV2:[0-9]+]].2d, v2.2d<br>
>  ; CHECK-DAG:  fcvtzs  v[[CONV3:[0-9]+]].2d, v3.2d<br>
> -; CHECK-DAG:  xtn  v[[NA0:[0-9]+]].2s, v[[CONV0]].2d<br>
> -; CHECK-DAG:  xtn  v[[NA1:[0-9]+]].2s, v[[CONV1]].2d<br>
>  ; CHECK-DAG:  xtn  v[[NA2:[0-9]+]].2s, v[[CONV2]].2d<br>
> -; CHECK-DAG:  xtn  v[[NA3:[0-9]+]].2s, v[[CONV3]].2d<br>
> -; CHECK-DAG:  uzp1  v[[TMP1:[0-9]+]].4h, v[[CONV1]].4h, v[[CONV0]].4h<br>
> -; CHECK-DAG:  uzp1  v[[TMP2:[0-9]+]].4h, v[[CONV3]].4h, v[[CONV2]].4h<br>
> -; CHECK:      uzp1  v0.8b, v[[TMP2]].8b, v[[TMP1]].8b<br>
> +; CHECK-DAG:  xtn2  v[[NA2]].4s, v[[CONV3]].2d<br>
> +; CHECK-DAG:  xtn  v[[NA0:[0-9]+]].2s, v[[CONV0]].2d<br>
> +; CHECK-DAG:  xtn2  v[[NA0]].4s, v[[CONV1]].2d<br>
> +; CHECK-DAG:  xtn  v[[TMP1:[0-9]+]].4h, v[[NA0]].4s<br>
> +; CHECK-DAG:  xtn2  v[[TMP1]].8h, v[[NA2]].4s<br>
> +; CHECK:      xtn  v0.8b, v[[TMP1]].8h<br>
>    %tmp1 = load <8 x double>, <8 x double>* %ptr<br>
>    %tmp2 = fptosi <8 x double> %tmp1 to <8 x i8><br>
>    ret <8 x i8> %tmp2<br>
><br>
> Added: llvm/trunk/test/CodeGen/AArch64/vcvt-oversize.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/vcvt-oversize.ll?rev=233681&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/vcvt-oversize.ll?rev=233681&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/test/CodeGen/AArch64/vcvt-oversize.ll (added)<br>
> +++ llvm/trunk/test/CodeGen/AArch64/vcvt-oversize.ll Tue Mar 31 05:20:58 2015<br>
> @@ -0,0 +1,16 @@<br>
> +; RUN: llc -mtriple=aarch64 < %s | FileCheck %s<br>
> +<br>
> +define <8 x i8> @float_to_i8(<8 x float>* %in) {<br>
> +; CHECK-LABEL: float_to_i8:<br>
> +; CHECK-DAG: fadd v[[LSB:[0-9]+]].4s, v0.4s, v0.4s<br>
> +; CHECK-DAG: fadd v[[MSB:[0-9]+]].4s, v1.4s, v1.4s<br>
> +; CHECK-DAG: fcvtzu v[[LSB2:[0-9]+]].4s, v[[LSB]].4s<br>
> +; CHECK-DAG: fcvtzu v[[MSB2:[0-9]+]].4s, v[[MSB]].4s<br>
> +; CHECK-DAG: xtn v[[TMP:[0-9]+]].4h, v[[LSB]].4s<br>
> +; CHECK-DAG: xtn2 v[[TMP]].8h, v[[MSB]].4s<br>
> +; CHECK-DAG: xtn v0.8b, v[[TMP]].8h<br>
> +  %l = load <8 x float>, <8 x float>* %in<br>
> +  %scale = fmul <8 x float> %l, <float 2.0, float 2.0, float 2.0, float 2.0, float 2.0, float 2.0, float 2.0, float 2.0><br>
> +  %conv = fptoui <8 x float> %scale to <8 x i8><br>
> +  ret <8 x i8> %conv<br>
> +}<br>
><br>
> Modified: llvm/trunk/test/CodeGen/ARM/vcvt.ll<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/vcvt.ll?rev=233681&r1=233680&r2=233681&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/vcvt.ll?rev=233681&r1=233680&r2=233681&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/test/CodeGen/ARM/vcvt.ll (original)<br>
> +++ llvm/trunk/test/CodeGen/ARM/vcvt.ll Tue Mar 31 05:20:58 2015<br>
> @@ -180,8 +180,8 @@ define <2 x i64> @fix_float_to_i64(<2 x<br>
><br>
>  define <4 x i16> @fix_double_to_i16(<4 x double> %in) {<br>
>  ; CHECK-LABEL: fix_double_to_i16:<br>
> -; CHECK: vcvt.s32.f64<br>
> -; CHECK: vcvt.s32.f64<br>
> +; CHECK: vcvt.u32.f64<br>
> +; CHECK: vcvt.u32.f64<br>
><br>
>    %scale = fmul <4 x double> %in, <double 2.0, double 2.0, double 2.0, double 2.0><br>
>    %conv = fptoui <4 x double> %scale to <4 x i16><br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">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>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">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>
</blockquote></div></div>