53#define DEBUG_TYPE "aarch64-promote-const"
57 cl::desc(
"Promote all vector constants"));
59STATISTIC(NumPromoted,
"Number of promoted constants");
60STATISTIC(NumPromotedUses,
"Number of promoted constants uses");
94class AArch64PromoteConstant :
public ModulePass {
96 struct PromotedConstant {
97 bool ShouldConvert =
false;
102 struct UpdateRecord {
125 bool Changed =
false;
126 PromotionCacheTy PromotionCache;
166 InsertionPoints &InsertPts);
182 InsertionPoints &InsertPts);
192 InsertionPoints &InsertPts);
198 InsertionPoints &InsertPts);
203 PromotionCacheTy &PromotionCache);
207 static void appendAndTransferDominatedUses(
Instruction *NewPt,
210 InsertionPoints &InsertPts) {
212 IPI->second.emplace_back(
User, OpNo);
218 Uses OldUses = std::move(IPI->second);
219 InsertPts[NewPt] = std::move(OldUses);
221 InsertPts.erase(OldInstr);
227char AArch64PromoteConstant::ID = 0;
230 "AArch64 Promote Constant Pass",
false,
false)
236 return new AArch64PromoteConstant();
245 EltIdx < EndEltIdx; ++EltIdx)
256 if (isa<ConstantData>(
C))
259 if (isa<GlobalValue>(
C) || isa<BlockAddress>(
C) || isa<ConstantExpr>(
C))
262 return all_of(
C->operands(), [](
const Use &U) {
263 return containsOnlyConstantData(cast<Constant>(&U));
276 if (isa<const ShuffleVectorInst>(Instr) && OpIdx == 2)
280 if (isa<const ExtractValueInst>(Instr) && OpIdx > 0)
284 if (isa<const InsertValueInst>(Instr) && OpIdx > 1)
287 if (isa<const AllocaInst>(Instr) && OpIdx > 0)
291 if (isa<const LoadInst>(Instr) && OpIdx > 0)
295 if (isa<const StoreInst>(Instr) && OpIdx > 1)
299 if (isa<const GetElementPtrInst>(Instr) && OpIdx > 0)
304 if (isa<const LandingPadInst>(Instr))
308 if (isa<const SwitchInst>(Instr))
312 if (isa<const IndirectBrInst>(Instr))
316 if (isa<const IntrinsicInst>(Instr))
320 const CallInst *CI = dyn_cast<const CallInst>(Instr);
339 if (isa<const UndefValue>(Cst))
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();
383 InsertionPoints &InsertPts) {
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);
409 InsertionPoints &InsertPts) {
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(
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");
491 "_PromotedConst",
nullptr, GlobalVariable::NotThreadLocal);
492 PC.GV->setInitializer(&
C);
499void AArch64PromoteConstant::insertDefinitions(
Function &
F,
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) {
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(
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()) {
565 Constant *Cst = dyn_cast<Constant>(U);
578 unsigned OpNo = &
U -
I.op_begin();
589 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)
Rewrite Partial Register Uses
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)
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
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
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()