LLVM API Documentation

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