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 llvm {

67

70

71}

72

73namespace {

74

76 static char ID;

77

79

83 }

84

86

88

91 MachineFunctionProperties::Property::NoVRegs);

92 }

93

94 private:

97

98

100

101 bool isNewValueJumpCandidate(const MachineInstr &MI) const;

102 };

103

104}

105

106char HexagonNewValueJump::ID = 0;

107

109 "Hexagon NewValueJump", false, false)

113

114

115

122

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

124 return false;

125

126

127

128

129

130

131

132

133

134

135

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

137 return false;

138

139 if (II->isImplicitDef())

140 return false;

141

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

143 return false;

144

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

146 return false;

147

148

149 bool HadDef = false;

151 if (Op.isReg() || Op.isDef())

152 continue;

153 if (HadDef)

154 return false;

155 HadDef = true;

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

157 return false;

158 }

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

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

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

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

179 ++localII;

180 Register Reg = II->getOperand(i).getReg();

182 ++localBegin) {

183 if (localBegin == skip)

184 continue;

185

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

187 localBegin->readsRegister(Reg, TRI))

188 return false;

189 }

190 }

191 }

192 return true;

193}

194

195

196

197

198

201

202 if (MII->mayStore())

203 return false;

204

205

206 if (MII->isCall())

207 return false;

208

209

210 if (!afterRA) {

211

212

213

214

215

216

217

218

219

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

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

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

223 return false;

224

225

226

227

228

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

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

231 return false;

232 }

233

234 return true;

235}

236

240 unsigned pReg,

241 bool secondReg,

242 bool optLocation,

246

247

248

249 if (!secondReg) {

251 if (!Op2.isImm())

252 return false;

253

254 int64_t v = Op2.getImm();

255 bool Valid = false;

256

257 switch (MI.getOpcode()) {

258 case Hexagon::C2_cmpeqi:

259 case Hexagon::C4_cmpneqi:

260 case Hexagon::C2_cmpgti:

261 case Hexagon::C4_cmpltei:

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

263 break;

264 case Hexagon::C2_cmpgtui:

265 case Hexagon::C4_cmplteui:

266 Valid = isUInt<5>(v);

267 break;

268 case Hexagon::S2_tstbit_i:

269 case Hexagon::S4_ntstbit_i:

270 Valid = (v == 0);

271 break;

272 }

273

274 if (!Valid)

275 return false;

276 }

277

278 unsigned cmpReg1, cmpOp2 = 0;

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

280

281 if (secondReg) {

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

283

284

285

286 if (cmpReg1 == cmpOp2)

287 return false;

288

289

290

291

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

296 return false;

297 }

298 }

299

300

301

302 ++II;

304 if (localII->isDebugInstr())

305 continue;

306

307

308

310 return false;

311

312

313

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

315 localII->readsRegister(pReg, TRI))

316 return false;

317

318

319

320

321

322

323

324

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

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

327 return false;

328 }

329 return true;

330}

331

332

333

335 bool secondRegNewified,

338 *MBPI) {

339 bool taken = false;

343

345 taken = true;

346

347 switch (MI->getOpcode()) {

348 case Hexagon::C2_cmpeq:

349 return taken ? Hexagon::J4_cmpeq_t_jumpnv_t

350 : Hexagon::J4_cmpeq_t_jumpnv_nt;

351

352 case Hexagon::C2_cmpeqi:

353 if (reg >= 0)

354 return taken ? Hexagon::J4_cmpeqi_t_jumpnv_t

355 : Hexagon::J4_cmpeqi_t_jumpnv_nt;

356 return taken ? Hexagon::J4_cmpeqn1_t_jumpnv_t

357 : Hexagon::J4_cmpeqn1_t_jumpnv_nt;

358

359 case Hexagon::C4_cmpneqi:

360 if (reg >= 0)

361 return taken ? Hexagon::J4_cmpeqi_f_jumpnv_t

362 : Hexagon::J4_cmpeqi_f_jumpnv_nt;

363 return taken ? Hexagon::J4_cmpeqn1_f_jumpnv_t :

364 Hexagon::J4_cmpeqn1_f_jumpnv_nt;

365

366 case Hexagon::C2_cmpgt:

367 if (secondRegNewified)

368 return taken ? Hexagon::J4_cmplt_t_jumpnv_t

369 : Hexagon::J4_cmplt_t_jumpnv_nt;

370 return taken ? Hexagon::J4_cmpgt_t_jumpnv_t

371 : Hexagon::J4_cmpgt_t_jumpnv_nt;

372

373 case Hexagon::C2_cmpgti:

374 if (reg >= 0)

375 return taken ? Hexagon::J4_cmpgti_t_jumpnv_t

376 : Hexagon::J4_cmpgti_t_jumpnv_nt;

377 return taken ? Hexagon::J4_cmpgtn1_t_jumpnv_t

378 : Hexagon::J4_cmpgtn1_t_jumpnv_nt;

379

380 case Hexagon::C2_cmpgtu:

381 if (secondRegNewified)

382 return taken ? Hexagon::J4_cmpltu_t_jumpnv_t

383 : Hexagon::J4_cmpltu_t_jumpnv_nt;

384 return taken ? Hexagon::J4_cmpgtu_t_jumpnv_t

385 : Hexagon::J4_cmpgtu_t_jumpnv_nt;

386

387 case Hexagon::C2_cmpgtui:

388 return taken ? Hexagon::J4_cmpgtui_t_jumpnv_t

389 : Hexagon::J4_cmpgtui_t_jumpnv_nt;

390

391 case Hexagon::C4_cmpneq:

392 return taken ? Hexagon::J4_cmpeq_f_jumpnv_t

393 : Hexagon::J4_cmpeq_f_jumpnv_nt;

394

395 case Hexagon::C4_cmplte:

396 if (secondRegNewified)

397 return taken ? Hexagon::J4_cmplt_f_jumpnv_t

398 : Hexagon::J4_cmplt_f_jumpnv_nt;

399 return taken ? Hexagon::J4_cmpgt_f_jumpnv_t

400 : Hexagon::J4_cmpgt_f_jumpnv_nt;

401

402 case Hexagon::C4_cmplteu:

403 if (secondRegNewified)

404 return taken ? Hexagon::J4_cmpltu_f_jumpnv_t

405 : Hexagon::J4_cmpltu_f_jumpnv_nt;

406 return taken ? Hexagon::J4_cmpgtu_f_jumpnv_t

407 : Hexagon::J4_cmpgtu_f_jumpnv_nt;

408

409 case Hexagon::C4_cmpltei:

410 if (reg >= 0)

411 return taken ? Hexagon::J4_cmpgti_f_jumpnv_t

412 : Hexagon::J4_cmpgti_f_jumpnv_nt;

413 return taken ? Hexagon::J4_cmpgtn1_f_jumpnv_t

414 : Hexagon::J4_cmpgtn1_f_jumpnv_nt;

415

416 case Hexagon::C4_cmplteui:

417 return taken ? Hexagon::J4_cmpgtui_f_jumpnv_t

418 : Hexagon::J4_cmpgtui_f_jumpnv_nt;

419

420 default:

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

422 }

423

424 return 0;

425}

426

427bool HexagonNewValueJump::isNewValueJumpCandidate(

429 switch (MI.getOpcode()) {

430 case Hexagon::C2_cmpeq:

431 case Hexagon::C2_cmpeqi:

432 case Hexagon::C2_cmpgt:

433 case Hexagon::C2_cmpgti:

434 case Hexagon::C2_cmpgtu:

435 case Hexagon::C2_cmpgtui:

436 case Hexagon::C4_cmpneq:

437 case Hexagon::C4_cmpneqi:

438 case Hexagon::C4_cmplte:

439 case Hexagon::C4_cmplteu:

440 case Hexagon::C4_cmpltei:

441 case Hexagon::C4_cmplteui:

442 return true;

443

444 default:

445 return false;

446 }

447}

448

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

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

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

452

454 return false;

455

456

457

458

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

463

466 return false;

467

469 int nvjGenerated = 0;

470

471

473 MBBb != MBBe; ++MBBb) {

475

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

480 bool foundJump = false;

481 bool foundCompare = false;

482 bool invertPredicate = false;

483 unsigned predReg = 0;

484 unsigned cmpReg1 = 0;

485 int cmpOp2 = 0;

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

490 bool afterRA = false;

491 bool isSecondOpReg = false;

492 bool isSecondOpNewified = false;

493

495 MII != E;) {

497 if (MI.isDebugInstr()) {

498 continue;

499 }

500

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

502 break;

503

505

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

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

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

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

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

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

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

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

514

515

516 jmpPos = MII;

517 jmpInstr = &MI;

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

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536 bool predLive = false;

538 if (SuccMBB->isLiveIn(predReg))

539 predLive = true;

540 if (predLive)

541 break;

542

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

544 continue;

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

546 foundJump = true;

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

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

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

550 invertPredicate = true;

551 }

552 continue;

553 }

554

555

556

557

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

559 break;

560

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

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

563

564 if (isNewValueJumpCandidate(MI)) {

566 (MI.getDesc().isCompare()) &&

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

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

569

571 afterRA, jmpPos, MF))

572 break;

573

574 cmpInstr = &MI;

575 cmpPos = MII;

576 foundCompare = true;

577

578

579

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

581

582 if (isSecondOpReg)

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

584 else

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

586 continue;

587 }

588 }

589

590 if (foundCompare && foundJump) {

591

593 break;

594

595 bool foundFeeder = false;

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

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

599 (isSecondOpReg &&

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

601

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

603

604

605

606

607

608

609

610 if (feederReg == cmpReg1) {

612 if (!isSecondOpReg)

613 break;

614 else

615 continue;

616 } else

617 foundFeeder = true;

618 }

619

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

622 break;

623

624 if (isSecondOpReg) {

625

626

627 unsigned COp = cmpInstr->getOpcode();

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

629 (feederReg == (unsigned)cmpOp2)) {

630 unsigned tmp = cmpReg1;

631 cmpReg1 = cmpOp2;

632 cmpOp2 = tmp;

633 }

634

635

636

637

638 if (feederReg == (unsigned)cmpOp2)

639 isSecondOpNewified = true;

640 }

641

642

643

644

645

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

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

649 continue;

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

652 if (I == cmpPos)

653 continue;

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

656 continue;

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

658 continue;

659

660

661 Op.setIsKill(false);

662 MO.setIsKill(true);

663 return;

664 }

665 }

666 }

667 };

668

669 TransferKills(*feederPos);

670 TransferKills(*cmpPos);

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

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

673

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

678

679 assert((isNewValueJumpCandidate(*cmpInstr)) &&

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

682 isSecondOpNewified,

683 jmpTarget, MBPI);

684 if (invertPredicate)

685 opc = QII->getInvertedPredicatedOpcode(opc);

686

687 if (isSecondOpReg)

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

692

693 else

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

698

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

700 (void)NewMI;

708 jmpInstr->eraseFromParent();

709 ++nvjGenerated;

710 ++NumNVJGenerated;

711 break;

712 }

713 }

714 }

715 }

716

717 return true;

718}

719

721 return new HexagonNewValueJump();

722}

unsigned const MachineRegisterInfo * MRI

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)

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

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

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"))

hexagon Hexagon NewValueJump

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

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

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

unsigned const TargetRegisterInfo * TRI

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)

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

static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)

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

#define STATISTIC(VARNAME, DESC)

Represent the analysis usage information of a pass.

AnalysisUsage & addRequired()

This class represents an Operation in the Expression.

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

bool useNewValueJumps() const

int getNumber() const

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

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

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.

virtual bool runOnMachineFunction(MachineFunction &MF)=0

runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...

virtual MachineFunctionProperties getRequiredProperties() const

Properties which a MachineFunction may have at a given point in time.

MachineFunctionProperties & set(Property P)

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.

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.

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

PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...

virtual StringRef getPassName() const

getPassName - Return a nice clean name for a pass.

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.

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

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

virtual const TargetRegisterInfo * getRegisterInfo() const

getRegisterInfo - If register information is available, return it.

virtual const TargetInstrInfo * getInstrInfo() const

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

void initializeHexagonNewValueJumpPass(PassRegistry &)

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

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

FunctionPass * createHexagonNewValueJump()

raw_ostream & dbgs()

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

unsigned getKillRegState(bool B)