1 //===-- ARMSelectionDAGInfo.cpp - ARM SelectionDAG Info -------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the ARMSelectionDAGInfo class.
12 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "arm-selectiondag-info"
15 #include "ARMTargetMachine.h"
18 ARMSelectionDAGInfo::ARMSelectionDAGInfo(const TargetMachine &TM)
19 : TargetSelectionDAGInfo(TM),
20 Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
23 ARMSelectionDAGInfo::~ARMSelectionDAGInfo() {
27 ARMSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl,
29 SDValue Dst, SDValue Src,
30 SDValue Size, unsigned Align,
31 bool isVolatile, bool AlwaysInline,
35 uint64_t SrcSVOff) const {
36 // Do repeated 4-byte loads and stores. To be improved.
37 // This requires 4-byte alignment.
40 // This requires the copy size to be a constant, preferrably
41 // within a subtarget-specific limit.
42 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
45 uint64_t SizeVal = ConstantSize->getZExtValue();
46 if (!AlwaysInline && SizeVal > Subtarget->getMaxInlineSizeThreshold())
49 unsigned BytesLeft = SizeVal & 3;
50 unsigned NumMemOps = SizeVal >> 2;
51 unsigned EmittedNumMemOps = 0;
55 const unsigned MAX_LOADS_IN_LDM = 6;
56 SDValue TFOps[MAX_LOADS_IN_LDM];
57 SDValue Loads[MAX_LOADS_IN_LDM];
58 uint64_t SrcOff = 0, DstOff = 0;
60 // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the
61 // same number of stores. The loads and stores will get combined into
63 while (EmittedNumMemOps < NumMemOps) {
65 i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
66 Loads[i] = DAG.getLoad(VT, dl, Chain,
67 DAG.getNode(ISD::ADD, dl, MVT::i32, Src,
68 DAG.getConstant(SrcOff, MVT::i32)),
69 SrcSV, SrcSVOff + SrcOff, isVolatile, false, 0);
70 TFOps[i] = Loads[i].getValue(1);
73 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);
76 i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
77 TFOps[i] = DAG.getStore(Chain, dl, Loads[i],
78 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst,
79 DAG.getConstant(DstOff, MVT::i32)),
80 DstSV, DstSVOff + DstOff, isVolatile, false, 0);
83 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);
85 EmittedNumMemOps += i;
91 // Issue loads / stores for the trailing (1 - 3) bytes.
92 unsigned BytesLeftSave = BytesLeft;
103 Loads[i] = DAG.getLoad(VT, dl, Chain,
104 DAG.getNode(ISD::ADD, dl, MVT::i32, Src,
105 DAG.getConstant(SrcOff, MVT::i32)),
106 SrcSV, SrcSVOff + SrcOff, false, false, 0);
107 TFOps[i] = Loads[i].getValue(1);
112 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);
115 BytesLeft = BytesLeftSave;
117 if (BytesLeft >= 2) {
125 TFOps[i] = DAG.getStore(Chain, dl, Loads[i],
126 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst,
127 DAG.getConstant(DstOff, MVT::i32)),
128 DstSV, DstSVOff + DstOff, false, false, 0);
133 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);