LLVM: lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

20

21using namespace llvm;

22

26 if (B == MBBEnd)

27 return true;

28 assert(A->getParent() == B->getParent() &&

29 "Iterators should be in same block");

32 for (; &*I != A && &*I != B; ++I)

33 ;

34 return &*I == A;

35}

36

39 void *&NodeInsertPos) {

41 assert(CSEInfo && "Can't get here without setting CSEInfo");

44 CSEInfo->getMachineInstrIfExists(ID, CurMBB, NodeInsertPos);

45 if (MI) {

49 if (MII == CurrPos) {

50

51

53 } else if (!dominates(MI, CurrPos)) {

54

55

57 MI->getDebugLoc().get());

58 MI->setDebugLoc(Loc);

59 CurMBB->splice(CurrPos, CurMBB, MI);

60 }

62 }

64}

65

66bool CSEMIRBuilder::canPerformCSEForOpc(unsigned Opc) const {

68 if (!CSEInfo || !CSEInfo->shouldCSE(Opc))

69 return false;

70 return true;

71}

72

73void CSEMIRBuilder::profileDstOp(const DstOp &Op,

75 switch (Op.getDstOpKind()) {

77 B.addNodeIDRegType(Op.getRegClass());

78 break;

79 }

81

82 B.addNodeIDReg(Op.getReg());

83 break;

84 }

86 B.addNodeIDRegType(Op.getLLTTy(*getMRI()));

87 break;

88 }

90 B.addNodeIDRegType(Op.getVRegAttrs());

91 break;

92 }

93 }

94}

95

96void CSEMIRBuilder::profileSrcOp(const SrcOp &Op,

98 switch (Op.getSrcOpKind()) {

100 B.addNodeIDImmediate(static_cast<int64_t>(Op.getImm()));

101 break;

103 B.addNodeIDImmediate(static_cast<int64_t>(Op.getPredicate()));

104 break;

105 default:

106 B.addNodeIDRegType(Op.getReg());

107 break;

108 }

109}

110

112 unsigned Opc) const {

113

114 B.addNodeIDMBB(&getMBB());

115

116 B.addNodeIDOpcode(Opc);

117}

118

119void CSEMIRBuilder::profileEverything(unsigned Opc, ArrayRef DstOps,

121 std::optional Flags,

123

124 profileMBBOpcode(B, Opc);

125

126 profileDstOps(DstOps, B);

127

128 profileSrcOps(SrcOps, B);

129

130 if (Flags)

131 B.addNodeIDFlag(*Flags);

132}

133

135 void *NodeInsertPos) {

137 "Attempting to CSE illegal op");

139 getCSEInfo()->insertInstr(MIBInstr, NodeInsertPos);

140 return MIB;

141}

142

143bool CSEMIRBuilder::checkCopyToDefsPossible(ArrayRef DstOps) {

144 if (DstOps.size() == 1)

145 return true;

146

150 });

151}

152

154CSEMIRBuilder::generateCopiesIfRequired(ArrayRef DstOps,

156 assert(checkCopyToDefsPossible(DstOps) &&

157 "Impossible return a single MIB with copies to multiple defs");

158 if (DstOps.size() == 1) {

159 const DstOp &Op = DstOps[0];

162 }

163

164

165

166

167

170 if (Observer)

174 if (Observer)

176 }

177

178 return MIB;

179}

180

184 std::optional Flag) {

185 switch (Opc) {

186 default:

187 break;

188 case TargetOpcode::G_ICMP: {

189 assert(SrcOps.size() == 3 && "Invalid sources");

190 assert(DstOps.size() == 1 && "Invalid dsts");

191 LLT SrcTy = SrcOps[1].getLLTTy(*getMRI());

192

199 }

200 break;

201 }

202 case TargetOpcode::G_ADD:

203 case TargetOpcode::G_PTR_ADD:

204 case TargetOpcode::G_AND:

205 case TargetOpcode::G_ASHR:

206 case TargetOpcode::G_LSHR:

207 case TargetOpcode::G_MUL:

208 case TargetOpcode::G_OR:

209 case TargetOpcode::G_SHL:

210 case TargetOpcode::G_SUB:

211 case TargetOpcode::G_XOR:

212 case TargetOpcode::G_UDIV:

213 case TargetOpcode::G_SDIV:

214 case TargetOpcode::G_UREM:

215 case TargetOpcode::G_SREM:

216 case TargetOpcode::G_SMIN:

217 case TargetOpcode::G_SMAX:

218 case TargetOpcode::G_UMIN:

219 case TargetOpcode::G_UMAX: {

220

221 assert(SrcOps.size() == 2 && "Invalid sources");

222 assert(DstOps.size() == 1 && "Invalid dsts");

223 LLT SrcTy = SrcOps[0].getLLTTy(*getMRI());

224

225 if (Opc == TargetOpcode::G_PTR_ADD &&

227 break;

228

230

233 if (!VecCst.empty())

235 break;

236 }

237

241 break;

242 }

243 case TargetOpcode::G_FADD:

244 case TargetOpcode::G_FSUB:

245 case TargetOpcode::G_FMUL:

246 case TargetOpcode::G_FDIV:

247 case TargetOpcode::G_FREM:

248 case TargetOpcode::G_FMINNUM:

249 case TargetOpcode::G_FMAXNUM:

250 case TargetOpcode::G_FMINNUM_IEEE:

251 case TargetOpcode::G_FMAXNUM_IEEE:

252 case TargetOpcode::G_FMINIMUM:

253 case TargetOpcode::G_FMAXIMUM:

254 case TargetOpcode::G_FCOPYSIGN: {

255

256 assert(SrcOps.size() == 2 && "Invalid sources");

257 assert(DstOps.size() == 1 && "Invalid dsts");

261 break;

262 }

263 case TargetOpcode::G_SEXT_INREG: {

264 assert(DstOps.size() == 1 && "Invalid dst ops");

265 assert(SrcOps.size() == 2 && "Invalid src ops");

266 const DstOp &Dst = DstOps[0];

267 const SrcOp &Src0 = SrcOps[0];

268 const SrcOp &Src1 = SrcOps[1];

269 if (auto MaybeCst =

272 break;

273 }

274 case TargetOpcode::G_SITOFP:

275 case TargetOpcode::G_UITOFP: {

276

277 assert(SrcOps.size() == 1 && "Invalid sources");

278 assert(DstOps.size() == 1 && "Invalid dsts");

282 break;

283 }

284 case TargetOpcode::G_CTLZ:

285 case TargetOpcode::G_CTTZ: {

286 assert(SrcOps.size() == 1 && "Expected one source");

287 assert(DstOps.size() == 1 && "Expected one dest");

289 if (Opc == TargetOpcode::G_CTLZ)

290 CB = [](APInt V) -> unsigned { return V.countl_zero(); };

291 else

292 CB = [](APInt V) -> unsigned { return V.countTrailingZeros(); };

294 if (!MaybeCsts)

295 break;

296 if (MaybeCsts->size() == 1)

297 return buildConstant(DstOps[0], (*MaybeCsts)[0]);

298

300 LLT VecTy = DstOps[0].getLLTTy(*getMRI());

301 for (unsigned Cst : *MaybeCsts)

305 }

306 }

307 bool CanCopy = checkCopyToDefsPossible(DstOps);

308 if (!canPerformCSEForOpc(Opc))

310

311

312 if (!CanCopy) {

314

315

317 return MIB;

318 }

321 void *InsertPos = nullptr;

322 profileEverything(Opc, DstOps, SrcOps, Flag, ProfBuilder);

324 if (MIB) {

325

326 return generateCopiesIfRequired(DstOps, MIB);

327 }

328

331 return memoizeMI(NewMIB, InsertPos);

332}

333

336 constexpr unsigned Opc = TargetOpcode::G_CONSTANT;

337 if (!canPerformCSEForOpc(Opc))

339

340

344

347 void *InsertPos = nullptr;

348 profileMBBOpcode(ProfBuilder, Opc);

349 profileDstOp(Res, ProfBuilder);

352 if (MIB) {

353

354 return generateCopiesIfRequired({Res}, MIB);

355 }

356

358 return memoizeMI(NewMIB, InsertPos);

359}

360

363 constexpr unsigned Opc = TargetOpcode::G_FCONSTANT;

364 if (!canPerformCSEForOpc(Opc))

366

367

371

374 void *InsertPos = nullptr;

375 profileMBBOpcode(ProfBuilder, Opc);

376 profileDstOp(Res, ProfBuilder);

379 if (MIB) {

380

381 return generateCopiesIfRequired({Res}, MIB);

382 }

384 return memoizeMI(NewMIB, InsertPos);

385}

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

Provides analysis for continuously CSEing during GISel passes.

This file implements a version of MachineIRBuilder which CSEs insts within a MachineBasicBlock.

This contains common code to allow clients to notify changes to machine instr.

static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)

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

Class for arbitrary precision integers.

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

const T & front() const

front - Get the first element.

size_t size() const

size - Get the array size.

MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef< DstOp > DstOps, ArrayRef< SrcOp > SrcOps, std::optional< unsigned > Flag=std::nullopt) override

MachineInstrBuilder buildFConstant(const DstOp &Res, const ConstantFP &Val) override

Build and insert Res = G_FCONSTANT Val.

MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val) override

Build and insert Res = G_CONSTANT Val.

ConstantFP - Floating Point Values [float, double].

This is the shared class of boolean and integer constants.

static DILocation * getMergedLocation(DILocation *LocA, DILocation *LocB)

When two instructions are combined into a single instruction we also need to combine the original loc...

This class represents an Operation in the Expression.

LLT getLLTTy(const MachineRegisterInfo &MRI) const

FoldingSetNodeID - This class is used to gather all the unique data bits of a node.

bool shouldCSE(unsigned Opc) const

void countOpcodeHit(unsigned Opc)

void handleRemoveInst(MachineInstr *MI)

Remove this inst from the CSE map.

Abstract class that contains various methods for clients to notify about changes.

virtual void changingInstr(MachineInstr &MI)=0

This instruction is about to be mutated in some way.

virtual void changedInstr(MachineInstr &MI)=0

This instruction was mutated in some way.

const GISelInstProfileBuilder & addNodeIDMachineOperand(const MachineOperand &MO) const

constexpr bool isVector() const

constexpr LLT getElementType() const

Returns the vector's element type. Only valid for vector types.

constexpr unsigned getAddressSpace() const

constexpr LLT getScalarType() const

void splice(iterator Where, MachineBasicBlock *Other, iterator From)

Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...

MachineInstrBundleIterator< MachineInstr > iterator

void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II)

Set the insertion point before the specified position.

GISelCSEInfo * getCSEInfo()

MachineBasicBlock::iterator getInsertPt()

Current insertion point for new instructions.

MachineInstrBuilder buildSplatBuildVector(const DstOp &Res, const SrcOp &Src)

Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.

MachineInstrBuilder buildBuildVector(const DstOp &Res, ArrayRef< Register > Ops)

Build and insert Res = G_BUILD_VECTOR Op0, ...

virtual MachineInstrBuilder buildFConstant(const DstOp &Res, const ConstantFP &Val)

Build and insert Res = G_FCONSTANT Val.

MachineInstrBuilder buildInstr(unsigned Opcode)

Build and insert = Opcode .

MachineInstrBuilder buildBuildVectorConstant(const DstOp &Res, ArrayRef< APInt > Ops)

Build and insert Res = G_BUILD_VECTOR Op0, ... where each OpN is built with G_CONSTANT.

MachineFunction & getMF()

Getter for the function we currently build.

const MachineBasicBlock & getMBB() const

Getter for the basic block we currently build.

const DebugLoc & getDebugLoc()

Get the current instruction's debug location.

MachineRegisterInfo * getMRI()

Getter for MRI.

MachineIRBuilderState & getState()

Getter for the State.

MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)

Build and insert Res = COPY Op.

const DataLayout & getDataLayout() const

virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)

Build and insert Res = G_CONSTANT Val.

Register getReg(unsigned Idx) const

Get the register for the operand index.

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

void setDebugLoc(DebugLoc DL)

Replace current source information with new such.

static MachineOperand CreateFPImm(const ConstantFP *CFP)

static MachineOperand CreateCImm(const ConstantInt *CI)

reference emplace_back(ArgTypes &&... Args)

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

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

This is an optimization pass for GlobalISel generic memory operations.

bool all_of(R &&range, UnaryPredicate P)

Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.

std::optional< APFloat > ConstantFoldIntToFloat(unsigned Opcode, LLT DstTy, Register Src, const MachineRegisterInfo &MRI)

std::optional< APFloat > ConstantFoldFPBinOp(unsigned Opcode, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)

std::optional< SmallVector< unsigned > > ConstantFoldCountZeros(Register Src, const MachineRegisterInfo &MRI, std::function< unsigned(APInt)> CB)

Tries to constant fold a counting-zero operation (G_CTLZ or G_CTTZ) on Src.

std::optional< APInt > ConstantFoldExtOp(unsigned Opcode, const Register Op1, uint64_t Imm, const MachineRegisterInfo &MRI)

std::optional< APInt > ConstantFoldBinOp(unsigned Opcode, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)

decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)

std::optional< SmallVector< APInt > > ConstantFoldICmp(unsigned Pred, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)

SmallVector< APInt > ConstantFoldVectorBinop(unsigned Opcode, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)

Tries to constant fold a vector binop with sources Op1 and Op2.

GISelChangeObserver * Observer