Implement Neon VST[234] operations.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78330 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
index 155ef59..0bfe213 100644
--- a/lib/Target/ARM/ARMISelLowering.cpp
+++ b/lib/Target/ARM/ARMISelLowering.cpp
@@ -323,6 +323,7 @@
   // We want to custom lower some of our intrinsics.
   setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
   setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom);
+  setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);
 
   setOperationAction(ISD::SETCC,     MVT::i32, Expand);
   setOperationAction(ISD::SETCC,     MVT::f32, Expand);
@@ -466,6 +467,9 @@
   case ARMISD::VLD2D:         return "ARMISD::VLD2D";
   case ARMISD::VLD3D:         return "ARMISD::VLD3D";
   case ARMISD::VLD4D:         return "ARMISD::VLD4D";
+  case ARMISD::VST2D:         return "ARMISD::VST2D";
+  case ARMISD::VST3D:         return "ARMISD::VST3D";
+  case ARMISD::VST4D:         return "ARMISD::VST4D";
   }
 }
 
@@ -1325,6 +1329,23 @@
   return DAG.getNode(Opcode, dl, Node->getVTList(), Ops, 2);
 }
 
+static SDValue LowerNeonVSTIntrinsic(SDValue Op, SelectionDAG &DAG,
+                                     unsigned Opcode, unsigned NumVecs) {
+  SDNode *Node = Op.getNode();
+  MVT VT = Node->getOperand(3).getValueType();
+  DebugLoc dl = Op.getDebugLoc();
+
+  if (!VT.is64BitVector())
+    return SDValue(); // unimplemented
+
+  SmallVector<SDValue, 6> Ops;
+  Ops.push_back(Node->getOperand(0));
+  Ops.push_back(Node->getOperand(2));
+  for (unsigned N = 0; N < NumVecs; ++N)
+    Ops.push_back(Node->getOperand(N + 3));
+  return DAG.getNode(Opcode, dl, MVT::Other, Ops.data(), Ops.size());
+}
+
 SDValue
 ARMTargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) {
   unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
@@ -1340,10 +1361,13 @@
     return LowerNeonVLDIntrinsic(Op, DAG, ARMISD::VLD4D);
   case Intrinsic::arm_neon_vst2i:
   case Intrinsic::arm_neon_vst2f:
+    return LowerNeonVSTIntrinsic(Op, DAG, ARMISD::VST2D, 2);
   case Intrinsic::arm_neon_vst3i:
   case Intrinsic::arm_neon_vst3f:
+    return LowerNeonVSTIntrinsic(Op, DAG, ARMISD::VST3D, 3);
   case Intrinsic::arm_neon_vst4i:
   case Intrinsic::arm_neon_vst4f:
+    return LowerNeonVSTIntrinsic(Op, DAG, ARMISD::VST4D, 4);
   default: return SDValue();    // Don't custom lower most intrinsics.
   }
 }
@@ -2381,6 +2405,7 @@
   case ISD::RETURNADDR:    break;
   case ISD::FRAMEADDR:     return LowerFRAMEADDR(Op, DAG);
   case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG);
+  case ISD::INTRINSIC_VOID:
   case ISD::INTRINSIC_W_CHAIN: return LowerINTRINSIC_W_CHAIN(Op, DAG);
   case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
   case ISD::BIT_CONVERT:   return ExpandBIT_CONVERT(Op.getNode(), DAG);