Go to the documentation of this file.
53 #define DEBUG_TYPE "aarch64-promote-const"
57 cl::desc(
"Promote all vector constants"));
59 STATISTIC(NumPromoted,
"Number of promoted constants");
60 STATISTIC(NumPromotedUses,
"Number of promoted constants uses");
94 class AArch64PromoteConstant :
public ModulePass {
96 struct PromotedConstant {
97 bool ShouldConvert =
false;
102 struct UpdateRecord {
117 StringRef getPassName()
const override {
return "AArch64 Promote Constant"; }
121 bool runOnModule(
Module &M)
override {
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,
209 InsertionPoints::iterator &IPI,
210 InsertionPoints &InsertPts) {
212 IPI->second.emplace_back(
User, OpNo);
221 InsertPts.erase(OldInstr);
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) {
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) {
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);
458 void 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");
492 PC.GV->setInitializer(&
C);
499 void 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) {
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);
536 void 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);
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);
NodeT * findNearestCommonDominator(NodeT *A, NodeT *B) const
Find nearest common dominator basic block for basic block A and B.
ModulePass * createAArch64PromoteConstantPass()
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
const Function * getParent() const
Return the enclosing method, or null if none.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
bool isInlineAsm() const
Check if this call is an inline asm statement.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
The instances of the Type class are immutable: once they are created, they are never changed.
void initializeAArch64PromoteConstantPass(PassRegistry &)
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
SmallPtrSet< MachineInstr *, 2 > Uses
LLVM Basic Block Representation.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
bool isArrayTy() const
True if this is an instance of ArrayType.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
(vector float) vec_cmpeq(*A, *B) C
Represent the analysis usage information of a pass.
bool isVectorTy() const
True if this is an instance of VectorType.
into llvm powi allowing the code generator to produce balanced multiplication trees First
Legacy analysis pass which computes a DominatorTree.
STATISTIC(NumFunctions, "Total number of functions")
@ InternalLinkage
Rename collisions when linking (static functions).
unsigned getStructNumElements() const
Type * getArrayElementType() const
inst_range instructions(Function *F)
This is an important base class in LLVM.
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A Module instance is used to store all the information related to an LLVM module.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
StringRef - Represent a constant reference to a string, i.e.
Type * getStructElementType(unsigned N) const
Type * getType() const
All values are typed, get the type of this value.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
An instruction for reading from memory.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
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...
static bool runOnFunction(Function &F, bool PostInlining)
bool isZeroValue() const
Return true if the value is negative zero or null value.
Pass interface - Implemented by all 'passes'.
bool isStructTy() const
True if this is an instance of StructType.
const BasicBlock * getParent() const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Type * getValueType() const
This class represents a function call, abstracting a target machine's calling convention.
AnalysisUsage & addRequired()
A Use represents the edge between a Value definition and its users.
reference emplace_back(ArgTypes &&... Args)