Esempio n. 1
0
SDNode *AArch64DAGToDAGISel::SelectVTBL(SDNode *N, unsigned NumVecs,
                                        bool IsExt) {
  assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
  SDLoc dl(N);

  // Check the element of look up table is 64-bit or not
  unsigned Vec0Idx = IsExt ? 2 : 1;
  assert(!N->getOperand(Vec0Idx + 0).getValueType().is64BitVector() &&
         "The element of lookup table for vtbl and vtbx must be 128-bit");

  // Check the return value type is 64-bit or not
  EVT ResVT = N->getValueType(0);
  bool is64BitRes = ResVT.is64BitVector();

  // Create new SDValue for vector list
  SmallVector<SDValue, 4> Regs(N->op_begin() + Vec0Idx,
                               N->op_begin() + Vec0Idx + NumVecs);
  SDValue TblReg = createQTuple(Regs);
  unsigned Opc = getTBLOpc(IsExt, is64BitRes, NumVecs);

  SmallVector<SDValue, 3> Ops;
  if (IsExt)
    Ops.push_back(N->getOperand(1));
  Ops.push_back(TblReg);
  Ops.push_back(N->getOperand(Vec0Idx + NumVecs));
  return CurDAG->getMachineNode(Opc, dl, ResVT, Ops);
}
Esempio n. 2
0
SDNode *AArch64DAGToDAGISel::SelectVST(SDNode *N, unsigned NumVecs,
                                       bool isUpdating,
                                       const uint16_t *Opcodes) {
  assert(NumVecs >= 1 && NumVecs <= 4 && "VST NumVecs out-of-range");
  SDLoc dl(N);

  MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
  MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();

  unsigned AddrOpIdx = isUpdating ? 1 : 2;
  unsigned Vec0Idx = 3; // AddrOpIdx + (isUpdating ? 2 : 1)
  EVT VT = N->getOperand(Vec0Idx).getValueType();
  unsigned OpcodeIndex;
  switch (VT.getSimpleVT().SimpleTy) {
  default: llvm_unreachable("unhandled vector store type");
  case MVT::v8i8:  OpcodeIndex = 0; break;
  case MVT::v4i16: OpcodeIndex = 1; break;
  case MVT::v2f32:
  case MVT::v2i32: OpcodeIndex = 2; break;
  case MVT::v1f64:
  case MVT::v1i64: OpcodeIndex = 3; break;
  case MVT::v16i8: OpcodeIndex = 4; break;
  case MVT::v8f16:
  case MVT::v8i16: OpcodeIndex = 5; break;
  case MVT::v4f32:
  case MVT::v4i32: OpcodeIndex = 6; break;
  case MVT::v2f64:
  case MVT::v2i64: OpcodeIndex = 7; break;
  }
  unsigned Opc = Opcodes[OpcodeIndex];

  std::vector<EVT> ResTys;
  if (isUpdating)
    ResTys.push_back(MVT::i64);
  ResTys.push_back(MVT::Other); // Type for the Chain

  SmallVector<SDValue, 6> Ops;
  Ops.push_back(N->getOperand(AddrOpIdx)); // Push back the Memory Address

  if (isUpdating) {
    SDValue Inc = N->getOperand(AddrOpIdx + 1);
    if (!isa<ConstantSDNode>(Inc.getNode())) // Increment in Register
      Opc = getVLDSTRegisterUpdateOpcode(Opc);
    Ops.push_back(Inc);
  }
  bool is64BitVector = VT.is64BitVector();

  SmallVector<SDValue, 4> Regs(N->op_begin() + Vec0Idx,
                               N->op_begin() + Vec0Idx + NumVecs);
  SDValue SrcReg = is64BitVector ? createDTuple(Regs) : createQTuple(Regs);
  Ops.push_back(SrcReg);

  // Push back the Chain
  Ops.push_back(N->getOperand(0));

  // Transfer memoperands.
  SDNode *VSt = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);
  cast<MachineSDNode>(VSt)->setMemRefs(MemOp, MemOp + 1);

  return VSt;
}
Esempio n. 3
0
SDNode *AArch64DAGToDAGISel::SelectVLD(SDNode *N, unsigned NumVecs,
                                       bool isUpdating,
                                       const uint16_t *Opcodes) {
  assert(NumVecs >= 1 && NumVecs <= 4 && "VLD NumVecs out-of-range");

  EVT VT = N->getValueType(0);
  unsigned OpcodeIndex;
  switch (VT.getSimpleVT().SimpleTy) {
  default: llvm_unreachable("unhandled vector load type");
  case MVT::v8i8:  OpcodeIndex = 0; break;
  case MVT::v4i16: OpcodeIndex = 1; break;
  case MVT::v2f32:
  case MVT::v2i32: OpcodeIndex = 2; break;
  case MVT::v1f64:
  case MVT::v1i64: OpcodeIndex = 3; break;
  case MVT::v16i8: OpcodeIndex = 4; break;
  case MVT::v8f16:
  case MVT::v8i16: OpcodeIndex = 5; break;
  case MVT::v4f32:
  case MVT::v4i32: OpcodeIndex = 6; break;
  case MVT::v2f64:
  case MVT::v2i64: OpcodeIndex = 7; break;
  }
  unsigned Opc = Opcodes[OpcodeIndex];

  SmallVector<SDValue, 2> Ops;
  unsigned AddrOpIdx = isUpdating ? 1 : 2;
  Ops.push_back(N->getOperand(AddrOpIdx)); // Push back the Memory Address

  if (isUpdating) {
    SDValue Inc = N->getOperand(AddrOpIdx + 1);
    if (!isa<ConstantSDNode>(Inc.getNode())) // Increment in Register
      Opc = getVLDSTRegisterUpdateOpcode(Opc);
    Ops.push_back(Inc);
  }

  Ops.push_back(N->getOperand(0)); // Push back the Chain

  std::vector<EVT> ResTys;
  bool is64BitVector = VT.is64BitVector();

  if (NumVecs == 1)
    ResTys.push_back(VT);
  else if (NumVecs == 3)
    ResTys.push_back(MVT::Untyped);
  else {
    EVT ResTy = EVT::getVectorVT(*CurDAG->getContext(), MVT::i64,
                                 is64BitVector ? NumVecs : NumVecs * 2);
    ResTys.push_back(ResTy);
  }

  if (isUpdating)
    ResTys.push_back(MVT::i64); // Type of the updated register
  ResTys.push_back(MVT::Other); // Type of the Chain
  SDLoc dl(N);
  SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops);

  // Transfer memoperands.
  MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
  MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand();
  cast<MachineSDNode>(VLd)->setMemRefs(MemOp, MemOp + 1);

  if (NumVecs == 1)
    return VLd;

  // If NumVecs > 1, the return result is a super register containing 2-4
  // consecutive vector registers.
  SDValue SuperReg = SDValue(VLd, 0);

  unsigned Sub0 = is64BitVector ? AArch64::dsub_0 : AArch64::qsub_0;
  for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
    ReplaceUses(SDValue(N, Vec),
                CurDAG->getTargetExtractSubreg(Sub0 + Vec, dl, VT, SuperReg));
  // Update users of the Chain
  ReplaceUses(SDValue(N, NumVecs), SDValue(VLd, 1));
  if (isUpdating)
    ReplaceUses(SDValue(N, NumVecs + 1), SDValue(VLd, 2));

  return NULL;
}