X86: Fix a bug in EltsFromConsecutiveLoads. We can't generate new loads without chains.
authorNadav Rotem <nrotem@apple.com>
Wed, 22 May 2013 19:28:41 +0000 (19:28 +0000)
committerNadav Rotem <nrotem@apple.com>
Wed, 22 May 2013 19:28:41 +0000 (19:28 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182507 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/X86/chain_order.ll [new file with mode: 0644]

index 769f90172ba2685d1ff32b27afa4c5db755299dc..bdb7ea6869cd845ad4667e3a06f7e4b2aac77a5d 100644 (file)
@@ -5109,15 +5109,27 @@ static SDValue EltsFromConsecutiveLoads(EVT VT, SmallVectorImpl<SDValue> &Elts,
   // load of the entire vector width starting at the base pointer.  If we found
   // consecutive loads for the low half, generate a vzext_load node.
   if (LastLoadedElt == NumElems - 1) {
+    SDValue NewLd = SDValue();
     if (DAG.InferPtrAlignment(LDBase->getBasePtr()) >= 16)
-      return DAG.getLoad(VT, DL, LDBase->getChain(), LDBase->getBasePtr(),
-                         LDBase->getPointerInfo(),
-                         LDBase->isVolatile(), LDBase->isNonTemporal(),
-                         LDBase->isInvariant(), 0);
-    return DAG.getLoad(VT, DL, LDBase->getChain(), LDBase->getBasePtr(),
-                       LDBase->getPointerInfo(),
-                       LDBase->isVolatile(), LDBase->isNonTemporal(),
-                       LDBase->isInvariant(), LDBase->getAlignment());
+      NewLd = DAG.getLoad(VT, DL, LDBase->getChain(), LDBase->getBasePtr(),
+                          LDBase->getPointerInfo(),
+                          LDBase->isVolatile(), LDBase->isNonTemporal(),
+                          LDBase->isInvariant(), 0);
+    NewLd = DAG.getLoad(VT, DL, LDBase->getChain(), LDBase->getBasePtr(),
+                        LDBase->getPointerInfo(),
+                        LDBase->isVolatile(), LDBase->isNonTemporal(),
+                        LDBase->isInvariant(), LDBase->getAlignment());
+
+    if (LDBase->hasAnyUseOfValue(1)) {
+      SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
+                                     SDValue(LDBase, 1),
+                                     SDValue(NewLd.getNode(), 1));
+      DAG.ReplaceAllUsesOfValueWith(SDValue(LDBase, 1), NewChain);
+      DAG.UpdateNodeOperands(NewChain.getNode(), SDValue(LDBase, 1),
+                             SDValue(NewLd.getNode(), 1));
+    }
+
+    return NewLd;
   }
   if (NumElems == 4 && LastLoadedElt == 1 &&
       DAG.getTargetLoweringInfo().isTypeLegal(MVT::v2i64)) {
diff --git a/test/CodeGen/X86/chain_order.ll b/test/CodeGen/X86/chain_order.ll
new file mode 100644 (file)
index 0000000..056fd27
--- /dev/null
@@ -0,0 +1,38 @@
+; RUN: llc < %s -mcpu=corei7-avx -mtriple=x86_64-linux | FileCheck %s
+
+;CHECK: cftx020
+;CHECK: vmovsd  (%rdi), %xmm{{.*}}
+;CHECK: vmovsd  16(%rdi), %xmm{{.*}}
+;CHECK: vmovhpd  8(%rdi), %xmm{{.*}}
+;CHECK: vmovsd  24(%rdi), %xmm{{.*}}
+;CHECK: vmovupd %xmm{{.*}}, (%rdi)
+;CHECK: vmovupd %xmm{{.*}}, 16(%rdi)
+;CHECK: ret
+
+; A test from pifft (after SLP-vectorization) that fails when we drop the chain on newly merged loads.
+define void @cftx020(double* nocapture %a) {
+entry:
+  %0 = load double* %a, align 8
+  %arrayidx1 = getelementptr inbounds double* %a, i64 2
+  %1 = load double* %arrayidx1, align 8
+  %arrayidx2 = getelementptr inbounds double* %a, i64 1
+  %2 = load double* %arrayidx2, align 8
+  %arrayidx3 = getelementptr inbounds double* %a, i64 3
+  %3 = load double* %arrayidx3, align 8
+  %4 = insertelement <2 x double> undef, double %0, i32 0
+  %5 = insertelement <2 x double> %4, double %3, i32 1
+  %6 = insertelement <2 x double> undef, double %1, i32 0
+  %7 = insertelement <2 x double> %6, double %2, i32 1
+  %8 = fadd <2 x double> %5, %7
+  %9 = bitcast double* %a to <2 x double>*
+  store <2 x double> %8, <2 x double>* %9, align 8
+  %10 = insertelement <2 x double> undef, double %0, i32 0
+  %11 = insertelement <2 x double> %10, double %2, i32 1
+  %12 = insertelement <2 x double> undef, double %1, i32 0
+  %13 = insertelement <2 x double> %12, double %3, i32 1
+  %14 = fsub <2 x double> %11, %13
+  %15 = bitcast double* %arrayidx1 to <2 x double>*
+  store <2 x double> %14, <2 x double>* %15, align 8
+  ret void
+}
+