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/CodeGen/SelectionDAG.h" 17#include "llvm/IR/DerivedTypes.h" 18using namespace llvm; 19 20ARMSelectionDAGInfo::ARMSelectionDAGInfo(const TargetMachine &TM) 21 : TargetSelectionDAGInfo(TM), 22 Subtarget(&TM.getSubtarget<ARMSubtarget>()) { 23} 24 25ARMSelectionDAGInfo::~ARMSelectionDAGInfo() { 26} 27 28SDValue 29ARMSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc 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, 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), 109 false, false, false, 0); 110 TFOps[i] = Loads[i].getValue(1); 111 ++i; 112 SrcOff += VTSize; 113 BytesLeft -= VTSize; 114 } 115 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 116 117 i = 0; 118 BytesLeft = BytesLeftSave; 119 while (BytesLeft) { 120 if (BytesLeft >= 2) { 121 VT = MVT::i16; 122 VTSize = 2; 123 } else { 124 VT = MVT::i8; 125 VTSize = 1; 126 } 127 128 TFOps[i] = DAG.getStore(Chain, dl, Loads[i], 129 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, 130 DAG.getConstant(DstOff, MVT::i32)), 131 DstPtrInfo.getWithOffset(DstOff), false, false, 0); 132 ++i; 133 DstOff += VTSize; 134 BytesLeft -= VTSize; 135 } 136 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); 137} 138 139// Adjust parameters for memset, EABI uses format (ptr, size, value), 140// GNU library uses (ptr, value, size) 141// See RTABI section 4.3.4 142SDValue ARMSelectionDAGInfo:: 143EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc dl, 144 SDValue Chain, SDValue Dst, 145 SDValue Src, SDValue Size, 146 unsigned Align, bool isVolatile, 147 MachinePointerInfo DstPtrInfo) const { 148 // Use default for non AAPCS (or Darwin) subtargets 149 if (!Subtarget->isAAPCS_ABI() || Subtarget->isTargetDarwin()) 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.getDataLayout()->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 TargetLowering::CallLoweringInfo CLI(Chain, 183 Type::getVoidTy(*DAG.getContext()), // return type 184 false, // return sign ext 185 false, // return zero ext 186 false, // is var arg 187 false, // is in regs 188 0, // number of fixed arguments 189 TLI.getLibcallCallingConv(RTLIB::MEMSET), // call conv 190 false, // is tail call 191 false, // does not return 192 false, // is return val used 193 DAG.getExternalSymbol(TLI.getLibcallName(RTLIB::MEMSET), 194 TLI.getPointerTy()), // callee 195 Args, DAG, dl); 196 std::pair<SDValue,SDValue> CallResult = 197 TLI.LowerCallTo(CLI); 198 199 return CallResult.second; 200} 201