LLVM: lib/Target/X86/X86FixupLEAs.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

28using namespace llvm;

29

30#define FIXUPLEA_DESC "X86 LEA Fixup"

31#define FIXUPLEA_NAME "x86-fixup-LEAs"

32

33#define DEBUG_TYPE FIXUPLEA_NAME

34

35STATISTIC(NumLEAs, "Number of LEA instructions created");

36

37namespace {

39 enum RegUsageState { RU_NotUsed, RU_Write, RU_Read };

40

41

42

43

44

45

47 MachineBasicBlock &MBB);

48

49

50

51

52

54 MachineBasicBlock &MBB);

55

56

57

59 MachineBasicBlock &MBB);

60

61

62

63

64

65

66

67

68

69

70

71

72

74 MachineBasicBlock &MBB, bool OptIncDec);

75

76

77

79 MachineBasicBlock &MBB, bool OptIncDec,

80 bool UseLEAForSP) const;

81

82

83

84

85

86

87

88

90

91

92

94 MachineBasicBlock &MBB) const;

95

96

97

98

99

100

103 bool &AluDestRef, MachineOperand **KilledBase,

104 MachineOperand **KilledIndex) const;

105

106

107

109

110

111

112

115 MachineBasicBlock &MBB);

116

117

118

119

120 MachineInstr *postRAConvertToLEA(MachineBasicBlock &MBB,

122

123public:

124 static char ID;

125

126 StringRef getPassName() const override { return FIXUPLEA_DESC; }

127

128 FixupLEAPass() : MachineFunctionPass(ID) { }

129

130

131

132

133 bool runOnMachineFunction(MachineFunction &MF) override;

134

135

136 MachineFunctionProperties getRequiredProperties() const override {

137 return MachineFunctionProperties().setNoVRegs();

138 }

139

140 void getAnalysisUsage(AnalysisUsage &AU) const override {

141 AU.addRequired();

142 AU.addRequired();

144 }

145

146private:

147 TargetSchedModel TSM;

148 const X86InstrInfo *TII = nullptr;

149 const X86RegisterInfo *TRI = nullptr;

150};

151}

152

153char FixupLEAPass::ID = 0;

154

156

161 switch (MI.getOpcode()) {

162 case X86::MOV32rr:

163 case X86::MOV64rr: {

164 const MachineOperand &Src = MI.getOperand(1);

165 const MachineOperand &Dest = MI.getOperand(0);

166 MachineInstr *NewMI =

167 BuildMI(MBB, MBBI, MI.getDebugLoc(),

168 TII->get(MI.getOpcode() == X86::MOV32rr ? X86::LEA32r

169 : X86::LEA64r))

170 .add(Dest)

171 .add(Src)

172 .addImm(1)

173 .addReg(0)

174 .addImm(0)

175 .addReg(0);

176 return NewMI;

177 }

178 }

179

180 if (MI.isConvertibleTo3Addr())

181 return nullptr;

182

183 switch (MI.getOpcode()) {

184 default:

185

186 return nullptr;

187 case X86::ADD64ri32:

188 case X86::ADD64ri32_DB:

189 case X86::ADD32ri:

190 case X86::ADD32ri_DB:

191 if (!MI.getOperand(2).isImm()) {

192

193

194 return nullptr;

195 }

196 break;

197 case X86::SHL64ri:

198 case X86::SHL32ri:

199 case X86::INC64r:

200 case X86::INC32r:

201 case X86::DEC64r:

202 case X86::DEC32r:

203 case X86::ADD64rr:

204 case X86::ADD64rr_DB:

205 case X86::ADD32rr:

206 case X86::ADD32rr_DB:

207

208 break;

209 }

210 return TII->convertToThreeAddress(MI, nullptr, nullptr);

211}

212

214

215static bool isLEA(unsigned Opcode) {

216 return Opcode == X86::LEA32r || Opcode == X86::LEA64r ||

217 Opcode == X86::LEA64_32r;

218}

219

220bool FixupLEAPass::runOnMachineFunction(MachineFunction &MF) {

222 return false;

223

224 const X86Subtarget &ST = MF.getSubtarget();

225 bool IsSlowLEA = ST.slowLEA();

226 bool IsSlow3OpsLEA = ST.slow3OpsLEA();

227 bool LEAUsesAG = ST.leaUsesAG();

228

230 bool UseLEAForSP = ST.useLeaForSP();

231

232 TSM.init(&ST);

233 TII = ST.getInstrInfo();

234 TRI = ST.getRegisterInfo();

235 auto *PSI = &getAnalysis().getPSI();

236 auto *MBFI = (PSI && PSI->hasProfileSummary())

237 ? &getAnalysis().getBFI()

238 : nullptr;

239

241 for (MachineBasicBlock &MBB : MF) {

242

243 bool OptIncDecPerBB =

246 if (isLEA(I->getOpcode()))

247 continue;

248

249 if (optTwoAddrLEA(I, MBB, OptIncDecPerBB, UseLEAForSP))

250 continue;

251

252 if (IsSlowLEA)

253 processInstructionForSlowLEA(I, MBB);

254 else if (IsSlow3OpsLEA)

255 processInstrForSlow3OpLEA(I, MBB, OptIncDecPerBB);

256 }

257

258

259

260 if (LEAUsesAG) {

262 processInstruction(I, MBB);

263 }

264 }

265

267

268 return true;

269}

270

271FixupLEAPass::RegUsageState

273 RegUsageState RegUsage = RU_NotUsed;

274 MachineInstr &MI = *I;

275

276 for (const MachineOperand &MO : MI.operands()) {

277 if (MO.isReg() && MO.getReg() == p.getReg()) {

278 if (MO.isDef())

279 return RU_Write;

281 }

282 }

284}

285

286

287

288

289

292 if (I == MBB.begin()) {

293 if (MBB.isPredecessor(&MBB)) {

294 I = --MBB.end();

295 return true;

296 } else

297 return false;

298 }

299 --I;

300 return true;

301}

302

305 MachineBasicBlock &MBB) {

306 int InstrDistance = 1;

308 static const int INSTR_DISTANCE_THRESHOLD = 5;

309

310 CurInst = I;

311 bool Found;

313 while (Found && I != CurInst) {

314 if (CurInst->isCall() || CurInst->isInlineAsm())

315 break;

316 if (InstrDistance > INSTR_DISTANCE_THRESHOLD)

317 break;

318 if (usesRegister(p, CurInst) == RU_Write) {

319 return CurInst;

320 }

321 InstrDistance += TSM.computeInstrLatency(&*CurInst);

323 }

325}

326

328 return Reg == X86::EBP || Reg == X86::RBP ||

329 Reg == X86::R13D || Reg == X86::R13;

330}

331

332

333

334

335

339 Index.getReg().isValid();

340}

341

346

348 switch (LEAOpcode) {

349 default:

351 case X86::LEA32r:

352 case X86::LEA64_32r:

353 return X86::ADD32rr;

354 case X86::LEA64r:

355 return X86::ADD64rr;

356 }

357}

358

360 switch (LEAOpcode) {

361 default:

363 case X86::LEA32r:

364 case X86::LEA64_32r:

365 return X86::SUB32rr;

366 case X86::LEA64r:

367 return X86::SUB64rr;

368 }

369}

370

373 switch (LEAOpcode) {

374 default:

376 case X86::LEA32r:

377 case X86::LEA64_32r:

378 return X86::ADD32ri;

379 case X86::LEA64r:

380 return X86::ADD64ri32;

381 }

382}

383

385 switch (LEAOpcode) {

386 default:

388 case X86::LEA32r:

389 case X86::LEA64_32r:

390 return IsINC ? X86::INC32r : X86::DEC32r;

391 case X86::LEA64r:

392 return IsINC ? X86::INC64r : X86::DEC64r;

393 }

394}

395

398 MachineBasicBlock &MBB) const {

399 const int InstrDistanceThreshold = 5;

400 int InstrDistance = 1;

402

403 unsigned LEAOpcode = I->getOpcode();

406 Register DestReg = I->getOperand(0).getReg();

407

408 while (CurInst != MBB.end()) {

409 if (CurInst->isCall() || CurInst->isInlineAsm())

410 break;

411 if (InstrDistance > InstrDistanceThreshold)

412 break;

413

414

415 for (unsigned I = 0, E = CurInst->getNumOperands(); I != E; ++I) {

416 MachineOperand &Opnd = CurInst->getOperand(I);

417 if (Opnd.isReg()) {

418 if (Opnd.getReg() == DestReg) {

421

422 unsigned AluOpcode = CurInst->getOpcode();

423 if (AluOpcode != AddOpcode && AluOpcode != SubOpcode)

425

426 MachineOperand &Opnd2 = CurInst->getOperand(3 - I);

427 MachineOperand AluDest = CurInst->getOperand(0);

430

431

432

433

434 if (!CurInst->registerDefIsDead(X86::EFLAGS, TRI))

436

437 return CurInst;

438 }

439 if (TRI->regsOverlap(DestReg, Opnd.getReg()))

441 }

442 }

443

444 InstrDistance++;

445 ++CurInst;

446 }

448}

449

452 bool &BaseIndexDef, bool &AluDestRef,

453 MachineOperand **KilledBase,

454 MachineOperand **KilledIndex) const {

455 BaseIndexDef = AluDestRef = false;

456 *KilledBase = *KilledIndex = nullptr;

459 Register AluDestReg = AluI->getOperand(0).getReg();

460

461 for (MachineInstr &CurInst : llvm::make_range(std::next(LeaI), AluI)) {

462 for (MachineOperand &Opnd : CurInst.operands()) {

463 if (!Opnd.isReg())

464 continue;

466 if (TRI->regsOverlap(Reg, AluDestReg))

467 AluDestRef = true;

468 if (TRI->regsOverlap(Reg, BaseReg)) {

469 if (Opnd.isDef())

470 BaseIndexDef = true;

471 else if (Opnd.isKill())

472 *KilledBase = &Opnd;

473 }

474 if (TRI->regsOverlap(Reg, IndexReg)) {

475 if (Opnd.isDef())

476 BaseIndexDef = true;

477 else if (Opnd.isKill())

478 *KilledIndex = &Opnd;

479 }

480 }

481 }

482}

483

485 MachineBasicBlock &MBB) const {

486

489 return false;

490

491

492 bool BaseIndexDef, AluDestRef;

493 MachineOperand *KilledBase, *KilledIndex;

494 checkRegUsage(I, AluI, BaseIndexDef, AluDestRef, &KilledBase, &KilledIndex);

495

497 if (BaseIndexDef) {

498 if (AluDestRef)

499 return false;

500 InsertPos = I;

501 KilledBase = KilledIndex = nullptr;

502 }

503

504

505 Register AluDestReg = AluI->getOperand(0).getReg();

508 if (I->getOpcode() == X86::LEA64_32r) {

509 BaseReg = TRI->getSubReg(BaseReg, X86::sub_32bit);

510 IndexReg = TRI->getSubReg(IndexReg, X86::sub_32bit);

511 }

512 if (AluDestReg == IndexReg) {

513 if (BaseReg == IndexReg)

514 return false;

516 std::swap(KilledBase, KilledIndex);

517 }

518 if (BaseReg == IndexReg)

519 KilledBase = nullptr;

520

521

522 MachineInstr *NewMI1, *NewMI2;

523 unsigned NewOpcode = AluI->getOpcode();

524 NewMI1 = BuildMI(MBB, InsertPos, AluI->getDebugLoc(), TII->get(NewOpcode),

525 AluDestReg)

529 NewMI2 = BuildMI(MBB, InsertPos, AluI->getDebugLoc(), TII->get(NewOpcode),

530 AluDestReg)

534

535

536 if (KilledBase)

538 if (KilledIndex)

540

544 I = NewMI1;

545 return true;

546}

547

549 MachineBasicBlock &MBB, bool OptIncDec,

550 bool UseLEAForSP) const {

551 MachineInstr &MI = *I;

552

556 const MachineOperand &Disp = MI.getOperand(1 + X86::AddrDisp);

558

562 return false;

563

564 Register DestReg = MI.getOperand(0).getReg();

567

568

569 if (UseLEAForSP && (DestReg == X86::ESP || DestReg == X86::RSP))

570 return false;

571

572

573 if (MI.getOpcode() == X86::LEA64_32r) {

574 if (BaseReg)

575 BaseReg = TRI->getSubReg(BaseReg, X86::sub_32bit);

576 if (IndexReg)

577 IndexReg = TRI->getSubReg(IndexReg, X86::sub_32bit);

578 }

579

580 MachineInstr *NewMI = nullptr;

581

582

583

584

586 (DestReg == BaseReg || DestReg == IndexReg)) {

588 if (DestReg != BaseReg)

590

591 if (MI.getOpcode() == X86::LEA64_32r) {

592

597 } else {

600 }

601 } else if (DestReg == BaseReg && !IndexReg) {

602

603

604

605

606

607

608

609 if (OptIncDec && (Disp.getImm() == 1 || Disp.getImm() == -1)) {

610 bool IsINC = Disp.getImm() == 1;

612

613 if (MI.getOpcode() == X86::LEA64_32r) {

614

617 } else {

620 }

621 } else {

623 if (MI.getOpcode() == X86::LEA64_32r) {

624

628 } else {

631 }

632 }

634

635

636

637

638 return optLEAALU(I, MBB);

639 } else

640 return false;

641

644 I = NewMI;

645 return true;

646}

647

649 MachineBasicBlock &MBB) {

650

651 MachineInstr &MI = *I;

652 const MCInstrDesc &Desc = MI.getDesc();

654 if (AddrOffset >= 0) {

657 if (p.isReg() && p.getReg() != X86::ESP) {

658 seekLEAFixup(p, I, MBB);

659 }

661 if (q.isReg() && q.getReg() != X86::ESP) {

662 seekLEAFixup(q, I, MBB);

663 }

664 }

665}

666

667void FixupLEAPass::seekLEAFixup(MachineOperand &p,

669 MachineBasicBlock &MBB) {

672 MachineInstr *NewMI = postRAConvertToLEA(MBB, MBI);

673 if (NewMI) {

674 ++NumLEAs;

675 LLVM_DEBUG(dbgs() << "FixLEA: Candidate to replace:"; MBI->dump(););

676

682 processInstruction(J, MBB);

683 }

684 }

685}

686

688 MachineBasicBlock &MBB) {

689 MachineInstr &MI = *I;

690 const unsigned Opcode = MI.getOpcode();

691

692 const MachineOperand &Dst = MI.getOperand(0);

698

702 return;

703 const Register DstR = Dst.getReg();

706 if ((!SrcR1 || SrcR1 != DstR) && (!SrcR2 || SrcR2 != DstR))

707 return;

708 if (Scale.getImm() > 1)

709 return;

710 LLVM_DEBUG(dbgs() << "FixLEA: Candidate to replace:"; I->dump(););

712 MachineInstr *NewMI = nullptr;

713

714 if (SrcR1 && SrcR2) {

716 const MachineOperand &Src = SrcR1 == DstR ? Index : Base;

717 NewMI =

720 }

721

722 if (Offset.getImm() != 0) {

723 const MCInstrDesc &ADDri =

725 const MachineOperand &SrcR = SrcR1 == DstR ? Base : Index;

726 NewMI = BuildMI(MBB, I, MI.getDebugLoc(), ADDri, DstR)

727 .add(SrcR)

730 }

731 if (NewMI) {

734 I = NewMI;

735 }

736}

737

739 MachineBasicBlock &MBB,

740 bool OptIncDec) {

741 MachineInstr &MI = *I;

742 const unsigned LEAOpcode = MI.getOpcode();

743

744 const MachineOperand &Dest = MI.getOperand(0);

750

755 return;

756

760

761 if (MI.getOpcode() == X86::LEA64_32r) {

762 if (BaseReg)

763 BaseReg = TRI->getSubReg(BaseReg, X86::sub_32bit);

764 if (IndexReg)

765 IndexReg = TRI->getSubReg(IndexReg, X86::sub_32bit);

766 }

767

768 bool IsScale1 = Scale.getImm() == 1;

771

772

773

774 if (IsInefficientBase && DestReg == BaseReg && !IsScale1)

775 return;

776

779

780 MachineInstr *NewMI = nullptr;

781 bool BaseOrIndexIsDst = DestReg == BaseReg || DestReg == IndexReg;

782

783

784

785

786

787

788 if (IsScale1 && BaseReg == IndexReg &&

789 (hasLEAOffset(Offset) || (IsInefficientBase && !BaseOrIndexIsDst))) {

791 .add(Dest)

794 .add(Index)

796 .add(Segment);

798

801 I = NewMI;

802 return;

803 } else if (IsScale1 && BaseOrIndexIsDst) {

804

805

806

807

808

810 if (DestReg != BaseReg)

812

813 if (MI.getOpcode() == X86::LEA64_32r) {

814

820 } else {

824 }

825 } else if (!IsInefficientBase || (!IsInefficientIndex && IsScale1)) {

826

827

828

829

831 .add(Dest)

832 .add(IsInefficientBase ? Index : Base)

833 .add(Scale)

834 .add(IsInefficientBase ? Base : Index)

836 .add(Segment);

838 }

839

840

841

842 if (NewMI) {

843

845 if (OptIncDec && Offset.isImm() &&

846 (Offset.getImm() == 1 || Offset.getImm() == -1)) {

847 unsigned NewOpc =

852 } else {

858 }

859 }

860

863 I = NewMI;

864 return;

865 }

866

867

868 assert(DestReg != BaseReg && "DestReg == BaseReg should be handled already!");

869 assert(IsInefficientBase && "efficient base should be handled already!");

870

871

872 if (LEAOpcode == X86::LEA64_32r)

873 return;

874

875

877 bool BIK = Base.isKill() && BaseReg != IndexReg;

880

884 .add(Index);

886

889 I = NewMI;

890 return;

891 }

892

893

894

896 .add(Dest)

898 .add(Scale)

899 .add(Index)

901 .add(Segment);

903

909

912 I = NewMI;

913}

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

const TargetInstrInfo & TII

MachineBasicBlock MachineBasicBlock::iterator MBBI

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

===- LazyMachineBlockFrequencyInfo.h - Lazy Block Frequency -*- C++ -*–===//

Register const TargetRegisterInfo * TRI

Promote Memory to Register

#define INITIALIZE_PASS(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)

static unsigned getINCDECFromLEA(unsigned LEAOpcode, bool IsINC)

Definition X86FixupLEAs.cpp:384

static bool isLEA(unsigned Opcode)

Definition X86FixupLEAs.cpp:215

static bool hasLEAOffset(const MachineOperand &Offset)

Definition X86FixupLEAs.cpp:342

static bool isInefficientLEAReg(Register Reg)

Definition X86FixupLEAs.cpp:327

static bool hasInefficientLEABaseReg(const MachineOperand &Base, const MachineOperand &Index)

Returns true if this LEA uses base and index registers, and the base register is known to be ineffici...

Definition X86FixupLEAs.cpp:336

static unsigned getADDriFromLEA(unsigned LEAOpcode, const MachineOperand &Offset)

Definition X86FixupLEAs.cpp:371

static bool getPreviousInstr(MachineBasicBlock::iterator &I, MachineBasicBlock &MBB)

getPreviousInstr - Given a reference to an instruction in a basic block, return a reference to the pr...

Definition X86FixupLEAs.cpp:290

#define FIXUPLEA_DESC

Definition X86FixupLEAs.cpp:30

static unsigned getADDrrFromLEA(unsigned LEAOpcode)

Definition X86FixupLEAs.cpp:347

#define FIXUPLEA_NAME

Definition X86FixupLEAs.cpp:31

static unsigned getSUBrrFromLEA(unsigned LEAOpcode)

Definition X86FixupLEAs.cpp:359

AnalysisUsage & addRequired()

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

bool hasOptSize() const

Optimize this function for size (-Os) or minimum size (-Oz).

const MCInstrDesc & get(unsigned Opcode) const

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

LLVM_ABI LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, MCRegister Reg, const_iterator Before, unsigned Neighborhood=10) const

Return whether (physical) register Reg has been defined and not killed as of just before Before.

const MachineFunction * getParent() const

Return the MachineFunction containing this basic block.

LLVM_ABI instr_iterator erase(instr_iterator I)

Remove an instruction from the instruction list and delete it.

MachineInstrBundleIterator< MachineInstr > iterator

@ LQR_Dead

Register is known to be fully dead.

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.

void substituteDebugValuesForInst(const MachineInstr &Old, MachineInstr &New, unsigned MaxOperand=UINT_MAX)

Create substitutions for any tracked values in Old, to point at New.

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 MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & add(const MachineOperand &MO) const

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

Add a new virtual register operand.

Representation of each machine instruction.

LLVM_ABI void dump() const

LLVM_ABI bool addRegisterDead(Register Reg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)

We have determined MI defined a register without a use.

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)

Register getReg() const

getReg - Returns the register number.

Wrapper class representing virtual and physical registers.

constexpr bool isValid() const

virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const

Emit instructions to copy a pair of physical registers.

LLVM_ABI void init(const TargetSubtargetInfo *TSInfo, bool EnableSModel=true, bool EnableSItins=true)

Initialize the machine model for instruction scheduling.

#define llvm_unreachable(msg)

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

@ Implicit

Not emitted register (e.g. carry, or temporary result).

@ Kill

The last use of a register.

int getMemoryOperandNo(uint64_t TSFlags)

unsigned getOperandBias(const MCInstrDesc &Desc)

Compute whether all of the def operands are repeated in the uses and therefore should be skipped.

BaseReg

Stack frame base register. Bit 0 of FREInfo.Info.

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.

iterator_range< T > make_range(T x, T y)

Convenience function for iterating over sub-ranges.

LLVM_ABI bool shouldOptimizeForSize(const MachineFunction *MF, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo *BFI, PGSOQueryType QueryType=PGSOQueryType::Other)

Returns true if machine function MF is suggested to be size-optimized based on the profile.

LLVM_ABI raw_ostream & dbgs()

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

FunctionPass * createX86FixupLEAs()

Return a pass that selectively replaces certain instructions (like add, sub, inc, dec,...

Definition X86FixupLEAs.cpp:213

void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)

Implement std::swap in terms of BitVector swap.