LLVM API Documentation
00001 //===-- ARMSelectionDAGInfo.cpp - ARM SelectionDAG Info -------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the ARMSelectionDAGInfo class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "ARMTargetMachine.h" 00015 #include "llvm/CodeGen/SelectionDAG.h" 00016 #include "llvm/IR/DerivedTypes.h" 00017 using namespace llvm; 00018 00019 #define DEBUG_TYPE "arm-selectiondag-info" 00020 00021 ARMSelectionDAGInfo::ARMSelectionDAGInfo(const DataLayout &DL) 00022 : TargetSelectionDAGInfo(&DL) {} 00023 00024 ARMSelectionDAGInfo::~ARMSelectionDAGInfo() { 00025 } 00026 00027 SDValue 00028 ARMSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc dl, 00029 SDValue Chain, 00030 SDValue Dst, SDValue Src, 00031 SDValue Size, unsigned Align, 00032 bool isVolatile, bool AlwaysInline, 00033 MachinePointerInfo DstPtrInfo, 00034 MachinePointerInfo SrcPtrInfo) const { 00035 const ARMSubtarget &Subtarget = DAG.getTarget().getSubtarget<ARMSubtarget>(); 00036 // Do repeated 4-byte loads and stores. To be improved. 00037 // This requires 4-byte alignment. 00038 if ((Align & 3) != 0) 00039 return SDValue(); 00040 // This requires the copy size to be a constant, preferably 00041 // within a subtarget-specific limit. 00042 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size); 00043 if (!ConstantSize) 00044 return SDValue(); 00045 uint64_t SizeVal = ConstantSize->getZExtValue(); 00046 if (!AlwaysInline && SizeVal > Subtarget.getMaxInlineSizeThreshold()) 00047 return SDValue(); 00048 00049 unsigned BytesLeft = SizeVal & 3; 00050 unsigned NumMemOps = SizeVal >> 2; 00051 unsigned EmittedNumMemOps = 0; 00052 EVT VT = MVT::i32; 00053 unsigned VTSize = 4; 00054 unsigned i = 0; 00055 // Emit a maximum of 4 loads in Thumb1 since we have fewer registers 00056 const unsigned MAX_LOADS_IN_LDM = Subtarget.isThumb1Only() ? 4 : 6; 00057 SDValue TFOps[6]; 00058 SDValue Loads[6]; 00059 uint64_t SrcOff = 0, DstOff = 0; 00060 00061 // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the 00062 // same number of stores. The loads and stores will get combined into 00063 // ldm/stm later on. 00064 while (EmittedNumMemOps < NumMemOps) { 00065 for (i = 0; 00066 i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { 00067 Loads[i] = DAG.getLoad(VT, dl, Chain, 00068 DAG.getNode(ISD::ADD, dl, MVT::i32, Src, 00069 DAG.getConstant(SrcOff, MVT::i32)), 00070 SrcPtrInfo.getWithOffset(SrcOff), isVolatile, 00071 false, false, 0); 00072 TFOps[i] = Loads[i].getValue(1); 00073 SrcOff += VTSize; 00074 } 00075 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 00076 makeArrayRef(TFOps, i)); 00077 00078 for (i = 0; 00079 i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { 00080 TFOps[i] = DAG.getStore(Chain, dl, Loads[i], 00081 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, 00082 DAG.getConstant(DstOff, MVT::i32)), 00083 DstPtrInfo.getWithOffset(DstOff), 00084 isVolatile, false, 0); 00085 DstOff += VTSize; 00086 } 00087 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 00088 makeArrayRef(TFOps, i)); 00089 00090 EmittedNumMemOps += i; 00091 } 00092 00093 if (BytesLeft == 0) 00094 return Chain; 00095 00096 // Issue loads / stores for the trailing (1 - 3) bytes. 00097 unsigned BytesLeftSave = BytesLeft; 00098 i = 0; 00099 while (BytesLeft) { 00100 if (BytesLeft >= 2) { 00101 VT = MVT::i16; 00102 VTSize = 2; 00103 } else { 00104 VT = MVT::i8; 00105 VTSize = 1; 00106 } 00107 00108 Loads[i] = DAG.getLoad(VT, dl, Chain, 00109 DAG.getNode(ISD::ADD, dl, MVT::i32, Src, 00110 DAG.getConstant(SrcOff, MVT::i32)), 00111 SrcPtrInfo.getWithOffset(SrcOff), 00112 false, false, false, 0); 00113 TFOps[i] = Loads[i].getValue(1); 00114 ++i; 00115 SrcOff += VTSize; 00116 BytesLeft -= VTSize; 00117 } 00118 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 00119 makeArrayRef(TFOps, i)); 00120 00121 i = 0; 00122 BytesLeft = BytesLeftSave; 00123 while (BytesLeft) { 00124 if (BytesLeft >= 2) { 00125 VT = MVT::i16; 00126 VTSize = 2; 00127 } else { 00128 VT = MVT::i8; 00129 VTSize = 1; 00130 } 00131 00132 TFOps[i] = DAG.getStore(Chain, dl, Loads[i], 00133 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, 00134 DAG.getConstant(DstOff, MVT::i32)), 00135 DstPtrInfo.getWithOffset(DstOff), false, false, 0); 00136 ++i; 00137 DstOff += VTSize; 00138 BytesLeft -= VTSize; 00139 } 00140 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 00141 makeArrayRef(TFOps, i)); 00142 } 00143 00144 // Adjust parameters for memset, EABI uses format (ptr, size, value), 00145 // GNU library uses (ptr, value, size) 00146 // See RTABI section 4.3.4 00147 SDValue ARMSelectionDAGInfo:: 00148 EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc dl, 00149 SDValue Chain, SDValue Dst, 00150 SDValue Src, SDValue Size, 00151 unsigned Align, bool isVolatile, 00152 MachinePointerInfo DstPtrInfo) const { 00153 const ARMSubtarget &Subtarget = DAG.getTarget().getSubtarget<ARMSubtarget>(); 00154 // Use default for non-AAPCS (or MachO) subtargets 00155 if (!Subtarget.isAAPCS_ABI() || Subtarget.isTargetMachO() || 00156 Subtarget.isTargetWindows()) 00157 return SDValue(); 00158 00159 const ARMTargetLowering &TLI = 00160 *DAG.getTarget().getSubtarget<ARMSubtarget>().getTargetLowering(); 00161 TargetLowering::ArgListTy Args; 00162 TargetLowering::ArgListEntry Entry; 00163 00164 // First argument: data pointer 00165 Type *IntPtrTy = TLI.getDataLayout()->getIntPtrType(*DAG.getContext()); 00166 Entry.Node = Dst; 00167 Entry.Ty = IntPtrTy; 00168 Args.push_back(Entry); 00169 00170 // Second argument: buffer size 00171 Entry.Node = Size; 00172 Entry.Ty = IntPtrTy; 00173 Entry.isSExt = false; 00174 Args.push_back(Entry); 00175 00176 // Extend or truncate the argument to be an i32 value for the call. 00177 if (Src.getValueType().bitsGT(MVT::i32)) 00178 Src = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src); 00179 else 00180 Src = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src); 00181 00182 // Third argument: value to fill 00183 Entry.Node = Src; 00184 Entry.Ty = Type::getInt32Ty(*DAG.getContext()); 00185 Entry.isSExt = true; 00186 Args.push_back(Entry); 00187 00188 // Emit __eabi_memset call 00189 TargetLowering::CallLoweringInfo CLI(DAG); 00190 CLI.setDebugLoc(dl).setChain(Chain) 00191 .setCallee(TLI.getLibcallCallingConv(RTLIB::MEMSET), 00192 Type::getVoidTy(*DAG.getContext()), 00193 DAG.getExternalSymbol(TLI.getLibcallName(RTLIB::MEMSET), 00194 TLI.getPointerTy()), std::move(Args), 0) 00195 .setDiscardResult(); 00196 00197 std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(CLI); 00198 return CallResult.second; 00199 }