45 #define DEBUG_TYPE "aarch64-promote-const"
49 cl::desc(
"Promote all vector constants"));
51 STATISTIC(NumPromoted,
"Number of promoted constants");
52 STATISTIC(NumPromotedUses,
"Number of promoted constants uses");
85 class AArch64PromoteConstant :
public ModulePass {
91 const char *getPassName()
const override {
return "AArch64 Promote Constant"; }
95 bool runOnModule(
Module &M)
override {
99 Changed |= runOnFunction(MF);
160 void computeInsertionPoints(
Constant *Val,
161 InsertionPointsPerFunc &InsPtsPerFunc);
166 bool insertDefinitions(
Constant *Cst, InsertionPointsPerFunc &InsPtsPerFunc);
177 bool computeAndInsertDefinitions(
Constant *Val);
182 bool promoteConstant(
Constant *Cst);
187 InsertionPoints::iterator &IPI,
188 InsertionPoints &InsertPts) {
190 IPI->second.push_back(&Use);
196 Uses OldUses = std::move(IPI->second);
197 InsertPts[NewPt] = std::move(OldUses);
199 InsertPts.erase(OldInstr);
211 "AArch64 Promote Constant Pass",
false,
false)
217 return new AArch64PromoteConstant();
226 EltIdx < EndEltIdx; ++EltIdx)
243 if (isa<const ShuffleVectorInst>(Instr) && OpIdx == 2)
247 if (isa<const ExtractValueInst>(Instr) && OpIdx > 0)
251 if (isa<const InsertValueInst>(Instr) && OpIdx > 1)
254 if (isa<const AllocaInst>(Instr) && OpIdx > 0)
258 if (isa<const LoadInst>(Instr) && OpIdx > 0)
262 if (isa<const StoreInst>(Instr) && OpIdx > 1)
266 if (isa<const GetElementPtrInst>(Instr) && OpIdx > 0)
271 if (isa<const LandingPadInst>(Instr))
275 if (isa<const SwitchInst>(Instr))
279 if (isa<const IndirectBrInst>(Instr))
283 if (isa<const IntrinsicInst>(Instr))
309 if (isa<const UndefValue>(Cst))
336 if (
PHINode *PhiInst = dyn_cast<PHINode>(User))
337 return PhiInst->getIncomingBlock(Use.
getOperandNo())->getTerminator();
342 bool AArch64PromoteConstant::isDominated(
Instruction *NewPt, Use &Use,
343 InsertionPoints &InsertPts) {
350 for (
auto &IPI : InsertPts) {
351 if (NewPt == IPI.first || DT.
dominates(IPI.first, NewPt) ||
355 (IPI.first->getParent() != NewPt->
getParent() &&
358 DEBUG(
dbgs() <<
"Insertion point dominated by:\n");
361 IPI.second.push_back(&Use);
368 bool AArch64PromoteConstant::tryAndMerge(
Instruction *NewPt, Use &Use,
369 InsertionPoints &InsertPts) {
377 for (InsertionPoints::iterator IPI = InsertPts.begin(),
378 EndIPI = InsertPts.end();
379 IPI != EndIPI; ++IPI) {
381 if (NewBB == CurBB) {
385 DEBUG(
dbgs() <<
"Merge insertion point with:\n");
387 DEBUG(
dbgs() <<
"\nat considered insertion point.\n");
388 appendAndTransferDominatedUses(NewPt, Use, IPI, InsertPts);
395 if (!CommonDominator)
398 if (CommonDominator != NewBB) {
400 assert(CommonDominator != CurBB &&
401 "Instruction has not been rejected during isDominated check!");
407 DEBUG(
dbgs() <<
"Merge insertion point with:\n");
412 appendAndTransferDominatedUses(NewPt, Use, IPI, InsertPts);
418 void AArch64PromoteConstant::computeInsertionPoints(
419 Constant *Val, InsertionPointsPerFunc &InsPtsPerFunc) {
420 DEBUG(
dbgs() <<
"** Compute insertion points **\n");
421 for (Use &Use : Val->
uses()) {
436 Instruction *InsertionPoint = findInsertionPoint(Use);
438 DEBUG(
dbgs() <<
"Considered insertion point:\n");
444 InsertionPoints &InsertPts =
446 if (isDominated(InsertionPoint, Use, InsertPts))
450 if (tryAndMerge(InsertionPoint, Use, InsertPts))
453 DEBUG(
dbgs() <<
"Keep considered insertion point\n");
456 InsertPts[InsertionPoint].push_back(&Use);
460 bool AArch64PromoteConstant::insertDefinitions(
461 Constant *Cst, InsertionPointsPerFunc &InsPtsPerFunc) {
464 bool HasChanged =
false;
467 for (
const auto &FctToInstPtsIt : InsPtsPerFunc) {
468 const InsertionPoints &InsertPts = FctToInstPtsIt.second;
472 *FctToInstPtsIt.first).getDomTree();
474 assert(!InsertPts.empty() &&
"Empty uses does not need a definition");
476 Module *M = FctToInstPtsIt.first->getParent();
490 for (
const auto &IPI : InsertPts) {
492 IRBuilder<> Builder(IPI.first->getParent(), IPI.first);
493 LoadInst *LoadedCst = Builder.CreateLoad(PromotedGV);
500 for (Use *Use : IPI.second) {
502 assert(DT.
dominates(LoadedCst, findInsertionPoint(*Use)) &&
503 "Inserted definition does not dominate all its uses!");
505 DEBUG(
dbgs() <<
"Use to update " << Use->getOperandNo() <<
":");
516 bool AArch64PromoteConstant::computeAndInsertDefinitions(
Constant *Val) {
517 InsertionPointsPerFunc InsertPtsPerFunc;
518 computeInsertionPoints(Val, InsertPtsPerFunc);
519 return insertDefinitions(Val, InsertPtsPerFunc);
522 bool AArch64PromoteConstant::promoteConstant(
Constant *Cst) {
523 assert(Cst &&
"Given variable is not a valid constant.");
528 DEBUG(
dbgs() <<
"******************************\n");
533 return computeAndInsertDefinitions(Cst);
536 bool AArch64PromoteConstant::runOnFunction(
Function &
F) {
540 bool LocalChange =
false;
546 for (
Value *Op :
I.operand_values()) {
551 if (Cst && !isa<GlobalValue>(Cst) && !isa<ConstantExpr>(Cst) &&
552 AlreadyChecked.
insert(Cst).second)
553 LocalChange |= promoteConstant(Cst);
Pass interface - Implemented by all 'passes'.
const Value * getCalledValue() const
getCalledValue - Get a pointer to the function that is invoked by this instruction.
iterator_range< use_iterator > uses()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
unsigned getStructNumElements() const
STATISTIC(NumFunctions,"Total number of functions")
A Module instance is used to store all the information related to an LLVM module. ...
CallInst - This class represents a function call, abstracting a target machine's calling convention...
const Function * getParent() const
Return the enclosing method, or null if none.
LoadInst - an instruction for reading from memory.
ModulePass * createAArch64PromoteConstantPass()
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
Type * getArrayElementType() const
A Use represents the edge between a Value definition and its users.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
void print(raw_ostream &O) const
Implement operator<< on Value.
bool isArrayTy() const
isArrayTy - True if this is an instance of ArrayType.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
void initializeAArch64PromoteConstantPass(PassRegistry &)
unsigned getOperandNo() const
Return the operand # of this use in its User.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
bool isVectorTy() const
isVectorTy - True if this is an instance of VectorType.
This is an important base class in LLVM.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool isZeroValue() const
Return true if the value is negative zero or null value.
Represent the analysis usage information of a pass.
User * getUser() const
Returns the User that contains this Use.
NodeT * findNearestCommonDominator(NodeT *A, NodeT *B)
findNearestCommonDominator - Find nearest common dominator basic block for basic block A and B...
bool dominates(const Instruction *Def, const Use &U) const
Return true if Def dominates a use in User.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
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_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
bool isStructTy() const
isStructTy - True if this is an instance of StructType.
iterator_range< inst_iterator > inst_range(Function *F)
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Rename collisions when linking (static functions).
LLVM Value Representation.
Type * getStructElementType(unsigned N) const
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Legacy analysis pass which computes a DominatorTree.
const BasicBlock * getParent() const