1fe6060f1SDimitry Andric //===-- SCCP.cpp ----------------------------------------------------------===// 2fe6060f1SDimitry Andric // 3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric // 7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric // 9fe6060f1SDimitry Andric // This file implements Interprocedural Sparse Conditional Constant Propagation. 10fe6060f1SDimitry Andric // 11fe6060f1SDimitry Andric //===----------------------------------------------------------------------===// 12fe6060f1SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/Transforms/IPO/SCCP.h" 14bdd1243dSDimitry Andric #include "llvm/ADT/SetVector.h" 150b57cec5SDimitry Andric #include "llvm/Analysis/AssumptionCache.h" 1606c3fb27SDimitry Andric #include "llvm/Analysis/BlockFrequencyInfo.h" 170b57cec5SDimitry Andric #include "llvm/Analysis/PostDominators.h" 180b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 19fe6060f1SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 20bdd1243dSDimitry Andric #include "llvm/Analysis/ValueLattice.h" 21bdd1243dSDimitry Andric #include "llvm/Analysis/ValueLatticeUtils.h" 22bdd1243dSDimitry Andric #include "llvm/Analysis/ValueTracking.h" 2306c3fb27SDimitry Andric #include "llvm/IR/AttributeMask.h" 24bdd1243dSDimitry Andric #include "llvm/IR/Constants.h" 255f757f3fSDimitry Andric #include "llvm/IR/DIBuilder.h" 26bdd1243dSDimitry Andric #include "llvm/IR/IntrinsicInst.h" 27bdd1243dSDimitry Andric #include "llvm/Support/CommandLine.h" 28bdd1243dSDimitry Andric #include "llvm/Support/ModRef.h" 290b57cec5SDimitry Andric #include "llvm/Transforms/IPO.h" 30bdd1243dSDimitry Andric #include "llvm/Transforms/IPO/FunctionSpecialization.h" 310b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/SCCP.h" 32bdd1243dSDimitry Andric #include "llvm/Transforms/Utils/Local.h" 3381ad6265SDimitry Andric #include "llvm/Transforms/Utils/SCCPSolver.h" 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric using namespace llvm; 360b57cec5SDimitry Andric 37bdd1243dSDimitry Andric #define DEBUG_TYPE "sccp" 38bdd1243dSDimitry Andric 39bdd1243dSDimitry Andric STATISTIC(NumInstRemoved, "Number of instructions removed"); 40bdd1243dSDimitry Andric STATISTIC(NumArgsElimed ,"Number of arguments constant propagated"); 41bdd1243dSDimitry Andric STATISTIC(NumGlobalConst, "Number of globals found to be constant"); 42bdd1243dSDimitry Andric STATISTIC(NumDeadBlocks , "Number of basic blocks unreachable"); 43bdd1243dSDimitry Andric STATISTIC(NumInstReplaced, 44bdd1243dSDimitry Andric "Number of instructions replaced with (simpler) instruction"); 45bdd1243dSDimitry Andric 4606c3fb27SDimitry Andric static cl::opt<unsigned> FuncSpecMaxIters( 475f757f3fSDimitry Andric "funcspec-max-iters", cl::init(10), cl::Hidden, cl::desc( 48bdd1243dSDimitry Andric "The maximum number of iterations function specialization is run")); 49bdd1243dSDimitry Andric 50bdd1243dSDimitry Andric static void findReturnsToZap(Function &F, 51bdd1243dSDimitry Andric SmallVector<ReturnInst *, 8> &ReturnsToZap, 52bdd1243dSDimitry Andric SCCPSolver &Solver) { 53bdd1243dSDimitry Andric // We can only do this if we know that nothing else can call the function. 54bdd1243dSDimitry Andric if (!Solver.isArgumentTrackedFunction(&F)) 55bdd1243dSDimitry Andric return; 56bdd1243dSDimitry Andric 57bdd1243dSDimitry Andric if (Solver.mustPreserveReturn(&F)) { 58bdd1243dSDimitry Andric LLVM_DEBUG( 59bdd1243dSDimitry Andric dbgs() 60bdd1243dSDimitry Andric << "Can't zap returns of the function : " << F.getName() 61bdd1243dSDimitry Andric << " due to present musttail or \"clang.arc.attachedcall\" call of " 62bdd1243dSDimitry Andric "it\n"); 63bdd1243dSDimitry Andric return; 64bdd1243dSDimitry Andric } 65bdd1243dSDimitry Andric 66bdd1243dSDimitry Andric assert( 67bdd1243dSDimitry Andric all_of(F.users(), 68bdd1243dSDimitry Andric [&Solver](User *U) { 69bdd1243dSDimitry Andric if (isa<Instruction>(U) && 70bdd1243dSDimitry Andric !Solver.isBlockExecutable(cast<Instruction>(U)->getParent())) 71bdd1243dSDimitry Andric return true; 72bdd1243dSDimitry Andric // Non-callsite uses are not impacted by zapping. Also, constant 73bdd1243dSDimitry Andric // uses (like blockaddresses) could stuck around, without being 74bdd1243dSDimitry Andric // used in the underlying IR, meaning we do not have lattice 75bdd1243dSDimitry Andric // values for them. 76bdd1243dSDimitry Andric if (!isa<CallBase>(U)) 77bdd1243dSDimitry Andric return true; 78bdd1243dSDimitry Andric if (U->getType()->isStructTy()) { 79bdd1243dSDimitry Andric return all_of(Solver.getStructLatticeValueFor(U), 80bdd1243dSDimitry Andric [](const ValueLatticeElement &LV) { 81bdd1243dSDimitry Andric return !SCCPSolver::isOverdefined(LV); 82bdd1243dSDimitry Andric }); 83bdd1243dSDimitry Andric } 84bdd1243dSDimitry Andric 85bdd1243dSDimitry Andric // We don't consider assume-like intrinsics to be actual address 86bdd1243dSDimitry Andric // captures. 87bdd1243dSDimitry Andric if (auto *II = dyn_cast<IntrinsicInst>(U)) { 88bdd1243dSDimitry Andric if (II->isAssumeLikeIntrinsic()) 89bdd1243dSDimitry Andric return true; 90bdd1243dSDimitry Andric } 91bdd1243dSDimitry Andric 92bdd1243dSDimitry Andric return !SCCPSolver::isOverdefined(Solver.getLatticeValueFor(U)); 93bdd1243dSDimitry Andric }) && 94bdd1243dSDimitry Andric "We can only zap functions where all live users have a concrete value"); 95bdd1243dSDimitry Andric 96bdd1243dSDimitry Andric for (BasicBlock &BB : F) { 97bdd1243dSDimitry Andric if (CallInst *CI = BB.getTerminatingMustTailCall()) { 98bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Can't zap return of the block due to present " 99bdd1243dSDimitry Andric << "musttail call : " << *CI << "\n"); 100bdd1243dSDimitry Andric (void)CI; 101bdd1243dSDimitry Andric return; 102bdd1243dSDimitry Andric } 103bdd1243dSDimitry Andric 104bdd1243dSDimitry Andric if (auto *RI = dyn_cast<ReturnInst>(BB.getTerminator())) 105bdd1243dSDimitry Andric if (!isa<UndefValue>(RI->getOperand(0))) 106bdd1243dSDimitry Andric ReturnsToZap.push_back(RI); 107bdd1243dSDimitry Andric } 108bdd1243dSDimitry Andric } 109bdd1243dSDimitry Andric 110bdd1243dSDimitry Andric static bool runIPSCCP( 111bdd1243dSDimitry Andric Module &M, const DataLayout &DL, FunctionAnalysisManager *FAM, 112bdd1243dSDimitry Andric std::function<const TargetLibraryInfo &(Function &)> GetTLI, 113bdd1243dSDimitry Andric std::function<TargetTransformInfo &(Function &)> GetTTI, 114bdd1243dSDimitry Andric std::function<AssumptionCache &(Function &)> GetAC, 11506c3fb27SDimitry Andric std::function<DominatorTree &(Function &)> GetDT, 11606c3fb27SDimitry Andric std::function<BlockFrequencyInfo &(Function &)> GetBFI, 117bdd1243dSDimitry Andric bool IsFuncSpecEnabled) { 118bdd1243dSDimitry Andric SCCPSolver Solver(DL, GetTLI, M.getContext()); 11906c3fb27SDimitry Andric FunctionSpecializer Specializer(Solver, M, FAM, GetBFI, GetTLI, GetTTI, 12006c3fb27SDimitry Andric GetAC); 121bdd1243dSDimitry Andric 122bdd1243dSDimitry Andric // Loop over all functions, marking arguments to those with their addresses 123bdd1243dSDimitry Andric // taken or that are external as overdefined. 124bdd1243dSDimitry Andric for (Function &F : M) { 125bdd1243dSDimitry Andric if (F.isDeclaration()) 126bdd1243dSDimitry Andric continue; 127bdd1243dSDimitry Andric 12806c3fb27SDimitry Andric DominatorTree &DT = GetDT(F); 12906c3fb27SDimitry Andric AssumptionCache &AC = GetAC(F); 13006c3fb27SDimitry Andric Solver.addPredicateInfo(F, DT, AC); 131bdd1243dSDimitry Andric 132bdd1243dSDimitry Andric // Determine if we can track the function's return values. If so, add the 133bdd1243dSDimitry Andric // function to the solver's set of return-tracked functions. 134bdd1243dSDimitry Andric if (canTrackReturnsInterprocedurally(&F)) 135bdd1243dSDimitry Andric Solver.addTrackedFunction(&F); 136bdd1243dSDimitry Andric 137bdd1243dSDimitry Andric // Determine if we can track the function's arguments. If so, add the 138bdd1243dSDimitry Andric // function to the solver's set of argument-tracked functions. 139bdd1243dSDimitry Andric if (canTrackArgumentsInterprocedurally(&F)) { 140bdd1243dSDimitry Andric Solver.addArgumentTrackedFunction(&F); 141bdd1243dSDimitry Andric continue; 142bdd1243dSDimitry Andric } 143bdd1243dSDimitry Andric 144bdd1243dSDimitry Andric // Assume the function is called. 145bdd1243dSDimitry Andric Solver.markBlockExecutable(&F.front()); 146bdd1243dSDimitry Andric 147bdd1243dSDimitry Andric for (Argument &AI : F.args()) 148*0fca6ea1SDimitry Andric Solver.trackValueOfArgument(&AI); 149bdd1243dSDimitry Andric } 150bdd1243dSDimitry Andric 151bdd1243dSDimitry Andric // Determine if we can track any of the module's global variables. If so, add 152bdd1243dSDimitry Andric // the global variables we can track to the solver's set of tracked global 153bdd1243dSDimitry Andric // variables. 154bdd1243dSDimitry Andric for (GlobalVariable &G : M.globals()) { 155bdd1243dSDimitry Andric G.removeDeadConstantUsers(); 156bdd1243dSDimitry Andric if (canTrackGlobalVariableInterprocedurally(&G)) 157bdd1243dSDimitry Andric Solver.trackValueOfGlobalVariable(&G); 158bdd1243dSDimitry Andric } 159bdd1243dSDimitry Andric 160bdd1243dSDimitry Andric // Solve for constants. 161bdd1243dSDimitry Andric Solver.solveWhileResolvedUndefsIn(M); 162bdd1243dSDimitry Andric 163bdd1243dSDimitry Andric if (IsFuncSpecEnabled) { 164bdd1243dSDimitry Andric unsigned Iters = 0; 16506c3fb27SDimitry Andric while (Iters++ < FuncSpecMaxIters && Specializer.run()); 166bdd1243dSDimitry Andric } 167bdd1243dSDimitry Andric 168bdd1243dSDimitry Andric // Iterate over all of the instructions in the module, replacing them with 169bdd1243dSDimitry Andric // constants if we have found them to be of constant values. 170bdd1243dSDimitry Andric bool MadeChanges = false; 171bdd1243dSDimitry Andric for (Function &F : M) { 172bdd1243dSDimitry Andric if (F.isDeclaration()) 173bdd1243dSDimitry Andric continue; 174bdd1243dSDimitry Andric 175bdd1243dSDimitry Andric SmallVector<BasicBlock *, 512> BlocksToErase; 176bdd1243dSDimitry Andric 177bdd1243dSDimitry Andric if (Solver.isBlockExecutable(&F.front())) { 178bdd1243dSDimitry Andric bool ReplacedPointerArg = false; 179bdd1243dSDimitry Andric for (Argument &Arg : F.args()) { 180bdd1243dSDimitry Andric if (!Arg.use_empty() && Solver.tryToReplaceWithConstant(&Arg)) { 181bdd1243dSDimitry Andric ReplacedPointerArg |= Arg.getType()->isPointerTy(); 182bdd1243dSDimitry Andric ++NumArgsElimed; 183bdd1243dSDimitry Andric } 184bdd1243dSDimitry Andric } 185bdd1243dSDimitry Andric 186bdd1243dSDimitry Andric // If we replaced an argument, we may now also access a global (currently 187bdd1243dSDimitry Andric // classified as "other" memory). Update memory attribute to reflect this. 188bdd1243dSDimitry Andric if (ReplacedPointerArg) { 189bdd1243dSDimitry Andric auto UpdateAttrs = [&](AttributeList AL) { 190bdd1243dSDimitry Andric MemoryEffects ME = AL.getMemoryEffects(); 191bdd1243dSDimitry Andric if (ME == MemoryEffects::unknown()) 192bdd1243dSDimitry Andric return AL; 193bdd1243dSDimitry Andric 19406c3fb27SDimitry Andric ME |= MemoryEffects(IRMemLocation::Other, 19506c3fb27SDimitry Andric ME.getModRef(IRMemLocation::ArgMem)); 196bdd1243dSDimitry Andric return AL.addFnAttribute( 197bdd1243dSDimitry Andric F.getContext(), 198bdd1243dSDimitry Andric Attribute::getWithMemoryEffects(F.getContext(), ME)); 199bdd1243dSDimitry Andric }; 200bdd1243dSDimitry Andric 201bdd1243dSDimitry Andric F.setAttributes(UpdateAttrs(F.getAttributes())); 202bdd1243dSDimitry Andric for (User *U : F.users()) { 203bdd1243dSDimitry Andric auto *CB = dyn_cast<CallBase>(U); 204bdd1243dSDimitry Andric if (!CB || CB->getCalledFunction() != &F) 205bdd1243dSDimitry Andric continue; 206bdd1243dSDimitry Andric 207bdd1243dSDimitry Andric CB->setAttributes(UpdateAttrs(CB->getAttributes())); 208bdd1243dSDimitry Andric } 209bdd1243dSDimitry Andric } 210bdd1243dSDimitry Andric MadeChanges |= ReplacedPointerArg; 211bdd1243dSDimitry Andric } 212bdd1243dSDimitry Andric 213bdd1243dSDimitry Andric SmallPtrSet<Value *, 32> InsertedValues; 214bdd1243dSDimitry Andric for (BasicBlock &BB : F) { 215bdd1243dSDimitry Andric if (!Solver.isBlockExecutable(&BB)) { 216bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << " BasicBlock Dead:" << BB); 217bdd1243dSDimitry Andric ++NumDeadBlocks; 218bdd1243dSDimitry Andric 219bdd1243dSDimitry Andric MadeChanges = true; 220bdd1243dSDimitry Andric 221bdd1243dSDimitry Andric if (&BB != &F.front()) 222bdd1243dSDimitry Andric BlocksToErase.push_back(&BB); 223bdd1243dSDimitry Andric continue; 224bdd1243dSDimitry Andric } 225bdd1243dSDimitry Andric 226bdd1243dSDimitry Andric MadeChanges |= Solver.simplifyInstsInBlock( 227bdd1243dSDimitry Andric BB, InsertedValues, NumInstRemoved, NumInstReplaced); 228bdd1243dSDimitry Andric } 229bdd1243dSDimitry Andric 23006c3fb27SDimitry Andric DominatorTree *DT = FAM->getCachedResult<DominatorTreeAnalysis>(F); 23106c3fb27SDimitry Andric PostDominatorTree *PDT = FAM->getCachedResult<PostDominatorTreeAnalysis>(F); 23206c3fb27SDimitry Andric DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy); 233bdd1243dSDimitry Andric // Change dead blocks to unreachable. We do it after replacing constants 234bdd1243dSDimitry Andric // in all executable blocks, because changeToUnreachable may remove PHI 235bdd1243dSDimitry Andric // nodes in executable blocks we found values for. The function's entry 236bdd1243dSDimitry Andric // block is not part of BlocksToErase, so we have to handle it separately. 237bdd1243dSDimitry Andric for (BasicBlock *BB : BlocksToErase) { 2385f757f3fSDimitry Andric NumInstRemoved += changeToUnreachable(BB->getFirstNonPHIOrDbg(), 239bdd1243dSDimitry Andric /*PreserveLCSSA=*/false, &DTU); 240bdd1243dSDimitry Andric } 241bdd1243dSDimitry Andric if (!Solver.isBlockExecutable(&F.front())) 2425f757f3fSDimitry Andric NumInstRemoved += changeToUnreachable(F.front().getFirstNonPHIOrDbg(), 243bdd1243dSDimitry Andric /*PreserveLCSSA=*/false, &DTU); 244bdd1243dSDimitry Andric 245bdd1243dSDimitry Andric BasicBlock *NewUnreachableBB = nullptr; 246bdd1243dSDimitry Andric for (BasicBlock &BB : F) 247bdd1243dSDimitry Andric MadeChanges |= Solver.removeNonFeasibleEdges(&BB, DTU, NewUnreachableBB); 248bdd1243dSDimitry Andric 249bdd1243dSDimitry Andric for (BasicBlock *DeadBB : BlocksToErase) 250bdd1243dSDimitry Andric if (!DeadBB->hasAddressTaken()) 251bdd1243dSDimitry Andric DTU.deleteBB(DeadBB); 252bdd1243dSDimitry Andric 253bdd1243dSDimitry Andric for (BasicBlock &BB : F) { 254bdd1243dSDimitry Andric for (Instruction &Inst : llvm::make_early_inc_range(BB)) { 255bdd1243dSDimitry Andric if (Solver.getPredicateInfoFor(&Inst)) { 256bdd1243dSDimitry Andric if (auto *II = dyn_cast<IntrinsicInst>(&Inst)) { 257bdd1243dSDimitry Andric if (II->getIntrinsicID() == Intrinsic::ssa_copy) { 258bdd1243dSDimitry Andric Value *Op = II->getOperand(0); 259bdd1243dSDimitry Andric Inst.replaceAllUsesWith(Op); 260bdd1243dSDimitry Andric Inst.eraseFromParent(); 261bdd1243dSDimitry Andric } 262bdd1243dSDimitry Andric } 263bdd1243dSDimitry Andric } 264bdd1243dSDimitry Andric } 265bdd1243dSDimitry Andric } 266bdd1243dSDimitry Andric } 267bdd1243dSDimitry Andric 268bdd1243dSDimitry Andric // If we inferred constant or undef return values for a function, we replaced 269bdd1243dSDimitry Andric // all call uses with the inferred value. This means we don't need to bother 270bdd1243dSDimitry Andric // actually returning anything from the function. Replace all return 271bdd1243dSDimitry Andric // instructions with return undef. 272bdd1243dSDimitry Andric // 273bdd1243dSDimitry Andric // Do this in two stages: first identify the functions we should process, then 274bdd1243dSDimitry Andric // actually zap their returns. This is important because we can only do this 275bdd1243dSDimitry Andric // if the address of the function isn't taken. In cases where a return is the 276bdd1243dSDimitry Andric // last use of a function, the order of processing functions would affect 277bdd1243dSDimitry Andric // whether other functions are optimizable. 278bdd1243dSDimitry Andric SmallVector<ReturnInst*, 8> ReturnsToZap; 279bdd1243dSDimitry Andric 280bdd1243dSDimitry Andric for (const auto &I : Solver.getTrackedRetVals()) { 281bdd1243dSDimitry Andric Function *F = I.first; 282bdd1243dSDimitry Andric const ValueLatticeElement &ReturnValue = I.second; 283bdd1243dSDimitry Andric 284*0fca6ea1SDimitry Andric // If there is a known constant range for the return value, add range 285*0fca6ea1SDimitry Andric // attribute to the return value. 286bdd1243dSDimitry Andric if (ReturnValue.isConstantRange() && 287bdd1243dSDimitry Andric !ReturnValue.getConstantRange().isSingleElement()) { 288bdd1243dSDimitry Andric // Do not add range metadata if the return value may include undef. 289bdd1243dSDimitry Andric if (ReturnValue.isConstantRangeIncludingUndef()) 290bdd1243dSDimitry Andric continue; 291bdd1243dSDimitry Andric 292*0fca6ea1SDimitry Andric // Do not touch existing attribute for now. 293bdd1243dSDimitry Andric // TODO: We should be able to take the intersection of the existing 294*0fca6ea1SDimitry Andric // attribute and the inferred range. 295*0fca6ea1SDimitry Andric if (F->hasRetAttribute(Attribute::Range)) 296bdd1243dSDimitry Andric continue; 297*0fca6ea1SDimitry Andric auto &CR = ReturnValue.getConstantRange(); 298*0fca6ea1SDimitry Andric F->addRangeRetAttr(CR); 299bdd1243dSDimitry Andric continue; 300bdd1243dSDimitry Andric } 301bdd1243dSDimitry Andric if (F->getReturnType()->isVoidTy()) 302bdd1243dSDimitry Andric continue; 303bdd1243dSDimitry Andric if (SCCPSolver::isConstant(ReturnValue) || ReturnValue.isUnknownOrUndef()) 304bdd1243dSDimitry Andric findReturnsToZap(*F, ReturnsToZap, Solver); 305bdd1243dSDimitry Andric } 306bdd1243dSDimitry Andric 307bdd1243dSDimitry Andric for (auto *F : Solver.getMRVFunctionsTracked()) { 308bdd1243dSDimitry Andric assert(F->getReturnType()->isStructTy() && 309bdd1243dSDimitry Andric "The return type should be a struct"); 310bdd1243dSDimitry Andric StructType *STy = cast<StructType>(F->getReturnType()); 311bdd1243dSDimitry Andric if (Solver.isStructLatticeConstant(F, STy)) 312bdd1243dSDimitry Andric findReturnsToZap(*F, ReturnsToZap, Solver); 313bdd1243dSDimitry Andric } 314bdd1243dSDimitry Andric 315bdd1243dSDimitry Andric // Zap all returns which we've identified as zap to change. 316bdd1243dSDimitry Andric SmallSetVector<Function *, 8> FuncZappedReturn; 317bdd1243dSDimitry Andric for (ReturnInst *RI : ReturnsToZap) { 318bdd1243dSDimitry Andric Function *F = RI->getParent()->getParent(); 319*0fca6ea1SDimitry Andric RI->setOperand(0, PoisonValue::get(F->getReturnType())); 320bdd1243dSDimitry Andric // Record all functions that are zapped. 321bdd1243dSDimitry Andric FuncZappedReturn.insert(F); 322bdd1243dSDimitry Andric } 323bdd1243dSDimitry Andric 324bdd1243dSDimitry Andric // Remove the returned attribute for zapped functions and the 325bdd1243dSDimitry Andric // corresponding call sites. 32606c3fb27SDimitry Andric // Also remove any attributes that convert an undef return value into 32706c3fb27SDimitry Andric // immediate undefined behavior 32806c3fb27SDimitry Andric AttributeMask UBImplyingAttributes = 32906c3fb27SDimitry Andric AttributeFuncs::getUBImplyingAttributes(); 330bdd1243dSDimitry Andric for (Function *F : FuncZappedReturn) { 331bdd1243dSDimitry Andric for (Argument &A : F->args()) 332bdd1243dSDimitry Andric F->removeParamAttr(A.getArgNo(), Attribute::Returned); 33306c3fb27SDimitry Andric F->removeRetAttrs(UBImplyingAttributes); 334bdd1243dSDimitry Andric for (Use &U : F->uses()) { 335bdd1243dSDimitry Andric CallBase *CB = dyn_cast<CallBase>(U.getUser()); 336bdd1243dSDimitry Andric if (!CB) { 337bdd1243dSDimitry Andric assert(isa<BlockAddress>(U.getUser()) || 338bdd1243dSDimitry Andric (isa<Constant>(U.getUser()) && 339bdd1243dSDimitry Andric all_of(U.getUser()->users(), [](const User *UserUser) { 340bdd1243dSDimitry Andric return cast<IntrinsicInst>(UserUser)->isAssumeLikeIntrinsic(); 341bdd1243dSDimitry Andric }))); 342bdd1243dSDimitry Andric continue; 343bdd1243dSDimitry Andric } 344bdd1243dSDimitry Andric 345bdd1243dSDimitry Andric for (Use &Arg : CB->args()) 346bdd1243dSDimitry Andric CB->removeParamAttr(CB->getArgOperandNo(&Arg), Attribute::Returned); 34706c3fb27SDimitry Andric CB->removeRetAttrs(UBImplyingAttributes); 348bdd1243dSDimitry Andric } 349bdd1243dSDimitry Andric } 350bdd1243dSDimitry Andric 351bdd1243dSDimitry Andric // If we inferred constant or undef values for globals variables, we can 352bdd1243dSDimitry Andric // delete the global and any stores that remain to it. 353bdd1243dSDimitry Andric for (const auto &I : make_early_inc_range(Solver.getTrackedGlobals())) { 354bdd1243dSDimitry Andric GlobalVariable *GV = I.first; 355bdd1243dSDimitry Andric if (SCCPSolver::isOverdefined(I.second)) 356bdd1243dSDimitry Andric continue; 357bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Found that GV '" << GV->getName() 358bdd1243dSDimitry Andric << "' is constant!\n"); 359bdd1243dSDimitry Andric while (!GV->use_empty()) { 360bdd1243dSDimitry Andric StoreInst *SI = cast<StoreInst>(GV->user_back()); 361bdd1243dSDimitry Andric SI->eraseFromParent(); 362bdd1243dSDimitry Andric } 3635f757f3fSDimitry Andric 3645f757f3fSDimitry Andric // Try to create a debug constant expression for the global variable 3655f757f3fSDimitry Andric // initializer value. 3665f757f3fSDimitry Andric SmallVector<DIGlobalVariableExpression *, 1> GVEs; 3675f757f3fSDimitry Andric GV->getDebugInfo(GVEs); 3685f757f3fSDimitry Andric if (GVEs.size() == 1) { 3695f757f3fSDimitry Andric DIBuilder DIB(M); 3705f757f3fSDimitry Andric if (DIExpression *InitExpr = getExpressionForConstant( 3715f757f3fSDimitry Andric DIB, *GV->getInitializer(), *GV->getValueType())) 3725f757f3fSDimitry Andric GVEs[0]->replaceOperandWith(1, InitExpr); 3735f757f3fSDimitry Andric } 3745f757f3fSDimitry Andric 37506c3fb27SDimitry Andric MadeChanges = true; 37606c3fb27SDimitry Andric M.eraseGlobalVariable(GV); 377bdd1243dSDimitry Andric ++NumGlobalConst; 378bdd1243dSDimitry Andric } 379bdd1243dSDimitry Andric 380bdd1243dSDimitry Andric return MadeChanges; 381bdd1243dSDimitry Andric } 382bdd1243dSDimitry Andric 3830b57cec5SDimitry Andric PreservedAnalyses IPSCCPPass::run(Module &M, ModuleAnalysisManager &AM) { 3840b57cec5SDimitry Andric const DataLayout &DL = M.getDataLayout(); 3850b57cec5SDimitry Andric auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 3868bcb0991SDimitry Andric auto GetTLI = [&FAM](Function &F) -> const TargetLibraryInfo & { 3878bcb0991SDimitry Andric return FAM.getResult<TargetLibraryAnalysis>(F); 3888bcb0991SDimitry Andric }; 389bdd1243dSDimitry Andric auto GetTTI = [&FAM](Function &F) -> TargetTransformInfo & { 390bdd1243dSDimitry Andric return FAM.getResult<TargetIRAnalysis>(F); 391bdd1243dSDimitry Andric }; 392bdd1243dSDimitry Andric auto GetAC = [&FAM](Function &F) -> AssumptionCache & { 393bdd1243dSDimitry Andric return FAM.getResult<AssumptionAnalysis>(F); 394bdd1243dSDimitry Andric }; 39506c3fb27SDimitry Andric auto GetDT = [&FAM](Function &F) -> DominatorTree & { 39606c3fb27SDimitry Andric return FAM.getResult<DominatorTreeAnalysis>(F); 39706c3fb27SDimitry Andric }; 39806c3fb27SDimitry Andric auto GetBFI = [&FAM](Function &F) -> BlockFrequencyInfo & { 39906c3fb27SDimitry Andric return FAM.getResult<BlockFrequencyAnalysis>(F); 4000b57cec5SDimitry Andric }; 4010b57cec5SDimitry Andric 40206c3fb27SDimitry Andric 40306c3fb27SDimitry Andric if (!runIPSCCP(M, DL, &FAM, GetTLI, GetTTI, GetAC, GetDT, GetBFI, 404bdd1243dSDimitry Andric isFuncSpecEnabled())) 4050b57cec5SDimitry Andric return PreservedAnalyses::all(); 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric PreservedAnalyses PA; 4080b57cec5SDimitry Andric PA.preserve<DominatorTreeAnalysis>(); 4090b57cec5SDimitry Andric PA.preserve<PostDominatorTreeAnalysis>(); 4100b57cec5SDimitry Andric PA.preserve<FunctionAnalysisManagerModuleProxy>(); 4110b57cec5SDimitry Andric return PA; 4120b57cec5SDimitry Andric } 413