<div dir="ltr">Hi Simon,<br><br><div>This commit was found to be faulty by random testing. The attached .ll file, when run with "llc crash-2.ll" will fall over in instruction selection.</div><div><br></div><div>The actual problem is an illegal BUILD_VECTOR is being created after type legalization (i8/i16 are illegal on ARM/AArch64).</div><div><br></div><div>Would you mind please having a look?</div><div><br></div><div>Cheers,</div><div><br></div><div>James</div><br><div class="gmail_quote">On Wed, 25 Mar 2015 at 22:38 Simon Pilgrim <<a href="mailto:llvm-dev@redking.me.uk">llvm-dev@redking.me.uk</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rksimon<br>
Date: Wed Mar 25 17:30:31 2015<br>
New Revision: 233224<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=233224&view=rev" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project?rev=233224&view=rev</a><br>
Log:<br>
[DAGCombiner] Add support for TRUNCATE + FP_EXTEND vector constant folding<br>
<br>
This patch adds supports for the vector constant folding of TRUNCATE and FP_EXTEND instructions and tidies up the SINT_TO_FP and UINT_TO_FP instructions to match.<br>
<br>
It also moves the vector constant folding for the FNEG and FABS instructions to use the DAG.getNode() functionality like the other unary instructions.<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D8593" target="_blank">http://reviews.llvm.org/D8593</a><br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/<u></u>CodeGen/SelectionDAGNodes.h<br>
    llvm/trunk/lib/CodeGen/<u></u>SelectionDAG/DAGCombiner.cpp<br>
    llvm/trunk/lib/CodeGen/<u></u>SelectionDAG/SelectionDAG.cpp<br>
    llvm/trunk/test/CodeGen/X86/<u></u>vec_fpext.ll<br>
    llvm/trunk/test/CodeGen/X86/<u></u>vector-trunc.ll<br>
<br>
Modified: llvm/trunk/include/llvm/<u></u>CodeGen/SelectionDAGNodes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=233224&r1=233223&r2=233224&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/include/<u></u>llvm/CodeGen/<u></u>SelectionDAGNodes.h?rev=<u></u>233224&r1=233223&r2=233224&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/include/llvm/<u></u>CodeGen/SelectionDAGNodes.h (original)<br>
+++ llvm/trunk/include/llvm/<u></u>CodeGen/SelectionDAGNodes.h Wed Mar 25 17:30:31 2015<br>
@@ -94,6 +94,10 @@ namespace ISD {<br>
   /// all ConstantSDNode or undef.<br>
   bool isBuildVectorOfConstantSDNodes<u></u>(const SDNode *N);<br>
<br>
+  /// \brief Return true if the specified node is a BUILD_VECTOR node of<br>
+  /// all ConstantFPSDNode or undef.<br>
+  bool isBuildVectorOfConstantFPSDNod<u></u>es(const SDNode *N);<br>
+<br>
   /// Return true if the specified node is a<br>
   /// ISD::SCALAR_TO_VECTOR node or a BUILD_VECTOR node where only the low<br>
   /// element is not an undef.<br>
<br>
Modified: llvm/trunk/lib/CodeGen/<u></u>SelectionDAG/DAGCombiner.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=233224&r1=233223&r2=233224&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/lib/<u></u>CodeGen/SelectionDAG/<u></u>DAGCombiner.cpp?rev=233224&r1=<u></u>233223&r2=233224&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/lib/CodeGen/<u></u>SelectionDAG/DAGCombiner.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/<u></u>SelectionDAG/DAGCombiner.cpp Wed Mar 25 17:30:31 2015<br>
@@ -251,7 +251,6 @@ namespace {<br>
     SDValue visitORLike(SDValue N0, SDValue N1, SDNode *LocReference);<br>
     SDValue visitXOR(SDNode *N);<br>
     SDValue SimplifyVBinOp(SDNode *N);<br>
-    SDValue SimplifyVUnaryOp(SDNode *N);<br>
     SDValue visitSHL(SDNode *N);<br>
     SDValue visitSRA(SDNode *N);<br>
     SDValue visitSRL(SDNode *N);<br>
@@ -716,6 +715,22 @@ static SDNode *isConstantBuildVectorOrCo<br>
   return nullptr;<br>
 }<br>
<br>
+static SDNode *<u></u>isConstantIntBuildVectorOrCons<u></u>tantInt(SDValue N) {<br>
+  if (isa<ConstantSDNode>(N))<br>
+    return N.getNode();<br>
+  if (ISD::<u></u>isBuildVectorOfConstantSDNodes<u></u>(N.getNode()))<br>
+    return N.getNode();<br>
+  return nullptr;<br>
+}<br>
+<br>
+static SDNode *<u></u>isConstantFPBuildVectorOrConst<u></u>antFP(SDValue N) {<br>
+  if (isa<ConstantFPSDNode>(N))<br>
+    return N.getNode();<br>
+  if (ISD::<u></u>isBuildVectorOfConstantFPSDNod<u></u>es(N.getNode()))<br>
+    return N.getNode();<br>
+  return nullptr;<br>
+}<br>
+<br>
 // \brief Returns the SDNode if it is a constant splat BuildVector or constant<br>
 // int.<br>
 static ConstantSDNode *isConstOrConstSplat(SDValue N) {<br>
@@ -6557,7 +6572,7 @@ SDValue DAGCombiner::visitTRUNCATE(<u></u>SDNod<br>
   if (N0.getValueType() == N->getValueType(0))<br>
     return N0;<br>
   // fold (truncate c1) -> c1<br>
-  if (isa<ConstantSDNode>(N0))<br>
+  if (<u></u>isConstantIntBuildVectorOrCons<u></u>tantInt(N0))<br>
     return DAG.getNode(ISD::TRUNCATE, SDLoc(N), VT, N0);<br>
   // fold (truncate (truncate x)) -> (truncate x)<br>
   if (N0.getOpcode() == ISD::TRUNCATE)<br>
@@ -7947,8 +7962,7 @@ SDValue DAGCombiner::visitSINT_TO_FP(<u></u>SDN<br>
   EVT OpVT = N0.getValueType();<br>
<br>
   // fold (sint_to_fp c1) -> c1fp<br>
-  ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);<br>
-  if (N0C &&<br>
+  if (<u></u>isConstantIntBuildVectorOrCons<u></u>tantInt(N0) &&<br>
       // ...but only if the target supports immediate floating-point values<br>
       (!LegalOperations ||<br>
        TLI.isOperationLegalOrCustom(<u></u>llvm::ISD::ConstantFP, VT)))<br>
@@ -8000,8 +8014,7 @@ SDValue DAGCombiner::visitUINT_TO_FP(<u></u>SDN<br>
   EVT OpVT = N0.getValueType();<br>
<br>
   // fold (uint_to_fp c1) -> c1fp<br>
-  ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);<br>
-  if (N0C &&<br>
+  if (<u></u>isConstantIntBuildVectorOrCons<u></u>tantInt(N0) &&<br>
       // ...but only if the target supports immediate floating-point values<br>
       (!LegalOperations ||<br>
        TLI.isOperationLegalOrCustom(<u></u>llvm::ISD::ConstantFP, VT)))<br>
@@ -8159,7 +8172,6 @@ SDValue DAGCombiner::visitFP_ROUND_<u></u>INREG<br>
<br>
 SDValue DAGCombiner::visitFP_EXTEND(<u></u>SDNode *N) {<br>
   SDValue N0 = N->getOperand(0);<br>
-  ConstantFPSDNode *N0CFP = dyn_cast<ConstantFPSDNode>(N0)<u></u>;<br>
   EVT VT = N->getValueType(0);<br>
<br>
   // If this is fp_round(fpextend), don't fold it, allow ourselves to be folded.<br>
@@ -8168,7 +8180,7 @@ SDValue DAGCombiner::visitFP_EXTEND(<u></u>SDNo<br>
     return SDValue();<br>
<br>
   // fold (fp_extend c1fp) -> c1fp<br>
-  if (N0CFP)<br>
+  if (<u></u>isConstantFPBuildVectorOrConst<u></u>antFP(N0))<br>
     return DAG.getNode(ISD::FP_EXTEND, SDLoc(N), VT, N0);<br>
<br>
   // Turn fp_extend(fp_round(X, 1)) -> x since the fp_round doesn't affect the<br>
@@ -8243,14 +8255,9 @@ SDValue DAGCombiner::visitFNEG(SDNode *N<br>
   SDValue N0 = N->getOperand(0);<br>
   EVT VT = N->getValueType(0);<br>
<br>
-  if (VT.isVector()) {<br>
-    SDValue FoldedVOp = SimplifyVUnaryOp(N);<br>
-    if (FoldedVOp.getNode()) return FoldedVOp;<br>
-  }<br>
-<br>
   // Constant fold FNEG.<br>
-  if (isa<ConstantFPSDNode>(N0))<br>
-    return DAG.getNode(ISD::FNEG, SDLoc(N), VT, N->getOperand(0));<br>
+  if (<u></u>isConstantFPBuildVectorOrConst<u></u>antFP(N0))<br>
+    return DAG.getNode(ISD::FNEG, SDLoc(N), VT, N0);<br>
<br>
   if (isNegatibleForFree(N0, LegalOperations, DAG.getTargetLoweringInfo(),<br>
                          &DAG.getTarget().Options))<br>
@@ -8345,13 +8352,8 @@ SDValue DAGCombiner::visitFABS(SDNode *N<br>
   SDValue N0 = N->getOperand(0);<br>
   EVT VT = N->getValueType(0);<br>
<br>
-  if (VT.isVector()) {<br>
-    SDValue FoldedVOp = SimplifyVUnaryOp(N);<br>
-    if (FoldedVOp.getNode()) return FoldedVOp;<br>
-  }<br>
-<br>
   // fold (fabs c1) -> fabs(c1)<br>
-  if (isa<ConstantFPSDNode>(N0))<br>
+  if (<u></u>isConstantFPBuildVectorOrConst<u></u>antFP(N0))<br>
     return DAG.getNode(ISD::FABS, SDLoc(N), VT, N0);<br>
<br>
   // fold (fabs (fabs x)) -> (fabs x)<br>
@@ -12401,38 +12403,6 @@ SDValue DAGCombiner::SimplifyVBinOp(<u></u>SDNo<br>
   return SDValue();<br>
 }<br>
<br>
-/// Visit a binary vector operation, like FABS/FNEG.<br>
-SDValue DAGCombiner::SimplifyVUnaryOp(<u></u>SDNode *N) {<br>
-  assert(N->getValueType(0).<u></u>isVector() &&<br>
-         "SimplifyVUnaryOp only works on vectors!");<br>
-<br>
-  SDValue N0 = N->getOperand(0);<br>
-<br>
-  if (N0.getOpcode() != ISD::BUILD_VECTOR)<br>
-    return SDValue();<br>
-<br>
-  // Operand is a BUILD_VECTOR node, see if we can constant fold it.<br>
-  SmallVector<SDValue, 8> Ops;<br>
-  for (unsigned i = 0, e = N0.getNumOperands(); i != e; ++i) {<br>
-    SDValue Op = N0.getOperand(i);<br>
-    if (Op.getOpcode() != ISD::UNDEF &&<br>
-        Op.getOpcode() != ISD::ConstantFP)<br>
-      break;<br>
-    EVT EltVT = Op.getValueType();<br>
-    SDValue FoldOp = DAG.getNode(N->getOpcode(), SDLoc(N0), EltVT, Op);<br>
-    if (FoldOp.getOpcode() != ISD::UNDEF &&<br>
-        FoldOp.getOpcode() != ISD::ConstantFP)<br>
-      break;<br>
-    Ops.push_back(FoldOp);<br>
-    AddToWorklist(FoldOp.getNode()<u></u>);<br>
-  }<br>
-<br>
-  if (Ops.size() != N0.getNumOperands())<br>
-    return SDValue();<br>
-<br>
-  return DAG.getNode(ISD::BUILD_VECTOR, SDLoc(N), N0.getValueType(), Ops);<br>
-}<br>
-<br>
 SDValue DAGCombiner::SimplifySelect(<u></u>SDLoc DL, SDValue N0,<br>
                                     SDValue N1, SDValue N2){<br>
   assert(N0.getOpcode() ==ISD::SETCC && "First argument must be a SetCC node!");<br>
<br>
Modified: llvm/trunk/lib/CodeGen/<u></u>SelectionDAG/SelectionDAG.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=233224&r1=233223&r2=233224&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/lib/<u></u>CodeGen/SelectionDAG/<u></u>SelectionDAG.cpp?rev=233224&<u></u>r1=233223&r2=233224&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/lib/CodeGen/<u></u>SelectionDAG/SelectionDAG.cpp (original)<br>
+++ llvm/trunk/lib/CodeGen/<u></u>SelectionDAG/SelectionDAG.cpp Wed Mar 25 17:30:31 2015<br>
@@ -196,6 +196,22 @@ bool ISD::<u></u>isBuildVectorOfConstantSDNodes<br>
   return true;<br>
 }<br>
<br>
+/// \brief Return true if the specified node is a BUILD_VECTOR node of<br>
+/// all ConstantFPSDNode or undef.<br>
+bool ISD::<u></u>isBuildVectorOfConstantFPSDNod<u></u>es(const SDNode *N) {<br>
+  if (N->getOpcode() != ISD::BUILD_VECTOR)<br>
+    return false;<br>
+<br>
+  for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {<br>
+    SDValue Op = N->getOperand(i);<br>
+    if (Op.getOpcode() == ISD::UNDEF)<br>
+      continue;<br>
+    if (!isa<ConstantFPSDNode>(Op))<br>
+      return false;<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
 /// isScalarToVector - Return true if the specified node is a<br>
 /// ISD::SCALAR_TO_VECTOR node or a BUILD_VECTOR node where only the low<br>
 /// element is not an undef.<br>
@@ -2827,7 +2843,7 @@ SDValue SelectionDAG::getNode(unsigned O<br>
     }<br>
   }<br>
<br>
-  // Constant fold unary operations with a vector integer operand.<br>
+  // Constant fold unary operations with a vector integer or float operand.<br>
   if (BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(<u></u>Operand.getNode())) {<br>
     if (BV->isConstant()) {<br>
       switch (Opcode) {<br>
@@ -2835,6 +2851,10 @@ SDValue SelectionDAG::getNode(unsigned O<br>
         // FIXME: Entirely reasonable to perform folding of other unary<br>
         // operations here as the need arises.<br>
         break;<br>
+      case ISD::FNEG:<br>
+      case ISD::FABS:<br>
+      case ISD::FP_EXTEND:<br>
+      case ISD::TRUNCATE:<br>
       case ISD::UINT_TO_FP:<br>
       case ISD::SINT_TO_FP: {<br>
         // Let the above scalar folding handle the folding of each element.<br>
@@ -2842,9 +2862,14 @@ SDValue SelectionDAG::getNode(unsigned O<br>
         for (int i = 0, e = VT.getVectorNumElements(); i != e; ++i) {<br>
           SDValue OpN = BV->getOperand(i);<br>
           OpN = getNode(Opcode, DL, VT.getVectorElementType(), OpN);<br>
+          if (OpN.getOpcode() != ISD::UNDEF &&<br>
+              OpN.getOpcode() != ISD::Constant &&<br>
+              OpN.getOpcode() != ISD::ConstantFP)<br>
+            break;<br>
           Ops.push_back(OpN);<br>
         }<br>
-        return getNode(ISD::BUILD_VECTOR, DL, VT, Ops);<br>
+        if (Ops.size() == VT.getVectorNumElements())<br>
+          return getNode(ISD::BUILD_VECTOR, DL, VT, Ops);<br>
       }<br>
       }<br>
     }<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/<u></u>vec_fpext.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec_fpext.ll?rev=233224&r1=233223&r2=233224&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/test/<u></u>CodeGen/X86/vec_fpext.ll?rev=<u></u>233224&r1=233223&r2=233224&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/test/CodeGen/X86/<u></u>vec_fpext.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/<u></u>vec_fpext.ll Wed Mar 25 17:30:31 2015<br>
@@ -42,3 +42,15 @@ entry:<br>
   store <8 x double> %1, <8 x double>* %out, align 1<br>
   ret void<br>
 }<br>
+<br>
+define <2 x double> @fpext_fromconst() {<br>
+; CHECK-LABEL: fpext_fromconst:<br>
+; AVX-LABEL: fpext_fromconst:<br>
+entry:<br>
+; CHECK: movaps {{.*#+}} xmm0 = [1.000000e+00,-2.000000e+00]<br>
+; AVX: vmovaps {{.*#+}} xmm0 = [1.000000e+00,-2.000000e+00]<br>
+  %0  = insertelement <2 x float> undef, float 1.0, i32 0<br>
+  %1  = insertelement <2 x float> %0, float -2.0, i32 1<br>
+  %2  = fpext <2 x float> %1 to <2 x double><br>
+  ret <2 x double> %2<br>
+}<br>
<br>
Modified: llvm/trunk/test/CodeGen/X86/<u></u>vector-trunc.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vector-trunc.ll?rev=233224&r1=233223&r2=233224&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/llvm/trunk/test/<u></u>CodeGen/X86/vector-trunc.ll?<u></u>rev=233224&r1=233223&r2=<u></u>233224&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- llvm/trunk/test/CodeGen/X86/<u></u>vector-trunc.ll (original)<br>
+++ llvm/trunk/test/CodeGen/X86/<u></u>vector-trunc.ll Wed Mar 25 17:30:31 2015<br>
@@ -221,3 +221,20 @@ entry:<br>
   %1 = bitcast <8 x i8> %0 to i64<br>
   ret i64 %1<br>
 }<br>
+<br>
+define <16 x i8> @trunc16i64_const() {<br>
+; SSE-LABEL:  trunc16i64_const<br>
+; SSE:        # BB#0: # %entry<br>
+; SSE-NEXT:   xorps %xmm0, %xmm0<br>
+; SSE-NEXT:   retq<br>
+;<br>
+; AVX-LABEL:  trunc16i64_const<br>
+; AVX:        # BB#0: # %entry<br>
+; AVX-NEXT:   vxorps %xmm0, %xmm0, %xmm0<br>
+; AVX-NEXT:   retq<br>
+<br>
+entry:<br>
+  %0 = trunc <16 x i64> zeroinitializer to <16 x i8><br>
+  %1 = shufflevector <16 x i8> %0, <16 x i8> %0, <16 x i32> <i32 28, i32 30, i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 undef, i32 14, i32 16, i32 18, i32 20, i32 22, i32 24, i32 26><br>
+  ret <16 x i8> %1<br>
+}<br>
<br>
<br>
______________________________<u></u>_________________<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/<u></u>mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div>