LLVM: lib/Target/AArch64/AArch64CollectLOH.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

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

111using namespace llvm;

112

113#define DEBUG_TYPE "aarch64-collect-loh"

114

116 "Number of simplifiable ADRP dominate by another");

117STATISTIC(NumADDToSTR, "Number of simplifiable STR reachable by ADD");

118STATISTIC(NumLDRToSTR, "Number of simplifiable STR reachable by LDR");

119STATISTIC(NumADDToLDR, "Number of simplifiable LDR reachable by ADD");

120STATISTIC(NumLDRToLDR, "Number of simplifiable LDR reachable by LDR");

121STATISTIC(NumADRPToLDR, "Number of simplifiable LDR reachable by ADRP");

122STATISTIC(NumADRSimpleCandidate, "Number of simplifiable ADRP + ADD");

123

124#define AARCH64_COLLECT_LOH_NAME "AArch64 Collect Linker Optimization Hint (LOH)"

125

126namespace {

127

129 static char ID;

131

133

136 }

137

139

140 void getAnalysisUsage(AnalysisUsage &AU) const override {

143 }

144};

145

146char AArch64CollectLOH::ID = 0;

147

148}

149

152

154

155 switch (MI.getOperand(2).getType()) {

156 default:

157 return false;

158 case MachineOperand::MO_GlobalAddress:

159 case MachineOperand::MO_JumpTableIndex:

160 case MachineOperand::MO_ConstantPoolIndex:

161 case MachineOperand::MO_BlockAddress:

162 return true;

163 }

164}

165

166

167

169

170 switch (MI.getOpcode()) {

171 default:

172 return false;

173 case AArch64::ADRP:

174 return true;

175 case AArch64::ADDXri:

176 return canAddBePartOfLOH(MI);

177 case AArch64::LDRXui:

178 case AArch64::LDRWui:

179

180 switch (MI.getOperand(2).getType()) {

181 default:

182 return false;

185 }

186 }

187}

188

189

190

192 switch (MI.getOpcode()) {

193 default:

194 return false;

195 case AArch64::STRBBui:

196 case AArch64::STRHHui:

197 case AArch64::STRBui:

198 case AArch64::STRHui:

199 case AArch64::STRWui:

200 case AArch64::STRXui:

201 case AArch64::STRSui:

202 case AArch64::STRDui:

203 case AArch64::STRQui:

204

205

206

207

209 MI.getOperand(0).getReg() != MI.getOperand(1).getReg();

210 }

211}

212

213

214

216 switch (MI.getOpcode()) {

217 default:

218 return false;

219 case AArch64::LDRSBWui:

220 case AArch64::LDRSBXui:

221 case AArch64::LDRSHWui:

222 case AArch64::LDRSHXui:

223 case AArch64::LDRSWui:

224 case AArch64::LDRBui:

225 case AArch64::LDRHui:

226 case AArch64::LDRWui:

227 case AArch64::LDRXui:

228 case AArch64::LDRSui:

229 case AArch64::LDRDui:

230 case AArch64::LDRQui:

232 }

233}

234

235

237 switch (MI.getOpcode()) {

238 default:

239 return false;

240 case AArch64::LDRSWui:

241 case AArch64::LDRWui:

242 case AArch64::LDRXui:

243 case AArch64::LDRSui:

244 case AArch64::LDRDui:

245 case AArch64::LDRQui:

246 return true;

247 }

248}

249

250

251

254 auto It = First->getIterator();

255 auto EndIt = First->getParent()->instr_end();

256 if (It == EndIt)

257 return false;

259}

260

261

263

265 static_assert(AArch64::X28 - AArch64::X0 + 3 == N_GPR_REGS, "Number of GPRs");

266 static_assert(AArch64::W30 - AArch64::W0 + 1 == N_GPR_REGS, "Number of GPRs");

267 if (AArch64::X0 <= Reg && Reg <= AArch64::X28)

268 return Reg - AArch64::X0;

269 if (AArch64::W0 <= Reg && Reg <= AArch64::W30)

270 return Reg - AArch64::W0;

271

272

273 if (Reg == AArch64::FP)

274 return 29;

275 if (Reg == AArch64::LR)

276 return 30;

277 return -1;

278}

279

280

281

282

296

297

300

301 if (Info.MultiUsers || Info.OneUser) {

302 Info.IsCandidate = false;

303 Info.MultiUsers = true;

304 return;

305 }

306 Info.OneUser = true;

307

308

311 Info.IsCandidate = true;

313

314

317 Info.IsCandidate = true;

319 Info.MI1 = nullptr;

320 } else if (MI.getOpcode() == AArch64::ADDXri) {

321 Info.Type = MCLOH_AdrpAdd;

322 Info.IsCandidate = true;

323 Info.MI0 = &MI;

324 } else if ((MI.getOpcode() == AArch64::LDRXui ||

325 MI.getOpcode() == AArch64::LDRWui) &&

327 Info.Type = MCLOH_AdrpLdrGot;

328 Info.IsCandidate = true;

329 Info.MI0 = &MI;

330 }

331}

332

333

335 Info.IsCandidate = false;

336 Info.OneUser = false;

337 Info.MultiUsers = false;

338 Info.LastADRP = nullptr;

339}

340

341

342

346 return false;

347

348 if (&DefInfo != &OpInfo) {

349 OpInfo = DefInfo;

350

352 } else

354

355

356 assert(OpInfo.IsCandidate && "Expect valid state");

357 if (MI.getOpcode() == AArch64::ADDXri && canAddBePartOfLOH(MI)) {

360 OpInfo.IsCandidate = true;

361 OpInfo.MI1 = &MI;

362 return true;

363 } else if (OpInfo.Type == MCLOH_AdrpAddStr && OpInfo.MI1 == nullptr) {

365 OpInfo.IsCandidate = true;

366 OpInfo.MI1 = &MI;

367 return true;

368 }

369 } else {

370 assert((MI.getOpcode() == AArch64::LDRXui ||

371 MI.getOpcode() == AArch64::LDRWui) &&

372 "Expect LDRXui or LDRWui");

374 "Expected GOT relocation");

375 if (OpInfo.Type == MCLOH_AdrpAddStr && OpInfo.MI1 == nullptr) {

377 OpInfo.IsCandidate = true;

378 OpInfo.MI1 = &MI;

379 return true;

382 OpInfo.IsCandidate = true;

383 OpInfo.MI1 = &MI;

384 return true;

385 }

386 }

387 return false;

388}

389

390

393 if (Info.LastADRP != nullptr) {

395 << '\t' << MI << '\t' << *Info.LastADRP);

397 ++NumADRPSimpleCandidate;

398 }

399

400

401 if (Info.IsCandidate) {

402 switch (Info.Type) {

404

405

406

407

408

414 break;

416 << '\t' << MI << '\t' << *Info.MI0);

418 ++NumADRSimpleCandidate;

419 break;

420 }

424 << '\t' << MI << '\t' << *Info.MI0);

426 ++NumADRPToLDR;

427 }

428 break;

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

447 break;

449 << '\t' << MI << '\t' << *Info.MI1 << '\t'

450 << *Info.MI0);

452 ++NumADDToLDR;

453 break;

455 if (Info.MI1)

456 break;

458 break;

460 << '\t' << MI << '\t' << *Info.MI1 << '\t'

461 << *Info.MI0);

463 ++NumADDToSTR;

464 break;

467 << '\t' << MI << '\t' << *Info.MI1 << '\t'

468 << *Info.MI0);

470 ++NumLDRToLDR;

471 break;

474 << '\t' << MI << '\t' << *Info.MI1 << '\t'

475 << *Info.MI0);

477 ++NumLDRToSTR;

478 break;

481 << '\t' << MI << '\t' << *Info.MI0);

483 break;

485 llvm_unreachable("MCLOH_AdrpAdrp not used in state machine");

486 }

487 }

488

491}

492

496 return;

498 if (Idx >= 0)

500}

501

503

505 if (MO.isRegMask()) {

506 const uint32_t *RegMask = MO.getRegMask();

511 continue;

512 }

513 if (!MO.isReg() || !MO.isDef())

514 continue;

516 if (Idx < 0)

517 continue;

519 }

520

521

524 if (!MO.isReg() || !MO.readsReg())

525 continue;

527 if (Idx < 0)

528 continue;

529

530

531

532

533

534 if (UsesSeen.insert(Idx).second)

536 }

537}

538

539bool AArch64CollectLOH::runOnMachineFunction(MachineFunction &MF) {

541 return false;

542

543 LLVM_DEBUG(dbgs() << "********** AArch64 Collect LOH **********\n"

544 << "Looking in function " << MF.getName() << '\n');

545

547 AArch64FunctionInfo &AFI = *MF.getInfo();

548 for (const MachineBasicBlock &MBB : MF) {

549

550 memset(LOHInfos, 0, sizeof(LOHInfos));

551

552 for (const MachineBasicBlock *Succ : MBB.successors()) {

553 for (const auto &LI : Succ->liveins()) {

555 if (RegIdx >= 0)

556 LOHInfos[RegIdx].OneUser = true;

557 }

558 }

559

560

561

562 for (const MachineInstr &MI :

564 unsigned Opcode = MI.getOpcode();

565 switch (Opcode) {

566 case AArch64::ADDXri:

567 case AArch64::LDRXui:

568 case AArch64::LDRWui:

570 const MachineOperand &Def = MI.getOperand(0);

571 const MachineOperand &Op = MI.getOperand(1);

572 assert(Def.isReg() && Def.isDef() && "Expected reg def");

573 assert(Op.isReg() && Op.isUse() && "Expected reg use");

576 if (DefIdx >= 0 && OpIdx >= 0 &&

578 continue;

579 }

580 break;

581 case AArch64::ADRP:

582 const MachineOperand &Op0 = MI.getOperand(0);

584 if (Idx >= 0) {

585 handleADRP(MI, AFI, LOHInfos[Idx], LOHInfos);

586 continue;

587 }

588 break;

589 }

591 }

592 }

593

594

595 return false;

596}

597

599 return new AArch64CollectLOH();

600}

static int mapRegToGPRIndex(MCRegister Reg)

Map register number to index from 0-30.

Definition AArch64CollectLOH.cpp:264

#define AARCH64_COLLECT_LOH_NAME

Definition AArch64CollectLOH.cpp:124

static bool handleMiddleInst(const MachineInstr &MI, LOHInfo &DefInfo, LOHInfo &OpInfo)

Update state Info given that MI is possibly the middle instruction of an LOH involving 3 instructions...

Definition AArch64CollectLOH.cpp:343

static bool areInstructionsConsecutive(const MachineInstr *First, const MachineInstr *Second)

Returns true if there are no non-debug instructions between First and Second.

Definition AArch64CollectLOH.cpp:252

static const unsigned N_GPR_REGS

Number of GPR registers tracked by mapRegToGPRIndex()

Definition AArch64CollectLOH.cpp:262

static bool isCandidateStore(const MachineInstr &MI, const MachineOperand &MO)

Check whether the given instruction can the end of a LOH chain involving a store.

Definition AArch64CollectLOH.cpp:191

static bool supportLoadFromLiteral(const MachineInstr &MI)

Check whether the given instruction can load a literal.

Definition AArch64CollectLOH.cpp:236

static void handleADRP(const MachineInstr &MI, AArch64FunctionInfo &AFI, LOHInfo &Info, LOHInfo *LOHInfos)

Update state when seeing and ADRP instruction.

Definition AArch64CollectLOH.cpp:391

static void handleRegMaskClobber(const uint32_t *RegMask, MCPhysReg Reg, LOHInfo *LOHInfos)

Definition AArch64CollectLOH.cpp:493

static void handleClobber(LOHInfo &Info)

Update state Info given the tracked register is clobbered.

Definition AArch64CollectLOH.cpp:334

static bool canDefBePartOfLOH(const MachineInstr &MI)

Answer the following question: Can Def be one of the definition involved in a part of a LOH?

Definition AArch64CollectLOH.cpp:168

static void handleNormalInst(const MachineInstr &MI, LOHInfo *LOHInfos)

Definition AArch64CollectLOH.cpp:502

static void handleUse(const MachineInstr &MI, const MachineOperand &MO, LOHInfo &Info)

Update state Info given MI uses the tracked register.

Definition AArch64CollectLOH.cpp:298

static bool isCandidateLoad(const MachineInstr &MI)

Check whether the given instruction can be the end of a LOH chain involving a load.

Definition AArch64CollectLOH.cpp:215

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

Analysis containing CSE Info

#define LLVM_PREFERRED_TYPE(T)

\macro LLVM_PREFERRED_TYPE Adjust type of bit-field in debug info.

MachineInstr unsigned OpIdx

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

This file defines the SmallSet class.

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

#define STATISTIC(VARNAME, DESC)

AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...

void addLOHDirective(MCLOHType Kind, MILOHArgs Args)

Add a LOH directive of this Kind and this Args.

Represent the analysis usage information of a pass.

void setPreservesAll()

Set by analyses that do not transform their input at all.

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

Wrapper class representing physical registers. Should be passed by value.

reverse_instr_iterator instr_rbegin()

reverse_instr_iterator instr_rend()

iterator_range< succ_iterator > successors()

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.

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

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

Function & getFunction()

Return the LLVM function that this machine code represents.

Ty * getInfo()

getInfo - Keep track of various per-function pieces of information for backends that would like to do...

Representation of each machine instruction.

const MachineOperand & getOperand(unsigned i) const

MachineOperand class - Representation of each machine instruction operand.

LLVM_ABI unsigned getOperandNo() const

Returns the index of this operand in the instruction that it belongs to.

Register getReg() const

getReg - Returns the register number.

static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)

clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.

@ MO_GlobalAddress

Address of a global value.

SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...

std::pair< const_iterator, bool > insert(const T &V)

insert - Insert an element into the set if it isn't already there.

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

self_iterator getIterator()

#define llvm_unreachable(msg)

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

@ MO_GOT

MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...

unsigned ID

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

NodeAddr< DefNode * > Def

This is an optimization pass for GlobalISel generic memory operations.

IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)

Increment It, then continue incrementing it while it points to a debug instruction.

LLVM_ABI raw_ostream & dbgs()

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

FunctionPass * createAArch64CollectLOHPass()

Definition AArch64CollectLOH.cpp:598

auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)

Construct a range iterator which begins at It and moves forwards until End is reached,...

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

uint16_t MCPhysReg

An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...

MCLOHType

Linker Optimization Hint Type.

@ MCLOH_AdrpAddLdr

Adrp _v@PAGE -> Add _v@PAGEOFF -> Ldr.

@ MCLOH_AdrpLdrGotStr

Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Str.

@ MCLOH_AdrpLdrGotLdr

Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF -> Ldr.

@ MCLOH_AdrpLdrGot

Adrp _v@GOTPAGE -> Ldr _v@GOTPAGEOFF.

@ MCLOH_AdrpLdr

Adrp _v@PAGE -> Ldr _v@PAGEOFF.

@ MCLOH_AdrpAdd

Adrp _v@PAGE -> Add _v@PAGEOFF.

@ MCLOH_AdrpAddStr

Adrp _v@PAGE -> Add _v@PAGEOFF -> Str.

@ MCLOH_AdrpAdrp

Adrp xY, _v1@PAGE -> Adrp xY, _v2@PAGE.

DWARFExpression::Operation Op

State tracked per register.

Definition AArch64CollectLOH.cpp:283

MCLOHType Type

"Best" type of LOH possible.

Definition AArch64CollectLOH.cpp:284

unsigned IsCandidate

Possible LOH candidate.

Definition AArch64CollectLOH.cpp:286

unsigned OneUser

Found exactly one user (yet).

Definition AArch64CollectLOH.cpp:288

const MachineInstr * LastADRP

Last ADRP in same register.

Definition AArch64CollectLOH.cpp:294

const MachineInstr * MI1

Second instruction involved in the LOH (if any).

Definition AArch64CollectLOH.cpp:292

const MachineInstr * MI0

First instruction involved in the LOH.

Definition AArch64CollectLOH.cpp:291

unsigned MultiUsers

Found multiple users.

Definition AArch64CollectLOH.cpp:290