LLVM: lib/Target/Hexagon/HexagonCopyToCombine.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

31

32using namespace llvm;

33

34#define DEBUG_TYPE "hexagon-copy-combine"

35

38

39 cl::desc("Disable merging into combines"));

42

43 cl::desc("Disable generation of const64"));

44static

48 cl::desc("Maximum distance between a tfr feeding a store we "

49 "consider the store still to be newifiable"));

50

51namespace llvm {

54}

55

56

57namespace {

58

64

67

68public:

69 static char ID;

70

72

75 }

76

78 return "Hexagon Copy-To-Combine Pass";

79 }

80

82

85 MachineFunctionProperties::Property::NoVRegs);

86 }

87

88private:

90 bool AllowC64);

91

93

96 bool OptForSize);

97

99 unsigned I1DestReg, unsigned I2DestReg,

100 bool &DoInsertAtI1);

101

104

107

110

113

116};

117

118}

119

120char HexagonCopyToCombine::ID = 0;

121

123 "Hexagon Copy-To-Combine Pass", false, false)

124

127 switch (MI.getOpcode()) {

128 case Hexagon::A2_tfr: {

129

133

136 return Hexagon::IntRegsRegClass.contains(DestReg) &&

137 Hexagon::IntRegsRegClass.contains(SrcReg);

138 }

139

140 case Hexagon::A2_tfrsi: {

141

142

146

148

149

150

152 return false;

153

154

155 bool NotExt = Op1.isImm() && isInt<8>(Op1.getImm());

156 return Hexagon::IntRegsRegClass.contains(DestReg) &&

158 }

159

160 case Hexagon::V6_vassign:

161 return true;

162

163 default:

164 break;

165 }

166

167 return false;

168}

169

171 if (I.getOpcode() == Hexagon::TFRI64_V4 ||

172 I.getOpcode() == Hexagon::A2_tfrsi) {

174 return Op.isImm() || !isInt(Op.getImm());

175 }

176 return false;

177}

178

179

180

184 unsigned HiOpc = HighRegInst.getOpcode();

185 unsigned LoOpc = LowRegInst.getOpcode();

186

187 auto verifyOpc = [](unsigned Opc) -> void {

188 switch (Opc) {

189 case Hexagon::A2_tfr:

190 case Hexagon::A2_tfrsi:

191 case Hexagon::V6_vassign:

192 break;

193 default:

195 }

196 };

197 verifyOpc(HiOpc);

198 verifyOpc(LoOpc);

199

200 if (HiOpc == Hexagon::V6_vassign || LoOpc == Hexagon::V6_vassign)

201 return HiOpc == LoOpc;

202

203 if (!AllowC64) {

204

205 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&

206 isGreaterThanNBitTFRI<6>(LowRegInst))

207 return false;

208 }

209

210

211

212 if (isGreaterThanNBitTFRI<16>(HighRegInst) &&

216

217

218

219 if (isGreaterThanNBitTFRI<8>(HighRegInst) &&

220 isGreaterThanNBitTFRI<8>(LowRegInst))

221 return false;

222

223 return true;

224}

225

228 if (Hexagon::IntRegsRegClass.contains(Reg))

229 return (Reg - Hexagon::R0) % 2 == 0;

230 if (Hexagon::HvxVRRegClass.contains(Reg))

231 return (Reg - Hexagon::V0) % 2 == 0;

233}

234

237 if (Op.isReg() && Op.getReg() == RegNotKilled && Op.isKill())

238 Op.setIsKill(false);

239}

240

241

242

244 unsigned DestReg,

247 MI.modifiesRegister(DestReg, TRI) || MI.readsRegister(DestReg, TRI) ||

248 MI.hasUnmodeledSideEffects() || MI.isInlineAsm() ||

249 MI.isMetaInstruction();

250}

251

254}

255

256

257

258bool HexagonCopyToCombine::isSafeToMoveTogether(MachineInstr &I1,

260 unsigned I1DestReg,

261 unsigned I2DestReg,

262 bool &DoInsertAtI1) {

264

265

266

267 if (I2UseReg && I1.modifiesRegister(I2UseReg, TRI))

268 return false;

269

270 bool isSafe = true;

271

272

273 {

274

275

276

279

281 End = ++I1.getIterator().getReverse();

282

283

284

285 unsigned KilledOperand = 0;

287 KilledOperand = I2UseReg;

289

290 for (; I != End; ++I) {

291

292

293

294

295

296

297 if (I->isDebugInstr())

298 continue;

299

301 isSafe = false;

302 break;

303 }

304

305

306 if (!KillingInstr && KilledOperand &&

307 I->readsRegister(KilledOperand, TRI))

308 KillingInstr = &*I;

309 }

310 if (isSafe) {

311

312 if (KillingInstr) {

314 (void)Added;

315 assert(Added && "Must successfully update kill flag");

317 }

318 DoInsertAtI1 = true;

319 return true;

320 }

321 }

322

323

324 {

325

327

331

332

333

335 unsigned KilledOperand = 0;

336

337 while(++I != End) {

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355 if (MI.isDebugInstr()) {

356 if (MI.readsRegister(I1DestReg, TRI))

357 DbgMItoMove.push_back(&MI);

358 continue;

359 }

360

362

363 (MI.killsRegister(I1UseReg, nullptr) &&

364 MI.killsRegister(I1UseReg, TRI)))

365 return false;

366

367

368 if (I1UseReg && MI.killsRegister(I1UseReg, nullptr)) {

369 assert(!KillingInstr && "Should only see one killing instruction");

370 KilledOperand = I1UseReg;

371 KillingInstr = &MI;

372 }

373 }

374 if (KillingInstr) {

376

377

378 bool Added = I1.addRegisterKilled(KilledOperand, TRI);

379 (void)Added;

380 assert(Added && "Must successfully update kill flag");

381 }

382 DoInsertAtI1 = false;

383 }

384

385 return true;

386}

387

388

389

390void

391HexagonCopyToCombine::findPotentialNewifiableTFRs(MachineBasicBlock &BB) {

394 if (MI.isDebugInstr())

395 continue;

396

397

399

401

402 if (Op.isReg() || Op.isUse() || Op.getReg())

403 continue;

404

405

408 if (!DefInst)

409 continue;

411 continue;

412

413

414

416 unsigned NumInstsToDef = 0;

417 while (&*It != &MI) {

418 if (!It->isDebugInstr())

419 ++NumInstsToDef;

420 ++It;

421 }

422

424 continue;

425

426 PotentiallyNewifiableTFR.insert(DefInst);

427 }

428

429 continue;

430 }

431

432

433

435 if (Op.isReg()) {

436 if (Op.isDef() || Op.getReg())

437 continue;

439 if (Hexagon::DoubleRegsRegClass.contains(Reg)) {

442 } else if (Hexagon::IntRegsRegClass.contains(Reg))

443 LastDef[Reg] = &MI;

444 } else if (Op.isRegMask()) {

445 for (unsigned Reg : Hexagon::IntRegsRegClass)

446 if (Op.clobbersPhysReg(Reg))

447 LastDef[Reg] = &MI;

448 }

449 }

450 }

451}

452

453bool HexagonCopyToCombine::runOnMachineFunction(MachineFunction &MF) {

455 return false;

456

458

459 bool HasChanged = false;

460

461

463 TRI = ST->getRegisterInfo();

464 TII = ST->getInstrInfo();

465

467 bool OptForSize = F.hasFnAttribute(Attribute::OptimizeForSize);

468

469

472

473

474 if (!OptForSize && ST->isTinyCore())

476

477

479 PotentiallyNewifiableTFR.clear();

480 findPotentialNewifiableTFRs(MBB);

481

482

486

487 if (I1.isDebugInstr())

488 continue;

489

490

491

492

494 continue;

495

496

498 continue;

499

500

501

502

503 bool DoInsertAtI1 = false;

504 DbgMItoMove.clear();

505 MachineInstr *I2 = findPairable(I1, DoInsertAtI1, OptForSize);

506 if (I2) {

507 HasChanged = true;

508 combine(I1, *I2, MI, DoInsertAtI1, OptForSize);

509 }

510 }

511 }

512

513 return HasChanged;

514}

515

516

517

518

519

521 bool &DoInsertAtI1,

522 bool AllowC64) {

524 while (I2 != I1.getParent()->end() && I2->isDebugInstr())

525 ++I2;

526

527 Register I1DestReg = I1.getOperand(0).getReg();

528

530 ++I2) {

531

532 if (I2->modifiesRegister(I1DestReg, TRI))

533 break;

534

535

537 continue;

538

539

541 continue;

542

543 Register I2DestReg = I2->getOperand(0).getReg();

544

545

546

547 bool IsI1LowReg = (I2DestReg - I1DestReg) == 1;

548 bool IsI2LowReg = (I1DestReg - I2DestReg) == 1;

549 unsigned FirstRegIndex = IsI1LowReg ? I1DestReg : I2DestReg;

550 if ((!IsI1LowReg && !IsI2LowReg) || isEvenReg(FirstRegIndex))

551 continue;

552

553

554

555

558 break;

559

560 if (isSafeToMoveTogether(I1, *I2, I1DestReg, I2DestReg, DoInsertAtI1))

561 return &*I2;

562

563

564 break;

565 }

566 return nullptr;

567}

568

571 bool DoInsertAtI1, bool OptForSize) {

572

573

575 ++MI;

576

577

578 Register I1DestReg = I1.getOperand(0).getReg();

580 bool IsI1Loreg = (I2DestReg - I1DestReg) == 1;

581 unsigned LoRegDef = IsI1Loreg ? I1DestReg : I2DestReg;

582 unsigned SubLo;

583

585 if (Hexagon::IntRegsRegClass.contains(LoRegDef)) {

586 SuperRC = &Hexagon::DoubleRegsRegClass;

587 SubLo = Hexagon::isub_lo;

588 } else if (Hexagon::HvxVRRegClass.contains(LoRegDef)) {

590 SuperRC = &Hexagon::HvxWRRegClass;

591 SubLo = Hexagon::vsub_lo;

592 } else

594

595

596 unsigned DoubleRegDest = TRI->getMatchingSuperReg(LoRegDef, SubLo, SuperRC);

597 assert(DoubleRegDest != 0 && "Expect a valid register");

598

599

602

603

604 bool IsHiReg = HiOperand.isReg();

605 bool IsLoReg = LoOperand.isReg();

606

607

608 bool IsC64 = OptForSize && LoOperand.isImm() && HiOperand.isImm() &&

609 isGreaterThanNBitTFRI<16>(I1) && isGreaterThanNBitTFRI<16>(I2);

610

612

613 if (IsHiReg && IsLoReg)

614 emitCombineRR(InsertPt, DoubleRegDest, HiOperand, LoOperand);

615 else if (IsHiReg)

616 emitCombineRI(InsertPt, DoubleRegDest, HiOperand, LoOperand);

617 else if (IsLoReg)

618 emitCombineIR(InsertPt, DoubleRegDest, HiOperand, LoOperand);

620 emitConst64(InsertPt, DoubleRegDest, HiOperand, LoOperand);

621 else

622 emitCombineII(InsertPt, DoubleRegDest, HiOperand, LoOperand);

623

624

625

626 if (!DoInsertAtI1 && DbgMItoMove.size() != 0) {

627

629 for (auto *NewMI : DbgMItoMove) {

630

631

632 if (NewMI == MI)

633 ++MI;

634 BB->splice(InsertPt, BB, NewMI);

635 }

636 }

637

638 I1.eraseFromParent();

640}

641

643 unsigned DoubleDestReg,

647

648 DebugLoc DL = InsertPt->getDebugLoc();

651 "Both operands must be immediate");

652

653 int64_t V = HiOperand.getImm();

654 V = (V << 32) | (0x0ffffffffLL & LoOperand.getImm());

655 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::CONST64), DoubleDestReg)

657}

658

660 unsigned DoubleDestReg,

663 DebugLoc DL = InsertPt->getDebugLoc();

665

666

668 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)

672 return;

673 }

675 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)

679 return;

680 }

681

682

684 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)

688 return;

689 }

691 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)

695 return;

696 }

697

698

699 if (HiOperand.isJTI()) {

700 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)

703 return;

704 }

705 if (LoOperand.isJTI()) {

706 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)

709 return;

710 }

711

712

713 if (HiOperand.isCPI()) {

714 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)

718 return;

719 }

720 if (LoOperand.isCPI()) {

721 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)

725 return;

726 }

727

728

729

730

731 if (isInt<8>(LoOperand.getImm())) {

732 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)

735 return;

736 }

737

738

739 if (isInt<8>(HiOperand.getImm())) {

740 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineii), DoubleDestReg)

743 return;

744 }

745

746

747

748 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A2_combineii), DoubleDestReg)

751}

752

754 unsigned DoubleDestReg,

759

760 DebugLoc DL = InsertPt->getDebugLoc();

762

763

765 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)

768 .addReg(LoReg, LoRegKillFlag);

769 return;

770 }

771

773 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)

776 .addReg(LoReg, LoRegKillFlag);

777 return;

778 }

779

780 if (HiOperand.isJTI()) {

781 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)

783 .addReg(LoReg, LoRegKillFlag);

784 return;

785 }

786

787 if (HiOperand.isCPI()) {

788 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)

791 .addReg(LoReg, LoRegKillFlag);

792 return;

793 }

794

795

796 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineir), DoubleDestReg)

798 .addReg(LoReg, LoRegKillFlag);

799}

800

802 unsigned DoubleDestReg,

807

808 DebugLoc DL = InsertPt->getDebugLoc();

810

811

813 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)

814 .addReg(HiReg, HiRegKillFlag)

817 return;

818 }

819

821 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)

822 .addReg(HiReg, HiRegKillFlag)

825 return;

826 }

827

828 if (LoOperand.isJTI()) {

829 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)

832 return;

833 }

834

835 if (LoOperand.isCPI()) {

836 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)

840 return;

841 }

842

843

844

845 BuildMI(*BB, InsertPt, DL, TII->get(Hexagon::A4_combineri), DoubleDestReg)

846 .addReg(HiReg, HiRegKillFlag)

848}

849

851 unsigned DoubleDestReg,

858

859 DebugLoc DL = InsertPt->getDebugLoc();

861

862

863

864 unsigned NewOpc;

865 if (Hexagon::DoubleRegsRegClass.contains(DoubleDestReg)) {

866 NewOpc = Hexagon::A2_combinew;

867 } else if (Hexagon::HvxWRRegClass.contains(DoubleDestReg)) {

869 NewOpc = Hexagon::V6_vcombine;

870 } else

872

873 BuildMI(*BB, InsertPt, DL, TII->get(NewOpc), DoubleDestReg)

874 .addReg(HiReg, HiRegKillFlag)

875 .addReg(LoReg, LoRegKillFlag);

876}

877

879 return new HexagonCopyToCombine();

880}

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

This file defines the DenseMap class.

This file defines the DenseSet and SmallDenseSet classes.

static Register UseReg(const MachineOperand &MO)

const HexagonInstrInfo * TII

static cl::opt< bool > IsConst64Disabled("disable-const64", cl::Hidden, cl::desc("Disable generation of const64"))

static bool isEvenReg(unsigned Reg)

static bool isUnsafeToMoveAcross(MachineInstr &MI, unsigned UseReg, unsigned DestReg, const TargetRegisterInfo *TRI)

Returns true if it is unsafe to move a copy instruction from UseReg to DestReg over the instruction M...

static cl::opt< bool > IsCombinesDisabled("disable-merge-into-combines", cl::Hidden, cl::desc("Disable merging into combines"))

const HexagonInstrInfo bool ShouldCombineAggressively

static bool areCombinableOperations(const TargetRegisterInfo *TRI, MachineInstr &HighRegInst, MachineInstr &LowRegInst, bool AllowC64)

areCombinableOperations - Returns true if the two instruction can be merge into a combine (ignoring r...

static cl::opt< unsigned > MaxNumOfInstsBetweenNewValueStoreAndTFR("max-num-inst-between-tfr-and-nv-store", cl::Hidden, cl::init(4), cl::desc("Maximum distance between a tfr feeding a store we " "consider the store still to be newifiable"))

static void removeKillInfo(MachineInstr &MI, unsigned RegNotKilled)

static bool isGreaterThanNBitTFRI(const MachineInstr &I)

unsigned const TargetRegisterInfo * TRI

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

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

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

Represent the analysis usage information of a pass.

This class represents an Operation in the Expression.

Implements a dense probed hash-table based set.

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

bool mayBeNewStore(const MachineInstr &MI) const

const MachineFunction * getParent() const

Return the MachineFunction containing this basic block.

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

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.

Function & getFunction()

Return the LLVM function that this machine code represents.

const TargetMachine & getTarget() const

getTarget - Return the target machine this machine code is compiled with

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & addBlockAddress(const BlockAddress *BA, int64_t Offset=0, unsigned TargetFlags=0) const

const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const

const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const

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

Add a new virtual register operand.

const MachineInstrBuilder & addJumpTableIndex(unsigned Idx, unsigned TargetFlags=0) const

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

bool killsRegister(Register Reg, const TargetRegisterInfo *TRI) const

Return true if the MachineInstr kills the specified register.

void eraseFromParent()

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

bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)

We have determined MI kills a register.

const MachineOperand & getOperand(unsigned i) const

MachineOperand class - Representation of each machine instruction operand.

const GlobalValue * getGlobal() const

bool isReg() const

isReg - Tests if this is a MO_Register operand.

bool isCPI() const

isCPI - Tests if this is a MO_ConstantPoolIndex operand.

bool isImm() const

isImm - Tests if this is a MO_Immediate operand.

bool isJTI() const

isJTI - Tests if this is a MO_JumpTableIndex operand.

const BlockAddress * getBlockAddress() const

unsigned getTargetFlags() const

bool isGlobal() const

isGlobal - Tests if this is a MO_GlobalAddress operand.

bool isBlockAddress() const

isBlockAddress - Tests if this is a MO_BlockAddress operand.

Register getReg() const

getReg - Returns the register number.

int64_t getOffset() const

Return the offset from the symbol in this operand.

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.

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

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

CodeGenOptLevel getOptLevel() const

Returns the optimization level: None, Less, Default, or Aggressive.

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

self_iterator getIterator()

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

Reg

All possible values of the reg field in the ModR/M byte.

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.

raw_ostream & dbgs()

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

FunctionPass * createHexagonCopyToCombine()

unsigned getKillRegState(bool B)

void initializeHexagonCopyToCombinePass(PassRegistry &)