diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.h b/llvm/lib/Target/Hexagon/HexagonISelLowering.h index e174e5279ac1..cfccb14a09c9 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLowering.h +++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.h @@ -486,6 +486,7 @@ private: SDValue SplitHvxMemOp(SDValue Op, SelectionDAG &DAG) const; SDValue WidenHvxLoad(SDValue Op, SelectionDAG &DAG) const; SDValue WidenHvxStore(SDValue Op, SelectionDAG &DAG) const; + SDValue WidenHvxSetCC(SDValue Op, SelectionDAG &DAG) const; SDValue WidenHvxExtend(SDValue Op, SelectionDAG &DAG) const; SDValue WidenHvxTruncate(SDValue Op, SelectionDAG &DAG) const; diff --git a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp index f228e0a23794..161035b93e8b 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp @@ -51,6 +51,13 @@ HexagonTargetLowering::initializeHVXLowering() { addRegisterClass(MVT::v256i8, &Hexagon::HvxWRRegClass); addRegisterClass(MVT::v128i16, &Hexagon::HvxWRRegClass); addRegisterClass(MVT::v64i32, &Hexagon::HvxWRRegClass); + // Treat v16i1 as a legal type, since there is no way to widen vNi1: + // the validity of vNi1 may depend on how the result was obtained. + // For example v32i1 is ok when it's a result of comparing v32i32, + // but would need to be widened if it came from comparing v32i16. + // This precludes using getTypeToTransformTo, since it doesn't have + // the necessary context to decide what to do. + addRegisterClass(MVT::v16i1, &Hexagon::HvxQRRegClass); addRegisterClass(MVT::v32i1, &Hexagon::HvxQRRegClass); addRegisterClass(MVT::v64i1, &Hexagon::HvxQRRegClass); addRegisterClass(MVT::v128i1, &Hexagon::HvxQRRegClass); @@ -241,7 +248,6 @@ HexagonTargetLowering::initializeHVXLowering() { } // Handle store widening for short vectors. - std::vector ShortTys; unsigned HwLen = Subtarget.getVectorLength(); for (MVT ElemTy : Subtarget.getHVXElementTypes()) { if (ElemTy == MVT::i1) @@ -254,6 +260,7 @@ HexagonTargetLowering::initializeHVXLowering() { if (Action == TargetLoweringBase::TypeWidenVector) { setOperationAction(ISD::LOAD, VecTy, Custom); setOperationAction(ISD::STORE, VecTy, Custom); + setOperationAction(ISD::SETCC, VecTy, Custom); setOperationAction(ISD::TRUNCATE, VecTy, Custom); setOperationAction(ISD::ANY_EXTEND, VecTy, Custom); setOperationAction(ISD::SIGN_EXTEND, VecTy, Custom); @@ -1932,6 +1939,27 @@ HexagonTargetLowering::WidenHvxStore(SDValue Op, SelectionDAG &DAG) const { MemOp, ISD::UNINDEXED, false, false); } +SDValue +HexagonTargetLowering::WidenHvxSetCC(SDValue Op, SelectionDAG &DAG) const { + const SDLoc &dl(Op); + SDValue Op0 = Op.getOperand(0), Op1 = Op.getOperand(1); + MVT ElemTy = ty(Op0).getVectorElementType(); + unsigned HwLen = Subtarget.getVectorLength(); + + unsigned WideOpLen = (8 * HwLen) / ElemTy.getSizeInBits(); + assert(WideOpLen * ElemTy.getSizeInBits() == 8 * HwLen); + MVT WideOpTy = MVT::getVectorVT(ElemTy, WideOpLen); + + SDValue WideOp0 = appendUndef(Op0, WideOpTy, DAG); + SDValue WideOp1 = appendUndef(Op1, WideOpTy, DAG); + EVT ResTy = + getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), WideOpTy); + SDValue SetCC = DAG.getNode(ISD::SETCC, dl, ResTy, + {WideOp0, WideOp1, Op.getOperand(2)}); + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, ty(Op), + {SetCC, getZero(dl, MVT::i32, DAG)}); +} + SDValue HexagonTargetLowering::WidenHvxExtend(SDValue Op, SelectionDAG &DAG) const { const SDLoc &dl(Op); @@ -2102,20 +2130,28 @@ HexagonTargetLowering::LowerHvxOperationWrapper(SDNode *N, case ISD::ANY_EXTEND: case ISD::SIGN_EXTEND: case ISD::ZERO_EXTEND: - assert(shouldWidenToHvx(ty(Op.getOperand(0)), DAG) && "Not widening?"); - if (SDValue T = WidenHvxExtend(Op, DAG)) - Results.push_back(T); + if (shouldWidenToHvx(ty(Op.getOperand(0)), DAG)) { + if (SDValue T = WidenHvxExtend(Op, DAG)) + Results.push_back(T); + } + break; + case ISD::SETCC: + if (shouldWidenToHvx(ty(Op.getOperand(0)), DAG)) { + if (SDValue T = WidenHvxSetCC(Op, DAG)) + Results.push_back(T); + } break; case ISD::TRUNCATE: - assert(shouldWidenToHvx(ty(Op.getOperand(0)), DAG) && "Not widening?"); - if (SDValue T = WidenHvxTruncate(Op, DAG)) - Results.push_back(T); + if (shouldWidenToHvx(ty(Op.getOperand(0)), DAG)) { + if (SDValue T = WidenHvxTruncate(Op, DAG)) + Results.push_back(T); + } break; case ISD::STORE: { - assert(shouldWidenToHvx(ty(cast(N)->getValue()), DAG) && - "Not widening?"); - SDValue Store = WidenHvxStore(SDValue(N, 0), DAG); - Results.push_back(Store); + if (shouldWidenToHvx(ty(cast(N)->getValue()), DAG)) { + SDValue Store = WidenHvxStore(Op, DAG); + Results.push_back(Store); + } break; } case ISD::MLOAD: @@ -2132,6 +2168,8 @@ HexagonTargetLowering::LowerHvxOperationWrapper(SDNode *N, Results.push_back(S); } break; + default: + break; } } @@ -2144,21 +2182,24 @@ HexagonTargetLowering::ReplaceHvxNodeResults(SDNode *N, case ISD::ANY_EXTEND: case ISD::SIGN_EXTEND: case ISD::ZERO_EXTEND: - assert(shouldWidenToHvx(ty(Op), DAG) && "Not widening?"); - if (SDValue T = WidenHvxExtend(Op, DAG)) - Results.push_back(T); + if (shouldWidenToHvx(ty(Op), DAG)) { + if (SDValue T = WidenHvxExtend(Op, DAG)) + Results.push_back(T); + } break; case ISD::TRUNCATE: - assert(shouldWidenToHvx(ty(Op), DAG) && "Not widening?"); - if (SDValue T = WidenHvxTruncate(Op, DAG)) - Results.push_back(T); + if (shouldWidenToHvx(ty(Op), DAG)) { + if (SDValue T = WidenHvxTruncate(Op, DAG)) + Results.push_back(T); + } break; case ISD::LOAD: { - assert(shouldWidenToHvx(ty(Op), DAG) && "Not widening?"); - SDValue Load = WidenHvxLoad(Op, DAG); - assert(Load->getOpcode() == ISD::MERGE_VALUES); - Results.push_back(Load.getOperand(0)); - Results.push_back(Load.getOperand(1)); + if (shouldWidenToHvx(ty(Op), DAG)) { + SDValue Load = WidenHvxLoad(Op, DAG); + assert(Load->getOpcode() == ISD::MERGE_VALUES); + Results.push_back(Load.getOperand(0)); + Results.push_back(Load.getOperand(1)); + } break; } case ISD::BITCAST: @@ -2180,7 +2221,6 @@ HexagonTargetLowering::PerformHvxDAGCombine(SDNode *N, DAGCombinerInfo &DCI) SelectionDAG &DAG = DCI.DAG; SDValue Op(N, 0); unsigned Opc = Op.getOpcode(); - if (DCI.isBeforeLegalizeOps()) return SDValue(); @@ -2231,7 +2271,6 @@ HexagonTargetLowering::PerformHvxDAGCombine(SDNode *N, DAGCombinerInfo &DCI) bool HexagonTargetLowering::shouldWidenToHvx(MVT Ty, SelectionDAG &DAG) const { - assert(!Subtarget.isHVXVectorType(Ty, true)); auto Action = getPreferredHvxVectorAction(Ty); if (Action == TargetLoweringBase::TypeWidenVector) { EVT WideTy = getTypeToTransformTo(*DAG.getContext(), Ty); diff --git a/llvm/test/CodeGen/Hexagon/autohvx/widen-setcc.ll b/llvm/test/CodeGen/Hexagon/autohvx/widen-setcc.ll new file mode 100644 index 000000000000..3475e86feb0c --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/autohvx/widen-setcc.ll @@ -0,0 +1,21 @@ +; RUN: llc -march=hexagon -hexagon-hvx-widen=32 < %s | FileCheck %s + +; Make sure that this doesn't crash. +; CHECK-LABEL: f0: +; CHECK: vmem + +target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048" +target triple = "hexagon" + +define dllexport void @f0(i16* %a0, <16 x i16> %a1) local_unnamed_addr #0 { +b0: + %v0 = getelementptr i16, i16* %a0, i32 undef + %v1 = bitcast i16* %v0 to <16 x i16>* + %v2 = load <16 x i16>, <16 x i16>* undef, align 2 + %v3 = icmp sgt <16 x i16> zeroinitializer, %v2 + %v4 = select <16 x i1> %v3, <16 x i16> %a1, <16 x i16> %v2 + store <16 x i16> %v4, <16 x i16>* %v1, align 2 + ret void +} + +attributes #0 = { "target-features"="+hvxv66,+hvx-length128b" }