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 {
108 : C(C), User(User), Op(Op) {}
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);
218 Uses OldUses = std::move(IPI->second);
219 InsertPts[NewPt] = std::move(OldUses);
221 InsertPts.erase(OldInstr);
230 "AArch64 Promote Constant Pass",
false,
false)
236 return new AArch64PromoteConstant();
245 EltIdx < EndEltIdx; ++EltIdx)
262 if (isa<const ShuffleVectorInst>(Instr) && OpIdx == 2)
266 if (isa<const ExtractValueInst>(Instr) && OpIdx > 0)
270 if (isa<const InsertValueInst>(Instr) && OpIdx > 1)
273 if (isa<const AllocaInst>(Instr) && OpIdx > 0)
277 if (isa<const LoadInst>(Instr) && OpIdx > 0)
281 if (isa<const StoreInst>(Instr) && OpIdx > 1)
285 if (isa<const GetElementPtrInst>(Instr) && OpIdx > 0)
290 if (isa<const LandingPadInst>(Instr))
294 if (isa<const SwitchInst>(Instr))
298 if (isa<const IndirectBrInst>(Instr))
302 if (isa<const IntrinsicInst>(Instr))
325 if (isa<const UndefValue>(Cst))
350 auto Converted = PromotionCache.
insert(
351 std::make_pair(&C, AArch64PromoteConstant::PromotedConstant()));
352 if (Converted.second)
354 return Converted.first->second.ShouldConvert;
361 if (
PHINode *PhiInst = dyn_cast<PHINode>(&User))
362 return PhiInst->getIncomingBlock(OpNo)->getTerminator();
369 InsertionPoints &InsertPts) {
375 for (
auto &IPI : InsertPts) {
376 if (NewPt == IPI.first || DT.
dominates(IPI.first, NewPt) ||
380 (IPI.first->getParent() != NewPt->
getParent() &&
386 IPI.second.emplace_back(User, OpNo);
395 InsertionPoints &InsertPts) {
403 for (InsertionPoints::iterator IPI = InsertPts.begin(),
404 EndIPI = InsertPts.end();
405 IPI != EndIPI; ++IPI) {
407 if (NewBB == CurBB) {
414 appendAndTransferDominatedUses(NewPt, User, OpNo, IPI, InsertPts);
421 if (!CommonDominator)
424 if (CommonDominator != NewBB) {
426 assert(CommonDominator != CurBB &&
427 "Instruction has not been rejected during isDominated check!");
438 appendAndTransferDominatedUses(NewPt, User, OpNo, IPI, InsertPts);
444 void AArch64PromoteConstant::computeInsertionPoint(
445 Instruction *User,
unsigned OpNo, InsertionPoints &InsertPts) {
450 Instruction *InsertionPoint = findInsertionPoint(*User, OpNo);
456 if (isDominated(InsertionPoint, User, OpNo, InsertPts))
460 if (tryAndMerge(InsertionPoint, User, OpNo, InsertPts))
466 InsertPts[InsertionPoint].emplace_back(User, OpNo);
470 AArch64PromoteConstant::PromotedConstant &PC) {
471 assert(PC.ShouldConvert &&
472 "Expected that we should convert this to a global");
485 void AArch64PromoteConstant::insertDefinitions(
Function &
F,
487 InsertionPoints &InsertPts) {
490 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>(
F).getDomTree();
492 assert(!InsertPts.empty() &&
"Empty uses does not need a definition");
494 for (
const auto &IPI : InsertPts) {
504 for (
auto Use : IPI.second) {
507 findInsertionPoint(*
Use.first,
Use.second)) &&
508 "Inserted definition does not dominate all its uses!");
511 dbgs() <<
"Use to update " <<
Use.second <<
":";
515 Use.first->setOperand(
Use.second, LoadedCst);
521 void AArch64PromoteConstant::promoteConstants(
523 PromotionCacheTy &PromotionCache) {
525 for (
auto U = Updates.
begin(),
E = Updates.
end(); U !=
E;) {
529 InsertionPoints InsertPts;
531 computeInsertionPoint(U->User, U->Op, InsertPts);
532 }
while (++U !=
E && U->C == C);
534 auto &Promotion = PromotionCache[
C];
536 insertDefinitions(F, *Promotion.GV, InsertPts);
541 PromotionCacheTy &PromotionCache) {
549 for (
Use &U :
I.operands()) {
554 if (!Cst || isa<GlobalValue>(Cst) || isa<ConstantExpr>(Cst))
562 unsigned OpNo = &U -
I.op_begin();
573 promoteConstants(F, Updates, PromotionCache);
Pass interface - Implemented by all 'passes'.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This class represents lattice values for constants.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
A Module instance is used to store all the information related to an LLVM module. ...
This class represents a function call, abstracting a target machine's calling convention.
NodeT * findNearestCommonDominator(NodeT *A, NodeT *B) const
findNearestCommonDominator - Find nearest common dominator basic block for basic block A and B...
STATISTIC(NumFunctions, "Total number of functions")
Type * getStructElementType(unsigned N) const
An instruction for reading from memory.
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 isVectorTy() const
True if this is an instance of VectorType.
ModulePass * createAArch64PromoteConstantPass()
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
A Use represents the edge between a Value definition and its users.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Type * getType() const
All values are typed, get the type of this value.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
bool isZeroValue() const
Return true if the value is negative zero or null value.
static bool runOnFunction(Function &F, bool PostInlining)
void initializeAArch64PromoteConstantPass(PassRegistry &)
Value * getCalledValue() const
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Represent the analysis usage information of a pass.
void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
unsigned getStructNumElements() const
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool dominates(const Instruction *Def, const Use &U) const
Return true if Def dominates a use in User.
Module.h This file contains the declarations for the Module class.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
void emplace_back(ArgTypes &&... Args)
LLVM_NODISCARD bool empty() const
const Function * getParent() const
Return the enclosing method, or null if none.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Rename collisions when linking (static functions).
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Module * getParent()
Get the module that this global value is contained inside of...
StringRef - Represent a constant reference to a string, i.e.
inst_range instructions(Function *F)
Type * getArrayElementType() const
Legacy analysis pass which computes a DominatorTree.
bool isStructTy() const
True if this is an instance of StructType.
bool isArrayTy() const
True if this is an instance of ArrayType.
const BasicBlock * getParent() const