From 07a8ff4892b2a54f0bd5843f863bcffa7a258f1f Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Fri, 4 Apr 2014 14:49:21 +0000 Subject: ARM64: handle v1i1 types arising from setcc properly. There were several overlapping problems here, and this solution is closely inspired by the one adopted in AArch64 in r201381. Firstly, scalarisation of v1i1 setcc operations simply fails if the input types are legal. This is fixed in LegalizeVectorTypes.cpp this time, and allows AArch64 code to be simplified slightly. Second, vselect with such a setcc feeding into it ends up in ScalarizeVectorOperand, where it's not handled. I experimented with an implementation, but found that whatever DAG came out was rather horrific. I think Hao's DAG combine approach is a good one for quality, though there are edge cases it won't catch (to be fixed separately). Should fix PR19335. llvm-svn: 205625 --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 28 -------------------- llvm/lib/Target/ARM64/ARM64ISelLowering.cpp | 34 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 28 deletions(-) (limited to 'llvm/lib/Target') diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 54277103902..2edb19281de 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -538,7 +538,6 @@ AArch64TargetLowering::AArch64TargetLowering(AArch64TargetMachine &TM) setOperationAction(ISD::FPOW, MVT::v2f32, Expand); } - setTargetDAGCombine(ISD::SETCC); setTargetDAGCombine(ISD::SIGN_EXTEND); setTargetDAGCombine(ISD::VSELECT); } @@ -4284,32 +4283,6 @@ static SDValue CombineVLDDUP(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) { return SDValue(N, 0); } -// v1i1 setcc -> -// v1i1 (bitcast (i1 setcc (extract_vector_elt, extract_vector_elt)) -// FIXME: Currently the type legalizer can't handle SETCC having v1i1 as result. -// If it can legalize "v1i1 SETCC" correctly, no need to combine such SETCC. -static SDValue PerformSETCCCombine(SDNode *N, SelectionDAG &DAG) { - EVT ResVT = N->getValueType(0); - - if (!ResVT.isVector() || ResVT.getVectorNumElements() != 1 || - ResVT.getVectorElementType() != MVT::i1) - return SDValue(); - - SDValue LHS = N->getOperand(0); - SDValue RHS = N->getOperand(1); - EVT CmpVT = LHS.getValueType(); - LHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N), - CmpVT.getVectorElementType(), LHS, - DAG.getConstant(0, MVT::i64)); - RHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N), - CmpVT.getVectorElementType(), RHS, - DAG.getConstant(0, MVT::i64)); - SDValue SetCC = - DAG.getSetCC(SDLoc(N), MVT::i1, LHS, RHS, - cast(N->getOperand(2))->get()); - return DAG.getNode(ISD::BITCAST, SDLoc(N), ResVT, SetCC); -} - // vselect (v1i1 setcc) -> // vselect (v1iXX setcc) (XX is the size of the compared operand type) // FIXME: Currently the type legalizer can't handle VSELECT having v1i1 as @@ -4378,7 +4351,6 @@ AArch64TargetLowering::PerformDAGCombine(SDNode *N, case ISD::SRA: case ISD::SRL: return PerformShiftCombine(N, DCI, getSubtarget()); - case ISD::SETCC: return PerformSETCCCombine(N, DCI.DAG); case ISD::VSELECT: return PerformVSelectCombine(N, DCI.DAG); case ISD::SIGN_EXTEND: return PerformSignExtendCombine(N, DCI.DAG); case ISD::INTRINSIC_WO_CHAIN: diff --git a/llvm/lib/Target/ARM64/ARM64ISelLowering.cpp b/llvm/lib/Target/ARM64/ARM64ISelLowering.cpp index 255685232d1..63957abdfdd 100644 --- a/llvm/lib/Target/ARM64/ARM64ISelLowering.cpp +++ b/llvm/lib/Target/ARM64/ARM64ISelLowering.cpp @@ -434,6 +434,8 @@ ARM64TargetLowering::ARM64TargetLowering(ARM64TargetMachine &TM) setTargetDAGCombine(ISD::MUL); + setTargetDAGCombine(ISD::VSELECT); + MaxStoresPerMemset = MaxStoresPerMemsetOptSize = 8; MaxStoresPerMemcpy = MaxStoresPerMemcpyOptSize = 4; MaxStoresPerMemmove = MaxStoresPerMemmoveOptSize = 4; @@ -7227,6 +7229,36 @@ static SDValue performBRCONDCombine(SDNode *N, return SDValue(); } +// vselect (v1i1 setcc) -> +// vselect (v1iXX setcc) (XX is the size of the compared operand type) +// FIXME: Currently the type legalizer can't handle VSELECT having v1i1 as +// condition. If it can legalize "VSELECT v1i1" correctly, no need to combine +// such VSELECT. +static SDValue performVSelectCombine(SDNode *N, SelectionDAG &DAG) { + SDValue N0 = N->getOperand(0); + EVT CCVT = N0.getValueType(); + + if (N0.getOpcode() != ISD::SETCC || CCVT.getVectorNumElements() != 1 || + CCVT.getVectorElementType() != MVT::i1) + return SDValue(); + + EVT ResVT = N->getValueType(0); + EVT CmpVT = N0.getOperand(0).getValueType(); + // Only combine when the result type is of the same size as the compared + // operands. + if (ResVT.getSizeInBits() != CmpVT.getSizeInBits()) + return SDValue(); + + SDValue IfTrue = N->getOperand(1); + SDValue IfFalse = N->getOperand(2); + SDValue SetCC = + DAG.getSetCC(SDLoc(N), CmpVT.changeVectorElementTypeToInteger(), + N0.getOperand(0), N0.getOperand(1), + cast(N0.getOperand(2))->get()); + return DAG.getNode(ISD::VSELECT, SDLoc(N), ResVT, SetCC, + IfTrue, IfFalse); +} + SDValue ARM64TargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -7255,6 +7287,8 @@ SDValue ARM64TargetLowering::PerformDAGCombine(SDNode *N, return performBitcastCombine(N, DCI, DAG); case ISD::CONCAT_VECTORS: return performConcatVectorsCombine(N, DCI, DAG); + case ISD::VSELECT: + return performVSelectCombine(N, DCI.DAG); case ISD::STORE: return performSTORECombine(N, DCI, DAG, Subtarget); case ARM64ISD::BRCOND: -- cgit v1.2.3