LLVM: lib/Target/ARM/ARMSelectionDAGInfo.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

17

18#define GET_SDNODE_DESC

19#include "ARMGenSDNodeInfo.inc"

20

21using namespace llvm;

22

23#define DEBUG_TYPE "arm-selectiondag-info"

24

27 cl::desc("Control conversion of memcpy to "

28 "Tail predicated loops (WLSTP)"),

31 "Don't convert memcpy to TP loop."),

33 "Always convert memcpy to TP loop."),

35 "Allow (may be subject to certain conditions) "

36 "conversion of memcpy to TP loop.")));

37

40

42#define MAKE_CASE(V) \

43 case V: \

44 return #V;

45

46

79 }

80#undef MAKE_CASE

81

83}

84

86

89 return true;

90

92}

93

96 switch (N->getOpcode()) {

97 default:

98 break;

99 case ARMISD::WIN__DBZCHK:

100

101 case ARMISD::WIN__CHKSTK:

102

103 case ARMISD::COPY_STRUCT_BYVAL:

104

105 case ARMISD::MEMCPY:

106

107 case ARMISD::VMOVRRD:

108

109 case ARMISD::VMOVIMM:

110

111 return;

112 }

113

115}

116

117

118

119

126

127

128

129

130

131

132

133 enum {

134 AEABI_MEMCPY = 0,

135 AEABI_MEMMOVE,

136 AEABI_MEMSET,

137 AEABI_MEMCLR

138 } AEABILibcall;

139 switch (LC) {

140 case RTLIB::MEMCPY:

141 if (TLI->getLibcallImpl(LC) != RTLIB::impl___aeabi_memcpy)

143

144 AEABILibcall = AEABI_MEMCPY;

145 break;

146 case RTLIB::MEMMOVE:

147 if (TLI->getLibcallImpl(LC) != RTLIB::impl___aeabi_memmove)

149

150 AEABILibcall = AEABI_MEMMOVE;

151 break;

152 case RTLIB::MEMSET:

153 if (TLI->getLibcallImpl(LC) != RTLIB::impl___aeabi_memset)

155

156 AEABILibcall = AEABI_MEMSET;

158 AEABILibcall = AEABI_MEMCLR;

159 break;

160 default:

162 }

163

164

165 enum {

166 ALIGN1 = 0,

167 ALIGN4,

168 ALIGN8

169 } AlignVariant;

170 if ((Align & 7) == 0)

171 AlignVariant = ALIGN8;

172 else if ((Align & 3) == 0)

173 AlignVariant = ALIGN4;

174 else

175 AlignVariant = ALIGN1;

176

179 Args.emplace_back(Dst, IntPtrTy);

180 if (AEABILibcall == AEABI_MEMCLR) {

181 Args.emplace_back(Size, IntPtrTy);

182 } else if (AEABILibcall == AEABI_MEMSET) {

183

184

185

186 Args.emplace_back(Size, IntPtrTy);

187

188

189 if (Src.getValueType().bitsGT(MVT::i32))

191 else if (Src.getValueType().bitsLT(MVT::i32))

193

196 Entry.IsSExt = false;

197 Args.push_back(Entry);

198 } else {

199 Args.emplace_back(Src, IntPtrTy);

200 Args.emplace_back(Size, IntPtrTy);

201 }

202

203 static const RTLIB::Libcall FunctionImpls[4][3] = {

204 {RTLIB::MEMCPY, RTLIB::AEABI_MEMCPY4, RTLIB::AEABI_MEMCPY8},

205 {RTLIB::MEMMOVE, RTLIB::AEABI_MEMMOVE4, RTLIB::AEABI_MEMMOVE8},

206 {RTLIB::MEMSET, RTLIB::AEABI_MEMSET4, RTLIB::AEABI_MEMSET8},

207 {RTLIB::AEABI_MEMCLR, RTLIB::AEABI_MEMCLR4, RTLIB::AEABI_MEMCLR8}};

208

209 RTLIB::Libcall NewLC = FunctionImpls[AEABILibcall][AlignVariant];

210

218 std::move(Args))

220 std::pair<SDValue,SDValue> CallResult = TLI->LowerCallTo(CLI);

221

222 return CallResult.second;

223}

224

228 Align Alignment, bool IsMemcpy) {

231 return false;

233 return true;

234

235

236 if (F.hasOptNone() || F.hasOptSize())

237 return false;

238

239

240 if (!IsMemcpy)

241 return true;

242 if (!ConstantSize && Alignment >= Align(4))

243 return true;

244 if (ConstantSize &&

248 return true;

249 return false;

250}

251

254 SDValue Size, Align Alignment, bool isVolatile, bool AlwaysInline,

259

260 if (Subtarget.hasMVEIntegerOps() &&

262 return DAG.getNode(ARMISD::MEMCPYLOOP, dl, MVT::Other, Chain, Dst, Src,

264

265

266

267 if (Alignment < Align(4))

269

270

271 if (!ConstantSize)

273 Alignment.value(), RTLIB::MEMCPY);

274 uint64_t SizeVal = ConstantSize->getZExtValue();

277 Alignment.value(), RTLIB::MEMCPY);

278

279 unsigned BytesLeft = SizeVal & 3;

280 unsigned NumMemOps = SizeVal >> 2;

281 unsigned EmittedNumMemOps = 0;

282 EVT VT = MVT::i32;

283 unsigned VTSize = 4;

284 unsigned i = 0;

285

286 const unsigned MaxLoadsInLDM = Subtarget.isThumb1Only() ? 4 : 6;

289 uint64_t SrcOff = 0, DstOff = 0;

290

291

292

293

294

295

296

297

298

299

300 unsigned NumMEMCPYs = (NumMemOps + MaxLoadsInLDM - 1) / MaxLoadsInLDM;

301

302

303

304 if (NumMEMCPYs > 1 && Subtarget.hasMinSize()) {

306 }

307

308 SDVTList VTs = DAG.getVTList(MVT::i32, MVT::i32, MVT::Other, MVT::Glue);

309

310 for (unsigned I = 0; I != NumMEMCPYs; ++I) {

311

312

313 unsigned NextEmittedNumMemOps = NumMemOps * (I + 1) / NumMEMCPYs;

314 unsigned NumRegs = NextEmittedNumMemOps - EmittedNumMemOps;

315

316 Dst = DAG.getNode(ARMISD::MEMCPY, dl, VTs, Chain, Dst, Src,

320

321 DstPtrInfo = DstPtrInfo.getWithOffset(NumRegs * VTSize);

322 SrcPtrInfo = SrcPtrInfo.getWithOffset(NumRegs * VTSize);

323

324 EmittedNumMemOps = NextEmittedNumMemOps;

325 }

326

327 if (BytesLeft == 0)

328 return Chain;

329

330

331 auto getRemainingValueType = [](unsigned BytesLeft) {

332 return (BytesLeft >= 2) ? MVT::i16 : MVT::i8;

333 };

334 auto getRemainingSize = [](unsigned BytesLeft) {

335 return (BytesLeft >= 2) ? 2 : 1;

336 };

337

338 unsigned BytesLeftSave = BytesLeft;

339 i = 0;

340 while (BytesLeft) {

341 VT = getRemainingValueType(BytesLeft);

342 VTSize = getRemainingSize(BytesLeft);

343 Loads[i] = DAG.getLoad(VT, dl, Chain,

347 TFOps[i] = Loads[i].getValue(1);

348 ++i;

349 SrcOff += VTSize;

350 BytesLeft -= VTSize;

351 }

353

354 i = 0;

355 BytesLeft = BytesLeftSave;

356 while (BytesLeft) {

357 VT = getRemainingValueType(BytesLeft);

358 VTSize = getRemainingSize(BytesLeft);

359 TFOps[i] = DAG.getStore(Chain, dl, Loads[i],

363 ++i;

364 DstOff += VTSize;

365 BytesLeft -= VTSize;

366 }

368}

369

375 Alignment.value(), RTLIB::MEMMOVE);

376}

377

380 SDValue Size, Align Alignment, bool isVolatile, bool AlwaysInline,

382

385

387

388

389 if (Subtarget.hasMVEIntegerOps() &&

391 false)) {

394 return DAG.getNode(ARMISD::MEMSETLOOP, dl, MVT::Other, Chain, Dst, Src,

396 }

397

398 if (!AlwaysInline)

400 Alignment.value(), RTLIB::MEMSET);

401

403}

static bool shouldGenerateInlineTPLoop(const ARMSubtarget &Subtarget, const SelectionDAG &DAG, ConstantSDNode *ConstantSize, Align Alignment, bool IsMemcpy)

Definition ARMSelectionDAGInfo.cpp:225

static cl::opt< TPLoop::MemTransfer > EnableMemtransferTPLoop("arm-memtransfer-tploop", cl::Hidden, cl::desc("Control conversion of memcpy to " "Tail predicated loops (WLSTP)"), cl::init(TPLoop::ForceDisabled), cl::values(clEnumValN(TPLoop::ForceDisabled, "force-disabled", "Don't convert memcpy to TP loop."), clEnumValN(TPLoop::ForceEnabled, "force-enabled", "Always convert memcpy to TP loop."), clEnumValN(TPLoop::Allow, "allow", "Allow (may be subject to certain conditions) " "conversion of memcpy to TP loop.")))

This file a TargetTransformInfoImplBase conforming object specific to the ARM target machine.

#define clEnumValN(ENUMVAL, FLAGNAME, DESC)

const char * getTargetNodeName(unsigned Opcode) const override

Returns the name of the given target-specific opcode, suitable for debug printing.

Definition ARMSelectionDAGInfo.cpp:41

ARMSelectionDAGInfo()

Definition ARMSelectionDAGInfo.cpp:38

SDValue EmitSpecializedLibcall(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, RTLIB::Libcall LC) const

Definition ARMSelectionDAGInfo.cpp:120

SDValue EmitTargetCodeForMemset(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Op1, SDValue Op2, SDValue Op3, Align Alignment, bool isVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo) const override

Emit target-specific code that performs a memset.

Definition ARMSelectionDAGInfo.cpp:378

SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const override

Emit target-specific code that performs a memcpy.

Definition ARMSelectionDAGInfo.cpp:252

SDValue EmitTargetCodeForMemmove(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVolatile, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo) const override

Emit target-specific code that performs a memmove.

Definition ARMSelectionDAGInfo.cpp:370

void verifyTargetNode(const SelectionDAG &DAG, const SDNode *N) const override

Checks that the given target-specific node is valid. Aborts if it is not.

Definition ARMSelectionDAGInfo.cpp:94

bool isTargetMemoryOpcode(unsigned Opcode) const override

Returns true if a node with the given target-specific opcode has a memory operand.

Definition ARMSelectionDAGInfo.cpp:85

bool isThumb1Only() const

const ARMTargetLowering * getTargetLowering() const override

unsigned getMaxMemcpyTPInlineSizeThreshold() const

getMaxMemcpyTPInlineSizeThreshold - Returns the maximum size that still makes it profitable to inline...

unsigned getMaxInlineSizeThreshold() const

getMaxInlineSizeThreshold - Returns the maximum memset / memcpy size that still makes it profitable t...

uint64_t getZExtValue() const

LLVM_ABI IntegerType * getIntPtrType(LLVMContext &C, unsigned AddressSpace=0) const

Returns an integer type with size at least as big as that of a pointer in the given address space.

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

Function & getFunction()

Return the LLVM function that this machine code represents.

Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...

Represents one node in the SelectionDAG.

Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.

SDValue getValue(unsigned R) const

const char * getTargetNodeName(unsigned Opcode) const override

Returns the name of the given target-specific opcode, suitable for debug printing.

SelectionDAGGenTargetInfo(const SDNodeInfo &GenNodeInfo)

bool isTargetMemoryOpcode(unsigned Opcode) const override

Returns true if a node with the given target-specific opcode has a memory operand.

void verifyTargetNode(const SelectionDAG &DAG, const SDNode *N) const override

Checks that the given target-specific node is valid. Aborts if it is not.

This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...

LLVM_ABI SDVTList getVTList(EVT VT)

Return an SDVTList that represents the list of values specified.

LLVM_ABI SDValue getLoad(EVT VT, const SDLoc &dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, MaybeAlign Alignment=MaybeAlign(), MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr)

Loads are not normal binary operators: their result type is not determined by their operands,...

const DataLayout & getDataLayout() const

LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)

Create a ConstantSDNode wrapping a constant value.

LLVM_ABI SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, Align Alignment, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())

Helper function to build ISD::STORE nodes.

LLVM_ABI SDValue getExternalSymbol(const char *Sym, EVT VT)

LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)

Gets or creates the specified node.

MachineFunction & getMachineFunction() const

SDValue getSplatBuildVector(EVT VT, const SDLoc &DL, SDValue Op)

Return a splat ISD::BUILD_VECTOR node, consisting of Op splatted to all elements.

LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)

Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...

LLVMContext * getContext() const

std::vector< ArgListEntry > ArgListTy

The instances of the Type class are immutable: once they are created, they are never changed.

static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)

static LLVM_ABI Type * getVoidTy(LLVMContext &C)

@ ADD

Simple integer binary arithmetic operators.

@ ZERO_EXTEND

ZERO_EXTEND - Used for integer types, zeroing the new bits.

@ TokenFactor

TokenFactor - This node takes multiple tokens as input and produces a single token result.

@ TRUNCATE

TRUNCATE - Completely drop the high bits.

ValuesClass values(OptsTy... Options)

Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI bool isNullConstant(SDValue V)

Returns true if V is a constant integer zero.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

ArrayRef(const T &OneElt) -> ArrayRef< T >

This struct is a compact representation of a valid (non-zero power of two) alignment.

constexpr uint64_t value() const

This is a hole in the type system and should not be abused.

This class contains a discriminated union of information about pointers in memory operands,...

MachinePointerInfo getWithOffset(int64_t O) const

This represents a list of ValueType's that has been intern'd by a SelectionDAG.

This structure contains all information that is necessary for lowering calls.

CallLoweringInfo & setLibCallee(CallingConv::ID CC, Type *ResultType, SDValue Target, ArgListTy &&ArgsList)

CallLoweringInfo & setDiscardResult(bool Value=true)

CallLoweringInfo & setDebugLoc(const SDLoc &dl)

CallLoweringInfo & setChain(SDValue InChain)