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