37#define DEBUG_TYPE "sccp"
39STATISTIC(NumInstRemoved,
"Number of instructions removed");
40STATISTIC(NumArgsElimed ,
"Number of arguments constant propagated");
41STATISTIC(NumGlobalConst,
"Number of globals found to be constant");
42STATISTIC(NumDeadBlocks ,
"Number of basic blocks unreachable");
44 "Number of instructions replaced with (simpler) instruction");
48 "The maximum number of iterations function specialization is run"));
60 <<
"Can't zap returns of the function : " <<
F.getName()
61 <<
" due to present musttail or \"clang.arc.attachedcall\" call of "
69 if (isa<Instruction>(U) &&
70 !Solver.isBlockExecutable(cast<Instruction>(U)->getParent()))
76 if (!isa<CallBase>(U))
78 if (U->getType()->isStructTy()) {
79 return all_of(Solver.getStructLatticeValueFor(U),
80 [](const ValueLatticeElement &LV) {
81 return !SCCPSolver::isOverdefined(LV);
87 if (
auto *
II = dyn_cast<IntrinsicInst>(U)) {
88 if (
II->isAssumeLikeIntrinsic())
94 "We can only zap functions where all live users have a concrete value");
97 if (
CallInst *CI = BB.getTerminatingMustTailCall()) {
98 LLVM_DEBUG(
dbgs() <<
"Can't zap return of the block due to present "
99 <<
"musttail call : " << *CI <<
"\n");
104 if (
auto *RI = dyn_cast<ReturnInst>(BB.getTerminator()))
105 if (!isa<UndefValue>(RI->getOperand(0)))
106 ReturnsToZap.push_back(RI);
117 bool IsFuncSpecEnabled) {
125 if (
F.isDeclaration())
155 G.removeDeadConstantUsers();
163 if (IsFuncSpecEnabled) {
170 bool MadeChanges =
false;
172 if (
F.isDeclaration())
178 bool ReplacedPointerArg =
false;
181 ReplacedPointerArg |= Arg.getType()->isPointerTy();
188 if (ReplacedPointerArg) {
196 return AL.addFnAttribute(
201 F.setAttributes(UpdateAttrs(
F.getAttributes()));
202 for (
User *U :
F.users()) {
203 auto *CB = dyn_cast<CallBase>(U);
204 if (!CB || CB->getCalledFunction() != &
F)
207 CB->setAttributes(UpdateAttrs(CB->getAttributes()));
210 MadeChanges |= ReplacedPointerArg;
221 if (&BB != &
F.front())
227 BB, InsertedValues, NumInstRemoved, NumInstReplaced);
232 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
250 if (!DeadBB->hasAddressTaken())
251 DTU.deleteBB(DeadBB);
256 if (
auto *
II = dyn_cast<IntrinsicInst>(&Inst)) {
257 if (
II->getIntrinsicID() == Intrinsic::ssa_copy) {
259 Inst.replaceAllUsesWith(
Op);
260 Inst.eraseFromParent();
295 if (
F->hasRetAttribute(Attribute::Range))
298 F->addRangeRetAttr(CR);
301 if (
F->getReturnType()->isVoidTy())
308 assert(
F->getReturnType()->isStructTy() &&
309 "The return type should be a struct");
310 StructType *STy = cast<StructType>(
F->getReturnType());
318 Function *
F = RI->getParent()->getParent();
332 F->removeParamAttr(
A.getArgNo(), Attribute::Returned);
333 F->removeRetAttrs(UBImplyingAttributes);
334 for (
Use &U :
F->uses()) {
335 CallBase *CB = dyn_cast<CallBase>(U.getUser());
337 assert(isa<BlockAddress>(U.getUser()) ||
338 (isa<Constant>(U.getUser()) &&
339 all_of(U.getUser()->users(), [](
const User *UserUser) {
340 return cast<IntrinsicInst>(UserUser)->isAssumeLikeIntrinsic();
358 <<
"' is constant!\n");
361 SI->eraseFromParent();
368 if (GVEs.
size() == 1) {
372 GVEs[0]->replaceOperandWith(1, InitExpr);
376 M.eraseGlobalVariable(GV);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void findReturnsToZap(Function &F, SmallVector< ReturnInst *, 8 > &ReturnsToZap, SCCPSolver &Solver)
static cl::opt< unsigned > FuncSpecMaxIters("funcspec-max-iters", cl::init(10), cl::Hidden, cl::desc("The maximum number of iterations function specialization is run"))
static bool runIPSCCP(Module &M, const DataLayout &DL, FunctionAnalysisManager *FAM, std::function< const TargetLibraryInfo &(Function &)> GetTLI, std::function< TargetTransformInfo &(Function &)> GetTTI, std::function< AssumptionCache &(Function &)> GetAC, std::function< DominatorTree &(Function &)> GetDT, std::function< BlockFrequencyInfo &(Function &)> GetBFI, bool IsFuncSpecEnabled)
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file implements a set that has insertion order iteration characteristics.
#define STATISTIC(VARNAME, DESC)
A container for analyses that lazily runs them and caches their results.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents an incoming formal argument to a Function.
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
static Attribute getWithMemoryEffects(LLVMContext &Context, MemoryEffects ME)
LLVM Basic Block Representation.
Analysis pass which computes BlockFrequencyInfo.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Removes the attribute from the given argument.
void removeRetAttrs(const AttributeMask &AttrsToRemove)
Removes the attributes from the return value.
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned getArgOperandNo(const Use *U) const
Given a use for a arg operand, get the arg operand number that corresponds to it.
This class represents a function call, abstracting a target machine's calling convention.
bool isSingleElement() const
Return true if this set contains exactly one member.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool run()
Attempt to specialize functions in the module to enable constant propagation across function boundari...
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
void getDebugInfo(SmallVectorImpl< DIGlobalVariableExpression * > &GVs) const
Fill the vector with all debug info attachements.
bool isFuncSpecEnabled() const
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
static MemoryEffectsBase unknown()
Create MemoryEffectsBase that can read and write any memory.
A Module instance is used to store all the information related to an LLVM module.
static PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Analysis pass which computes a PostDominatorTree.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserve()
Mark an analysis as preserved.
Return a value (possibly void), from a function.
SCCPSolver - This interface class is a general purpose solver for Sparse Conditional Constant Propaga...
const DenseMap< GlobalVariable *, ValueLatticeElement > & getTrackedGlobals()
getTrackedGlobals - Get and return the set of inferred initializers for global variables.
void trackValueOfGlobalVariable(GlobalVariable *GV)
trackValueOfGlobalVariable - Clients can use this method to inform the SCCPSolver that it should trac...
bool tryToReplaceWithConstant(Value *V)
bool isStructLatticeConstant(Function *F, StructType *STy)
void addPredicateInfo(Function &F, DominatorTree &DT, AssumptionCache &AC)
void trackValueOfArgument(Argument *V)
trackValueOfArgument - Mark the specified argument overdefined unless it have range attribute.
void addTrackedFunction(Function *F)
addTrackedFunction - If the SCCP solver is supposed to track calls into and out of the specified func...
const MapVector< Function *, ValueLatticeElement > & getTrackedRetVals()
getTrackedRetVals - Get the inferred return value map.
void solveWhileResolvedUndefsIn(Module &M)
const PredicateBase * getPredicateInfoFor(Instruction *I)
void addArgumentTrackedFunction(Function *F)
const SmallPtrSet< Function *, 16 > getMRVFunctionsTracked()
getMRVFunctionsTracked - Get the set of functions which return multiple values tracked by the pass.
bool simplifyInstsInBlock(BasicBlock &BB, SmallPtrSetImpl< Value * > &InsertedValues, Statistic &InstRemovedStat, Statistic &InstReplacedStat)
const ValueLatticeElement & getLatticeValueFor(Value *V) const
bool removeNonFeasibleEdges(BasicBlock *BB, DomTreeUpdater &DTU, BasicBlock *&NewUnreachableBB) const
bool isBlockExecutable(BasicBlock *BB) const
bool markBlockExecutable(BasicBlock *BB)
markBlockExecutable - This method can be used by clients to mark all of the blocks that are known to ...
static bool isConstant(const ValueLatticeElement &LV)
bool mustPreserveReturn(Function *F)
Returns true if the return of the given function cannot be modified.
static bool isOverdefined(const ValueLatticeElement &LV)
bool isArgumentTrackedFunction(Function *F)
Returns true if the given function is in the solver's set of argument-tracked functions.
bool insert(const value_type &X)
Insert a new element into the SetVector.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
A SetVector that performs no allocations if smaller than a certain size.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Class to represent struct types.
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
A Use represents the edge between a Value definition and its users.
This class represents lattice values for constants.
bool isConstantRangeIncludingUndef() const
const ConstantRange & getConstantRange(bool UndefAllowed=true) const
Returns the constant range for this value.
bool isConstantRange(bool UndefAllowed=true) const
Returns true if this value is a constant range.
bool isUnknownOrUndef() const
LLVM Value Representation.
StringRef getName() const
Return a constant reference to the value's name.
AttributeMask getUBImplyingAttributes()
Get param/return attributes which imply immediate undefined behavior if an invalid value is passed.
initializer< Ty > init(const Ty &Val)
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.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
bool canTrackGlobalVariableInterprocedurally(GlobalVariable *GV)
Determine if the value maintained in the given global variable can be tracked interprocedurally.
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
DIExpression * getExpressionForConstant(DIBuilder &DIB, const Constant &C, Type &Ty)
Given a constant, create a debug information expression.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned changeToUnreachable(Instruction *I, bool PreserveLCSSA=false, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...
bool canTrackReturnsInterprocedurally(Function *F)
Determine if the values of the given function's returns can be tracked interprocedurally.
bool canTrackArgumentsInterprocedurally(Function *F)
Determine if the values of the given function's arguments can be tracked interprocedurally.