[Hexagon] Avoid widening vectors with non-HVX element types
authorKrzysztof Parzyszek <kparzysz@quicinc.com>
Sat, 12 Sep 2020 21:32:24 +0000 (16:32 -0500)
committerKrzysztof Parzyszek <kparzysz@quicinc.com>
Sun, 13 Sep 2020 01:26:54 +0000 (20:26 -0500)
llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
llvm/lib/Target/Hexagon/HexagonSubtarget.h
llvm/test/CodeGen/Hexagon/autohvx/isel-widen-truncate-illegal-elem.ll [new file with mode: 0644]

index e63cb50a0fb84b7408fba9dfb45ca7a547ddbfb4..65bc2e3577cc45fbe8c5ebcc1662de06d38d6cb4 100644 (file)
@@ -1925,6 +1925,17 @@ HexagonTargetLowering::WidenHvxTruncate(SDValue Op, SelectionDAG &DAG) const {
   const SDLoc &dl(Op);
   unsigned HwWidth = 8*Subtarget.getVectorLength();
 
+  SDValue Op0 = Op.getOperand(0);
+  MVT ResTy = ty(Op);
+  MVT OpTy = ty(Op0);
+  if (!Subtarget.isHVXElementType(OpTy) || !Subtarget.isHVXElementType(ResTy))
+    return SDValue();
+
+  // .-res, op->  Scalar         Illegal      HVX
+  // Scalar           ok  extract(widen)        -
+  // Illegal           -           widen    widen
+  // HVX               -               -       ok
+
   auto getFactor = [HwWidth](MVT Ty) {
     unsigned Width = Ty.getSizeInBits();
     assert(HwWidth % Width == 0);
@@ -1936,15 +1947,6 @@ HexagonTargetLowering::WidenHvxTruncate(SDValue Op, SelectionDAG &DAG) const {
     return MVT::getVectorVT(Ty.getVectorElementType(), WideLen);
   };
 
-  SDValue Op0 = Op.getOperand(0);
-  MVT ResTy = ty(Op);
-  MVT OpTy = ty(Op0);
-
-  // .-res, op->  Scalar         Illegal      HVX
-  // Scalar           ok  extract(widen)        -
-  // Illegal           -           widen    widen
-  // HVX               -               -       ok
-
   if (Subtarget.isHVXVectorType(OpTy))
     return DAG.getNode(HexagonISD::VPACKL, dl, getWideTy(ResTy), Op0);
 
@@ -2053,8 +2055,8 @@ HexagonTargetLowering::LowerHvxOperationWrapper(SDNode *N,
   switch (Opc) {
     case ISD::TRUNCATE: {
       assert(shouldWidenToHvx(ty(Op.getOperand(0)), DAG) && "Not widening?");
-      SDValue T = WidenHvxTruncate(Op, DAG);
-      Results.push_back(T);
+      if (SDValue T = WidenHvxTruncate(Op, DAG))
+        Results.push_back(T);
       break;
     }
     case ISD::STORE: {
@@ -2089,8 +2091,8 @@ HexagonTargetLowering::ReplaceHvxNodeResults(SDNode *N,
   switch (Opc) {
     case ISD::TRUNCATE: {
       assert(shouldWidenToHvx(ty(Op), DAG) && "Not widening?");
-      SDValue T = WidenHvxTruncate(Op, DAG);
-      Results.push_back(T);
+      if (SDValue T = WidenHvxTruncate(Op, DAG))
+        Results.push_back(T);
       break;
     }
     case ISD::BITCAST:
index c47b95c5ad2aae11af45bdec906e09d22ee32913..5b71784bac260db3c436d9d73095a8225a222a14 100644 (file)
@@ -275,6 +275,17 @@ public:
     return makeArrayRef(Types);
   }
 
+  bool isHVXElementType(MVT Ty, bool IncludeBool = false) const {
+    if (!useHVXOps())
+      return false;
+    if (Ty.isVector())
+      Ty = Ty.getVectorElementType();
+    if (IncludeBool && Ty == MVT::i1)
+      return true;
+    ArrayRef<MVT> ElemTypes = getHVXElementTypes();
+    return llvm::find(ElemTypes, Ty) != ElemTypes.end();
+  }
+
   bool isHVXVectorType(MVT VecTy, bool IncludeBool = false) const {
     if (!VecTy.isVector() || !useHVXOps() || VecTy.isScalableVector())
       return false;
@@ -298,7 +309,7 @@ public:
     unsigned VecWidth = VecTy.getSizeInBits();
     if (VecWidth != 8*HwLen && VecWidth != 16*HwLen)
       return false;
-    return llvm::any_of(ElemTypes, [ElemTy] (MVT T) { return ElemTy == T; });
+    return llvm::find(ElemTypes, ElemTy) != ElemTypes.end();
   }
 
   unsigned getTypeAlignment(MVT Ty) const {
diff --git a/llvm/test/CodeGen/Hexagon/autohvx/isel-widen-truncate-illegal-elem.ll b/llvm/test/CodeGen/Hexagon/autohvx/isel-widen-truncate-illegal-elem.ll
new file mode 100644 (file)
index 0000000..3f55d22
--- /dev/null
@@ -0,0 +1,34 @@
+; RUN: llc -march=hexagon < %s | FileCheck %s
+
+; Check that this does not crash.
+; 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 dso_local void @f0() local_unnamed_addr #0 {
+b0:
+  %v0 = load i32, i32* undef, align 4
+  %v1 = select i1 undef, i32 0, i32 1073741823
+  %v2 = shl i32 %v1, 0
+  %v3 = sext i32 %v0 to i64
+  %v4 = sext i32 %v2 to i64
+  %v5 = mul nsw i64 %v4, %v3
+  %v6 = lshr i64 %v5, 32
+  %v7 = trunc i64 %v6 to i32
+  %v8 = sext i32 %v7 to i64
+  %v9 = insertelement <32 x i64> undef, i64 %v8, i32 0
+  %v10 = shufflevector <32 x i64> %v9, <32 x i64> undef, <32 x i32> zeroinitializer
+  %v11 = getelementptr i32, i32* null, i32 32
+  %v12 = bitcast i32* %v11 to <32 x i32>*
+  %v13 = load <32 x i32>, <32 x i32>* %v12, align 4
+  %v14 = shl <32 x i32> %v13, zeroinitializer
+  %v15 = sext <32 x i32> %v14 to <32 x i64>
+  %v16 = mul nsw <32 x i64> %v10, %v15
+  %v17 = lshr <32 x i64> %v16, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32>
+  %v18 = trunc <32 x i64> %v17 to <32 x i32>
+  store <32 x i32> %v18, <32 x i32>* %v12, align 4
+  ret void
+}
+
+attributes #0 = { "target-features"="+hvx-length128b,+hvxv67,+v67,-long-calls" }