ARMSelectionDAGInfo.cpp revision cd81d94322a39503e4a3e87b6ee03d4fcb3465fb
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 DataLayout &DL) 22 : TargetSelectionDAGInfo(&DL) {} 23 24ARMSelectionDAGInfo::~ARMSelectionDAGInfo() { 25} 26 27SDValue 28ARMSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc dl, 29 SDValue Chain, 30 SDValue Dst, SDValue Src, 31 SDValue Size, unsigned Align, 32 bool isVolatile, bool AlwaysInline, 33 MachinePointerInfo DstPtrInfo, 34 MachinePointerInfo SrcPtrInfo) const { 35 const ARMSubtarget &Subtarget = DAG.getTarget().getSubtarget<ARMSubtarget>(); 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 // Emit a maximum of 4 loads in Thumb1 since we have fewer registers 56 const unsigned MAX_LOADS_IN_LDM = Subtarget.isThumb1Only() ? 4 : 6; 57 SDValue TFOps[6]; 58 SDValue Loads[6]; 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, 76 makeArrayRef(TFOps, i)); 77 78 for (i = 0; 79 i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { 80 TFOps[i] = DAG.getStore(Chain, dl, Loads[i], 81 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, 82 DAG.getConstant(DstOff, MVT::i32)), 83 DstPtrInfo.getWithOffset(DstOff), 84 isVolatile, false, 0); 85 DstOff += VTSize; 86 } 87 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 88 makeArrayRef(TFOps, i)); 89 90 EmittedNumMemOps += i; 91 } 92 93 if (BytesLeft == 0) 94 return Chain; 95 96 // Issue loads / stores for the trailing (1 - 3) bytes. 97 unsigned BytesLeftSave = BytesLeft; 98 i = 0; 99 while (BytesLeft) { 100 if (BytesLeft >= 2) { 101 VT = MVT::i16; 102 VTSize = 2; 103 } else { 104 VT = MVT::i8; 105 VTSize = 1; 106 } 107 108 Loads[i] = DAG.getLoad(VT, dl, Chain, 109 DAG.getNode(ISD::ADD, dl, MVT::i32, Src, 110 DAG.getConstant(SrcOff, MVT::i32)), 111 SrcPtrInfo.getWithOffset(SrcOff), 112 false, false, false, 0); 113 TFOps[i] = Loads[i].getValue(1); 114 ++i; 115 SrcOff += VTSize; 116 BytesLeft -= VTSize; 117 } 118 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 119 makeArrayRef(TFOps, i)); 120 121 i = 0; 122 BytesLeft = BytesLeftSave; 123 while (BytesLeft) { 124 if (BytesLeft >= 2) { 125 VT = MVT::i16; 126 VTSize = 2; 127 } else { 128 VT = MVT::i8; 129 VTSize = 1; 130 } 131 132 TFOps[i] = DAG.getStore(Chain, dl, Loads[i], 133 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, 134 DAG.getConstant(DstOff, MVT::i32)), 135 DstPtrInfo.getWithOffset(DstOff), false, false, 0); 136 ++i; 137 DstOff += VTSize; 138 BytesLeft -= VTSize; 139 } 140 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 141 makeArrayRef(TFOps, i)); 142} 143 144// Adjust parameters for memset, EABI uses format (ptr, size, value), 145// GNU library uses (ptr, value, size) 146// See RTABI section 4.3.4 147SDValue ARMSelectionDAGInfo:: 148EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc dl, 149 SDValue Chain, SDValue Dst, 150 SDValue Src, SDValue Size, 151 unsigned Align, bool isVolatile, 152 MachinePointerInfo DstPtrInfo) const { 153 const ARMSubtarget &Subtarget = DAG.getTarget().getSubtarget<ARMSubtarget>(); 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()), std::move(Args), 0) 195 .setDiscardResult(); 196 197 std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(CLI); 198 return CallResult.second; 199} 200