1 //===-- ARMSelectionDAGInfo.cpp - ARM SelectionDAG Info -------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the ARMSelectionDAGInfo class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #define DEBUG_TYPE "arm-selectiondag-info" 15 #include "ARMTargetMachine.h" 16 using namespace llvm; 17 18 ARMSelectionDAGInfo::ARMSelectionDAGInfo(const TargetMachine &TM) 19 : TargetSelectionDAGInfo(TM), 20 Subtarget(&TM.getSubtarget<ARMSubtarget>()) { 21 } 22 23 ARMSelectionDAGInfo::~ARMSelectionDAGInfo() { 24 } 25 26 SDValue 27 ARMSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, 28 SDValue Chain, 29 SDValue Dst, SDValue Src, 30 SDValue Size, unsigned Align, 31 bool isVolatile, bool AlwaysInline, 32 MachinePointerInfo DstPtrInfo, 33 MachinePointerInfo SrcPtrInfo) const { 34 // Do repeated 4-byte loads and stores. To be improved. 35 // This requires 4-byte alignment. 36 if ((Align & 3) != 0) 37 return SDValue(); 38 // This requires the copy size to be a constant, preferably 39 // within a subtarget-specific limit. 40 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size); 41 if (!ConstantSize) 42 return SDValue(); 43 uint64_t SizeVal = ConstantSize->getZExtValue(); 44 if (!AlwaysInline && SizeVal > Subtarget->getMaxInlineSizeThreshold()) 45 return SDValue(); 46 47 unsigned BytesLeft = SizeVal & 3; 48 unsigned NumMemOps = SizeVal >> 2; 49 unsigned EmittedNumMemOps = 0; 50 EVT VT = MVT::i32; 51 unsigned VTSize = 4; 52 unsigned i = 0; 53 const unsigned MAX_LOADS_IN_LDM = 6; 54 SDValue TFOps[MAX_LOADS_IN_LDM]; 55 SDValue Loads[MAX_LOADS_IN_LDM]; 56 uint64_t SrcOff = 0, DstOff = 0; 57 58 // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the 59 // same number of stores. The loads and stores will get combined into 60 // ldm/stm later on. 61 while (EmittedNumMemOps < NumMemOps) { 62 for (i = 0; 63 i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { 64 Loads[i] = DAG.getLoad(VT, dl, Chain, 65 DAG.getNode(ISD::ADD, dl, MVT::i32, Src, 66 DAG.getConstant(SrcOff, MVT::i32)), 67 SrcPtrInfo.getWithOffset(SrcOff), isVolatile, 68 false, 0); 69 TFOps[i] = Loads[i].getValue(1); 70 SrcOff += VTSize; 71 } 72 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 73 74 for (i = 0; 75 i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { 76 TFOps[i] = DAG.getStore(Chain, dl, Loads[i], 77 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, 78 DAG.getConstant(DstOff, MVT::i32)), 79 DstPtrInfo.getWithOffset(DstOff), 80 isVolatile, false, 0); 81 DstOff += VTSize; 82 } 83 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 84 85 EmittedNumMemOps += i; 86 } 87 88 if (BytesLeft == 0) 89 return Chain; 90 91 // Issue loads / stores for the trailing (1 - 3) bytes. 92 unsigned BytesLeftSave = BytesLeft; 93 i = 0; 94 while (BytesLeft) { 95 if (BytesLeft >= 2) { 96 VT = MVT::i16; 97 VTSize = 2; 98 } else { 99 VT = MVT::i8; 100 VTSize = 1; 101 } 102 103 Loads[i] = DAG.getLoad(VT, dl, Chain, 104 DAG.getNode(ISD::ADD, dl, MVT::i32, Src, 105 DAG.getConstant(SrcOff, MVT::i32)), 106 SrcPtrInfo.getWithOffset(SrcOff), false, false, 0); 107 TFOps[i] = Loads[i].getValue(1); 108 ++i; 109 SrcOff += VTSize; 110 BytesLeft -= VTSize; 111 } 112 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 113 114 i = 0; 115 BytesLeft = BytesLeftSave; 116 while (BytesLeft) { 117 if (BytesLeft >= 2) { 118 VT = MVT::i16; 119 VTSize = 2; 120 } else { 121 VT = MVT::i8; 122 VTSize = 1; 123 } 124 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 DstPtrInfo.getWithOffset(DstOff), false, false, 0); 129 ++i; 130 DstOff += VTSize; 131 BytesLeft -= VTSize; 132 } 133 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 134 } 135