]> granicus.if.org Git - llvm/commitdiff
[x86] fix assert with horizontal math + broadcast of vector (PR43402)
authorSanjay Patel <spatel@rotateright.com>
Mon, 23 Sep 2019 13:30:23 +0000 (13:30 +0000)
committerSanjay Patel <spatel@rotateright.com>
Mon, 23 Sep 2019 13:30:23 +0000 (13:30 +0000)
https://bugs.llvm.org/show_bug.cgi?id=43402

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@372606 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86ISelLowering.h
test/CodeGen/X86/haddsub-broadcast.ll [new file with mode: 0644]

index 59670d0ec3c8d7e482aa63f1b54a0d64adf4b1e1..fabacaefb6f7ddf2d46d111516d01249fcf26368 100644 (file)
@@ -34326,14 +34326,14 @@ static SDValue foldShuffleOfHorizOp(SDNode *N, SelectionDAG &DAG) {
 
   // When the operands of a horizontal math op are identical, the low half of
   // the result is the same as the high half. If a target shuffle is also
-  // replicating low and high halves, we don't need the shuffle.
+  // replicating low and high halves (and without changing the type/length of
+  // the vector), we don't need the shuffle.
   if (Opcode == X86ISD::MOVDDUP || Opcode == X86ISD::VBROADCAST) {
-    if (HOp.getScalarValueSizeInBits() == 64) {
+    if (HOp.getScalarValueSizeInBits() == 64 && HOp.getValueType() == VT) {
       // movddup (hadd X, X) --> hadd X, X
       // broadcast (extract_vec_elt (hadd X, X), 0) --> hadd X, X
       assert((HOp.getValueType() == MVT::v2f64 ||
-        HOp.getValueType() == MVT::v4f64) && HOp.getValueType() == VT &&
-        "Unexpected type for h-op");
+              HOp.getValueType() == MVT::v4f64) && "Unexpected type for h-op");
       return updateHOp(HOp, DAG);
     }
     return SDValue();
index 2cd49e4778229e019b0a37bd3d580c660b9068fa..90188e758e511235ab21cfda2b24cf1d7b675d0c 100644 (file)
@@ -425,7 +425,8 @@ namespace llvm {
       // Tests Types Of a FP Values for scalar types.
       VFPCLASSS,
 
-      // Broadcast scalar to vector.
+      // Broadcast (splat) scalar or element 0 of a vector. If the operand is
+      // a vector, this node may change the vector length as part of the splat.
       VBROADCAST,
       // Broadcast mask to vector.
       VBROADCASTM,
diff --git a/test/CodeGen/X86/haddsub-broadcast.ll b/test/CodeGen/X86/haddsub-broadcast.ll
new file mode 100644 (file)
index 0000000..a37cf80
--- /dev/null
@@ -0,0 +1,20 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=i686-- -mattr=avx2  | FileCheck %s
+
+; The broadcast node takes a vector operand as input and changes its length.
+
+define <4 x double> @PR43402(i64 %x) {
+; CHECK-LABEL: PR43402:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    vmovsd {{.*#+}} xmm0 = mem[0],zero
+; CHECK-NEXT:    vunpcklps {{.*#+}} xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
+; CHECK-NEXT:    vsubpd {{\.LCPI.*}}, %xmm0, %xmm0
+; CHECK-NEXT:    vhaddpd %xmm0, %xmm0, %xmm0
+; CHECK-NEXT:    vbroadcastsd %xmm0, %ymm0
+; CHECK-NEXT:    retl
+  %conv = uitofp i64 %x to double
+  %t2 = insertelement <4 x double> undef, double %conv, i32 0
+  %t3 = shufflevector <4 x double> %t2, <4 x double> undef, <4 x i32> zeroinitializer
+  ret <4 x double> %t3
+}
+