1 //===-- ARMSelectionDAGInfo.cpp - ARM SelectionDAG Info -------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the ARMSelectionDAGInfo class.
12 //===----------------------------------------------------------------------===//
14 #include "ARMTargetMachine.h"
15 #include "llvm/CodeGen/SelectionDAG.h"
16 #include "llvm/IR/DerivedTypes.h"
19 #define DEBUG_TYPE "arm-selectiondag-info"
21 ARMSelectionDAGInfo::ARMSelectionDAGInfo(const TargetMachine &TM)
22 : TargetSelectionDAGInfo(TM),
23 Subtarget(&TM.getSubtarget<ARMSubtarget>()) {
26 ARMSelectionDAGInfo::~ARMSelectionDAGInfo() {
30 ARMSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc dl,
32 SDValue Dst, SDValue Src,
33 SDValue Size, unsigned Align,
34 bool isVolatile, bool AlwaysInline,
35 MachinePointerInfo DstPtrInfo,
36 MachinePointerInfo SrcPtrInfo) const {
37 // Do repeated 4-byte loads and stores. To be improved.
38 // This requires 4-byte alignment.
41 // This requires the copy size to be a constant, preferably
42 // within a subtarget-specific limit.
43 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
46 uint64_t SizeVal = ConstantSize->getZExtValue();
47 if (!AlwaysInline && SizeVal > Subtarget->getMaxInlineSizeThreshold())
50 unsigned BytesLeft = SizeVal & 3;
51 unsigned NumMemOps = SizeVal >> 2;
52 unsigned EmittedNumMemOps = 0;
56 const unsigned MAX_LOADS_IN_LDM = 6;
57 SDValue TFOps[MAX_LOADS_IN_LDM];
58 SDValue Loads[MAX_LOADS_IN_LDM];
59 uint64_t SrcOff = 0, DstOff = 0;
61 // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the
62 // same number of stores. The loads and stores will get combined into
64 while (EmittedNumMemOps < NumMemOps) {
66 i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
67 Loads[i] = DAG.getLoad(VT, dl, Chain,
68 DAG.getNode(ISD::ADD, dl, MVT::i32, Src,
69 DAG.getConstant(SrcOff, MVT::i32)),
70 SrcPtrInfo.getWithOffset(SrcOff), isVolatile,
72 TFOps[i] = Loads[i].getValue(1);
75 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
76 ArrayRef<SDValue>(TFOps, i));
79 i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
80 TFOps[i] = DAG.getStore(Chain, dl, Loads[i],
81 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst,
82 DAG.getConstant(DstOff, MVT::i32)),
83 DstPtrInfo.getWithOffset(DstOff),
84 isVolatile, false, 0);
87 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
88 ArrayRef<SDValue>(TFOps, i));
90 EmittedNumMemOps += i;
96 // Issue loads / stores for the trailing (1 - 3) bytes.
97 unsigned BytesLeftSave = BytesLeft;
100 if (BytesLeft >= 2) {
108 Loads[i] = DAG.getLoad(VT, dl, Chain,
109 DAG.getNode(ISD::ADD, dl, MVT::i32, Src,
110 DAG.getConstant(SrcOff, MVT::i32)),
111 SrcPtrInfo.getWithOffset(SrcOff),
112 false, false, false, 0);
113 TFOps[i] = Loads[i].getValue(1);
118 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
119 ArrayRef<SDValue>(TFOps, i));
122 BytesLeft = BytesLeftSave;
124 if (BytesLeft >= 2) {
132 TFOps[i] = DAG.getStore(Chain, dl, Loads[i],
133 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst,
134 DAG.getConstant(DstOff, MVT::i32)),
135 DstPtrInfo.getWithOffset(DstOff), false, false, 0);
140 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
141 ArrayRef<SDValue>(TFOps, i));
144 // Adjust parameters for memset, EABI uses format (ptr, size, value),
145 // GNU library uses (ptr, value, size)
146 // See RTABI section 4.3.4
147 SDValue ARMSelectionDAGInfo::
148 EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc dl,
149 SDValue Chain, SDValue Dst,
150 SDValue Src, SDValue Size,
151 unsigned Align, bool isVolatile,
152 MachinePointerInfo DstPtrInfo) const {
153 // Use default for non-AAPCS (or MachO) subtargets
154 if (!Subtarget->isAAPCS_ABI() || Subtarget->isTargetMachO())
157 const ARMTargetLowering &TLI =
158 *static_cast<const ARMTargetLowering*>(DAG.getTarget().getTargetLowering());
159 TargetLowering::ArgListTy Args;
160 TargetLowering::ArgListEntry Entry;
162 // First argument: data pointer
163 Type *IntPtrTy = TLI.getDataLayout()->getIntPtrType(*DAG.getContext());
166 Args.push_back(Entry);
168 // Second argument: buffer size
171 Entry.isSExt = false;
172 Args.push_back(Entry);
174 // Extend or truncate the argument to be an i32 value for the call.
175 if (Src.getValueType().bitsGT(MVT::i32))
176 Src = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src);
178 Src = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src);
180 // Third argument: value to fill
182 Entry.Ty = Type::getInt32Ty(*DAG.getContext());
184 Args.push_back(Entry);
186 // Emit __eabi_memset call
187 TargetLowering::CallLoweringInfo CLI(Chain,
188 Type::getVoidTy(*DAG.getContext()), // return type
189 false, // return sign ext
190 false, // return zero ext
193 0, // number of fixed arguments
194 TLI.getLibcallCallingConv(RTLIB::MEMSET), // call conv
195 false, // is tail call
196 false, // does not return
197 false, // is return val used
198 DAG.getExternalSymbol(TLI.getLibcallName(RTLIB::MEMSET),
199 TLI.getPointerTy()), // callee
201 std::pair<SDValue,SDValue> CallResult =
202 TLI.LowerCallTo(CLI);
204 return CallResult.second;