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 << ":";
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