LLVM API Documentation

X86SelectionDAGInfo.cpp
Go to the documentation of this file.
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 }