ARMSelectionDAGInfo.cpp revision 208599
163437Ssheldonh//===-- ARMSelectionDAGInfo.cpp - ARM SelectionDAG Info -------------------===//
263437Ssheldonh//
363437Ssheldonh//                     The LLVM Compiler Infrastructure
463437Ssheldonh//
563437Ssheldonh// This file is distributed under the University of Illinois Open Source
663437Ssheldonh// License. See LICENSE.TXT for details.
763437Ssheldonh//
863437Ssheldonh//===----------------------------------------------------------------------===//
963437Ssheldonh//
1063437Ssheldonh// This file implements the ARMSelectionDAGInfo class.
1163437Ssheldonh//
1263437Ssheldonh//===----------------------------------------------------------------------===//
1363437Ssheldonh
1463437Ssheldonh#define DEBUG_TYPE "arm-selectiondag-info"
1563437Ssheldonh#include "ARMTargetMachine.h"
1663437Ssheldonhusing namespace llvm;
1763437Ssheldonh
1863437SsheldonhARMSelectionDAGInfo::ARMSelectionDAGInfo(const TargetMachine &TM)
1963437Ssheldonh  : TargetSelectionDAGInfo(TM),
2063437Ssheldonh    Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
2163437Ssheldonh}
2263437Ssheldonh
2363437SsheldonhARMSelectionDAGInfo::~ARMSelectionDAGInfo() {
2463437Ssheldonh}
2563437Ssheldonh
2663437SsheldonhSDValue
2763437SsheldonhARMSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl,
2863437Ssheldonh                                             SDValue Chain,
2963437Ssheldonh                                             SDValue Dst, SDValue Src,
3063437Ssheldonh                                             SDValue Size, unsigned Align,
3163437Ssheldonh                                             bool isVolatile, bool AlwaysInline,
3263437Ssheldonh                                             const Value *DstSV,
3363437Ssheldonh                                             uint64_t DstSVOff,
3463437Ssheldonh                                             const Value *SrcSV,
3563437Ssheldonh                                             uint64_t SrcSVOff) const {
3663437Ssheldonh  // Do repeated 4-byte loads and stores. To be improved.
3763437Ssheldonh  // This requires 4-byte alignment.
3863437Ssheldonh  if ((Align & 3) != 0)
3963437Ssheldonh    return SDValue();
4063437Ssheldonh  // This requires the copy size to be a constant, preferrably
4163437Ssheldonh  // within a subtarget-specific limit.
4263437Ssheldonh  ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
4363437Ssheldonh  if (!ConstantSize)
4463437Ssheldonh    return SDValue();
4563437Ssheldonh  uint64_t SizeVal = ConstantSize->getZExtValue();
4663437Ssheldonh  if (!AlwaysInline && SizeVal > Subtarget->getMaxInlineSizeThreshold())
4763437Ssheldonh    return SDValue();
4863437Ssheldonh
4963437Ssheldonh  unsigned BytesLeft = SizeVal & 3;
5063437Ssheldonh  unsigned NumMemOps = SizeVal >> 2;
5163437Ssheldonh  unsigned EmittedNumMemOps = 0;
5263437Ssheldonh  EVT VT = MVT::i32;
5363437Ssheldonh  unsigned VTSize = 4;
5463437Ssheldonh  unsigned i = 0;
5563437Ssheldonh  const unsigned MAX_LOADS_IN_LDM = 6;
5663437Ssheldonh  SDValue TFOps[MAX_LOADS_IN_LDM];
5763437Ssheldonh  SDValue Loads[MAX_LOADS_IN_LDM];
5863437Ssheldonh  uint64_t SrcOff = 0, DstOff = 0;
5963437Ssheldonh
6063437Ssheldonh  // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the
6163437Ssheldonh  // same number of stores.  The loads and stores will get combined into
6263437Ssheldonh  // ldm/stm later on.
6363437Ssheldonh  while (EmittedNumMemOps < NumMemOps) {
6463437Ssheldonh    for (i = 0;
6563437Ssheldonh         i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
6663437Ssheldonh      Loads[i] = DAG.getLoad(VT, dl, Chain,
6763437Ssheldonh                             DAG.getNode(ISD::ADD, dl, MVT::i32, Src,
6863437Ssheldonh                                         DAG.getConstant(SrcOff, MVT::i32)),
6963437Ssheldonh                             SrcSV, SrcSVOff + SrcOff, isVolatile, false, 0);
7063437Ssheldonh      TFOps[i] = Loads[i].getValue(1);
7163437Ssheldonh      SrcOff += VTSize;
7263437Ssheldonh    }
7363437Ssheldonh    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);
7463437Ssheldonh
7563437Ssheldonh    for (i = 0;
7663437Ssheldonh         i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
7763437Ssheldonh      TFOps[i] = DAG.getStore(Chain, dl, Loads[i],
7863437Ssheldonh                              DAG.getNode(ISD::ADD, dl, MVT::i32, Dst,
7963437Ssheldonh                                          DAG.getConstant(DstOff, MVT::i32)),
8063437Ssheldonh                              DstSV, DstSVOff + DstOff, isVolatile, false, 0);
8163437Ssheldonh      DstOff += VTSize;
8263437Ssheldonh    }
8363437Ssheldonh    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);
8463437Ssheldonh
8563437Ssheldonh    EmittedNumMemOps += i;
8663437Ssheldonh  }
8763437Ssheldonh
8863437Ssheldonh  if (BytesLeft == 0)
8963437Ssheldonh    return Chain;
9063437Ssheldonh
9163437Ssheldonh  // Issue loads / stores for the trailing (1 - 3) bytes.
9263437Ssheldonh  unsigned BytesLeftSave = BytesLeft;
9363437Ssheldonh  i = 0;
9463437Ssheldonh  while (BytesLeft) {
9563437Ssheldonh    if (BytesLeft >= 2) {
9663437Ssheldonh      VT = MVT::i16;
9763437Ssheldonh      VTSize = 2;
9863437Ssheldonh    } else {
9963437Ssheldonh      VT = MVT::i8;
10063437Ssheldonh      VTSize = 1;
10163437Ssheldonh    }
10263437Ssheldonh
10363437Ssheldonh    Loads[i] = DAG.getLoad(VT, dl, Chain,
10463437Ssheldonh                           DAG.getNode(ISD::ADD, dl, MVT::i32, Src,
10563437Ssheldonh                                       DAG.getConstant(SrcOff, MVT::i32)),
10663437Ssheldonh                           SrcSV, SrcSVOff + SrcOff, false, false, 0);
10763437Ssheldonh    TFOps[i] = Loads[i].getValue(1);
10863437Ssheldonh    ++i;
10963437Ssheldonh    SrcOff += VTSize;
11063437Ssheldonh    BytesLeft -= VTSize;
11163437Ssheldonh  }
11263437Ssheldonh  Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);
11363437Ssheldonh
11463437Ssheldonh  i = 0;
11563437Ssheldonh  BytesLeft = BytesLeftSave;
11663437Ssheldonh  while (BytesLeft) {
11763437Ssheldonh    if (BytesLeft >= 2) {
11863437Ssheldonh      VT = MVT::i16;
11963437Ssheldonh      VTSize = 2;
12063437Ssheldonh    } else {
12163437Ssheldonh      VT = MVT::i8;
12263437Ssheldonh      VTSize = 1;
12363437Ssheldonh    }
12463437Ssheldonh
12563437Ssheldonh    TFOps[i] = DAG.getStore(Chain, dl, Loads[i],
12663437Ssheldonh                            DAG.getNode(ISD::ADD, dl, MVT::i32, Dst,
12763437Ssheldonh                                        DAG.getConstant(DstOff, MVT::i32)),
12863437Ssheldonh                            DstSV, DstSVOff + DstOff, false, false, 0);
12963437Ssheldonh    ++i;
13063437Ssheldonh    DstOff += VTSize;
13163437Ssheldonh    BytesLeft -= VTSize;
13263437Ssheldonh  }
13363437Ssheldonh  return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);
13463437Ssheldonh}
13563437Ssheldonh