ARMSelectionDAGInfo.cpp revision 4bfcd4acbc7d12aa55f8de9af84a38422f0f6d83
153c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//===-- ARMSelectionDAGInfo.cpp - ARM SelectionDAG Info -------------------===//
253c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//
353c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//                     The LLVM Compiler Infrastructure
453c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//
553c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman// This file is distributed under the University of Illinois Open Source
653c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman// License. See LICENSE.TXT for details.
753c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//
853c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//===----------------------------------------------------------------------===//
953c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//
1053c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman// This file implements the ARMSelectionDAGInfo class.
1153c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//
1253c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman//===----------------------------------------------------------------------===//
1353c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman
1453c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman#define DEBUG_TYPE "arm-selectiondag-info"
15ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman#include "ARMTargetMachine.h"
161ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin#include "llvm/DerivedTypes.h"
171ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin#include "llvm/CodeGen/SelectionDAG.h"
1853c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohmanusing namespace llvm;
1953c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman
20ff7a562751604a9fe13efc75bd59622244b54d35Dan GohmanARMSelectionDAGInfo::ARMSelectionDAGInfo(const TargetMachine &TM)
21ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  : TargetSelectionDAGInfo(TM),
22ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
2353c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman}
2453c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman
2553c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan GohmanARMSelectionDAGInfo::~ARMSelectionDAGInfo() {
2653c5e42ab9c1a2cce7ad19bb0b4dffe33c9473e6Dan Gohman}
27ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
28ff7a562751604a9fe13efc75bd59622244b54d35Dan GohmanSDValue
29ff7a562751604a9fe13efc75bd59622244b54d35Dan GohmanARMSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl,
30ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                             SDValue Chain,
31ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                             SDValue Dst, SDValue Src,
32ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                             SDValue Size, unsigned Align,
33ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                             bool isVolatile, bool AlwaysInline,
34e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner                                             MachinePointerInfo DstPtrInfo,
35e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner                                          MachinePointerInfo SrcPtrInfo) const {
36ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  // Do repeated 4-byte loads and stores. To be improved.
37ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  // This requires 4-byte alignment.
38ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  if ((Align & 3) != 0)
39ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    return SDValue();
407a2bdde0a0eebcd2125055e0eacaca040f0b766cChris Lattner  // This requires the copy size to be a constant, preferably
41ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  // within a subtarget-specific limit.
42ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
43ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  if (!ConstantSize)
44ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    return SDValue();
45ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  uint64_t SizeVal = ConstantSize->getZExtValue();
46ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  if (!AlwaysInline && SizeVal > Subtarget->getMaxInlineSizeThreshold())
47ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    return SDValue();
48ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
49ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  unsigned BytesLeft = SizeVal & 3;
50ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  unsigned NumMemOps = SizeVal >> 2;
51ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  unsigned EmittedNumMemOps = 0;
52ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  EVT VT = MVT::i32;
53ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  unsigned VTSize = 4;
54ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  unsigned i = 0;
55ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  const unsigned MAX_LOADS_IN_LDM = 6;
56ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  SDValue TFOps[MAX_LOADS_IN_LDM];
57ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  SDValue Loads[MAX_LOADS_IN_LDM];
58ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  uint64_t SrcOff = 0, DstOff = 0;
59ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
60ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the
61ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  // same number of stores.  The loads and stores will get combined into
62ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  // ldm/stm later on.
63ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  while (EmittedNumMemOps < NumMemOps) {
64ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    for (i = 0;
65ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman         i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
66ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      Loads[i] = DAG.getLoad(VT, dl, Chain,
67ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                             DAG.getNode(ISD::ADD, dl, MVT::i32, Src,
68ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                         DAG.getConstant(SrcOff, MVT::i32)),
69e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner                             SrcPtrInfo.getWithOffset(SrcOff), isVolatile,
70d752e0f7e64585839cb3a458ef52456eaebbea3cPete Cooper                             false, false, 0);
71ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      TFOps[i] = Loads[i].getValue(1);
72ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      SrcOff += VTSize;
73ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    }
74ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);
75ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
76ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    for (i = 0;
77ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman         i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
78ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      TFOps[i] = DAG.getStore(Chain, dl, Loads[i],
79ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                              DAG.getNode(ISD::ADD, dl, MVT::i32, Dst,
80ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                          DAG.getConstant(DstOff, MVT::i32)),
81e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner                              DstPtrInfo.getWithOffset(DstOff),
82e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner                              isVolatile, false, 0);
83ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      DstOff += VTSize;
84ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    }
85ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);
86ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
87ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    EmittedNumMemOps += i;
88ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  }
89ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
90ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  if (BytesLeft == 0)
91ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    return Chain;
92ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
93ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  // Issue loads / stores for the trailing (1 - 3) bytes.
94ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  unsigned BytesLeftSave = BytesLeft;
95ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  i = 0;
96ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  while (BytesLeft) {
97ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    if (BytesLeft >= 2) {
98ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      VT = MVT::i16;
99ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      VTSize = 2;
100ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    } else {
101ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      VT = MVT::i8;
102ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      VTSize = 1;
103ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    }
104ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
105ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    Loads[i] = DAG.getLoad(VT, dl, Chain,
106ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                           DAG.getNode(ISD::ADD, dl, MVT::i32, Src,
107ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                       DAG.getConstant(SrcOff, MVT::i32)),
108d752e0f7e64585839cb3a458ef52456eaebbea3cPete Cooper                           SrcPtrInfo.getWithOffset(SrcOff),
109d752e0f7e64585839cb3a458ef52456eaebbea3cPete Cooper                           false, false, false, 0);
110ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    TFOps[i] = Loads[i].getValue(1);
111ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    ++i;
112ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    SrcOff += VTSize;
113ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    BytesLeft -= VTSize;
114ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  }
115ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);
116ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
117ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  i = 0;
118ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  BytesLeft = BytesLeftSave;
119ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  while (BytesLeft) {
120ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    if (BytesLeft >= 2) {
121ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      VT = MVT::i16;
122ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      VTSize = 2;
123ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    } else {
124ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      VT = MVT::i8;
125ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman      VTSize = 1;
126ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    }
127ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman
128ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    TFOps[i] = DAG.getStore(Chain, dl, Loads[i],
129ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                            DAG.getNode(ISD::ADD, dl, MVT::i32, Dst,
130ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman                                        DAG.getConstant(DstOff, MVT::i32)),
131e72f2027e9116c55a5b39ac72732df8d6c45d37cChris Lattner                            DstPtrInfo.getWithOffset(DstOff), false, false, 0);
132ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    ++i;
133ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    DstOff += VTSize;
134ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman    BytesLeft -= VTSize;
135ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  }
136ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman  return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i);
137ff7a562751604a9fe13efc75bd59622244b54d35Dan Gohman}
1381ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin
1391ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin// Adjust parameters for memset, EABI uses format (ptr, size, value),
1401ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin// GNU library uses (ptr, value, size)
1411ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin// See RTABI section 4.3.4
142b04546ff5b1a7a03eec1076900c945223bf494ccJim GrosbachSDValue ARMSelectionDAGInfo::
143b04546ff5b1a7a03eec1076900c945223bf494ccJim GrosbachEmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl,
144b04546ff5b1a7a03eec1076900c945223bf494ccJim Grosbach                        SDValue Chain, SDValue Dst,
145b04546ff5b1a7a03eec1076900c945223bf494ccJim Grosbach                        SDValue Src, SDValue Size,
146b04546ff5b1a7a03eec1076900c945223bf494ccJim Grosbach                        unsigned Align, bool isVolatile,
147b04546ff5b1a7a03eec1076900c945223bf494ccJim Grosbach                        MachinePointerInfo DstPtrInfo) const {
14807043279f60622243d16d8a3f60805960482083cEvan Cheng  // Use default for non AAPCS (or Darwin) subtargets
14907043279f60622243d16d8a3f60805960482083cEvan Cheng  if (!Subtarget->isAAPCS_ABI() || Subtarget->isTargetDarwin())
1501ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin    return SDValue();
1511ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin
1521ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  const ARMTargetLowering &TLI =
1531ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin    *static_cast<const ARMTargetLowering*>(DAG.getTarget().getTargetLowering());
1541ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  TargetLowering::ArgListTy Args;
1551ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  TargetLowering::ArgListEntry Entry;
1561ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin
1571ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  // First argument: data pointer
158db125cfaf57cc83e7dd7453de2d509bc8efd0e5eChris Lattner  Type *IntPtrTy = TLI.getTargetData()->getIntPtrType(*DAG.getContext());
1591ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  Entry.Node = Dst;
1601ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  Entry.Ty = IntPtrTy;
1611ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  Args.push_back(Entry);
1621ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin
1631ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  // Second argument: buffer size
1641ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  Entry.Node = Size;
1651ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  Entry.Ty = IntPtrTy;
1661ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  Entry.isSExt = false;
1671ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  Args.push_back(Entry);
1681ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin
1691ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  // Extend or truncate the argument to be an i32 value for the call.
1701ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  if (Src.getValueType().bitsGT(MVT::i32))
1711ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin    Src = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src);
1721ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  else
1731ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin    Src = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src);
1741ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin
1751ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  // Third argument: value to fill
1761ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  Entry.Node = Src;
1771ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  Entry.Ty = Type::getInt32Ty(*DAG.getContext());
1781ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  Entry.isSExt = true;
1791ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  Args.push_back(Entry);
1801ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin
1811ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  // Emit __eabi_memset call
1821ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  std::pair<SDValue,SDValue> CallResult =
1831ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin    TLI.LowerCallTo(Chain,
1841ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin                    Type::getVoidTy(*DAG.getContext()), // return type
1851ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin                    false, // return sign ext
1861ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin                    false, // return zero ext
1871ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin                    false, // is var arg
1881ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin                    false, // is in regs
1891ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin                    0,     // number of fixed arguments
1901ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin                    TLI.getLibcallCallingConv(RTLIB::MEMSET), // call conv
1911ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin                    false, // is tail call
1924bfcd4acbc7d12aa55f8de9af84a38422f0f6d83Evan Cheng                    false, // does not return
1931ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin                    false, // is return val used
1941ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin                    DAG.getExternalSymbol(TLI.getLibcallName(RTLIB::MEMSET),
1951ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin                                          TLI.getPointerTy()), // callee
1961ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin                    Args, DAG, dl); // arg list, DAG and debug
1971ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin
1981ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin  return CallResult.second;
1991ec11fb8b502971071a57b8b2de129f86bd41de0Renato Golin}
200