diff --git a/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp b/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp index 58fd740d7a8..4aad920f2bc 100644 --- a/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp +++ b/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp @@ -971,6 +971,32 @@ HexagonTargetLowering::LowerHvxConcatVectors(SDValue Op, SelectionDAG &DAG) SmallVector Elems; for (SDValue V : Op.getNode()->ops()) DAG.ExtractVectorElements(V, Elems); + // A vector of i16 will be broken up into a build_vector of i16's. + // This is a problem, since at the time of operation legalization, + // all operations are expected to be type-legalized, and i16 is not + // a legal type. If any of the extracted elements is not of a valid + // type, sign-extend it to a valid one. + for (unsigned i = 0, e = Elems.size(); i != e; ++i) { + SDValue V = Elems[i]; + MVT Ty = ty(V); + if (!isTypeLegal(Ty)) { + EVT NTy = getTypeToTransformTo(*DAG.getContext(), Ty); + if (V.getOpcode() == ISD::EXTRACT_VECTOR_ELT) { + Elems[i] = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, NTy, + DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NTy, + V.getOperand(0), V.getOperand(1)), + DAG.getValueType(Ty)); + continue; + } + // A few less complicated cases. + if (V.getOpcode() == ISD::Constant) + Elems[i] = DAG.getSExtOrTrunc(V, dl, NTy); + else if (V.isUndef()) + Elems[i] = DAG.getUNDEF(NTy); + else + llvm_unreachable("Unexpected vector element"); + } + } return DAG.getBuildVector(VecTy, dl, Elems); } diff --git a/test/CodeGen/Hexagon/autohvx/isel-extractelt-illegal-type.ll b/test/CodeGen/Hexagon/autohvx/isel-extractelt-illegal-type.ll new file mode 100644 index 00000000000..2e915e017f5 --- /dev/null +++ b/test/CodeGen/Hexagon/autohvx/isel-extractelt-illegal-type.ll @@ -0,0 +1,34 @@ +; RUN: llc -march=hexagon < %s | FileCheck %s + +; Make sure this doesn't crash. +; CHECK: = mem + +target triple = "hexagon" + +; Function Attrs: nounwind readnone +declare i32 @llvm.hexagon.A2.subh.l16.sat.ll(i32, i32) #0 + +; Function Attrs: nounwind readonly +define dso_local signext i16 @f0(i16* nocapture readonly %a0) local_unnamed_addr #1 { +b0: + %v0 = load <8 x i16>, <8 x i16>* undef, align 2, !tbaa !0 + %v1 = shufflevector <8 x i16> %v0, <8 x i16> undef, <8 x i32> + %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <16 x i32> + %v3 = lshr <16 x i16> %v2, + %v4 = and <16 x i16> %v3, + %v5 = extractelement <16 x i16> %v4, i32 0 + %v6 = sext i16 %v5 to i32 + %v7 = tail call i32 @llvm.hexagon.A2.subh.l16.sat.ll(i32 %v6, i32 16) + %v8 = trunc i32 %v7 to i16 + %v9 = icmp sgt i16 %v8, -1 + %v10 = select i1 %v9, i16 0, i16 undef + ret i16 %v10 +} + +attributes #0 = { nounwind readnone } +attributes #1 = { nounwind readonly "target-cpu"="hexagonv60" "target-features"="+hvx-length64b,+hvxv60" } + +!0 = !{!1, !1, i64 0} +!1 = !{!"short", !2, i64 0} +!2 = !{!"omnipotent char", !3, i64 0} +!3 = !{!"Simple C/C++ TBAA"}