LLVM: lib/Target/X86/X86SelectionDAGInfo.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

21

22using namespace llvm;

23

24#define DEBUG_TYPE "x86-selectiondag-info"

25

28 cl::desc("Use fast short rep mov in memcpy lowering"));

29

33}

34

38}

39

40

43 assert((Align != 0) && "Align is normalized");

46 case 1:

47 return MVT::i8;

48 case 2:

49 return MVT::i16;

50 case 4:

51 return MVT::i32;

52 default:

53 return Subtarget.is64Bit() ? MVT::i64 : MVT::i32;

54 }

55}

56

57bool X86SelectionDAGInfo::isBaseRegConflictPossible(

59

60

61

62

63

66 return false;

67

71}

72

73

78 unsigned AX = X86::AL;

80 case 8:

81 AX = X86::AL;

82 break;

83 case 16:

84 AX = X86::AX;

85 break;

86 case 32:

87 AX = X86::EAX;

88 break;

89 default:

90 AX = X86::RAX;

91 break;

92 }

93

94 const unsigned CX = Use64BitRegs ? X86::RCX : X86::ECX;

95 const unsigned DI = Use64BitRegs ? X86::RDI : X86::EDI;

96

98 Chain = DAG.getCopyToReg(Chain, dl, AX, Val, InGlue);

102 Chain = DAG.getCopyToReg(Chain, dl, DI, Dst, InGlue);

104

108}

109

110

114 return emitRepstos(Subtarget, DAG, dl, Chain, Dst, Val,

116}

117

118

119

120

121

127 bool isVolatile, bool AlwaysInline,

129

130

132 if (auto *ValC = dyn_cast(Val)) {

133

134

135 if ((Size & 31) == 0 && (ValC->getZExtValue() & 255) == 0) {

136 MVT BlockType = MVT::i32;

137 const uint64_t BlockBits = BlockType.getSizeInBits();

138 const uint64_t BlockBytes = BlockBits / 8;

139 const uint64_t BlockCount = Size / BlockBytes;

140

142

143 return emitRepstos(Subtarget, DAG, dl, Chain, Dst, Val,

145 }

146 }

147 return emitRepstosB(Subtarget, DAG, dl, Chain, Dst, Val, Size);

148 }

149

152

153

154

155

156 if (Alignment < Align(4))

158

159 MVT BlockType = MVT::i8;

162

163 SDValue OriginalVal = Val;

164 if (auto *ValC = dyn_cast(Val)) {

167 const uint64_t BlockBits = BlockType.getSizeInBits();

168

169 if (BlockBits >= 16)

171

172 if (BlockBits >= 32)

174

175 if (BlockBits >= 64)

177

178 const uint64_t BlockBytes = BlockBits / 8;

179 BlockCount = Size / BlockBytes;

180 BytesLeft = Size % BlockBytes;

182 }

183

185 emitRepstos(Subtarget, DAG, dl, Chain, Dst, Val,

187

188 if (BytesLeft == 0)

189 return RepStos;

190

191

193 Results.push_back(RepStos);

195 EVT AddrVT = Dst.getValueType();

196

201 OriginalVal, DAG.getConstant(BytesLeft, dl, SizeVT),

202 Alignment, isVolatile, AlwaysInline,

204

206}

207

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

212

215

216

217 const MCPhysReg ClobberSet[] = {X86::RCX, X86::RAX, X86::RDI,

218 X86::ECX, X86::EAX, X86::EDI};

219 if (isBaseRegConflictPossible(DAG, ClobberSet))

221

223 if (!ConstantSize)

225

229 DAG, Subtarget, dl, Chain, Dst, Val, ConstantSize->getZExtValue(),

230 Size.getValueType(), Alignment, isVolatile, AlwaysInline, DstPtrInfo);

231}

232

233

238 const unsigned CX = Use64BitRegs ? X86::RCX : X86::ECX;

239 const unsigned DI = Use64BitRegs ? X86::RDI : X86::EDI;

240 const unsigned SI = Use64BitRegs ? X86::RSI : X86::ESI;

241

245 Chain = DAG.getCopyToReg(Chain, dl, DI, Dst, InGlue);

247 Chain = DAG.getCopyToReg(Chain, dl, SI, Src, InGlue);

249

253}

254

255

259 return emitRepmovs(Subtarget, DAG, dl, Chain, Dst, Src,

261}

262

263

264

265

266

270 Align Alignment, bool isVolatile, bool AlwaysInline,

272

273

275 return emitRepmovsB(Subtarget, DAG, dl, Chain, Dst, Src, Size);

276

277

278

281

282

283 if (Subtarget.hasERMSB())

284 return emitRepmovsB(Subtarget, DAG, dl, Chain, Dst, Src, Size);

285

286 assert(!Subtarget.hasERMSB() && "No efficient RepMovs");

287

288

289 if (!AlwaysInline && (Alignment < Align(4)))

291

293 const uint64_t BlockBytes = BlockType.getSizeInBits() / 8;

294 const uint64_t BlockCount = Size / BlockBytes;

295 const uint64_t BytesLeft = Size % BlockBytes;

297 emitRepmovs(Subtarget, DAG, dl, Chain, Dst, Src,

299

300

301 if (BytesLeft == 0)

302 return RepMovs;

303

304 assert(BytesLeft && "We have leftover at this point");

305

306

308 Results.push_back(RepMovs);

310 EVT DstVT = Dst.getValueType();

311 EVT SrcVT = Src.getValueType();

313 Chain, dl,

316 DAG.getConstant(BytesLeft, dl, SizeVT), Alignment, isVolatile,

317 true, nullptr, std::nullopt,

320}

321

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

326

329

330

331

332 const MCPhysReg ClobberSet[] = {X86::RCX, X86::RSI, X86::RDI,

333 X86::ECX, X86::ESI, X86::EDI};

334 if (isBaseRegConflictPossible(DAG, ClobberSet))

336

339

340

342 return emitRepmovs(Subtarget, DAG, dl, Chain, Dst, Src, Size, MVT::i8);

343

344

347 ConstantSize->getZExtValue(),

348 Size.getValueType(), Alignment, isVolatile,

349 AlwaysInline, DstPtrInfo, SrcPtrInfo);

350

352}

Function Alias Analysis Results

unsigned const TargetRegisterInfo * TRI

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file describes how to lower LLVM code to machine code.

static SDValue emitRepstos(const X86Subtarget &Subtarget, SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Val, SDValue Size, MVT AVT)

Emit a single REP STOSB instruction for a particular constant size.

static SDValue emitRepmovsB(const X86Subtarget &Subtarget, SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src, uint64_t Size)

Emit a single REP MOVSB instruction for a particular constant size.

static SDValue emitRepstosB(const X86Subtarget &Subtarget, SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Val, uint64_t Size)

Emit a single REP STOSB instruction for a particular constant size.

static SDValue emitConstantSizeRepmov(SelectionDAG &DAG, const X86Subtarget &Subtarget, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src, uint64_t Size, EVT SizeVT, Align Alignment, bool isVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo)

Returns a REP MOVS instruction, possibly with a few load/stores to implement a constant size memory c...

static MVT getOptimalRepType(const X86Subtarget &Subtarget, Align Alignment)

Returns the best type to use with repmovs/repstos depending on alignment.

static cl::opt< bool > UseFSRMForMemcpy("x86-use-fsrm-for-memcpy", cl::Hidden, cl::init(false), cl::desc("Use fast short rep mov in memcpy lowering"))

static SDValue emitConstantSizeRepstos(SelectionDAG &DAG, const X86Subtarget &Subtarget, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Val, uint64_t Size, EVT SizeVT, Align Alignment, bool isVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo)

Returns a REP STOS instruction, possibly with a few load/stores to implement a constant size memory s...

static SDValue emitRepmovs(const X86Subtarget &Subtarget, SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, MVT AVT)

Emit a single REP MOVS{B,W,D,Q} instruction.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

uint64_t getZExtValue() const

bool hasMinSize() const

Optimize this function for minimum size (-Oz).

TypeSize getSizeInBits() const

Returns the size of the specified MVT in bits.

The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.

bool hasVarSizedObjects() const

This method may be called any time after instruction selection is complete to determine if the stack ...

bool hasOpaqueSPAdjustment() const

Returns true if the function contains opaque dynamic stack adjustments.

const TargetSubtargetInfo & getSubtarget() const

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

MachineFrameInfo & getFrameInfo()

getFrameInfo - Return the frame info object for the current function.

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...

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

SDValue getValue(unsigned R) const

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

const TargetSubtargetInfo & getSubtarget() const

SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, Register Reg, SDValue N)

SDVTList getVTList(EVT VT)

Return an SDVTList that represents the list of values specified.

SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, std::optional< bool > OverrideTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo=AAMDNodes(), AAResults *AA=nullptr)

SDValue getMemset(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI, MachinePointerInfo DstPtrInfo, const AAMDNodes &AAInfo=AAMDNodes())

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

Create a ConstantSDNode wrapping a constant value.

SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)

SDValue getValueType(EVT)

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

Gets or creates the specified node.

MachineFunction & getMachineFunction() const

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

virtual const TargetRegisterInfo * getRegisterInfo() const

getRegisterInfo - If register information is available, return it.

LLVM Value Representation.

bool isTargetMemoryOpcode(unsigned Opcode) const override

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

bool isTargetStrictFPOpcode(unsigned Opcode) const override

Returns true if a node with the given target-specific opcode has strict floating-point semantics.

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.

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

Emit target-specific code that performs a memset.

bool isTarget64BitLP64() const

Is this x86_64 with the LP64 programming model (standard AMD64, no x32)?

unsigned getMaxInlineSizeThreshold() const

Returns the maximum memset / memcpy size that still makes it profitable to inline the call.

@ ADD

Simple integer binary arithmetic operators.

@ TokenFactor

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

@ REP_MOVS

Repeat move, corresponds to X86::REP_MOVSx.

@ REP_STOS

Repeat fill, corresponds to X86::REP_STOSx.

@ FIRST_STRICTFP_OPCODE

X86 strict FP compare instructions.

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

constexpr bool isPowerOf2_64(uint64_t Value)

Return true if the argument is a power of two > 0 (64 bit edition.)

bool is_contained(R &&Range, const E &Element)

Returns true if Element is found in Range.

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

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,...

unsigned getAddrSpace() const

Return the LLVM IR address space number that this pointer points into.

MachinePointerInfo getWithOffset(int64_t O) const

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