xref: /openbsd-src/gnu/llvm/llvm/lib/Transforms/Scalar/SCCP.cpp (revision a96b36398fcfb4953e8190127da8bf074c7552f1)
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