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 #define DEBUG_TYPE "arm-selectiondag-info"
15 #include "ARMTargetMachine.h"
16 #include "llvm/DerivedTypes.h"
17 #include "llvm/CodeGen/SelectionDAG.h"
20 ARMSelectionDAGInfo::ARMSelectionDAGInfo(const TargetMachine
&TM
)
21 : TargetSelectionDAGInfo(TM
),
22 Subtarget(&TM
.getSubtarget
<ARMSubtarget
>()) {
25 ARMSelectionDAGInfo::~ARMSelectionDAGInfo() {
29 ARMSelectionDAGInfo::EmitTargetCodeForMemcpy(SelectionDAG
&DAG
, DebugLoc dl
,
31 SDValue Dst
, SDValue Src
,
32 SDValue Size
, unsigned Align
,
33 bool isVolatile
, bool AlwaysInline
,
34 MachinePointerInfo DstPtrInfo
,
35 MachinePointerInfo SrcPtrInfo
) const {
36 // Do repeated 4-byte loads and stores. To be improved.
37 // This requires 4-byte alignment.
40 // This requires the copy size to be a constant, preferably
41 // within a subtarget-specific limit.
42 ConstantSDNode
*ConstantSize
= dyn_cast
<ConstantSDNode
>(Size
);
45 uint64_t SizeVal
= ConstantSize
->getZExtValue();
46 if (!AlwaysInline
&& SizeVal
> Subtarget
->getMaxInlineSizeThreshold())
49 unsigned BytesLeft
= SizeVal
& 3;
50 unsigned NumMemOps
= SizeVal
>> 2;
51 unsigned EmittedNumMemOps
= 0;
55 const unsigned MAX_LOADS_IN_LDM
= 6;
56 SDValue TFOps
[MAX_LOADS_IN_LDM
];
57 SDValue Loads
[MAX_LOADS_IN_LDM
];
58 uint64_t SrcOff
= 0, DstOff
= 0;
60 // Emit up to MAX_LOADS_IN_LDM loads, then a TokenFactor barrier, then the
61 // same number of stores. The loads and stores will get combined into
63 while (EmittedNumMemOps
< NumMemOps
) {
65 i
< MAX_LOADS_IN_LDM
&& EmittedNumMemOps
+ i
< NumMemOps
; ++i
) {
66 Loads
[i
] = DAG
.getLoad(VT
, dl
, Chain
,
67 DAG
.getNode(ISD::ADD
, dl
, MVT::i32
, Src
,
68 DAG
.getConstant(SrcOff
, MVT::i32
)),
69 SrcPtrInfo
.getWithOffset(SrcOff
), isVolatile
,
71 TFOps
[i
] = Loads
[i
].getValue(1);
74 Chain
= DAG
.getNode(ISD::TokenFactor
, dl
, MVT::Other
, &TFOps
[0], i
);
77 i
< MAX_LOADS_IN_LDM
&& EmittedNumMemOps
+ i
< NumMemOps
; ++i
) {
78 TFOps
[i
] = DAG
.getStore(Chain
, dl
, Loads
[i
],
79 DAG
.getNode(ISD::ADD
, dl
, MVT::i32
, Dst
,
80 DAG
.getConstant(DstOff
, MVT::i32
)),
81 DstPtrInfo
.getWithOffset(DstOff
),
82 isVolatile
, false, 0);
85 Chain
= DAG
.getNode(ISD::TokenFactor
, dl
, MVT::Other
, &TFOps
[0], i
);
87 EmittedNumMemOps
+= i
;
93 // Issue loads / stores for the trailing (1 - 3) bytes.
94 unsigned BytesLeftSave
= BytesLeft
;
105 Loads
[i
] = DAG
.getLoad(VT
, dl
, Chain
,
106 DAG
.getNode(ISD::ADD
, dl
, MVT::i32
, Src
,
107 DAG
.getConstant(SrcOff
, MVT::i32
)),
108 SrcPtrInfo
.getWithOffset(SrcOff
), false, false, 0);
109 TFOps
[i
] = Loads
[i
].getValue(1);
114 Chain
= DAG
.getNode(ISD::TokenFactor
, dl
, MVT::Other
, &TFOps
[0], i
);
117 BytesLeft
= BytesLeftSave
;
119 if (BytesLeft
>= 2) {
127 TFOps
[i
] = DAG
.getStore(Chain
, dl
, Loads
[i
],
128 DAG
.getNode(ISD::ADD
, dl
, MVT::i32
, Dst
,
129 DAG
.getConstant(DstOff
, MVT::i32
)),
130 DstPtrInfo
.getWithOffset(DstOff
), false, false, 0);
135 return DAG
.getNode(ISD::TokenFactor
, dl
, MVT::Other
, &TFOps
[0], i
);
138 // Adjust parameters for memset, EABI uses format (ptr, size, value),
139 // GNU library uses (ptr, value, size)
140 // See RTABI section 4.3.4
142 ARMSelectionDAGInfo::EmitTargetCodeForMemset(SelectionDAG
&DAG
, DebugLoc dl
,
143 SDValue Chain
, SDValue Dst
,
144 SDValue Src
, SDValue Size
,
145 unsigned Align
, bool isVolatile
,
146 MachinePointerInfo DstPtrInfo
) const
148 // Use default for non AAPCS subtargets
149 if (!Subtarget
->isAAPCS_ABI())
152 const ARMTargetLowering
&TLI
=
153 *static_cast<const ARMTargetLowering
*>(DAG
.getTarget().getTargetLowering());
154 TargetLowering::ArgListTy Args
;
155 TargetLowering::ArgListEntry Entry
;
157 // First argument: data pointer
158 const Type
*IntPtrTy
= TLI
.getTargetData()->getIntPtrType(*DAG
.getContext());
161 Args
.push_back(Entry
);
163 // Second argument: buffer size
166 Entry
.isSExt
= false;
167 Args
.push_back(Entry
);
169 // Extend or truncate the argument to be an i32 value for the call.
170 if (Src
.getValueType().bitsGT(MVT::i32
))
171 Src
= DAG
.getNode(ISD::TRUNCATE
, dl
, MVT::i32
, Src
);
173 Src
= DAG
.getNode(ISD::ZERO_EXTEND
, dl
, MVT::i32
, Src
);
175 // Third argument: value to fill
177 Entry
.Ty
= Type::getInt32Ty(*DAG
.getContext());
179 Args
.push_back(Entry
);
181 // Emit __eabi_memset call
182 std::pair
<SDValue
,SDValue
> CallResult
=
183 TLI
.LowerCallTo(Chain
,
184 Type::getVoidTy(*DAG
.getContext()), // return type
185 false, // return sign ext
186 false, // return zero ext
189 0, // number of fixed arguments
190 TLI
.getLibcallCallingConv(RTLIB::MEMSET
), // call conv
191 false, // is tail call
192 false, // is return val used
193 DAG
.getExternalSymbol(TLI
.getLibcallName(RTLIB::MEMSET
),
194 TLI
.getPointerTy()), // callee
195 Args
, DAG
, dl
); // arg list, DAG and debug
197 return CallResult
.second
;