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

46#include

47#include

48

49using namespace llvm;

50

51#define DEBUG_TYPE "aarch64-promote-const"

52

53

55 cl::desc("Promote all vector constants"));

56

57STATISTIC(NumPromoted, "Number of promoted constants");

58STATISTIC(NumPromotedUses, "Number of promoted constants uses");

59

60

61

62

63

64namespace {

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

92class AArch64PromoteConstant : public ModulePass {

93public:

94 struct PromotedConstant {

95 bool ShouldConvert = false;

97 };

98 using PromotionCacheTy = SmallDenseMap<Constant *, PromotedConstant, 16>;

99

100 struct UpdateRecord {

103 unsigned Op;

104

105 UpdateRecord(Constant *C, Instruction *User, unsigned Op)

106 : C(C), User(User), Op(Op) {}

107 };

108

109 static char ID;

110

111 AArch64PromoteConstant() : ModulePass(ID) {}

112

113 StringRef getPassName() const override { return "AArch64 Promote Constant"; }

114

115

116

117 bool runOnModule(Module &M) override {

119 if (skipModule(M))

120 return false;

122 PromotionCacheTy PromotionCache;

123 for (auto &MF : M) {

125 }

127 }

128

129private:

130

131

132

133 bool runOnFunction(Function &F, PromotionCacheTy &PromotionCache);

134

135

136 void getAnalysisUsage(AnalysisUsage &AU) const override {

138 AU.addRequired();

140 }

141

142

144

145 using InsertionPoints = DenseMap<Instruction *, Uses>;

146

147

148 Instruction *findInsertionPoint(Instruction &User, unsigned OpNo);

149

150

151

152

153

154

155

156

157

158

159

160

161 bool isDominated(Instruction *NewPt, Instruction *User, unsigned OpNo,

162 InsertionPoints &InsertPts);

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177 bool tryAndMerge(Instruction *NewPt, Instruction *User, unsigned OpNo,

178 InsertionPoints &InsertPts);

179

180

181

182

183

184

185

186

187 void computeInsertionPoint(Instruction *User, unsigned OpNo,

188 InsertionPoints &InsertPts);

189

190

191

192

193 void insertDefinitions(Function &F, GlobalVariable &GV,

194 InsertionPoints &InsertPts);

195

196

197

198 void promoteConstants(Function &F, SmallVectorImpl &Updates,

199 PromotionCacheTy &PromotionCache);

200

201

202

203 static void appendAndTransferDominatedUses(Instruction *NewPt,

204 Instruction *User, unsigned OpNo,

206 InsertionPoints &InsertPts) {

207

208 IPI->second.emplace_back(User, OpNo);

209

210

211

212

214 Uses OldUses = std::move(IPI->second);

215 InsertPts[NewPt] = std::move(OldUses);

216

217 InsertPts.erase(OldInstr);

218 }

219};

220

221}

222

223char AArch64PromoteConstant::ID = 0;

224

226 "AArch64 Promote Constant Pass", false, false)

230

232 return new AArch64PromoteConstant();

233}

234

235

238 return true;

241 EltIdx < EndEltIdx; ++EltIdx)

243 return true;

246 return false;

247}

248

249

250

253 return true;

254

256 return false;

257

258 return all_of(C->operands(), [](const Use &U) {

259 return containsOnlyConstantData(cast(&U));

260 });

261}

262

263

264

265

266

267

269 unsigned OpIdx) {

270

271

273 return false;

274

275

277 return false;

278

279

281 return false;

282

284 return false;

285

286

288 return false;

289

290

292 return false;

293

294

296 return false;

297

298

299

301 return false;

302

303

305 return false;

306

307

309 return false;

310

311

313 return false;

314

315

318}

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

336 return false;

337

338

339

340

341

342

343

344

346 return false;

347

348

350 return false;

351

353 return true;

354

355

357 return false;

359}

360

361static bool

363 AArch64PromoteConstant::PromotionCacheTy &PromotionCache) {

364 auto Converted = PromotionCache.insert(

365 std::make_pair(&C, AArch64PromoteConstant::PromotedConstant()));

366 if (Converted.second)

368 return Converted.first->second.ShouldConvert;

369}

370

372 unsigned OpNo) {

373

374

376 return PhiInst->getIncomingBlock(OpNo)->getTerminator();

377

378 return &User;

379}

380

381bool AArch64PromoteConstant::isDominated(Instruction *NewPt, Instruction *User,

382 unsigned OpNo,

383 InsertionPoints &InsertPts) {

384 DominatorTree &DT = getAnalysis(

385 *NewPt->getParent()->getParent()).getDomTree();

386

387

388

389 for (auto &IPI : InsertPts) {

390 if (NewPt == IPI.first || DT.dominates(IPI.first, NewPt) ||

391

392

393

394 (IPI.first->getParent() != NewPt->getParent() &&

396

397 LLVM_DEBUG(dbgs() << "Insertion point dominated by:\n");

400 IPI.second.emplace_back(User, OpNo);

401 return true;

402 }

403 }

404 return false;

405}

406

407bool AArch64PromoteConstant::tryAndMerge(Instruction *NewPt, Instruction *User,

408 unsigned OpNo,

409 InsertionPoints &InsertPts) {

410 DominatorTree &DT = getAnalysis(

411 *NewPt->getParent()->getParent()).getDomTree();

413

414

415

416

417 for (InsertionPoints::iterator IPI = InsertPts.begin(),

418 EndIPI = InsertPts.end();

419 IPI != EndIPI; ++IPI) {

420 BasicBlock *CurBB = IPI->first->getParent();

421 if (NewBB == CurBB) {

422

423

424

425 LLVM_DEBUG(dbgs() << "Merge insertion point with:\n");

427 LLVM_DEBUG(dbgs() << "\nat considered insertion point.\n");

428 appendAndTransferDominatedUses(NewPt, User, OpNo, IPI, InsertPts);

429 return true;

430 }

431

432

434

435 if (!CommonDominator)

436 continue;

437

438 if (CommonDominator != NewBB) {

439

440 assert(CommonDominator != CurBB &&

441 "Instruction has not been rejected during isDominated check!");

442

444 }

445

446

447 LLVM_DEBUG(dbgs() << "Merge insertion point with:\n");

452 appendAndTransferDominatedUses(NewPt, User, OpNo, IPI, InsertPts);

453 return true;

454 }

455 return false;

456}

457

458void AArch64PromoteConstant::computeInsertionPoint(

459 Instruction *User, unsigned OpNo, InsertionPoints &InsertPts) {

460 LLVM_DEBUG(dbgs() << "Considered use, opidx " << OpNo << ":\n");

463

464 Instruction *InsertionPoint = findInsertionPoint(*User, OpNo);

465

466 LLVM_DEBUG(dbgs() << "Considered insertion point:\n");

469

470 if (isDominated(InsertionPoint, User, OpNo, InsertPts))

471 return;

472

473

474 if (tryAndMerge(InsertionPoint, User, OpNo, InsertPts))

475 return;

476

477 LLVM_DEBUG(dbgs() << "Keep considered insertion point\n");

478

479

480 InsertPts[InsertionPoint].emplace_back(User, OpNo);

481}

482

484 AArch64PromoteConstant::PromotedConstant &PC) {

485 assert(PC.ShouldConvert &&

486 "Expected that we should convert this to a global");

487 if (PC.GV)

488 return;

496 ++NumPromoted;

497}

498

499void AArch64PromoteConstant::insertDefinitions(Function &F,

500 GlobalVariable &PromotedGV,

501 InsertionPoints &InsertPts) {

502#ifndef NDEBUG

503

504 DominatorTree &DT = getAnalysis(F).getDomTree();

505#endif

506 assert(!InsertPts.empty() && "Empty uses does not need a definition");

507

508 for (const auto &IPI : InsertPts) {

509

511 LoadInst *LoadedCst =

512 Builder.CreateLoad(PromotedGV.getValueType(), &PromotedGV);

517

518

519 for (auto Use : IPI.second) {

520#ifndef NDEBUG

522 findInsertionPoint(*Use.first, Use.second)) &&

523 "Inserted definition does not dominate all its uses!");

524#endif

526 dbgs() << "Use to update " << Use.second << ":";

527 Use.first->print(dbgs());

528 dbgs() << '\n';

529 });

530 Use.first->setOperand(Use.second, LoadedCst);

531 ++NumPromotedUses;

532 }

533 }

534}

535

536void AArch64PromoteConstant::promoteConstants(

537 Function &F, SmallVectorImpl &Updates,

538 PromotionCacheTy &PromotionCache) {

539

540 for (auto U = Updates.begin(), E = Updates.end(); U != E;) {

541 LLVM_DEBUG(dbgs() << "** Compute insertion points **\n");

544 InsertionPoints InsertPts;

545 do {

546 computeInsertionPoint(U->User, U->Op, InsertPts);

547 } while (++U != E && U->C == C);

548

549 auto &Promotion = PromotionCache[C];

551 insertDefinitions(F, *Promotion.GV, InsertPts);

552 }

553}

554

555bool AArch64PromoteConstant::runOnFunction(Function &F,

556 PromotionCacheTy &PromotionCache) {

557

558

559

562

563

564 for (Use &U : I.operands()) {

566

567

568

569

571 continue;

572

573

575 continue;

576

577

578 unsigned OpNo = &U - I.op_begin();

580 continue;

581

583 }

584 }

585

586 if (Updates.empty())

587 return false;

588

589 promoteConstants(F, Updates, PromotionCache);

590 return true;

591}

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

Expand Atomic instructions

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

This file contains the declarations for the subclasses of Constant, which represent the different fla...

This file defines the DenseMap class.

static cl::opt< bool > Stress("stress-early-ifcvt", cl::Hidden, cl::desc("Turn all knobs to 11"))

static bool runOnFunction(Function &F, bool PostInlining)

Module.h This file contains the declarations for the Module class.

Machine Check Debug Module

MachineInstr unsigned OpIdx

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

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

#define STATISTIC(VARNAME, DESC)

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

Add the specified Pass class to the set of analyses preserved by this pass.

LLVM_ABI void setPreservesCFG()

This function should be called by the pass, iff they do not:

const Instruction * getTerminator() const LLVM_READONLY

Returns the terminator instruction if the block is well formed or null if the block is not well forme...

bool isInlineAsm() const

Check if this call is an inline asm statement.

This class represents a function call, abstracting a target machine's calling convention.

This is an important base class in LLVM.

LLVM_ABI bool isZeroValue() const

Return true if the value is negative zero or null value.

DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator

std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)

Legacy analysis pass which computes a DominatorTree.

LLVM_ABI Instruction * findNearestCommonDominator(Instruction *I1, Instruction *I2) const

Find the nearest instruction I that dominates both I1 and I2, in the sense that a result produced bef...

LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const

Return true if the (end of the) basic block BB dominates the use U.

@ InternalLinkage

Rename collisions when linking (static functions).

Type * getValueType() const

LLVM_ABI void setInitializer(Constant *InitVal)

setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...

ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...

reference emplace_back(ArgTypes &&... Args)

The instances of the Type class are immutable: once they are created, they are never changed.

LLVM_ABI Type * getStructElementType(unsigned N) const

bool isVectorTy() const

True if this is an instance of VectorType.

bool isArrayTy() const

True if this is an instance of ArrayType.

LLVM_ABI bool isScalableTy(SmallPtrSetImpl< const Type * > &Visited) const

Return true if this is a type whose size is a known multiple of vscale.

Type * getArrayElementType() const

LLVM_ABI unsigned getStructNumElements() const

bool isStructTy() const

True if this is an instance of StructType.

A Use represents the edge between a Value definition and its users.

Type * getType() const

All values are typed, get the type of this value.

LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false) const

Implement operator<< on Value.

const ParentTy * getParent() const

@ C

The default llvm calling convention, compatible with C.

@ BasicBlock

Various leaf nodes.

@ User

could "use" a pointer

NodeAddr< UseNode * > Use

friend class Instruction

Iterator for Instructions in a `BasicBlock.

This is an optimization pass for GlobalISel generic memory operations.

bool all_of(R &&range, UnaryPredicate P)

Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

LLVM_ABI raw_ostream & dbgs()

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

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >

ModulePass * createAArch64PromoteConstantPass()

Definition AArch64PromoteConstant.cpp:231