LLVM API Documentation
00001 //===-- X86SelectionDAGInfo.cpp - X86 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 X86SelectionDAGInfo class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "X86InstrInfo.h" 00015 #include "X86ISelLowering.h" 00016 #include "X86RegisterInfo.h" 00017 #include "X86Subtarget.h" 00018 #include "X86SelectionDAGInfo.h" 00019 #include "llvm/CodeGen/SelectionDAG.h" 00020 #include "llvm/IR/DerivedTypes.h" 00021 #include "llvm/Target/TargetLowering.h" 00022 00023 using namespace llvm; 00024 00025 #define DEBUG_TYPE "x86-selectiondag-info" 00026 00027 X86SelectionDAGInfo::X86SelectionDAGInfo(const DataLayout &DL) 00028 : TargetSelectionDAGInfo(&DL) {} 00029 00030 X86SelectionDAGInfo::~X86SelectionDAGInfo() {} 00031 00032 bool X86SelectionDAGInfo::isBaseRegConflictPossible( 00033 SelectionDAG &DAG, ArrayRef<unsigned> ClobberSet) const { 00034 // We cannot use TRI->hasBasePointer() until *after* we select all basic 00035 // blocks. Legalization may introduce new stack temporaries with large 00036 // alignment requirements. Fall back to generic code if there are any 00037 // dynamic stack adjustments (hopefully rare) and the base pointer would 00038 // conflict if we had to use it. 00039 MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); 00040 if (!MFI->hasVarSizedObjects() && !MFI->hasInlineAsmWithSPAdjust()) 00041 return false; 00042 00043 const X86RegisterInfo *TRI = static_cast<const X86RegisterInfo *>( 00044 DAG.getSubtarget().getRegisterInfo()); 00045 unsigned BaseReg = TRI->getBaseRegister(); 00046 for (unsigned R : ClobberSet) 00047 if (BaseReg == R) 00048 return true; 00049 return false; 00050 } 00051 00052 SDValue 00053 X86SelectionDAGInfo::EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc dl, 00054 SDValue Chain, 00055 SDValue Dst, SDValue Src, 00056 SDValue Size, unsigned Align, 00057 bool isVolatile, 00058 MachinePointerInfo DstPtrInfo) const { 00059 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size); 00060 const X86Subtarget &Subtarget = DAG.getTarget().getSubtarget<X86Subtarget>(); 00061 00062 #ifndef NDEBUG 00063 // If the base register might conflict with our physical registers, bail out. 00064 unsigned ClobberSet[] = {X86::RCX, X86::RAX, X86::RDI, 00065 X86::ECX, X86::EAX, X86::EDI}; 00066 assert(!isBaseRegConflictPossible(DAG, ClobberSet)); 00067 #endif 00068 00069 // If to a segment-relative address space, use the default lowering. 00070 if (DstPtrInfo.getAddrSpace() >= 256) 00071 return SDValue(); 00072 00073 // If not DWORD aligned or size is more than the threshold, call the library. 00074 // The libc version is likely to be faster for these cases. It can use the 00075 // address value and run time information about the CPU. 00076 if ((Align & 3) != 0 || !ConstantSize || 00077 ConstantSize->getZExtValue() > Subtarget.getMaxInlineSizeThreshold()) { 00078 // Check to see if there is a specialized entry-point for memory zeroing. 00079 ConstantSDNode *V = dyn_cast<ConstantSDNode>(Src); 00080 00081 if (const char *bzeroEntry = V && 00082 V->isNullValue() ? Subtarget.getBZeroEntry() : nullptr) { 00083 EVT IntPtr = DAG.getTargetLoweringInfo().getPointerTy(); 00084 Type *IntPtrTy = getDataLayout()->getIntPtrType(*DAG.getContext()); 00085 TargetLowering::ArgListTy Args; 00086 TargetLowering::ArgListEntry Entry; 00087 Entry.Node = Dst; 00088 Entry.Ty = IntPtrTy; 00089 Args.push_back(Entry); 00090 Entry.Node = Size; 00091 Args.push_back(Entry); 00092 00093 TargetLowering::CallLoweringInfo CLI(DAG); 00094 CLI.setDebugLoc(dl).setChain(Chain) 00095 .setCallee(CallingConv::C, Type::getVoidTy(*DAG.getContext()), 00096 DAG.getExternalSymbol(bzeroEntry, IntPtr), std::move(Args), 00097 0) 00098 .setDiscardResult(); 00099 00100 std::pair<SDValue,SDValue> CallResult = DAG.getTargetLoweringInfo().LowerCallTo(CLI); 00101 return CallResult.second; 00102 } 00103 00104 // Otherwise have the target-independent code call memset. 00105 return SDValue(); 00106 } 00107 00108 uint64_t SizeVal = ConstantSize->getZExtValue(); 00109 SDValue InFlag; 00110 EVT AVT; 00111 SDValue Count; 00112 ConstantSDNode *ValC = dyn_cast<ConstantSDNode>(Src); 00113 unsigned BytesLeft = 0; 00114 bool TwoRepStos = false; 00115 if (ValC) { 00116 unsigned ValReg; 00117 uint64_t Val = ValC->getZExtValue() & 255; 00118 00119 // If the value is a constant, then we can potentially use larger sets. 00120 switch (Align & 3) { 00121 case 2: // WORD aligned 00122 AVT = MVT::i16; 00123 ValReg = X86::AX; 00124 Val = (Val << 8) | Val; 00125 break; 00126 case 0: // DWORD aligned 00127 AVT = MVT::i32; 00128 ValReg = X86::EAX; 00129 Val = (Val << 8) | Val; 00130 Val = (Val << 16) | Val; 00131 if (Subtarget.is64Bit() && ((Align & 0x7) == 0)) { // QWORD aligned 00132 AVT = MVT::i64; 00133 ValReg = X86::RAX; 00134 Val = (Val << 32) | Val; 00135 } 00136 break; 00137 default: // Byte aligned 00138 AVT = MVT::i8; 00139 ValReg = X86::AL; 00140 Count = DAG.getIntPtrConstant(SizeVal); 00141 break; 00142 } 00143 00144 if (AVT.bitsGT(MVT::i8)) { 00145 unsigned UBytes = AVT.getSizeInBits() / 8; 00146 Count = DAG.getIntPtrConstant(SizeVal / UBytes); 00147 BytesLeft = SizeVal % UBytes; 00148 } 00149 00150 Chain = DAG.getCopyToReg(Chain, dl, ValReg, DAG.getConstant(Val, AVT), 00151 InFlag); 00152 InFlag = Chain.getValue(1); 00153 } else { 00154 AVT = MVT::i8; 00155 Count = DAG.getIntPtrConstant(SizeVal); 00156 Chain = DAG.getCopyToReg(Chain, dl, X86::AL, Src, InFlag); 00157 InFlag = Chain.getValue(1); 00158 } 00159 00160 Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RCX : X86::ECX, 00161 Count, InFlag); 00162 InFlag = Chain.getValue(1); 00163 Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RDI : X86::EDI, 00164 Dst, InFlag); 00165 InFlag = Chain.getValue(1); 00166 00167 SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Glue); 00168 SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag }; 00169 Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops); 00170 00171 if (TwoRepStos) { 00172 InFlag = Chain.getValue(1); 00173 Count = Size; 00174 EVT CVT = Count.getValueType(); 00175 SDValue Left = DAG.getNode(ISD::AND, dl, CVT, Count, 00176 DAG.getConstant((AVT == MVT::i64) ? 7 : 3, CVT)); 00177 Chain = DAG.getCopyToReg(Chain, dl, (CVT == MVT::i64) ? X86::RCX : 00178 X86::ECX, 00179 Left, InFlag); 00180 InFlag = Chain.getValue(1); 00181 Tys = DAG.getVTList(MVT::Other, MVT::Glue); 00182 SDValue Ops[] = { Chain, DAG.getValueType(MVT::i8), InFlag }; 00183 Chain = DAG.getNode(X86ISD::REP_STOS, dl, Tys, Ops); 00184 } else if (BytesLeft) { 00185 // Handle the last 1 - 7 bytes. 00186 unsigned Offset = SizeVal - BytesLeft; 00187 EVT AddrVT = Dst.getValueType(); 00188 EVT SizeVT = Size.getValueType(); 00189 00190 Chain = DAG.getMemset(Chain, dl, 00191 DAG.getNode(ISD::ADD, dl, AddrVT, Dst, 00192 DAG.getConstant(Offset, AddrVT)), 00193 Src, 00194 DAG.getConstant(BytesLeft, SizeVT), 00195 Align, isVolatile, DstPtrInfo.getWithOffset(Offset)); 00196 } 00197 00198 // TODO: Use a Tokenfactor, as in memcpy, instead of a single chain. 00199 return Chain; 00200 } 00201 00202 SDValue 00203 X86SelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc dl, 00204 SDValue Chain, SDValue Dst, SDValue Src, 00205 SDValue Size, unsigned Align, 00206 bool isVolatile, bool AlwaysInline, 00207 MachinePointerInfo DstPtrInfo, 00208 MachinePointerInfo SrcPtrInfo) const { 00209 // This requires the copy size to be a constant, preferably 00210 // within a subtarget-specific limit. 00211 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size); 00212 const X86Subtarget &Subtarget = DAG.getTarget().getSubtarget<X86Subtarget>(); 00213 if (!ConstantSize) 00214 return SDValue(); 00215 uint64_t SizeVal = ConstantSize->getZExtValue(); 00216 if (!AlwaysInline && SizeVal > Subtarget.getMaxInlineSizeThreshold()) 00217 return SDValue(); 00218 00219 /// If not DWORD aligned, it is more efficient to call the library. However 00220 /// if calling the library is not allowed (AlwaysInline), then soldier on as 00221 /// the code generated here is better than the long load-store sequence we 00222 /// would otherwise get. 00223 if (!AlwaysInline && (Align & 3) != 0) 00224 return SDValue(); 00225 00226 // If to a segment-relative address space, use the default lowering. 00227 if (DstPtrInfo.getAddrSpace() >= 256 || 00228 SrcPtrInfo.getAddrSpace() >= 256) 00229 return SDValue(); 00230 00231 // If the base register might conflict with our physical registers, bail out. 00232 unsigned ClobberSet[] = {X86::RCX, X86::RSI, X86::RDI, 00233 X86::ECX, X86::ESI, X86::EDI}; 00234 if (isBaseRegConflictPossible(DAG, ClobberSet)) 00235 return SDValue(); 00236 00237 MVT AVT; 00238 if (Align & 1) 00239 AVT = MVT::i8; 00240 else if (Align & 2) 00241 AVT = MVT::i16; 00242 else if (Align & 4) 00243 // DWORD aligned 00244 AVT = MVT::i32; 00245 else 00246 // QWORD aligned 00247 AVT = Subtarget.is64Bit() ? MVT::i64 : MVT::i32; 00248 00249 unsigned UBytes = AVT.getSizeInBits() / 8; 00250 unsigned CountVal = SizeVal / UBytes; 00251 SDValue Count = DAG.getIntPtrConstant(CountVal); 00252 unsigned BytesLeft = SizeVal % UBytes; 00253 00254 SDValue InFlag; 00255 Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RCX : 00256 X86::ECX, 00257 Count, InFlag); 00258 InFlag = Chain.getValue(1); 00259 Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RDI : 00260 X86::EDI, 00261 Dst, InFlag); 00262 InFlag = Chain.getValue(1); 00263 Chain = DAG.getCopyToReg(Chain, dl, Subtarget.is64Bit() ? X86::RSI : 00264 X86::ESI, 00265 Src, InFlag); 00266 InFlag = Chain.getValue(1); 00267 00268 SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Glue); 00269 SDValue Ops[] = { Chain, DAG.getValueType(AVT), InFlag }; 00270 SDValue RepMovs = DAG.getNode(X86ISD::REP_MOVS, dl, Tys, Ops); 00271 00272 SmallVector<SDValue, 4> Results; 00273 Results.push_back(RepMovs); 00274 if (BytesLeft) { 00275 // Handle the last 1 - 7 bytes. 00276 unsigned Offset = SizeVal - BytesLeft; 00277 EVT DstVT = Dst.getValueType(); 00278 EVT SrcVT = Src.getValueType(); 00279 EVT SizeVT = Size.getValueType(); 00280 Results.push_back(DAG.getMemcpy(Chain, dl, 00281 DAG.getNode(ISD::ADD, dl, DstVT, Dst, 00282 DAG.getConstant(Offset, DstVT)), 00283 DAG.getNode(ISD::ADD, dl, SrcVT, Src, 00284 DAG.getConstant(Offset, SrcVT)), 00285 DAG.getConstant(BytesLeft, SizeVT), 00286 Align, isVolatile, AlwaysInline, 00287 DstPtrInfo.getWithOffset(Offset), 00288 SrcPtrInfo.getWithOffset(Offset))); 00289 } 00290 00291 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Results); 00292 }