10b57cec5SDimitry Andric //===- SCCP.cpp - Sparse Conditional Constant Propagation -----------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements sparse conditional constant propagation and merging: 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric // Specifically, this: 120b57cec5SDimitry Andric // * Assumes values are constant unless proven otherwise 130b57cec5SDimitry Andric // * Assumes BasicBlocks are dead unless proven otherwise 140b57cec5SDimitry Andric // * Proves values to be constant, and replaces them with constants 150b57cec5SDimitry Andric // * Proves conditional branches to be unconditional 160b57cec5SDimitry Andric // 170b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #include "llvm/Transforms/Scalar/SCCP.h" 200b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 210b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 220b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 230b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 245ffd83dbSDimitry Andric #include "llvm/Analysis/DomTreeUpdater.h" 250b57cec5SDimitry Andric #include "llvm/Analysis/GlobalsModRef.h" 260b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 27e8d8bef9SDimitry Andric #include "llvm/Analysis/ValueTracking.h" 280b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h" 290b57cec5SDimitry Andric #include "llvm/IR/Constant.h" 300b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 310b57cec5SDimitry Andric #include "llvm/IR/Function.h" 320b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h" 330b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h" 340b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 350b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 360b57cec5SDimitry Andric #include "llvm/IR/Module.h" 370b57cec5SDimitry Andric #include "llvm/IR/PassManager.h" 380b57cec5SDimitry Andric #include "llvm/IR/Type.h" 390b57cec5SDimitry Andric #include "llvm/IR/User.h" 400b57cec5SDimitry Andric #include "llvm/IR/Value.h" 410b57cec5SDimitry Andric #include "llvm/Pass.h" 420b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 430b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 440b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 450b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 460b57cec5SDimitry Andric #include "llvm/Transforms/Scalar.h" 47480093f4SDimitry Andric #include "llvm/Transforms/Utils/Local.h" 4881ad6265SDimitry Andric #include "llvm/Transforms/Utils/SCCPSolver.h" 490b57cec5SDimitry Andric #include <utility> 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric using namespace llvm; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric #define DEBUG_TYPE "sccp" 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric STATISTIC(NumInstRemoved, "Number of instructions removed"); 560b57cec5SDimitry Andric STATISTIC(NumDeadBlocks , "Number of basic blocks unreachable"); 575ffd83dbSDimitry Andric STATISTIC(NumInstReplaced, 585ffd83dbSDimitry Andric "Number of instructions replaced with (simpler) instruction"); 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric // runSCCP() - Run the Sparse Conditional Constant Propagation algorithm, 610b57cec5SDimitry Andric // and return true if the function was modified. 620b57cec5SDimitry Andric static bool runSCCP(Function &F, const DataLayout &DL, 6381ad6265SDimitry Andric const TargetLibraryInfo *TLI, DomTreeUpdater &DTU) { 640b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "SCCP on function '" << F.getName() << "'\n"); 658bcb0991SDimitry Andric SCCPSolver Solver( 665ffd83dbSDimitry Andric DL, [TLI](Function &F) -> const TargetLibraryInfo & { return *TLI; }, 675ffd83dbSDimitry Andric F.getContext()); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric // Mark the first block of the function as being executable. 70fe6060f1SDimitry Andric Solver.markBlockExecutable(&F.front()); 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric // Mark all arguments to the function as being overdefined. 730b57cec5SDimitry Andric for (Argument &AI : F.args()) 740b57cec5SDimitry Andric Solver.markOverdefined(&AI); 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric // Solve for constants. 770b57cec5SDimitry Andric bool ResolvedUndefs = true; 780b57cec5SDimitry Andric while (ResolvedUndefs) { 79fe6060f1SDimitry Andric Solver.solve(); 800b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "RESOLVING UNDEFs\n"); 81fe6060f1SDimitry Andric ResolvedUndefs = Solver.resolvedUndefsIn(F); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric bool MadeChanges = false; 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric // If we decided that there are basic blocks that are dead in this function, 870b57cec5SDimitry Andric // delete their contents now. Note that we cannot actually delete the blocks, 880b57cec5SDimitry Andric // as we cannot modify the CFG of the function. 890b57cec5SDimitry Andric 905ffd83dbSDimitry Andric SmallPtrSet<Value *, 32> InsertedValues; 9181ad6265SDimitry Andric SmallVector<BasicBlock *, 8> BlocksToErase; 920b57cec5SDimitry Andric for (BasicBlock &BB : F) { 930b57cec5SDimitry Andric if (!Solver.isBlockExecutable(&BB)) { 940b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " BasicBlock Dead:" << BB); 950b57cec5SDimitry Andric ++NumDeadBlocks; 9681ad6265SDimitry Andric BlocksToErase.push_back(&BB); 970b57cec5SDimitry Andric MadeChanges = true; 980b57cec5SDimitry Andric continue; 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 101bdd1243dSDimitry Andric MadeChanges |= Solver.simplifyInstsInBlock(BB, InsertedValues, 1025ffd83dbSDimitry Andric NumInstRemoved, NumInstReplaced); 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 10581ad6265SDimitry Andric // Remove unreachable blocks and non-feasible edges. 10681ad6265SDimitry Andric for (BasicBlock *DeadBB : BlocksToErase) 10781ad6265SDimitry Andric NumInstRemoved += changeToUnreachable(DeadBB->getFirstNonPHI(), 10881ad6265SDimitry Andric /*PreserveLCSSA=*/false, &DTU); 10981ad6265SDimitry Andric 11081ad6265SDimitry Andric BasicBlock *NewUnreachableBB = nullptr; 11181ad6265SDimitry Andric for (BasicBlock &BB : F) 112bdd1243dSDimitry Andric MadeChanges |= Solver.removeNonFeasibleEdges(&BB, DTU, NewUnreachableBB); 11381ad6265SDimitry Andric 11481ad6265SDimitry Andric for (BasicBlock *DeadBB : BlocksToErase) 11581ad6265SDimitry Andric if (!DeadBB->hasAddressTaken()) 11681ad6265SDimitry Andric DTU.deleteBB(DeadBB); 11781ad6265SDimitry Andric 1180b57cec5SDimitry Andric return MadeChanges; 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric PreservedAnalyses SCCPPass::run(Function &F, FunctionAnalysisManager &AM) { 122*0fca6ea1SDimitry Andric const DataLayout &DL = F.getDataLayout(); 1230b57cec5SDimitry Andric auto &TLI = AM.getResult<TargetLibraryAnalysis>(F); 12481ad6265SDimitry Andric auto *DT = AM.getCachedResult<DominatorTreeAnalysis>(F); 12581ad6265SDimitry Andric DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy); 12681ad6265SDimitry Andric if (!runSCCP(F, DL, &TLI, DTU)) 1270b57cec5SDimitry Andric return PreservedAnalyses::all(); 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric auto PA = PreservedAnalyses(); 13081ad6265SDimitry Andric PA.preserve<DominatorTreeAnalysis>(); 1310b57cec5SDimitry Andric return PA; 1320b57cec5SDimitry Andric } 133