LLVM: lib/Target/RISCV/RISCVInsertWriteVXRM.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

32#include

33

34using namespace llvm;

35

36#define DEBUG_TYPE "riscv-insert-write-vxrm"

37#define RISCV_INSERT_WRITE_VXRM_NAME "RISC-V Insert Write VXRM Pass"

38

39namespace {

40

41class VXRMInfo {

43

46 Static,

49

50public:

51 VXRMInfo() = default;

52

53 static VXRMInfo getUnknown() {

54 VXRMInfo Info;

55 Info.setUnknown();

57 }

58

60 void setUnknown() { State = Unknown; }

61 bool isUnknown() const { return State == Unknown; }

62

63 bool isStatic() const { return State == Static; }

64

65 void setVXRMImm(unsigned Imm) {

66 assert(Imm <= 3 && "Unexpected VXRM value");

67 VXRMImm = Imm;

68 State = Static;

69 }

70 unsigned getVXRMImm() const {

71 assert(isStatic() && VXRMImm <= 3 && "Unexpected state");

72 return VXRMImm;

73 }

74

76

77 if (State != Other.State)

78 return false;

79

80 if (isStatic())

81 return VXRMImm == Other.VXRMImm;

82

83 assert((isValid() || isUnknown()) && "Unexpected state");

84 return true;

85 }

86

88

89

90

92

93 if (Other.isValid())

94 return *this;

95

96

99

100

101 if (isUnknown() || Other.isUnknown())

102 return VXRMInfo::getUnknown();

103

104

105 if (*this == Other)

106 return *this;

107

108

109 return VXRMInfo::getUnknown();

110 }

111

112

113

114

115

116

117

118 VXRMInfo intersectAnticipated(const VXRMInfo &Other) const {

119

120 if (Other.isValid())

121 return *this;

122

123

126

127

128 if (isUnknown())

130 if (Other.isUnknown())

131 return *this;

132

133

134 if (*this == Other)

135 return *this;

136

137

138 return VXRMInfo::getUnknown();

139 }

140

141#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

142

145 dbgs() << "\n";

146 }

147

149 OS << '{';

151 OS << "Uninitialized";

152 else if (isUnknown())

153 OS << "Unknown";

154 else

155 OS << getVXRMImm();

156 OS << '}';

157 }

158#endif

159};

160

161#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

164 V.print(OS);

165 return OS;

166}

167#endif

168

170

171 VXRMInfo VXRMUse;

172

173

174 VXRMInfo VXRMOut;

175

176

177 VXRMInfo AvailableIn;

178

179

180 VXRMInfo AvailableOut;

181

182

183 VXRMInfo AnticipatedIn;

184

185

186 VXRMInfo AnticipatedOut;

187

188

189 bool InQueue;

190

192};

193

196

197 std::vector BlockInfo;

198 std::queue<const MachineBasicBlock *> WorkList;

199

200public:

201 static char ID;

202

204

206

207 void getAnalysisUsage(AnalysisUsage &AU) const override {

210 }

211

212 StringRef getPassName() const override {

214 }

215

216private:

221};

222

223}

224

225char RISCVInsertWriteVXRM::ID = 0;

226

228 false, false)

229

231 BlockData &BBInfo = BlockInfo[MBB.getNumber()];

232

233 bool NeedVXRMWrite = false;

236 if (VXRMIdx >= 0 && !RISCVInstrInfo::ignoresVXRM(MI)) {

237 unsigned NewVXRMImm = MI.getOperand(VXRMIdx).getImm();

238

239 if (!BBInfo.VXRMUse.isValid())

240 BBInfo.VXRMUse.setVXRMImm(NewVXRMImm);

241

242 BBInfo.VXRMOut.setVXRMImm(NewVXRMImm);

243 NeedVXRMWrite = true;

244 continue;

245 }

246

247 if (MI.isCall() || MI.isInlineAsm() ||

248 MI.modifiesRegister(RISCV::VXRM, nullptr)) {

249 if (!BBInfo.VXRMUse.isValid())

250 BBInfo.VXRMUse.setUnknown();

251

252 BBInfo.VXRMOut.setUnknown();

253 }

254 }

255

256 return NeedVXRMWrite;

257}

258

260 BlockData &BBInfo = BlockInfo[MBB.getNumber()];

261

262 BBInfo.InQueue = false;

263

267 } else {

270 }

271

272

274 return;

275

276 if (Available != BBInfo.AvailableIn) {

279 << " changed to " << BBInfo.AvailableIn << "\n");

280 }

281

282 if (BBInfo.VXRMOut.isValid())

284

285 if (Available == BBInfo.AvailableOut)

286 return;

287

290 << " changed to " << BBInfo.AvailableOut << "\n");

291

292

294 if (!BlockInfo[S->getNumber()].InQueue) {

295 BlockInfo[S->getNumber()].InQueue = true;

296 WorkList.push(S);

297 }

298 }

299}

300

301void RISCVInsertWriteVXRM::computeAnticipated(const MachineFunction &MF, const MachineBasicBlock &MBB) {

302 BlockData &BBInfo = BlockInfo[MBB.getNumber()];

303 const RISCVSubtarget &ST = MF.getSubtarget();

304

305 BBInfo.InQueue = false;

306

307 VXRMInfo Anticipated;

309 Anticipated.setUnknown();

310 } else {

311 for (const MachineBasicBlock *S : MBB.successors())

312 if (ST.hasVXRMPipelineFlush())

313 Anticipated =

314 Anticipated.intersectAnticipated(BlockInfo[S->getNumber()].AnticipatedIn);

315 else

316 Anticipated =

317 Anticipated.intersect(BlockInfo[S->getNumber()].AnticipatedIn);

318 }

319

320

321 if (!Anticipated.isValid())

322 return;

323

324 if (Anticipated != BBInfo.AnticipatedOut) {

325 BBInfo.AnticipatedOut = Anticipated;

327 << " changed to " << BBInfo.AnticipatedOut << "\n");

328 }

329

330

331 if (BBInfo.VXRMUse.isValid())

332 Anticipated = BBInfo.VXRMUse;

333

334 if (Anticipated == BBInfo.AnticipatedIn)

335 return;

336

337 BBInfo.AnticipatedIn = Anticipated;

339 << " changed to " << BBInfo.AnticipatedIn << "\n");

340

341

343 if (!BlockInfo[P->getNumber()].InQueue) {

344 BlockInfo[P->getNumber()].InQueue = true;

345 WorkList.push(P);

346 }

347 }

348}

349

350void RISCVInsertWriteVXRM::emitWriteVXRM(MachineBasicBlock &MBB) {

351 const BlockData &BBInfo = BlockInfo[MBB.getNumber()];

352

353 VXRMInfo Info = BBInfo.AvailableIn;

354

355

356

357 bool PendingInsert = false;

358

359

360 if (BBInfo.AnticipatedIn.isStatic()) {

361

363 PendingInsert = true;

364 } else {

365

366

367

368

369

371 const BlockData &PInfo = BlockInfo[P->getNumber()];

372

373 if (PInfo.AvailableOut.isStatic() &&

374 PInfo.AvailableOut.getVXRMImm() ==

375 BBInfo.AnticipatedIn.getVXRMImm())

376 continue;

377

378

379

380 if (PInfo.AnticipatedOut.isStatic() &&

381 PInfo.AnticipatedOut.getVXRMImm() ==

382 BBInfo.AnticipatedIn.getVXRMImm())

383 continue;

384 PendingInsert = true;

385 break;

386 }

387 }

388

389 Info = BBInfo.AnticipatedIn;

390 }

391

392 for (MachineInstr &MI : MBB) {

394 if (VXRMIdx >= 0 && !RISCVInstrInfo::ignoresVXRM(MI)) {

395 unsigned NewVXRMImm = MI.getOperand(VXRMIdx).getImm();

396

397 if (PendingInsert || Info.isStatic() ||

398 Info.getVXRMImm() != NewVXRMImm) {

399 assert((!PendingInsert ||

400 (Info.isStatic() && Info.getVXRMImm() == NewVXRMImm)) &&

401 "Pending VXRM insertion mismatch");

405 PendingInsert = false;

406 }

407

409 true));

410 Info.setVXRMImm(NewVXRMImm);

411 continue;

412 }

413

414 if (MI.isCall() || MI.isInlineAsm() ||

415 MI.modifiesRegister(RISCV::VXRM, nullptr))

416 Info.setUnknown();

417 }

418

419

420

421

422

423

424 if (PendingInsert ||

425 (BBInfo.AnticipatedOut.isStatic() &&

426 (Info.isStatic() ||

427 Info.getVXRMImm() != BBInfo.AnticipatedOut.getVXRMImm()))) {

428 assert((!PendingInsert ||

429 (Info.isStatic() && BBInfo.AnticipatedOut.isStatic() &&

430 Info.getVXRMImm() == BBInfo.AnticipatedOut.getVXRMImm())) &&

431 "Pending VXRM insertion mismatch");

433 << " changing to " << BBInfo.AnticipatedOut << "\n");

435 TII->get(RISCV::WriteVXRMImm))

436 .addImm(BBInfo.AnticipatedOut.getVXRMImm());

437 }

438}

439

440bool RISCVInsertWriteVXRM::runOnMachineFunction(MachineFunction &MF) {

441

442 const RISCVSubtarget &ST = MF.getSubtarget();

443 if (ST.hasVInstructions())

444 return false;

445

446 TII = ST.getInstrInfo();

447

448 assert(BlockInfo.empty() && "Expect empty block infos");

450

451

452 bool NeedVXRMChange = false;

453 for (const MachineBasicBlock &MBB : MF)

454 NeedVXRMChange |= computeVXRMChanges(MBB);

455

456 if (!NeedVXRMChange) {

457 BlockInfo.clear();

458 return false;

459 }

460

461

462 for (const MachineBasicBlock &MBB : MF) {

463 WorkList.push(&MBB);

465 }

466 while (!WorkList.empty()) {

467 const MachineBasicBlock &MBB = *WorkList.front();

468 WorkList.pop();

469 computeAvailable(MBB);

470 }

471

472

474 WorkList.push(&MBB);

476 }

477 while (!WorkList.empty()) {

478 const MachineBasicBlock &MBB = *WorkList.front();

479 WorkList.pop();

480 computeAnticipated(MF, MBB);

481 }

482

483

484 for (MachineBasicBlock &MBB : MF)

485 emitWriteVXRM(MBB);

486

487 BlockInfo.clear();

488

489 return true;

490}

491

493 return new RISCVInsertWriteVXRM();

494}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

const TargetInstrInfo & TII

Analysis containing CSE Info

#define LLVM_ATTRIBUTE_USED

#define LLVM_DUMP_METHOD

Mark debug helper function definitions like dump() that should not be stripped from debug builds.

@ Available

We know the block is fully available. This is a fixpoint.

static Interval intersect(const Interval &I1, const Interval &I2)

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

#define RISCV_INSERT_WRITE_VXRM_NAME

Definition RISCVInsertWriteVXRM.cpp:37

static bool isValid(const char C)

Returns true if C is a valid mangled character: <0-9a-zA-Z_>.

Represent the analysis usage information of a pass.

LLVM_ABI void setPreservesCFG()

This function should be called by the pass, iff they do not:

FunctionPass class - This class is used to implement most global optimizations.

const MCInstrDesc & get(unsigned Opcode) const

Return the machine instruction descriptor that corresponds to the specified instruction opcode.

int getNumber() const

MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...

LLVM_ABI iterator getFirstTerminator()

Returns an iterator to the first terminator instruction of this basic block.

LLVM_ABI bool isEntryBlock() const

Returns true if this is the entry block of the function.

iterator_range< succ_iterator > successors()

iterator_range< pred_iterator > predecessors()

MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

const TargetSubtargetInfo & getSubtarget() const

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

unsigned getNumBlockIDs() const

getNumBlockIDs - Return the number of MBB ID's allocated.

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

Representation of each machine instruction.

static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)

virtual void print(raw_ostream &OS, const Module *M) const

print - Print out the internal state of the pass.

StringRef - Represent a constant reference to a string, i.e.

TargetInstrInfo - Interface to description of machine instruction set.

This class implements an extremely fast bulk output stream that can only output to a stream.

unsigned ID

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

static int getVXRMOpNum(const MCInstrDesc &Desc)

This is an optimization pass for GlobalISel generic memory operations.

void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)

Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

bool operator!=(uint64_t V1, const APInt &V2)

bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)

auto reverse(ContainerTy &&C)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)

FunctionPass * createRISCVInsertWriteVXRMPass()

Definition RISCVInsertWriteVXRM.cpp:492

LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)

Prints a machine basic block reference.