-void SelectionDAGLowering::visitMemIntrinsic(CallInst &I, unsigned Op) {
- SDOperand Op1 = getValue(I.getOperand(1));
- SDOperand Op2 = getValue(I.getOperand(2));
- SDOperand Op3 = getValue(I.getOperand(3));
- SDOperand Op4 = getValue(I.getOperand(4));
- unsigned Align = (unsigned)cast<ConstantSDNode>(Op4)->getValue();
- if (Align == 0) Align = 1;
-
- // If the source and destination are known to not be aliases, we can
- // lower memmove as memcpy.
- if (Op == ISD::MEMMOVE) {
- uint64_t Size = -1ULL;
- if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op3))
- Size = C->getValue();
- if (AA.alias(I.getOperand(1), Size, I.getOperand(2), Size) ==
- AliasAnalysis::NoAlias)
- Op = ISD::MEMCPY;
- }
-
- if (ConstantSDNode *Size = dyn_cast<ConstantSDNode>(Op3)) {
- std::vector<MVT::ValueType> MemOps;
-
- // Expand memset / memcpy to a series of load / store ops
- // if the size operand falls below a certain threshold.
- SmallVector<SDOperand, 8> OutChains;
- switch (Op) {
- default: break; // Do nothing for now.
- case ISD::MEMSET: {
- if (MeetsMaxMemopRequirement(MemOps, TLI.getMaxStoresPerMemset(),
- Size->getValue(), Align, TLI)) {
- unsigned NumMemOps = MemOps.size();
- unsigned Offset = 0;
- for (unsigned i = 0; i < NumMemOps; i++) {
- MVT::ValueType VT = MemOps[i];
- unsigned VTSize = MVT::getSizeInBits(VT) / 8;
- SDOperand Value = getMemsetValue(Op2, VT, DAG);
- SDOperand Store = DAG.getStore(getRoot(), Value,
- getMemBasePlusOffset(Op1, Offset, DAG, TLI),
- I.getOperand(1), Offset);
- OutChains.push_back(Store);
- Offset += VTSize;
- }
- }
- break;
- }
- case ISD::MEMCPY: {
- if (MeetsMaxMemopRequirement(MemOps, TLI.getMaxStoresPerMemcpy(),
- Size->getValue(), Align, TLI)) {
- unsigned NumMemOps = MemOps.size();
- unsigned SrcOff = 0, DstOff = 0, SrcDelta = 0;
- GlobalAddressSDNode *G = NULL;
- std::string Str;
- bool CopyFromStr = false;
-
- if (Op2.getOpcode() == ISD::GlobalAddress)
- G = cast<GlobalAddressSDNode>(Op2);
- else if (Op2.getOpcode() == ISD::ADD &&
- Op2.getOperand(0).getOpcode() == ISD::GlobalAddress &&
- Op2.getOperand(1).getOpcode() == ISD::Constant) {
- G = cast<GlobalAddressSDNode>(Op2.getOperand(0));
- SrcDelta = cast<ConstantSDNode>(Op2.getOperand(1))->getValue();
- }
- if (G) {
- GlobalVariable *GV = dyn_cast<GlobalVariable>(G->getGlobal());
- if (GV && GV->isConstant()) {
- Str = GV->getStringValue(false);
- if (!Str.empty()) {
- CopyFromStr = true;
- SrcOff += SrcDelta;
- }
- }
- }
-
- for (unsigned i = 0; i < NumMemOps; i++) {
- MVT::ValueType VT = MemOps[i];
- unsigned VTSize = MVT::getSizeInBits(VT) / 8;
- SDOperand Value, Chain, Store;
-
- if (CopyFromStr) {
- Value = getMemsetStringVal(VT, DAG, TLI, Str, SrcOff);
- Chain = getRoot();
- Store =
- DAG.getStore(Chain, Value,
- getMemBasePlusOffset(Op1, DstOff, DAG, TLI),
- I.getOperand(1), DstOff);
- } else {
- Value = DAG.getLoad(VT, getRoot(),
- getMemBasePlusOffset(Op2, SrcOff, DAG, TLI),
- I.getOperand(2), SrcOff, false, Align);
- Chain = Value.getValue(1);
- Store =
- DAG.getStore(Chain, Value,
- getMemBasePlusOffset(Op1, DstOff, DAG, TLI),
- I.getOperand(1), DstOff, false, Align);
- }
- OutChains.push_back(Store);
- SrcOff += VTSize;
- DstOff += VTSize;
- }
- }
- break;
- }
- }
-
- if (!OutChains.empty()) {
- DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other,
- &OutChains[0], OutChains.size()));
- return;
- }
- }
-
- SDOperand AlwaysInline = DAG.getConstant(0, MVT::i1);
- SDOperand Node;
- switch(Op) {
- default:
- assert(0 && "Unknown Op");
- case ISD::MEMCPY:
- Node = DAG.getMemcpy(getRoot(), Op1, Op2, Op3, Op4, AlwaysInline);
- break;
- case ISD::MEMMOVE:
- Node = DAG.getMemmove(getRoot(), Op1, Op2, Op3, Op4, AlwaysInline);
- break;
- case ISD::MEMSET:
- Node = DAG.getMemset(getRoot(), Op1, Op2, Op3, Op4, AlwaysInline);
- break;
- }
- DAG.setRoot(Node);
-}