1 //===-- X86SelectionDAGInfo.cpp - X86 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 X86SelectionDAGInfo class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #define DEBUG_TYPE "x86-selectiondag-info" 15 #include "X86TargetMachine.h" 16 #include "llvm/DerivedTypes.h" 17 #include "llvm/CodeGen/SelectionDAG.h" 18 using namespace llvm; 19 20 X86SelectionDAGInfo::X86SelectionDAGInfo(const X86TargetMachine &TM) : 21 TargetSelectionDAGInfo(TM), 22 Subtarget(&TM.getSubtarget<X86Subtarget>()), 23 TLI(*TM.getTargetLowering()) { 24 } 25 26 X86SelectionDAGInfo::~X86SelectionDAGInfo() { 27 } 28 29 SDValue 30 X86SelectionDAGInfo::EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl, 31 SDValue Chain, 32 SDValue Dst, SDValue Src, 33 SDValue Size, unsigned Align, 34 bool isVolatile, 35 MachinePointerInfo DstPtrInfo) const { 36 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size); 37 38 // If to a segment-relative address space, use the default lowering. 39 if (DstPtrInfo.getAddrSpace() >= 256) 40 return SDValue(); 41 42 // If not DWORD aligned or size is more than the threshold, call the library. 43 // The libc version is likely to be faster for these cases. It can use the 44 // address value and run time information about the CPU. 45 if ((Align & 3) != 0 || 46 !ConstantSize || 47 ConstantSize->getZExtValue() > 48 Subtarget->getMaxInlineSizeThreshold()) { 49 SDValue InFlag(0, 0); 50 51 // Check to see if there is a specialized entry-point for memory zeroing. 52 ConstantSDNode *V = dyn_cast<ConstantSDNode>(Src); 53 54 if (const char *bzeroEntry = V && 55 V->isNullValue() ? Subtarget->getBZeroEntry() : 0) { 56 EVT IntPtr = TLI.getPointerTy(); 57 Type *IntPtrTy = getTargetData()->getIntPtrType(*DAG.getContext()); 58 TargetLowering::ArgListTy Args; 59 TargetLowering::ArgListEntry Entry; 60 Entry.Node = Dst; 61 Entry.Ty = IntPtrTy; 62 Args.push_back(Entry); 63 Entry.Node = Size; 64 Args.push_back(Entry); 65 TargetLowering:: 66 CallLoweringInfo CLI(Chain, Type::getVoidTy(*DAG.getContext()), 67 false, false, false, false, 68 0, CallingConv::C, /*isTailCall=*/false, 69 /*doesNotRet=*/false, /*isReturnValueUsed=*/false, 70 DAG.getExternalSymbol(bzeroEntry, IntPtr), Args, 71 DAG, dl); 72 std::pair<SDValue,SDValue> CallResult = 73 TLI.LowerCallTo(CLI); 74 return CallResult.second; 75 } 76 77 // Otherwise have the target-independent code call memset. 78 return SDValue(); 79 } 80 81 uint64_t SizeVal = ConstantSize->getZExtValue(); 82 SDValue InFlag(0, 0); 83 EVT AVT; 84 SDValue Count; 85 ConstantSDNode *ValC = dyn_cast<ConstantSDNode>(Src); 86 unsigned BytesLeft = 0; 87 bool TwoRepStos = false; 88 if (ValC) { 89 unsigned ValReg; 90 uint64_t Val = ValC->getZExtValue() & 255; 91 92 // If the value is a constant, then we can potentially use larger sets. 93 switch (Align & 3) { 94 case 2: // WORD aligned 95 AVT = MVT::i16; 96 ValReg = X86::AX; 97 Val = (Val << 8) | Val; 98 break; 99 case 0: // DWORD aligned 100 AVT = MVT::i32; 101 ValReg = X86::EAX; 102 Val = (Val << 8) | Val; 103 Val = (Val << 16) | Val; 104 if (Subtarget->is64Bit() && ((Align & 0x7) == 0)) { // QWORD aligned 105 AVT = MVT::i64; 106 ValReg = X86::RAX; 107 Val = (Val << 32) | Val; 108 } 109 break; 110 default: // Byte aligned 111 AVT = MVT::i8; 112 ValReg = X86::AL; 113 Count = DAG.getIntPtrConstant(SizeVal); 114 break; 115 } 116 117 if (AVT.bitsGT(MVT::i8)) { 118 unsigned UBytes = AVT.getSizeInBits() / 8; 119 Count = DAG.getIntPtrConstant(SizeVal / UBytes); 120 BytesLeft = SizeVal % UBytes; 121 } 122 123 Chain = DAG.getCopyToReg(Chain, dl, ValReg, DAG.getConstant(Val, AVT), 124 InFlag); 125 InFlag = Chain.getValue(1); 126 } else { 127 AVT = MVT::i8; 128 Count = DAG.getIntPtrConstant(SizeVal); 129 Chain = DAG.getCopyToReg(Chain, dl, X86::AL, Src, InFlag); 130 InFlag = Chain.getValue(1); 131 } 132 133 Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RCX : 134 X86::ECX, 135 Count, InFlag); 136 InFlag = Chain.getValue(1); 137 Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RDI : 138 X86::EDI, 139 Dst, InFlag); 140 InFlag = Chain.getValue(1); 141 142 SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Glue); 143 SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag }; 144 Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops, array_lengthof(Ops)); 145 146 if (TwoRepStos) { 147 InFlag = Chain.getValue(1); 148 Count = Size; 149 EVT CVT = Count.getValueType(); 150 SDValue Left = DAG.getNode(ISD::AND, dl, CVT, Count, 151 DAG.getConstant((AVT == MVT::i64) ? 7 : 3, CVT)); 152 Chain = DAG.getCopyToReg(Chain, dl, (CVT == MVT::i64) ? X86::RCX : 153 X86::ECX, 154 Left, InFlag); 155 InFlag = Chain.getValue(1); 156 Tys = DAG.getVTList(MVT::Other, MVT::Glue); 157 SDValue Ops[] = { Chain, DAG.getValueType(MVT::i8), InFlag }; 158 Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops, array_lengthof(Ops)); 159 } else if (BytesLeft) { 160 // Handle the last 1 - 7 bytes. 161 unsigned Offset = SizeVal - BytesLeft; 162 EVT AddrVT = Dst.getValueType(); 163 EVT SizeVT = Size.getValueType(); 164 165 Chain = DAG.getMemset(Chain, dl, 166 DAG.getNode(ISD::ADD, dl, AddrVT, Dst, 167 DAG.getConstant(Offset, AddrVT)), 168 Src, 169 DAG.getConstant(BytesLeft, SizeVT), 170 Align, isVolatile, DstPtrInfo.getWithOffset(Offset)); 171 } 172 173 // TODO: Use a Tokenfactor, as in memcpy, instead of a single chain. 174 return Chain; 175 } 176 177 SDValue 178 X86SelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, 179 SDValue Chain, SDValue Dst, SDValue Src, 180 SDValue Size, unsigned Align, 181 bool isVolatile, bool AlwaysInline, 182 MachinePointerInfo DstPtrInfo, 183 MachinePointerInfo SrcPtrInfo) const { 184 // This requires the copy size to be a constant, preferably 185 // within a subtarget-specific limit. 186 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size); 187 if (!ConstantSize) 188 return SDValue(); 189 uint64_t SizeVal = ConstantSize->getZExtValue(); 190 if (!AlwaysInline && SizeVal > Subtarget->getMaxInlineSizeThreshold()) 191 return SDValue(); 192 193 /// If not DWORD aligned, it is more efficient to call the library. However 194 /// if calling the library is not allowed (AlwaysInline), then soldier on as 195 /// the code generated here is better than the long load-store sequence we 196 /// would otherwise get. 197 if (!AlwaysInline && (Align & 3) != 0) 198 return SDValue(); 199 200 // If to a segment-relative address space, use the default lowering. 201 if (DstPtrInfo.getAddrSpace() >= 256 || 202 SrcPtrInfo.getAddrSpace() >= 256) 203 return SDValue(); 204 205 MVT AVT; 206 if (Align & 1) 207 AVT = MVT::i8; 208 else if (Align & 2) 209 AVT = MVT::i16; 210 else if (Align & 4) 211 // DWORD aligned 212 AVT = MVT::i32; 213 else 214 // QWORD aligned 215 AVT = Subtarget->is64Bit() ? MVT::i64 : MVT::i32; 216 217 unsigned UBytes = AVT.getSizeInBits() / 8; 218 unsigned CountVal = SizeVal / UBytes; 219 SDValue Count = DAG.getIntPtrConstant(CountVal); 220 unsigned BytesLeft = SizeVal % UBytes; 221 222 SDValue InFlag(0, 0); 223 Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RCX : 224 X86::ECX, 225 Count, InFlag); 226 InFlag = Chain.getValue(1); 227 Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RDI : 228 X86::EDI, 229 Dst, InFlag); 230 InFlag = Chain.getValue(1); 231 Chain = DAG.getCopyToReg(Chain, dl, Subtarget->is64Bit() ? X86::RSI : 232 X86::ESI, 233 Src, InFlag); 234 InFlag = Chain.getValue(1); 235 236 SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Glue); 237 SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag }; 238 SDValue RepMovs = DAG.getNode(X86ISD::REP_MOVS, dl, Tys, Ops, 239 array_lengthof(Ops)); 240 241 SmallVector<SDValue, 4> Results; 242 Results.push_back(RepMovs); 243 if (BytesLeft) { 244 // Handle the last 1 - 7 bytes. 245 unsigned Offset = SizeVal - BytesLeft; 246 EVT DstVT = Dst.getValueType(); 247 EVT SrcVT = Src.getValueType(); 248 EVT SizeVT = Size.getValueType(); 249 Results.push_back(DAG.getMemcpy(Chain, dl, 250 DAG.getNode(ISD::ADD, dl, DstVT, Dst, 251 DAG.getConstant(Offset, DstVT)), 252 DAG.getNode(ISD::ADD, dl, SrcVT, Src, 253 DAG.getConstant(Offset, SrcVT)), 254 DAG.getConstant(BytesLeft, SizeVT), 255 Align, isVolatile, AlwaysInline, 256 DstPtrInfo.getWithOffset(Offset), 257 SrcPtrInfo.getWithOffset(Offset))); 258 } 259 260 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 261 &Results[0], Results.size()); 262 } 263