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;
100 struct UpdateRecord {
123 bool Changed =
false;
124 PromotionCacheTy PromotionCache;
164 InsertionPoints &InsertPts);
180 InsertionPoints &InsertPts);
190 InsertionPoints &InsertPts);
196 InsertionPoints &InsertPts);
201 PromotionCacheTy &PromotionCache);
205 static void appendAndTransferDominatedUses(
Instruction *NewPt,
208 InsertionPoints &InsertPts) {
210 IPI->second.emplace_back(
User, OpNo);
216 Uses OldUses = std::move(IPI->second);
217 InsertPts[NewPt] = std::move(OldUses);
219 InsertPts.erase(OldInstr);
225char AArch64PromoteConstant::ID = 0;
228 "AArch64 Promote Constant Pass",
false,
false)
234 return new AArch64PromoteConstant();
243 EltIdx < EndEltIdx; ++EltIdx)
254 if (isa<ConstantData>(
C))
257 if (isa<GlobalValue>(
C) || isa<BlockAddress>(
C) || isa<ConstantExpr>(
C))
260 return all_of(
C->operands(), [](
const Use &U) {
261 return containsOnlyConstantData(cast<Constant>(&U));
274 if (isa<const ShuffleVectorInst>(Instr) && OpIdx == 2)
278 if (isa<const ExtractValueInst>(Instr) && OpIdx > 0)
282 if (isa<const InsertValueInst>(Instr) && OpIdx > 1)
285 if (isa<const AllocaInst>(Instr) && OpIdx > 0)
289 if (isa<const LoadInst>(Instr) && OpIdx > 0)
293 if (isa<const StoreInst>(Instr) && OpIdx > 1)
297 if (isa<const GetElementPtrInst>(Instr) && OpIdx > 0)
302 if (isa<const LandingPadInst>(Instr))
306 if (isa<const SwitchInst>(Instr))
310 if (isa<const IndirectBrInst>(Instr))
314 if (isa<const IntrinsicInst>(Instr))
318 const CallInst *CI = dyn_cast<const CallInst>(Instr);
337 if (isa<const UndefValue>(Cst))
362 auto Converted = PromotionCache.
insert(
363 std::make_pair(&
C, AArch64PromoteConstant::PromotedConstant()));
364 if (Converted.second)
366 return Converted.first->second.ShouldConvert;
374 return PhiInst->getIncomingBlock(OpNo)->getTerminator();
381 InsertionPoints &InsertPts) {
383 *NewPt->
getParent()->getParent()).getDomTree();
387 for (
auto &IPI : InsertPts) {
388 if (NewPt == IPI.first || DT.
dominates(IPI.first, NewPt) ||
392 (IPI.first->getParent() != NewPt->
getParent() &&
398 IPI.second.emplace_back(
User, OpNo);
407 InsertionPoints &InsertPts) {
409 *NewPt->
getParent()->getParent()).getDomTree();
415 for (InsertionPoints::iterator IPI = InsertPts.begin(),
416 EndIPI = InsertPts.end();
417 IPI != EndIPI; ++IPI) {
419 if (NewBB == CurBB) {
426 appendAndTransferDominatedUses(NewPt,
User, OpNo, IPI, InsertPts);
433 if (!CommonDominator)
436 if (CommonDominator != NewBB) {
438 assert(CommonDominator != CurBB &&
439 "Instruction has not been rejected during isDominated check!");
450 appendAndTransferDominatedUses(NewPt,
User, OpNo, IPI, InsertPts);
456void AArch64PromoteConstant::computeInsertionPoint(
482 AArch64PromoteConstant::PromotedConstant &PC) {
483 assert(PC.ShouldConvert &&
484 "Expected that we should convert this to a global");
489 "_PromotedConst",
nullptr, GlobalVariable::NotThreadLocal);
490 PC.GV->setInitializer(&
C);
497void AArch64PromoteConstant::insertDefinitions(
Function &
F,
499 InsertionPoints &InsertPts) {
502 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(
F).getDomTree();
504 assert(!InsertPts.empty() &&
"Empty uses does not need a definition");
506 for (
const auto &IPI : InsertPts) {
510 Builder.CreateLoad(PromotedGV.
getValueType(), &PromotedGV);
517 for (
auto Use : IPI.second) {
520 findInsertionPoint(*
Use.first,
Use.second)) &&
521 "Inserted definition does not dominate all its uses!");
524 dbgs() <<
"Use to update " <<
Use.second <<
":";
528 Use.first->setOperand(
Use.second, LoadedCst);
534void AArch64PromoteConstant::promoteConstants(
536 PromotionCacheTy &PromotionCache) {
538 for (
auto U = Updates.
begin(), E = Updates.
end(); U != E;) {
542 InsertionPoints InsertPts;
544 computeInsertionPoint(
U->User,
U->Op, InsertPts);
545 }
while (++U != E &&
U->C ==
C);
547 auto &Promotion = PromotionCache[
C];
549 insertDefinitions(
F, *Promotion.GV, InsertPts);
553bool AArch64PromoteConstant::runOnFunction(
Function &
F,
554 PromotionCacheTy &PromotionCache) {
562 for (
Use &U :
I.operands()) {
563 Constant *Cst = dyn_cast<Constant>(U);
576 unsigned OpNo = &
U -
I.op_begin();
587 promoteConstants(
F, Updates, PromotionCache);
Expand Atomic instructions
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
Module.h This file contains the declarations for the Module class.
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Remove Loads Into Fake Uses
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
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.
bool isZeroValue() const
Return true if the value is negative zero or null value.
This class represents an Operation in the Expression.
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
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...
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
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
An instruction for reading from memory.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
bool skipModule(Module &M) const
Optional passes call this function to check whether the pass should be skipped.
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Pass interface - Implemented by all 'passes'.
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
The instances of the Type class are immutable: once they are created, they are never changed.
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.
Type * getArrayElementType() const
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.
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
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.
void initializeAArch64PromoteConstantPass(PassRegistry &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
ModulePass * createAArch64PromoteConstantPass()