SDValue XCoreSelectionDAGInfo::EmitTargetCodeForMemcpy(
    SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src,
    SDValue Size, unsigned Align, bool isVolatile, bool AlwaysInline,
    MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const {
  unsigned SizeBitWidth = Size.getValueSizeInBits();
  // Call __memcpy_4 if the src, dst and size are all 4 byte aligned.
  if (!AlwaysInline && (Align & 3) == 0 &&
      DAG.MaskedValueIsZero(Size, APInt(SizeBitWidth, 3))) {
    const TargetLowering &TLI = *DAG.getSubtarget().getTargetLowering();
    TargetLowering::ArgListTy Args;
    TargetLowering::ArgListEntry Entry;
    Entry.Ty = DAG.getDataLayout().getIntPtrType(*DAG.getContext());
    Entry.Node = Dst; Args.push_back(Entry);
    Entry.Node = Src; Args.push_back(Entry);
    Entry.Node = Size; Args.push_back(Entry);

    TargetLowering::CallLoweringInfo CLI(DAG);
    CLI.setDebugLoc(dl)
        .setChain(Chain)
        .setLibCallee(TLI.getLibcallCallingConv(RTLIB::MEMCPY),
                      Type::getVoidTy(*DAG.getContext()),
                      DAG.getExternalSymbol(
                          "__memcpy_4", TLI.getPointerTy(DAG.getDataLayout())),
                      std::move(Args))
        .setDiscardResult();

    std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(CLI);
    return CallResult.second;
  }

  // Otherwise have the target-independent code call memcpy.
  return SDValue();
}
Example #2
0
SDNode *VDAGToDAGISel::SelectImmediate(SDNode *N, bool ForceMove) {
  SDValue Imm = SDValue(N, 0);
  DebugLoc dl = Imm.getDebugLoc();

  if (ConstantSDNode *CSD = dyn_cast<ConstantSDNode>(N)) {
    // Do not need to select target constant.
    if (CSD->getOpcode() == ISD::TargetConstant && !ForceMove)
      return 0;

    // FIXME: We do not need this since we have the bit width operand to hold
    // the bit width of a constant.
    // Build the target constant.
    int64_t Val = CSD->getZExtValue();
    Imm = CurDAG->getTargetConstant(Val, N->getValueType(0));
  } else if (ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(N))
    Imm = CurDAG->getTargetExternalSymbol(ES->getSymbol(), Imm.getValueType(),
                                          Imm.getValueSizeInBits());
  else {
    GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N);
    Imm = CurDAG->getTargetGlobalAddress(GA->getGlobal(), dl,
                                          Imm.getValueType(), GA->getOffset(),
                                          Imm.getValueSizeInBits());
  }

  SDValue Ops[] = { Imm, SDValue()/*The dummy bit width operand*/,
                    CurDAG->getTargetConstant(0, MVT::i64) /*and trace number*/
                  };

  computeOperandsBitWidth(N, Ops, array_lengthof(Ops));

  // Do not create cycle.
  if (ForceMove)
    return CurDAG->getMachineNode(VTM::VOpMove, dl, N->getVTList(),
                                  Ops, array_lengthof(Ops));
  else
    return CurDAG->SelectNodeTo(N, VTM::VOpMove, N->getVTList(),
                                Ops, array_lengthof(Ops));
}
Example #3
0
/// Spill a value incoming to the statepoint. It might be either part of
/// vmstate
/// or gcstate. In both cases unconditionally spill it on the stack unless it
/// is a null constant. Return pair with first element being frame index
/// containing saved value and second element with outgoing chain from the
/// emitted store
static std::pair<SDValue, SDValue>
spillIncomingStatepointValue(SDValue Incoming, SDValue Chain,
                             SelectionDAGBuilder &Builder) {
  SDValue Loc = Builder.StatepointLowering.getLocation(Incoming);

  // Emit new store if we didn't do it for this ptr before
  if (!Loc.getNode()) {
    Loc = Builder.StatepointLowering.allocateStackSlot(Incoming.getValueType(),
                                                       Builder);
    int Index = cast<FrameIndexSDNode>(Loc)->getIndex();
    // We use TargetFrameIndex so that isel will not select it into LEA
    Loc = Builder.DAG.getTargetFrameIndex(Index, Builder.getFrameIndexTy());

    // TODO: We can create TokenFactor node instead of
    //       chaining stores one after another, this may allow
    //       a bit more optimal scheduling for them

#ifndef NDEBUG
    // Right now we always allocate spill slots that are of the same
    // size as the value we're about to spill (the size of spillee can
    // vary since we spill vectors of pointers too).  At some point we
    // can consider allowing spills of smaller values to larger slots
    // (i.e. change the '==' in the assert below to a '>=').
    MachineFrameInfo &MFI = Builder.DAG.getMachineFunction().getFrameInfo();
    assert((MFI.getObjectSize(Index) * 8) == Incoming.getValueSizeInBits() &&
           "Bad spill:  stack slot does not match!");
#endif

    Chain = Builder.DAG.getStore(Chain, Builder.getCurSDLoc(), Incoming, Loc,
                                 MachinePointerInfo::getFixedStack(
                                     Builder.DAG.getMachineFunction(), Index));

    Builder.StatepointLowering.setLocation(Incoming, Loc);
  }

  assert(Loc.getNode());
  return std::make_pair(Loc, Chain);
}
void DAGTypeLegalizer::ExpandRes_BITCAST(SDNode *N, SDValue &Lo, SDValue &Hi) {
    EVT OutVT = N->getValueType(0);
    EVT NOutVT = TLI.getTypeToTransformTo(*DAG.getContext(), OutVT);
    SDValue InOp = N->getOperand(0);
    EVT InVT = InOp.getValueType();
    SDLoc dl(N);

    // Handle some special cases efficiently.
    switch (getTypeAction(InVT)) {
    case TargetLowering::TypeLegal:
    case TargetLowering::TypePromoteInteger:
        break;
    case TargetLowering::TypePromoteFloat:
        llvm_unreachable("Bitcast of a promotion-needing float should never need"
                         "expansion");
    case TargetLowering::TypeSoftenFloat: {
        // Expand the floating point operand only if it was converted to integers.
        // Otherwise, it is a legal type like f128 that can be saved in a register.
        auto SoftenedOp = GetSoftenedFloat(InOp);
        if (SoftenedOp == InOp)
            break;
        SplitInteger(SoftenedOp, Lo, Hi);
        Lo = DAG.getNode(ISD::BITCAST, dl, NOutVT, Lo);
        Hi = DAG.getNode(ISD::BITCAST, dl, NOutVT, Hi);
        return;
    }
    case TargetLowering::TypeExpandInteger:
    case TargetLowering::TypeExpandFloat: {
        auto &DL = DAG.getDataLayout();
        // Convert the expanded pieces of the input.
        GetExpandedOp(InOp, Lo, Hi);
        if (TLI.hasBigEndianPartOrdering(InVT, DL) !=
                TLI.hasBigEndianPartOrdering(OutVT, DL))
            std::swap(Lo, Hi);
        Lo = DAG.getNode(ISD::BITCAST, dl, NOutVT, Lo);
        Hi = DAG.getNode(ISD::BITCAST, dl, NOutVT, Hi);
        return;
    }
    case TargetLowering::TypeSplitVector:
        GetSplitVector(InOp, Lo, Hi);
        if (TLI.hasBigEndianPartOrdering(OutVT, DAG.getDataLayout()))
            std::swap(Lo, Hi);
        Lo = DAG.getNode(ISD::BITCAST, dl, NOutVT, Lo);
        Hi = DAG.getNode(ISD::BITCAST, dl, NOutVT, Hi);
        return;
    case TargetLowering::TypeScalarizeVector:
        // Convert the element instead.
        SplitInteger(BitConvertToInteger(GetScalarizedVector(InOp)), Lo, Hi);
        Lo = DAG.getNode(ISD::BITCAST, dl, NOutVT, Lo);
        Hi = DAG.getNode(ISD::BITCAST, dl, NOutVT, Hi);
        return;
    case TargetLowering::TypeWidenVector: {
        assert(!(InVT.getVectorNumElements() & 1) && "Unsupported BITCAST");
        InOp = GetWidenedVector(InOp);
        EVT LoVT, HiVT;
        std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(InVT);
        std::tie(Lo, Hi) = DAG.SplitVector(InOp, dl, LoVT, HiVT);
        if (TLI.hasBigEndianPartOrdering(OutVT, DAG.getDataLayout()))
            std::swap(Lo, Hi);
        Lo = DAG.getNode(ISD::BITCAST, dl, NOutVT, Lo);
        Hi = DAG.getNode(ISD::BITCAST, dl, NOutVT, Hi);
        return;
    }
    }

    if (InVT.isVector() && OutVT.isInteger()) {
        // Handle cases like i64 = BITCAST v1i64 on x86, where the operand
        // is legal but the result is not.
        unsigned NumElems = 2;
        EVT ElemVT = NOutVT;
        EVT NVT = EVT::getVectorVT(*DAG.getContext(), ElemVT, NumElems);

        // If <ElemVT * N> is not a legal type, try <ElemVT/2 * (N*2)>.
        while (!isTypeLegal(NVT)) {
            unsigned NewSizeInBits = ElemVT.getSizeInBits() / 2;
            // If the element size is smaller than byte, bail.
            if (NewSizeInBits < 8)
                break;
            NumElems *= 2;
            ElemVT = EVT::getIntegerVT(*DAG.getContext(), NewSizeInBits);
            NVT = EVT::getVectorVT(*DAG.getContext(), ElemVT, NumElems);
        }

        if (isTypeLegal(NVT)) {
            SDValue CastInOp = DAG.getNode(ISD::BITCAST, dl, NVT, InOp);

            SmallVector<SDValue, 8> Vals;
            for (unsigned i = 0; i < NumElems; ++i)
                Vals.push_back(DAG.getNode(
                                   ISD::EXTRACT_VECTOR_ELT, dl, ElemVT, CastInOp,
                                   DAG.getConstant(i, dl, TLI.getVectorIdxTy(DAG.getDataLayout()))));

            // Build Lo, Hi pair by pairing extracted elements if needed.
            unsigned Slot = 0;
            for (unsigned e = Vals.size(); e - Slot > 2; Slot += 2, e += 1) {
                // Each iteration will BUILD_PAIR two nodes and append the result until
                // there are only two nodes left, i.e. Lo and Hi.
                SDValue LHS = Vals[Slot];
                SDValue RHS = Vals[Slot + 1];

                if (DAG.getDataLayout().isBigEndian())
                    std::swap(LHS, RHS);

                Vals.push_back(DAG.getNode(
                                   ISD::BUILD_PAIR, dl,
                                   EVT::getIntegerVT(*DAG.getContext(), LHS.getValueSizeInBits() << 1),
                                   LHS, RHS));
            }
            Lo = Vals[Slot++];
            Hi = Vals[Slot++];

            if (DAG.getDataLayout().isBigEndian())
                std::swap(Lo, Hi);

            return;
        }
    }

    // Lower the bit-convert to a store/load from the stack.
    assert(NOutVT.isByteSized() && "Expanded type not byte sized!");

    // Create the stack frame object.  Make sure it is aligned for both
    // the source and expanded destination types.
    unsigned Alignment = DAG.getDataLayout().getPrefTypeAlignment(
                             NOutVT.getTypeForEVT(*DAG.getContext()));
    SDValue StackPtr = DAG.CreateStackTemporary(InVT, Alignment);
    int SPFI = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
    MachinePointerInfo PtrInfo =
        MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), SPFI);

    // Emit a store to the stack slot.
    SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, PtrInfo);

    // Load the first half from the stack slot.
    Lo = DAG.getLoad(NOutVT, dl, Store, StackPtr, PtrInfo);

    // Increment the pointer to the other half.
    unsigned IncrementSize = NOutVT.getSizeInBits() / 8;
    StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr,
                           DAG.getConstant(IncrementSize, dl,
                                           StackPtr.getValueType()));

    // Load the second half from the stack slot.
    Hi = DAG.getLoad(NOutVT, dl, Store, StackPtr,
                     PtrInfo.getWithOffset(IncrementSize),
                     MinAlign(Alignment, IncrementSize));

    // Handle endianness of the load.
    if (TLI.hasBigEndianPartOrdering(OutVT, DAG.getDataLayout()))
        std::swap(Lo, Hi);
}