[llvm] r233224 - [DAGCombiner] Add support for TRUNCATE + FP_EXTEND vector constant folding

Simon Pilgrim llvm-dev at redking.me.uk
Fri Apr 10 08:02:37 PDT 2015


Thanks for the test case James, I'll take a look and get back to you.

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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150410/7491e3ef/attachment.html>


More information about the llvm-commits mailing list