[llvm] r233224 - [DAGCombiner] Add support for TRUNCATE + FP_EXTEND vector constant folding
James Molloy
james at jamesmolloy.co.uk
Fri Apr 10 04:53:03 PDT 2015
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> 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
> 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/f2887a06/attachment.html>
-------------- next part --------------
; ModuleID = 'bugpoint-reduced-simplified.bc'
target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
target triple = "aarch64--linux-gnu"
; Function Attrs: nounwind
define i64 @dotests_616() #0 {
entry:
%0 = bitcast <2 x i64> zeroinitializer to <8 x i16>
%1 = and <8 x i16> zeroinitializer, %0
%2 = icmp ne <8 x i16> %1, zeroinitializer
%3 = extractelement <8 x i1> %2, i32 2
%vgetq_lane285 = sext i1 %3 to i16
%vset_lane = insertelement <4 x i16> undef, i16 %vgetq_lane285, i32 0
%4 = bitcast <4 x i16> %vset_lane to <1 x i64>
%vget_lane = extractelement <1 x i64> %4, i32 0
ret i64 %vget_lane
}
attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="cortex-a57" "target-features"="+neon,+crc,+crypto" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.ident = !{!0}
!0 = !{!"clang version 3.7.0 (trunk 234576)"}
More information about the llvm-commits
mailing list