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(); }
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)); }
/// 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); }