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