ARMSelectionDAGInfo.cpp revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
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" 17using namespace llvm; 18 19#define DEBUG_TYPE "arm-selectiondag-info" 20 21ARMSelectionDAGInfo::ARMSelectionDAGInfo(const TargetMachine &TM) 22 : TargetSelectionDAGInfo(TM), 23 Subtarget(&TM.getSubtarget<ARMSubtarget>()) { 24} 25 26ARMSelectionDAGInfo::~ARMSelectionDAGInfo() { 27} 28 29SDValue 30ARMSelectionDAGInfo::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 // Emit a maximum of 4 loads in Thumb1 since we have fewer registers 57 const unsigned MAX_LOADS_IN_LDM = Subtarget->isThumb1Only() ? 4 : 6; 58 SDValue TFOps[6]; 59 SDValue Loads[6]; 60 uint64_t SrcOff = 0, DstOff = 0; 61 62 // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the 63 // same number of stores. The loads and stores will get combined into 64 // ldm/stm later on. 65 while (EmittedNumMemOps < NumMemOps) { 66 for (i = 0; 67 i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { 68 Loads[i] = DAG.getLoad(VT, dl, Chain, 69 DAG.getNode(ISD::ADD, dl, MVT::i32, Src, 70 DAG.getConstant(SrcOff, MVT::i32)), 71 SrcPtrInfo.getWithOffset(SrcOff), isVolatile, 72 false, false, 0); 73 TFOps[i] = Loads[i].getValue(1); 74 SrcOff += VTSize; 75 } 76 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 77 makeArrayRef(TFOps, i)); 78 79 for (i = 0; 80 i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { 81 TFOps[i] = DAG.getStore(Chain, dl, Loads[i], 82 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, 83 DAG.getConstant(DstOff, MVT::i32)), 84 DstPtrInfo.getWithOffset(DstOff), 85 isVolatile, false, 0); 86 DstOff += VTSize; 87 } 88 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 89 makeArrayRef(TFOps, i)); 90 91 EmittedNumMemOps += i; 92 } 93 94 if (BytesLeft == 0) 95 return Chain; 96 97 // Issue loads / stores for the trailing (1 - 3) bytes. 98 unsigned BytesLeftSave = BytesLeft; 99 i = 0; 100 while (BytesLeft) { 101 if (BytesLeft >= 2) { 102 VT = MVT::i16; 103 VTSize = 2; 104 } else { 105 VT = MVT::i8; 106 VTSize = 1; 107 } 108 109 Loads[i] = DAG.getLoad(VT, dl, Chain, 110 DAG.getNode(ISD::ADD, dl, MVT::i32, Src, 111 DAG.getConstant(SrcOff, MVT::i32)), 112 SrcPtrInfo.getWithOffset(SrcOff), 113 false, false, false, 0); 114 TFOps[i] = Loads[i].getValue(1); 115 ++i; 116 SrcOff += VTSize; 117 BytesLeft -= VTSize; 118 } 119 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 120 makeArrayRef(TFOps, i)); 121 122 i = 0; 123 BytesLeft = BytesLeftSave; 124 while (BytesLeft) { 125 if (BytesLeft >= 2) { 126 VT = MVT::i16; 127 VTSize = 2; 128 } else { 129 VT = MVT::i8; 130 VTSize = 1; 131 } 132 133 TFOps[i] = DAG.getStore(Chain, dl, Loads[i], 134 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, 135 DAG.getConstant(DstOff, MVT::i32)), 136 DstPtrInfo.getWithOffset(DstOff), false, false, 0); 137 ++i; 138 DstOff += VTSize; 139 BytesLeft -= VTSize; 140 } 141 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 142 makeArrayRef(TFOps, i)); 143} 144 145// Adjust parameters for memset, EABI uses format (ptr, size, value), 146// GNU library uses (ptr, value, size) 147// See RTABI section 4.3.4 148SDValue ARMSelectionDAGInfo:: 149EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc dl, 150 SDValue Chain, SDValue Dst, 151 SDValue Src, SDValue Size, 152 unsigned Align, bool isVolatile, 153 MachinePointerInfo DstPtrInfo) const { 154 // Use default for non-AAPCS (or MachO) subtargets 155 if (!Subtarget->isAAPCS_ABI() || Subtarget->isTargetMachO() || 156 Subtarget->isTargetWindows()) 157 return SDValue(); 158 159 const ARMTargetLowering &TLI = 160 *static_cast<const ARMTargetLowering*>(DAG.getTarget().getTargetLowering()); 161 TargetLowering::ArgListTy Args; 162 TargetLowering::ArgListEntry Entry; 163 164 // First argument: data pointer 165 Type *IntPtrTy = TLI.getDataLayout()->getIntPtrType(*DAG.getContext()); 166 Entry.Node = Dst; 167 Entry.Ty = IntPtrTy; 168 Args.push_back(Entry); 169 170 // Second argument: buffer size 171 Entry.Node = Size; 172 Entry.Ty = IntPtrTy; 173 Entry.isSExt = false; 174 Args.push_back(Entry); 175 176 // Extend or truncate the argument to be an i32 value for the call. 177 if (Src.getValueType().bitsGT(MVT::i32)) 178 Src = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src); 179 else 180 Src = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src); 181 182 // Third argument: value to fill 183 Entry.Node = Src; 184 Entry.Ty = Type::getInt32Ty(*DAG.getContext()); 185 Entry.isSExt = true; 186 Args.push_back(Entry); 187 188 // Emit __eabi_memset call 189 TargetLowering::CallLoweringInfo CLI(DAG); 190 CLI.setDebugLoc(dl).setChain(Chain) 191 .setCallee(TLI.getLibcallCallingConv(RTLIB::MEMSET), 192 Type::getVoidTy(*DAG.getContext()), 193 DAG.getExternalSymbol(TLI.getLibcallName(RTLIB::MEMSET), 194 TLI.getPointerTy()), &Args, 0) 195 .setDiscardResult(); 196 197 std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(CLI); 198 return CallResult.second; 199} 200