51#define DEBUG_TYPE "aarch64-promote-const"
55 cl::desc(
"Promote all vector constants"));
57STATISTIC(NumPromoted,
"Number of promoted constants");
58STATISTIC(NumPromotedUses,
"Number of promoted constants uses");
92class AArch64PromoteConstant :
public ModulePass {
94 struct PromotedConstant {
95 bool ShouldConvert =
false;
98 using PromotionCacheTy = SmallDenseMap<Constant *, PromotedConstant, 16>;
100 struct UpdateRecord {
105 UpdateRecord(Constant *C, Instruction *User,
unsigned Op)
106 : C(C), User(User), Op(Op) {}
111 AArch64PromoteConstant() : ModulePass(ID) {}
113 StringRef getPassName()
const override {
return "AArch64 Promote Constant"; }
117 bool runOnModule(
Module &M)
override {
122 PromotionCacheTy PromotionCache;
133 bool runOnFunction(Function &
F, PromotionCacheTy &PromotionCache);
136 void getAnalysisUsage(AnalysisUsage &AU)
const override {
145 using InsertionPoints = DenseMap<Instruction *, Uses>;
148 Instruction *findInsertionPoint(Instruction &User,
unsigned OpNo);
161 bool isDominated(Instruction *NewPt, Instruction *User,
unsigned OpNo,
162 InsertionPoints &InsertPts);
177 bool tryAndMerge(Instruction *NewPt, Instruction *User,
unsigned OpNo,
178 InsertionPoints &InsertPts);
187 void computeInsertionPoint(Instruction *User,
unsigned OpNo,
188 InsertionPoints &InsertPts);
193 void insertDefinitions(Function &
F, GlobalVariable &GV,
194 InsertionPoints &InsertPts);
198 void promoteConstants(Function &
F, SmallVectorImpl<UpdateRecord> &Updates,
199 PromotionCacheTy &PromotionCache);
203 static void appendAndTransferDominatedUses(Instruction *NewPt,
204 Instruction *User,
unsigned OpNo,
206 InsertionPoints &InsertPts) {
208 IPI->second.emplace_back(User, OpNo);
214 Uses OldUses = std::move(IPI->second);
215 InsertPts[NewPt] = std::move(OldUses);
217 InsertPts.erase(OldInstr);
223char AArch64PromoteConstant::ID = 0;
226 "AArch64 Promote Constant Pass",
false,
false)
232 return new AArch64PromoteConstant();
241 EltIdx < EndEltIdx; ++EltIdx)
258 return all_of(
C->operands(), [](
const Use &U) {
259 return containsOnlyConstantData(cast<Constant>(&U));
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;
376 return PhiInst->getIncomingBlock(OpNo)->getTerminator();
381bool AArch64PromoteConstant::isDominated(Instruction *NewPt, Instruction *User,
383 InsertionPoints &InsertPts) {
384 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(
385 *NewPt->
getParent()->getParent()).getDomTree();
389 for (
auto &IPI : InsertPts) {
390 if (NewPt == IPI.first || DT.
dominates(IPI.first, NewPt) ||
394 (IPI.first->getParent() != NewPt->
getParent() &&
400 IPI.second.emplace_back(User, OpNo);
407bool AArch64PromoteConstant::tryAndMerge(Instruction *NewPt, Instruction *User,
409 InsertionPoints &InsertPts) {
410 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(
411 *NewPt->
getParent()->getParent()).getDomTree();
417 for (InsertionPoints::iterator IPI = InsertPts.begin(),
418 EndIPI = InsertPts.end();
419 IPI != EndIPI; ++IPI) {
421 if (NewBB == CurBB) {
428 appendAndTransferDominatedUses(NewPt, User, OpNo, IPI, InsertPts);
435 if (!CommonDominator)
438 if (CommonDominator != NewBB) {
440 assert(CommonDominator != CurBB &&
441 "Instruction has not been rejected during isDominated check!");
452 appendAndTransferDominatedUses(NewPt, User, OpNo, IPI, InsertPts);
458void AArch64PromoteConstant::computeInsertionPoint(
459 Instruction *User,
unsigned OpNo, InsertionPoints &InsertPts) {
464 Instruction *InsertionPoint = findInsertionPoint(*User, OpNo);
470 if (isDominated(InsertionPoint, User, OpNo, InsertPts))
474 if (tryAndMerge(InsertionPoint, User, OpNo, InsertPts))
480 InsertPts[InsertionPoint].emplace_back(User, OpNo);
484 AArch64PromoteConstant::PromotedConstant &PC) {
485 assert(PC.ShouldConvert &&
486 "Expected that we should convert this to a global");
499void AArch64PromoteConstant::insertDefinitions(Function &
F,
500 GlobalVariable &PromotedGV,
501 InsertionPoints &InsertPts) {
504 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(
F).getDomTree();
506 assert(!InsertPts.empty() &&
"Empty uses does not need a definition");
508 for (
const auto &IPI : InsertPts) {
511 LoadInst *LoadedCst =
512 Builder.CreateLoad(PromotedGV.
getValueType(), &PromotedGV);
519 for (
auto Use : IPI.second) {
522 findInsertionPoint(*
Use.first,
Use.second)) &&
523 "Inserted definition does not dominate all its uses!");
526 dbgs() <<
"Use to update " <<
Use.second <<
":";
530 Use.first->setOperand(
Use.second, LoadedCst);
536void AArch64PromoteConstant::promoteConstants(
537 Function &
F, SmallVectorImpl<UpdateRecord> &Updates,
538 PromotionCacheTy &PromotionCache) {
540 for (
auto U = Updates.
begin(),
E = Updates.
end(); U !=
E;) {
544 InsertionPoints InsertPts;
546 computeInsertionPoint(
U->User,
U->Op, InsertPts);
547 }
while (++U !=
E &&
U->C ==
C);
549 auto &Promotion = PromotionCache[
C];
551 insertDefinitions(
F, *Promotion.GV, InsertPts);
555bool AArch64PromoteConstant::runOnFunction(Function &
F,
556 PromotionCacheTy &PromotionCache) {
564 for (Use &U :
I.operands()) {
578 unsigned OpNo = &
U -
I.op_begin();
589 promoteConstants(
F, Updates, PromotionCache);
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<X> - 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<X> - 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()