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 #include "ARMTargetMachine.h" 15 #include "llvm/CodeGen/SelectionDAG.h" 16 #include "llvm/IR/DerivedTypes.h" 17 using namespace llvm; 18 19 #define DEBUG_TYPE "arm-selectiondag-info" 20 21 ARMSelectionDAGInfo::ARMSelectionDAGInfo(const TargetMachine &TM) 22 : TargetSelectionDAGInfo(TM), 23 Subtarget(&TM.getSubtarget<ARMSubtarget>()) { 24 } 25 26 ARMSelectionDAGInfo::~ARMSelectionDAGInfo() { 27 } 28 29 SDValue 30 ARMSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc dl, 31 SDValue Chain, 32 SDValue Dst, SDValue Src, 33 SDValue Size, unsigned Align, 34 bool isVolatile, bool AlwaysInline, 35 MachinePointerInfo DstPtrInfo, 36 MachinePointerInfo SrcPtrInfo) const { 37 // Do repeated 4-byte loads and stores. To be improved. 38 // This requires 4-byte alignment. 39 if ((Align & 3) != 0) 40 return SDValue(); 41 // This requires the copy size to be a constant, preferably 42 // within a subtarget-specific limit. 43 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size); 44 if (!ConstantSize) 45 return SDValue(); 46 uint64_t SizeVal = ConstantSize->getZExtValue(); 47 if (!AlwaysInline && SizeVal > Subtarget->getMaxInlineSizeThreshold()) 48 return SDValue(); 49 50 unsigned BytesLeft = SizeVal & 3; 51 unsigned NumMemOps = SizeVal >> 2; 52 unsigned EmittedNumMemOps = 0; 53 EVT VT = MVT::i32; 54 unsigned VTSize = 4; 55 unsigned i = 0; 56 const unsigned MAX_LOADS_IN_LDM = 6; 57 SDValue TFOps[MAX_LOADS_IN_LDM]; 58 SDValue Loads[MAX_LOADS_IN_LDM]; 59 uint64_t SrcOff = 0, DstOff = 0; 60 61 // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the 62 // same number of stores. The loads and stores will get combined into 63 // ldm/stm later on. 64 while (EmittedNumMemOps < NumMemOps) { 65 for (i = 0; 66 i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { 67 Loads[i] = DAG.getLoad(VT, dl, Chain, 68 DAG.getNode(ISD::ADD, dl, MVT::i32, Src, 69 DAG.getConstant(SrcOff, MVT::i32)), 70 SrcPtrInfo.getWithOffset(SrcOff), isVolatile, 71 false, false, 0); 72 TFOps[i] = Loads[i].getValue(1); 73 SrcOff += VTSize; 74 } 75 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 76 77 for (i = 0; 78 i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { 79 TFOps[i] = DAG.getStore(Chain, dl, Loads[i], 80 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, 81 DAG.getConstant(DstOff, MVT::i32)), 82 DstPtrInfo.getWithOffset(DstOff), 83 isVolatile, false, 0); 84 DstOff += VTSize; 85 } 86 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 87 88 EmittedNumMemOps += i; 89 } 90 91 if (BytesLeft == 0) 92 return Chain; 93 94 // Issue loads / stores for the trailing (1 - 3) bytes. 95 unsigned BytesLeftSave = BytesLeft; 96 i = 0; 97 while (BytesLeft) { 98 if (BytesLeft >= 2) { 99 VT = MVT::i16; 100 VTSize = 2; 101 } else { 102 VT = MVT::i8; 103 VTSize = 1; 104 } 105 106 Loads[i] = DAG.getLoad(VT, dl, Chain, 107 DAG.getNode(ISD::ADD, dl, MVT::i32, Src, 108 DAG.getConstant(SrcOff, MVT::i32)), 109 SrcPtrInfo.getWithOffset(SrcOff), 110 false, false, false, 0); 111 TFOps[i] = Loads[i].getValue(1); 112 ++i; 113 SrcOff += VTSize; 114 BytesLeft -= VTSize; 115 } 116 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 117 118 i = 0; 119 BytesLeft = BytesLeftSave; 120 while (BytesLeft) { 121 if (BytesLeft >= 2) { 122 VT = MVT::i16; 123 VTSize = 2; 124 } else { 125 VT = MVT::i8; 126 VTSize = 1; 127 } 128 129 TFOps[i] = DAG.getStore(Chain, dl, Loads[i], 130 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, 131 DAG.getConstant(DstOff, MVT::i32)), 132 DstPtrInfo.getWithOffset(DstOff), false, false, 0); 133 ++i; 134 DstOff += VTSize; 135 BytesLeft -= VTSize; 136 } 137 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 138 } 139 140 // Adjust parameters for memset, EABI uses format (ptr, size, value), 141 // GNU library uses (ptr, value, size) 142 // See RTABI section 4.3.4 143 SDValue ARMSelectionDAGInfo:: 144 EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc dl, 145 SDValue Chain, SDValue Dst, 146 SDValue Src, SDValue Size, 147 unsigned Align, bool isVolatile, 148 MachinePointerInfo DstPtrInfo) const { 149 // Use default for non-AAPCS (or MachO) subtargets 150 if (!Subtarget->isAAPCS_ABI() || Subtarget->isTargetMachO()) 151 return SDValue(); 152 153 const ARMTargetLowering &TLI = 154 *static_cast<const ARMTargetLowering*>(DAG.getTarget().getTargetLowering()); 155 TargetLowering::ArgListTy Args; 156 TargetLowering::ArgListEntry Entry; 157 158 // First argument: data pointer 159 Type *IntPtrTy = TLI.getDataLayout()->getIntPtrType(*DAG.getContext()); 160 Entry.Node = Dst; 161 Entry.Ty = IntPtrTy; 162 Args.push_back(Entry); 163 164 // Second argument: buffer size 165 Entry.Node = Size; 166 Entry.Ty = IntPtrTy; 167 Entry.isSExt = false; 168 Args.push_back(Entry); 169 170 // Extend or truncate the argument to be an i32 value for the call. 171 if (Src.getValueType().bitsGT(MVT::i32)) 172 Src = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src); 173 else 174 Src = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src); 175 176 // Third argument: value to fill 177 Entry.Node = Src; 178 Entry.Ty = Type::getInt32Ty(*DAG.getContext()); 179 Entry.isSExt = true; 180 Args.push_back(Entry); 181 182 // Emit __eabi_memset call 183 TargetLowering::CallLoweringInfo CLI(Chain, 184 Type::getVoidTy(*DAG.getContext()), // return type 185 false, // return sign ext 186 false, // return zero ext 187 false, // is var arg 188 false, // is in regs 189 0, // number of fixed arguments 190 TLI.getLibcallCallingConv(RTLIB::MEMSET), // call conv 191 false, // is tail call 192 false, // does not return 193 false, // is return val used 194 DAG.getExternalSymbol(TLI.getLibcallName(RTLIB::MEMSET), 195 TLI.getPointerTy()), // callee 196 Args, DAG, dl); 197 std::pair<SDValue,SDValue> CallResult = 198 TLI.LowerCallTo(CLI); 199 200 return CallResult.second; 201 } 202