LLVM: lib/Target/Hexagon/HexagonNewValueJump.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

49#include

50#include

51#include

52

53using namespace llvm;

54

55#define DEBUG_TYPE "hexagon-nvj"

56

57STATISTIC(NumNVJGenerated, "Number of New Value Jump Instructions created");

58

60 cl::desc("Maximum number of predicated jumps to be converted to "

61 "New Value Jump"));

62

64 cl::desc("Disable New Value Jumps"));

65

66namespace {

67

69 static char ID;

70

72

73 void getAnalysisUsage(AnalysisUsage &AU) const override {

74 AU.addRequired();

76 }

77

78 StringRef getPassName() const override { return "Hexagon NewValueJump"; }

79

80 bool runOnMachineFunction(MachineFunction &Fn) override;

81

82 MachineFunctionProperties getRequiredProperties() const override {

83 return MachineFunctionProperties().setNoVRegs();

84 }

85

86 private:

87 const HexagonInstrInfo *QII;

88 const HexagonRegisterInfo *QRI;

89

90

91 const MachineBranchProbabilityInfo *MBPI;

92

93 bool isNewValueJumpCandidate(const MachineInstr &MI) const;

94 };

95

96}

97

98char HexagonNewValueJump::ID = 0;

99

101 "Hexagon NewValueJump", false, false)

105

106

107

114

115 if (QII->isPredicated(*II))

116 return false;

117

118

119

120

121

122

123

124

125

126

127

128 if (II->getOpcode() == TargetOpcode::KILL)

129 return false;

130

131 if (II->isImplicitDef())

132 return false;

133

134 if (QII->isSolo(*II))

135 return false;

136

137 if (QII->isFloat(*II))

138 return false;

139

140

141 [[maybe_unused]] bool HadDef = false;

143 if (!Op.isReg() || !Op.isDef())

144 continue;

145 if (HadDef)

146 return false;

147 HadDef = true;

148 if (!Hexagon::IntRegsRegClass.contains(Op.getReg()))

149 return false;

150 }

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167 for (unsigned i = 0; i < II->getNumOperands(); ++i) {

168 if (II->getOperand(i).isReg() &&

169 (II->getOperand(i).isUse() || II->getOperand(i).isDef())) {

171 ++localII;

174 ++localBegin) {

175 if (localBegin == skip)

176 continue;

177

178 if (localBegin->modifiesRegister(Reg, TRI) ||

179 localBegin->readsRegister(Reg, TRI))

180 return false;

181 }

182 }

183 }

184 return true;

185}

186

187

188

189

190

193

194 if (MII->mayStore())

195 return false;

196

197

198 if (MII->isCall())

199 return false;

200

201

202 if (!afterRA) {

203

204

205

206

207

208

209

210

211

212 if (MII->getOpcode() == TargetOpcode::KILL ||

213 MII->getOpcode() == TargetOpcode::PHI ||

214 MII->getOpcode() == TargetOpcode::COPY)

215 return false;

216

217

218

219

220

221 if (MII->getOpcode() == Hexagon::LDriw_pred ||

222 MII->getOpcode() == Hexagon::STriw_pred)

223 return false;

224 }

225

226 return true;

227}

228

232 unsigned pReg,

233 bool secondReg,

234 bool optLocation,

238

239

240

241 if (!secondReg) {

243 if (!Op2.isImm())

244 return false;

245

246 int64_t v = Op2.getImm();

247 bool Valid = false;

248

249 switch (MI.getOpcode()) {

250 case Hexagon::C2_cmpeqi:

251 case Hexagon::C4_cmpneqi:

252 case Hexagon::C2_cmpgti:

253 case Hexagon::C4_cmpltei:

254 Valid = (isUInt<5>(v) || v == -1);

255 break;

256 case Hexagon::C2_cmpgtui:

257 case Hexagon::C4_cmplteui:

259 break;

260 case Hexagon::S2_tstbit_i:

261 case Hexagon::S4_ntstbit_i:

262 Valid = (v == 0);

263 break;

264 }

265

266 if (!Valid)

267 return false;

268 }

269

270 unsigned cmpReg1, cmpOp2 = 0;

271 cmpReg1 = MI.getOperand(1).getReg();

272

273 if (secondReg) {

274 cmpOp2 = MI.getOperand(2).getReg();

275

276

277

278 if (cmpReg1 == cmpOp2)

279 return false;

280

281

282

283

287 if (def->getOpcode() == TargetOpcode::COPY)

288 return false;

289 }

290 }

291

292

293

294 ++II;

296 if (localII->isDebugInstr())

297 continue;

298

299

300

302 return false;

303

304

305

306 if (localII->modifiesRegister(pReg, TRI) ||

307 localII->readsRegister(pReg, TRI))

308 return false;

309

310

311

312

313

314

315

316

317 if (localII->modifiesRegister(cmpReg1, TRI) ||

318 (secondReg && localII->modifiesRegister(cmpOp2, TRI)))

319 return false;

320 }

321 return true;

322}

323

324

325

327 bool secondRegNewified,

330 *MBPI) {

331 bool taken = false;

335

337 taken = true;

338

339 switch (MI->getOpcode()) {

340 case Hexagon::C2_cmpeq:

341 return taken ? Hexagon::J4_cmpeq_t_jumpnv_t

342 : Hexagon::J4_cmpeq_t_jumpnv_nt;

343

344 case Hexagon::C2_cmpeqi:

345 if (reg >= 0)

346 return taken ? Hexagon::J4_cmpeqi_t_jumpnv_t

347 : Hexagon::J4_cmpeqi_t_jumpnv_nt;

348 return taken ? Hexagon::J4_cmpeqn1_t_jumpnv_t

349 : Hexagon::J4_cmpeqn1_t_jumpnv_nt;

350

351 case Hexagon::C4_cmpneqi:

352 if (reg >= 0)

353 return taken ? Hexagon::J4_cmpeqi_f_jumpnv_t

354 : Hexagon::J4_cmpeqi_f_jumpnv_nt;

355 return taken ? Hexagon::J4_cmpeqn1_f_jumpnv_t :

356 Hexagon::J4_cmpeqn1_f_jumpnv_nt;

357

358 case Hexagon::C2_cmpgt:

359 if (secondRegNewified)

360 return taken ? Hexagon::J4_cmplt_t_jumpnv_t

361 : Hexagon::J4_cmplt_t_jumpnv_nt;

362 return taken ? Hexagon::J4_cmpgt_t_jumpnv_t

363 : Hexagon::J4_cmpgt_t_jumpnv_nt;

364

365 case Hexagon::C2_cmpgti:

366 if (reg >= 0)

367 return taken ? Hexagon::J4_cmpgti_t_jumpnv_t

368 : Hexagon::J4_cmpgti_t_jumpnv_nt;

369 return taken ? Hexagon::J4_cmpgtn1_t_jumpnv_t

370 : Hexagon::J4_cmpgtn1_t_jumpnv_nt;

371

372 case Hexagon::C2_cmpgtu:

373 if (secondRegNewified)

374 return taken ? Hexagon::J4_cmpltu_t_jumpnv_t

375 : Hexagon::J4_cmpltu_t_jumpnv_nt;

376 return taken ? Hexagon::J4_cmpgtu_t_jumpnv_t

377 : Hexagon::J4_cmpgtu_t_jumpnv_nt;

378

379 case Hexagon::C2_cmpgtui:

380 return taken ? Hexagon::J4_cmpgtui_t_jumpnv_t

381 : Hexagon::J4_cmpgtui_t_jumpnv_nt;

382

383 case Hexagon::C4_cmpneq:

384 return taken ? Hexagon::J4_cmpeq_f_jumpnv_t

385 : Hexagon::J4_cmpeq_f_jumpnv_nt;

386

387 case Hexagon::C4_cmplte:

388 if (secondRegNewified)

389 return taken ? Hexagon::J4_cmplt_f_jumpnv_t

390 : Hexagon::J4_cmplt_f_jumpnv_nt;

391 return taken ? Hexagon::J4_cmpgt_f_jumpnv_t

392 : Hexagon::J4_cmpgt_f_jumpnv_nt;

393

394 case Hexagon::C4_cmplteu:

395 if (secondRegNewified)

396 return taken ? Hexagon::J4_cmpltu_f_jumpnv_t

397 : Hexagon::J4_cmpltu_f_jumpnv_nt;

398 return taken ? Hexagon::J4_cmpgtu_f_jumpnv_t

399 : Hexagon::J4_cmpgtu_f_jumpnv_nt;

400

401 case Hexagon::C4_cmpltei:

402 if (reg >= 0)

403 return taken ? Hexagon::J4_cmpgti_f_jumpnv_t

404 : Hexagon::J4_cmpgti_f_jumpnv_nt;

405 return taken ? Hexagon::J4_cmpgtn1_f_jumpnv_t

406 : Hexagon::J4_cmpgtn1_f_jumpnv_nt;

407

408 case Hexagon::C4_cmplteui:

409 return taken ? Hexagon::J4_cmpgtui_f_jumpnv_t

410 : Hexagon::J4_cmpgtui_f_jumpnv_nt;

411

412 default:

413 llvm_unreachable("Could not find matching New Value Jump instruction.");

414 }

415

416 return 0;

417}

418

419bool HexagonNewValueJump::isNewValueJumpCandidate(

421 switch (MI.getOpcode()) {

422 case Hexagon::C2_cmpeq:

423 case Hexagon::C2_cmpeqi:

424 case Hexagon::C2_cmpgt:

425 case Hexagon::C2_cmpgti:

426 case Hexagon::C2_cmpgtu:

427 case Hexagon::C2_cmpgtui:

428 case Hexagon::C4_cmpneq:

429 case Hexagon::C4_cmpneqi:

430 case Hexagon::C4_cmplte:

431 case Hexagon::C4_cmplteu:

432 case Hexagon::C4_cmpltei:

433 case Hexagon::C4_cmplteui:

434 return true;

435

436 default:

437 return false;

438 }

439}

440

441bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) {

442 LLVM_DEBUG(dbgs() << "********** Hexagon New Value Jump **********\n"

443 << "********** Function: " << MF.getName() << "\n");

444

446 return false;

447

448

449

450

451 QII = static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo());

452 QRI = static_cast<const HexagonRegisterInfo *>(

454 MBPI = &getAnalysis().getMBPI();

455

457 !MF.getSubtarget().useNewValueJumps())

458 return false;

459

461 int nvjGenerated = 0;

462

463

465 MBBb != MBBe; ++MBBb) {

466 MachineBasicBlock *MBB = &*MBBb;

467

471 << "********** dumping instr bottom up **********\n");

472 bool foundJump = false;

473 bool foundCompare = false;

474 bool invertPredicate = false;

475 unsigned predReg = 0;

476 unsigned cmpReg1 = 0;

477 int cmpOp2 = 0;

480 MachineInstr *cmpInstr = nullptr, *jmpInstr = nullptr;

481 MachineBasicBlock *jmpTarget = nullptr;

482 bool afterRA = false;

483 bool isSecondOpReg = false;

484 bool isSecondOpNewified = false;

485

487 MII != E;) {

488 MachineInstr &MI = *--MII;

489 if (MI.isDebugInstr()) {

490 continue;

491 }

492

493 if ((nvjCount == 0) || (nvjCount > -1 && nvjCount <= nvjGenerated))

494 break;

495

497

498 if (!foundJump && (MI.getOpcode() == Hexagon::J2_jumpt ||

499 MI.getOpcode() == Hexagon::J2_jumptpt ||

500 MI.getOpcode() == Hexagon::J2_jumpf ||

501 MI.getOpcode() == Hexagon::J2_jumpfpt ||

502 MI.getOpcode() == Hexagon::J2_jumptnewpt ||

503 MI.getOpcode() == Hexagon::J2_jumptnew ||

504 MI.getOpcode() == Hexagon::J2_jumpfnewpt ||

505 MI.getOpcode() == Hexagon::J2_jumpfnew)) {

506

507

508 jmpPos = MII;

509 jmpInstr = &MI;

510 predReg = MI.getOperand(0).getReg();

511 afterRA = Register::isPhysicalRegister(predReg);

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528 bool predLive = false;

529 for (const MachineBasicBlock *SuccMBB : MBB->successors())

530 if (SuccMBB->isLiveIn(predReg))

531 predLive = true;

532 if (predLive)

533 break;

534

535 if (MI.getOperand(1).isMBB())

536 continue;

537 jmpTarget = MI.getOperand(1).getMBB();

538 foundJump = true;

539 if (MI.getOpcode() == Hexagon::J2_jumpf ||

540 MI.getOpcode() == Hexagon::J2_jumpfnewpt ||

541 MI.getOpcode() == Hexagon::J2_jumpfnew) {

542 invertPredicate = true;

543 }

544 continue;

545 }

546

547

548

549

550 if (foundJump && MI.getNumOperands() == 0)

551 break;

552

553 if (foundJump && !foundCompare && MI.getOperand(0).isReg() &&

554 MI.getOperand(0).getReg() == predReg) {

555

556 if (isNewValueJumpCandidate(MI)) {

558 (MI.getDesc().isCompare()) &&

559 "Only compare instruction can be collapsed into New Value Jump");

560 isSecondOpReg = MI.getOperand(2).isReg();

561

563 afterRA, jmpPos, MF))

564 break;

565

566 cmpInstr = &MI;

567 cmpPos = MII;

568 foundCompare = true;

569

570

571

572 cmpReg1 = MI.getOperand(1).getReg();

573

574 if (isSecondOpReg)

575 cmpOp2 = MI.getOperand(2).getReg();

576 else

577 cmpOp2 = MI.getOperand(2).getImm();

578 continue;

579 }

580 }

581

582 if (foundCompare && foundJump) {

583

585 break;

586

587 bool foundFeeder = false;

589 if (MI.getOperand(0).isReg() && MI.getOperand(0).isDef() &&

590 (MI.getOperand(0).getReg() == cmpReg1 ||

591 (isSecondOpReg &&

592 MI.getOperand(0).getReg() == (unsigned)cmpOp2))) {

593

594 Register feederReg = MI.getOperand(0).getReg();

595

596

597

598

599

600

601

602 if (feederReg == cmpReg1) {

604 if (!isSecondOpReg)

605 break;

606 else

607 continue;

608 } else

609 foundFeeder = true;

610 }

611

612 if (!foundFeeder && isSecondOpReg && feederReg == (unsigned)cmpOp2)

614 break;

615

616 if (isSecondOpReg) {

617

618

619 unsigned COp = cmpInstr->getOpcode();

620 if ((COp == Hexagon::C2_cmpeq || COp == Hexagon::C4_cmpneq) &&

621 (feederReg == (unsigned)cmpOp2)) {

622 unsigned tmp = cmpReg1;

623 cmpReg1 = cmpOp2;

624 cmpOp2 = tmp;

625 }

626

627

628

629

630 if (feederReg == (unsigned)cmpOp2)

631 isSecondOpNewified = true;

632 }

633

634

635

636

637

638 auto TransferKills = [jmpPos,cmpPos] (MachineInstr &MI) {

639 for (MachineOperand &MO : MI.operands()) {

640 if (!MO.isReg() || !MO.isUse())

641 continue;

643 for (auto I = std::next(MI.getIterator()); I != jmpPos; ++I) {

644 if (I == cmpPos)

645 continue;

646 for (MachineOperand &Op : I->operands()) {

647 if (Op.isReg() || Op.isUse() || Op.isKill())

648 continue;

649 if (Op.getReg() != UseR)

650 continue;

651

652

653 Op.setIsKill(false);

654 MO.setIsKill(true);

655 return;

656 }

657 }

658 }

659 };

660

661 TransferKills(*feederPos);

662 TransferKills(*cmpPos);

663 bool MO1IsKill = cmpPos->killsRegister(cmpReg1, QRI);

664 bool MO2IsKill = isSecondOpReg && cmpPos->killsRegister(cmpOp2, QRI);

665

667 MBB->splice(jmpPos, MI.getParent(), cmpInstr);

669 MachineInstr *NewMI;

670

671 assert((isNewValueJumpCandidate(*cmpInstr)) &&

672 "This compare is not a New Value Jump candidate.");

674 isSecondOpNewified,

675 jmpTarget, MBPI);

676 if (invertPredicate)

678

679 if (isSecondOpReg)

680 NewMI = BuildMI(*MBB, jmpPos, dl, QII->get(opc))

684

685 else

686 NewMI = BuildMI(*MBB, jmpPos, dl, QII->get(opc))

690

691 assert(NewMI && "New Value Jump Instruction Not created!");

692 (void)NewMI;

700 jmpInstr->eraseFromParent();

701 ++nvjGenerated;

702 ++NumNVJGenerated;

703 break;

704 }

705 }

706 }

707 }

708

709 return true;

710}

711

713 return new HexagonNewValueJump();

714}

unsigned const MachineRegisterInfo * MRI

for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))

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

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static cl::opt< bool > DisableNewValueJumps("disable-nvjump", cl::Hidden, cl::desc("Disable New Value Jumps"))

static bool canCompareBeNewValueJump(const HexagonInstrInfo *QII, const TargetRegisterInfo *TRI, MachineBasicBlock::iterator II, unsigned pReg, bool secondReg, bool optLocation, MachineBasicBlock::iterator end, MachineFunction &MF)

Definition HexagonNewValueJump.cpp:229

static bool commonChecksToProhibitNewValueJump(bool afterRA, MachineBasicBlock::iterator MII)

Definition HexagonNewValueJump.cpp:191

hexagon Hexagon static false bool canBeFeederToNewValueJump(const HexagonInstrInfo *QII, const TargetRegisterInfo *TRI, MachineBasicBlock::iterator II, MachineBasicBlock::iterator end, MachineBasicBlock::iterator skip, MachineFunction &MF)

Definition HexagonNewValueJump.cpp:108

static cl::opt< int > DbgNVJCount("nvj-count", cl::init(-1), cl::Hidden, cl::desc("Maximum number of predicated jumps to be converted to " "New Value Jump"))

static unsigned getNewValueJumpOpcode(MachineInstr *MI, int reg, bool secondRegNewified, MachineBasicBlock *jmpTarget, const MachineBranchProbabilityInfo *MBPI)

Definition HexagonNewValueJump.cpp:326

static bool skip(DataExtractor &Data, uint64_t &Offset, bool SkippedRanges)

Skip an InlineInfo object in the specified data at the specified offset.

Register const TargetRegisterInfo * TRI

Promote Memory to Register

uint64_t IntrinsicInst * II

#define INITIALIZE_PASS_DEPENDENCY(depName)

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

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

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

AnalysisUsage & addRequired()

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

unsigned getInvertedPredicatedOpcode(const int Opc) const

int getNumber() const

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

LLVM_ABI void dump() const

iterator_range< succ_iterator > successors()

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

BranchProbability getEdgeProbability(const MachineBasicBlock *Src, const MachineBasicBlock *Dst) const

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.

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

BasicBlockListType::iterator iterator

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

LLVM_ABI void eraseFromParent()

Unlink 'this' from the containing basic block and delete it.

const MachineOperand & getOperand(unsigned i) const

MachineOperand class - Representation of each machine instruction operand.

bool isReg() const

isReg - Tests if this is a MO_Register operand.

bool isImm() const

isImm - Tests if this is a MO_Immediate operand.

void setIsKill(bool Val=true)

MachineRegisterInfo - Keep track of information for virtual and physical registers,...

Wrapper class representing virtual and physical registers.

static constexpr bool isPhysicalRegister(unsigned Reg)

Return true if the specified register number is in the physical register namespace.

TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

unsigned ID

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

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

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

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

FunctionPass * createHexagonNewValueJump()

Definition HexagonNewValueJump.cpp:712

LLVM_ABI raw_ostream & dbgs()

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

constexpr bool isUInt(uint64_t x)

Checks if an unsigned integer fits into the given bit width.

unsigned getKillRegState(bool B)

DWARFExpression::Operation Op