109467b48Spatrick //===- SCCP.cpp - Sparse Conditional Constant Propagation -----------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file implements sparse conditional constant propagation and merging:
1009467b48Spatrick //
1109467b48Spatrick // Specifically, this:
1209467b48Spatrick // * Assumes values are constant unless proven otherwise
1309467b48Spatrick // * Assumes BasicBlocks are dead unless proven otherwise
1409467b48Spatrick // * Proves values to be constant, and replaces them with constants
1509467b48Spatrick // * Proves conditional branches to be unconditional
1609467b48Spatrick //
1709467b48Spatrick //===----------------------------------------------------------------------===//
1809467b48Spatrick
1909467b48Spatrick #include "llvm/Transforms/Scalar/SCCP.h"
2009467b48Spatrick #include "llvm/ADT/DenseMap.h"
2109467b48Spatrick #include "llvm/ADT/MapVector.h"
2209467b48Spatrick #include "llvm/ADT/STLExtras.h"
23a0747c9fSpatrick #include "llvm/ADT/SetVector.h"
2409467b48Spatrick #include "llvm/ADT/SmallPtrSet.h"
2509467b48Spatrick #include "llvm/ADT/SmallVector.h"
2609467b48Spatrick #include "llvm/ADT/Statistic.h"
27097a140dSpatrick #include "llvm/Analysis/DomTreeUpdater.h"
2809467b48Spatrick #include "llvm/Analysis/GlobalsModRef.h"
2909467b48Spatrick #include "llvm/Analysis/TargetLibraryInfo.h"
30a0747c9fSpatrick #include "llvm/Analysis/ValueTracking.h"
3109467b48Spatrick #include "llvm/IR/BasicBlock.h"
3209467b48Spatrick #include "llvm/IR/Constant.h"
3309467b48Spatrick #include "llvm/IR/DerivedTypes.h"
3409467b48Spatrick #include "llvm/IR/Function.h"
3509467b48Spatrick #include "llvm/IR/GlobalVariable.h"
3609467b48Spatrick #include "llvm/IR/InstrTypes.h"
3709467b48Spatrick #include "llvm/IR/Instruction.h"
3809467b48Spatrick #include "llvm/IR/Instructions.h"
3909467b48Spatrick #include "llvm/IR/Module.h"
4009467b48Spatrick #include "llvm/IR/PassManager.h"
4109467b48Spatrick #include "llvm/IR/Type.h"
4209467b48Spatrick #include "llvm/IR/User.h"
4309467b48Spatrick #include "llvm/IR/Value.h"
4409467b48Spatrick #include "llvm/InitializePasses.h"
4509467b48Spatrick #include "llvm/Pass.h"
4609467b48Spatrick #include "llvm/Support/Casting.h"
4709467b48Spatrick #include "llvm/Support/Debug.h"
4809467b48Spatrick #include "llvm/Support/ErrorHandling.h"
4909467b48Spatrick #include "llvm/Support/raw_ostream.h"
5009467b48Spatrick #include "llvm/Transforms/Scalar.h"
5109467b48Spatrick #include "llvm/Transforms/Utils/Local.h"
52*a96b3639Srobert #include "llvm/Transforms/Utils/SCCPSolver.h"
5309467b48Spatrick #include <cassert>
5409467b48Spatrick #include <utility>
5509467b48Spatrick #include <vector>
5609467b48Spatrick
5709467b48Spatrick using namespace llvm;
5809467b48Spatrick
5909467b48Spatrick #define DEBUG_TYPE "sccp"
6009467b48Spatrick
6109467b48Spatrick STATISTIC(NumInstRemoved, "Number of instructions removed");
6209467b48Spatrick STATISTIC(NumDeadBlocks , "Number of basic blocks unreachable");
63097a140dSpatrick STATISTIC(NumInstReplaced,
64097a140dSpatrick "Number of instructions replaced with (simpler) instruction");
6509467b48Spatrick
6609467b48Spatrick // runSCCP() - Run the Sparse Conditional Constant Propagation algorithm,
6709467b48Spatrick // and return true if the function was modified.
runSCCP(Function & F,const DataLayout & DL,const TargetLibraryInfo * TLI,DomTreeUpdater & DTU)6809467b48Spatrick static bool runSCCP(Function &F, const DataLayout &DL,
69*a96b3639Srobert const TargetLibraryInfo *TLI, DomTreeUpdater &DTU) {
7009467b48Spatrick LLVM_DEBUG(dbgs() << "SCCP on function '" << F.getName() << "'\n");
7109467b48Spatrick SCCPSolver Solver(
72097a140dSpatrick DL, [TLI](Function &F) -> const TargetLibraryInfo & { return *TLI; },
73097a140dSpatrick F.getContext());
7409467b48Spatrick
7509467b48Spatrick // Mark the first block of the function as being executable.
76a0747c9fSpatrick Solver.markBlockExecutable(&F.front());
7709467b48Spatrick
7809467b48Spatrick // Mark all arguments to the function as being overdefined.
7909467b48Spatrick for (Argument &AI : F.args())
8009467b48Spatrick Solver.markOverdefined(&AI);
8109467b48Spatrick
8209467b48Spatrick // Solve for constants.
8309467b48Spatrick bool ResolvedUndefs = true;
8409467b48Spatrick while (ResolvedUndefs) {
85a0747c9fSpatrick Solver.solve();
8609467b48Spatrick LLVM_DEBUG(dbgs() << "RESOLVING UNDEFs\n");
87a0747c9fSpatrick ResolvedUndefs = Solver.resolvedUndefsIn(F);
8809467b48Spatrick }
8909467b48Spatrick
9009467b48Spatrick bool MadeChanges = false;
9109467b48Spatrick
9209467b48Spatrick // If we decided that there are basic blocks that are dead in this function,
9309467b48Spatrick // delete their contents now. Note that we cannot actually delete the blocks,
9409467b48Spatrick // as we cannot modify the CFG of the function.
9509467b48Spatrick
96097a140dSpatrick SmallPtrSet<Value *, 32> InsertedValues;
97*a96b3639Srobert SmallVector<BasicBlock *, 8> BlocksToErase;
9809467b48Spatrick for (BasicBlock &BB : F) {
9909467b48Spatrick if (!Solver.isBlockExecutable(&BB)) {
10009467b48Spatrick LLVM_DEBUG(dbgs() << " BasicBlock Dead:" << BB);
10109467b48Spatrick ++NumDeadBlocks;
102*a96b3639Srobert BlocksToErase.push_back(&BB);
10309467b48Spatrick MadeChanges = true;
10409467b48Spatrick continue;
10509467b48Spatrick }
10609467b48Spatrick
107*a96b3639Srobert MadeChanges |= Solver.simplifyInstsInBlock(BB, InsertedValues,
108097a140dSpatrick NumInstRemoved, NumInstReplaced);
10909467b48Spatrick }
11009467b48Spatrick
111*a96b3639Srobert // Remove unreachable blocks and non-feasible edges.
112*a96b3639Srobert for (BasicBlock *DeadBB : BlocksToErase)
113*a96b3639Srobert NumInstRemoved += changeToUnreachable(DeadBB->getFirstNonPHI(),
114*a96b3639Srobert /*PreserveLCSSA=*/false, &DTU);
115*a96b3639Srobert
116*a96b3639Srobert BasicBlock *NewUnreachableBB = nullptr;
117*a96b3639Srobert for (BasicBlock &BB : F)
118*a96b3639Srobert MadeChanges |= Solver.removeNonFeasibleEdges(&BB, DTU, NewUnreachableBB);
119*a96b3639Srobert
120*a96b3639Srobert for (BasicBlock *DeadBB : BlocksToErase)
121*a96b3639Srobert if (!DeadBB->hasAddressTaken())
122*a96b3639Srobert DTU.deleteBB(DeadBB);
123*a96b3639Srobert
12409467b48Spatrick return MadeChanges;
12509467b48Spatrick }
12609467b48Spatrick
run(Function & F,FunctionAnalysisManager & AM)12709467b48Spatrick PreservedAnalyses SCCPPass::run(Function &F, FunctionAnalysisManager &AM) {
12809467b48Spatrick const DataLayout &DL = F.getParent()->getDataLayout();
12909467b48Spatrick auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
130*a96b3639Srobert auto *DT = AM.getCachedResult<DominatorTreeAnalysis>(F);
131*a96b3639Srobert DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
132*a96b3639Srobert if (!runSCCP(F, DL, &TLI, DTU))
13309467b48Spatrick return PreservedAnalyses::all();
13409467b48Spatrick
13509467b48Spatrick auto PA = PreservedAnalyses();
136*a96b3639Srobert PA.preserve<DominatorTreeAnalysis>();
13709467b48Spatrick return PA;
13809467b48Spatrick }
13909467b48Spatrick
14009467b48Spatrick namespace {
14109467b48Spatrick
14209467b48Spatrick //===--------------------------------------------------------------------===//
14309467b48Spatrick //
14409467b48Spatrick /// SCCP Class - This class uses the SCCPSolver to implement a per-function
14509467b48Spatrick /// Sparse Conditional Constant Propagator.
14609467b48Spatrick ///
14709467b48Spatrick class SCCPLegacyPass : public FunctionPass {
14809467b48Spatrick public:
14909467b48Spatrick // Pass identification, replacement for typeid
15009467b48Spatrick static char ID;
15109467b48Spatrick
SCCPLegacyPass()15209467b48Spatrick SCCPLegacyPass() : FunctionPass(ID) {
15309467b48Spatrick initializeSCCPLegacyPassPass(*PassRegistry::getPassRegistry());
15409467b48Spatrick }
15509467b48Spatrick
getAnalysisUsage(AnalysisUsage & AU) const15609467b48Spatrick void getAnalysisUsage(AnalysisUsage &AU) const override {
15709467b48Spatrick AU.addRequired<TargetLibraryInfoWrapperPass>();
15809467b48Spatrick AU.addPreserved<GlobalsAAWrapperPass>();
159*a96b3639Srobert AU.addPreserved<DominatorTreeWrapperPass>();
16009467b48Spatrick }
16109467b48Spatrick
16209467b48Spatrick // runOnFunction - Run the Sparse Conditional Constant Propagation
16309467b48Spatrick // algorithm, and return true if the function was modified.
runOnFunction(Function & F)16409467b48Spatrick bool runOnFunction(Function &F) override {
16509467b48Spatrick if (skipFunction(F))
16609467b48Spatrick return false;
16709467b48Spatrick const DataLayout &DL = F.getParent()->getDataLayout();
16809467b48Spatrick const TargetLibraryInfo *TLI =
16909467b48Spatrick &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
170*a96b3639Srobert auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
171*a96b3639Srobert DomTreeUpdater DTU(DTWP ? &DTWP->getDomTree() : nullptr,
172*a96b3639Srobert DomTreeUpdater::UpdateStrategy::Lazy);
173*a96b3639Srobert return runSCCP(F, DL, TLI, DTU);
17409467b48Spatrick }
17509467b48Spatrick };
17609467b48Spatrick
17709467b48Spatrick } // end anonymous namespace
17809467b48Spatrick
17909467b48Spatrick char SCCPLegacyPass::ID = 0;
18009467b48Spatrick
18109467b48Spatrick INITIALIZE_PASS_BEGIN(SCCPLegacyPass, "sccp",
18209467b48Spatrick "Sparse Conditional Constant Propagation", false, false)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)18309467b48Spatrick INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
18409467b48Spatrick INITIALIZE_PASS_END(SCCPLegacyPass, "sccp",
18509467b48Spatrick "Sparse Conditional Constant Propagation", false, false)
18609467b48Spatrick
18709467b48Spatrick // createSCCPPass - This is the public interface to this file.
18809467b48Spatrick FunctionPass *llvm::createSCCPPass() { return new SCCPLegacyPass(); }
18909467b48Spatrick
190