blob: 06bde40e037a459a9fdf2ebc2a2618cc06638e74 [file] [log] [blame]
Dan Gohman9becddd2010-04-16 23:04:22 +00001//===-- ARMSelectionDAGInfo.cpp - ARM SelectionDAG Info -------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the ARMSelectionDAGInfo class.
11//
12//===----------------------------------------------------------------------===//
13
Dan Gohmanbb919df2010-05-11 17:31:57 +000014#include "ARMTargetMachine.h"
Renato Golin4cd51872011-05-22 21:41:23 +000015#include "llvm/CodeGen/SelectionDAG.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000016#include "llvm/IR/DerivedTypes.h"
Dan Gohman9becddd2010-04-16 23:04:22 +000017using namespace llvm;
18
Chandler Carruth84e68b22014-04-22 02:41:26 +000019#define DEBUG_TYPE "arm-selectiondag-info"
20
Eric Christopher70e005a2014-06-12 23:39:49 +000021ARMSelectionDAGInfo::ARMSelectionDAGInfo(const DataLayout &DL)
22 : TargetSelectionDAGInfo(&DL) {}
Dan Gohman9becddd2010-04-16 23:04:22 +000023
24ARMSelectionDAGInfo::~ARMSelectionDAGInfo() {
25}
Dan Gohmanbb919df2010-05-11 17:31:57 +000026
27SDValue
Andrew Trickef9de2a2013-05-25 02:42:55 +000028ARMSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc dl,
Dan Gohmanbb919df2010-05-11 17:31:57 +000029 SDValue Chain,
30 SDValue Dst, SDValue Src,
31 SDValue Size, unsigned Align,
32 bool isVolatile, bool AlwaysInline,
Chris Lattner2510de22010-09-21 05:40:29 +000033 MachinePointerInfo DstPtrInfo,
34 MachinePointerInfo SrcPtrInfo) const {
Eric Christopher22b2ad22015-02-20 08:24:37 +000035 const ARMSubtarget &Subtarget =
36 DAG.getMachineFunction().getSubtarget<ARMSubtarget>();
Dan Gohmanbb919df2010-05-11 17:31:57 +000037 // Do repeated 4-byte loads and stores. To be improved.
38 // This requires 4-byte alignment.
39 if ((Align & 3) != 0)
40 return SDValue();
Chris Lattner0ab5e2c2011-04-15 05:18:47 +000041 // This requires the copy size to be a constant, preferably
Dan Gohmanbb919df2010-05-11 17:31:57 +000042 // within a subtarget-specific limit.
43 ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
44 if (!ConstantSize)
45 return SDValue();
46 uint64_t SizeVal = ConstantSize->getZExtValue();
Eric Christopher70e005a2014-06-12 23:39:49 +000047 if (!AlwaysInline && SizeVal > Subtarget.getMaxInlineSizeThreshold())
Dan Gohmanbb919df2010-05-11 17:31:57 +000048 return SDValue();
49
50 unsigned BytesLeft = SizeVal & 3;
51 unsigned NumMemOps = SizeVal >> 2;
52 unsigned EmittedNumMemOps = 0;
53 EVT VT = MVT::i32;
54 unsigned VTSize = 4;
55 unsigned i = 0;
James Molloya70697e2014-05-16 14:24:22 +000056 // Emit a maximum of 4 loads in Thumb1 since we have fewer registers
Eric Christopher70e005a2014-06-12 23:39:49 +000057 const unsigned MAX_LOADS_IN_LDM = Subtarget.isThumb1Only() ? 4 : 6;
James Molloya70697e2014-05-16 14:24:22 +000058 SDValue TFOps[6];
59 SDValue Loads[6];
Dan Gohmanbb919df2010-05-11 17:31:57 +000060 uint64_t SrcOff = 0, DstOff = 0;
61
62 // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the
63 // same number of stores. The loads and stores will get combined into
64 // ldm/stm later on.
65 while (EmittedNumMemOps < NumMemOps) {
66 for (i = 0;
67 i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
68 Loads[i] = DAG.getLoad(VT, dl, Chain,
69 DAG.getNode(ISD::ADD, dl, MVT::i32, Src,
Sergey Dmitroukadb4c692015-04-28 11:56:37 +000070 DAG.getConstant(SrcOff, dl, MVT::i32)),
Chris Lattner2510de22010-09-21 05:40:29 +000071 SrcPtrInfo.getWithOffset(SrcOff), isVolatile,
Pete Cooper82cd9e82011-11-08 18:42:53 +000072 false, false, 0);
Dan Gohmanbb919df2010-05-11 17:31:57 +000073 TFOps[i] = Loads[i].getValue(1);
74 SrcOff += VTSize;
75 }
Craig Topper48d114b2014-04-26 18:35:24 +000076 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Craig Topper2d2aa0c2014-04-30 07:17:30 +000077 makeArrayRef(TFOps, i));
Dan Gohmanbb919df2010-05-11 17:31:57 +000078
79 for (i = 0;
80 i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) {
81 TFOps[i] = DAG.getStore(Chain, dl, Loads[i],
82 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst,
Sergey Dmitroukadb4c692015-04-28 11:56:37 +000083 DAG.getConstant(DstOff, dl, MVT::i32)),
Chris Lattner2510de22010-09-21 05:40:29 +000084 DstPtrInfo.getWithOffset(DstOff),
85 isVolatile, false, 0);
Dan Gohmanbb919df2010-05-11 17:31:57 +000086 DstOff += VTSize;
87 }
Craig Topper48d114b2014-04-26 18:35:24 +000088 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Craig Topper2d2aa0c2014-04-30 07:17:30 +000089 makeArrayRef(TFOps, i));
Dan Gohmanbb919df2010-05-11 17:31:57 +000090
91 EmittedNumMemOps += i;
92 }
93
94 if (BytesLeft == 0)
95 return Chain;
96
97 // Issue loads / stores for the trailing (1 - 3) bytes.
98 unsigned BytesLeftSave = BytesLeft;
99 i = 0;
100 while (BytesLeft) {
101 if (BytesLeft >= 2) {
102 VT = MVT::i16;
103 VTSize = 2;
104 } else {
105 VT = MVT::i8;
106 VTSize = 1;
107 }
108
109 Loads[i] = DAG.getLoad(VT, dl, Chain,
110 DAG.getNode(ISD::ADD, dl, MVT::i32, Src,
Sergey Dmitroukadb4c692015-04-28 11:56:37 +0000111 DAG.getConstant(SrcOff, dl, MVT::i32)),
Pete Cooper82cd9e82011-11-08 18:42:53 +0000112 SrcPtrInfo.getWithOffset(SrcOff),
113 false, false, false, 0);
Dan Gohmanbb919df2010-05-11 17:31:57 +0000114 TFOps[i] = Loads[i].getValue(1);
115 ++i;
116 SrcOff += VTSize;
117 BytesLeft -= VTSize;
118 }
Craig Topper48d114b2014-04-26 18:35:24 +0000119 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Craig Topper2d2aa0c2014-04-30 07:17:30 +0000120 makeArrayRef(TFOps, i));
Dan Gohmanbb919df2010-05-11 17:31:57 +0000121
122 i = 0;
123 BytesLeft = BytesLeftSave;
124 while (BytesLeft) {
125 if (BytesLeft >= 2) {
126 VT = MVT::i16;
127 VTSize = 2;
128 } else {
129 VT = MVT::i8;
130 VTSize = 1;
131 }
132
133 TFOps[i] = DAG.getStore(Chain, dl, Loads[i],
134 DAG.getNode(ISD::ADD, dl, MVT::i32, Dst,
Sergey Dmitroukadb4c692015-04-28 11:56:37 +0000135 DAG.getConstant(DstOff, dl, MVT::i32)),
Chris Lattner2510de22010-09-21 05:40:29 +0000136 DstPtrInfo.getWithOffset(DstOff), false, false, 0);
Dan Gohmanbb919df2010-05-11 17:31:57 +0000137 ++i;
138 DstOff += VTSize;
139 BytesLeft -= VTSize;
140 }
Craig Topper48d114b2014-04-26 18:35:24 +0000141 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Craig Topper2d2aa0c2014-04-30 07:17:30 +0000142 makeArrayRef(TFOps, i));
Dan Gohmanbb919df2010-05-11 17:31:57 +0000143}
Renato Golin4cd51872011-05-22 21:41:23 +0000144
145// Adjust parameters for memset, EABI uses format (ptr, size, value),
146// GNU library uses (ptr, value, size)
147// See RTABI section 4.3.4
Jim Grosbache7e2aca2011-09-13 20:30:37 +0000148SDValue ARMSelectionDAGInfo::
Andrew Trickef9de2a2013-05-25 02:42:55 +0000149EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc dl,
Jim Grosbache7e2aca2011-09-13 20:30:37 +0000150 SDValue Chain, SDValue Dst,
151 SDValue Src, SDValue Size,
152 unsigned Align, bool isVolatile,
153 MachinePointerInfo DstPtrInfo) const {
Eric Christopher22b2ad22015-02-20 08:24:37 +0000154 const ARMSubtarget &Subtarget =
155 DAG.getMachineFunction().getSubtarget<ARMSubtarget>();
Tim Northoverd6a729b2014-01-06 14:28:05 +0000156 // Use default for non-AAPCS (or MachO) subtargets
Eric Christopher70e005a2014-06-12 23:39:49 +0000157 if (!Subtarget.isAAPCS_ABI() || Subtarget.isTargetMachO() ||
158 Subtarget.isTargetWindows())
Renato Golin4cd51872011-05-22 21:41:23 +0000159 return SDValue();
160
Eric Christopher22b2ad22015-02-20 08:24:37 +0000161 const ARMTargetLowering &TLI = *Subtarget.getTargetLowering();
Renato Golin4cd51872011-05-22 21:41:23 +0000162 TargetLowering::ArgListTy Args;
163 TargetLowering::ArgListEntry Entry;
164
165 // First argument: data pointer
Chandler Carruth7ec50852012-11-01 08:07:29 +0000166 Type *IntPtrTy = TLI.getDataLayout()->getIntPtrType(*DAG.getContext());
Renato Golin4cd51872011-05-22 21:41:23 +0000167 Entry.Node = Dst;
168 Entry.Ty = IntPtrTy;
169 Args.push_back(Entry);
170
171 // Second argument: buffer size
172 Entry.Node = Size;
173 Entry.Ty = IntPtrTy;
174 Entry.isSExt = false;
175 Args.push_back(Entry);
176
177 // Extend or truncate the argument to be an i32 value for the call.
178 if (Src.getValueType().bitsGT(MVT::i32))
179 Src = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Src);
180 else
181 Src = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Src);
182
183 // Third argument: value to fill
184 Entry.Node = Src;
185 Entry.Ty = Type::getInt32Ty(*DAG.getContext());
186 Entry.isSExt = true;
187 Args.push_back(Entry);
188
189 // Emit __eabi_memset call
Saleem Abdulrasoolf3a5a5c2014-05-17 21:50:17 +0000190 TargetLowering::CallLoweringInfo CLI(DAG);
191 CLI.setDebugLoc(dl).setChain(Chain)
192 .setCallee(TLI.getLibcallCallingConv(RTLIB::MEMSET),
193 Type::getVoidTy(*DAG.getContext()),
194 DAG.getExternalSymbol(TLI.getLibcallName(RTLIB::MEMSET),
Juergen Ributzka3bd03c72014-07-01 22:01:54 +0000195 TLI.getPointerTy()), std::move(Args), 0)
Saleem Abdulrasoolf3a5a5c2014-05-17 21:50:17 +0000196 .setDiscardResult();
Renato Golin4cd51872011-05-22 21:41:23 +0000197
Saleem Abdulrasoolf3a5a5c2014-05-17 21:50:17 +0000198 std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(CLI);
Renato Golin4cd51872011-05-22 21:41:23 +0000199 return CallResult.second;
200}