| //===- ConstantProp.cpp - Code to perform Simple Constant Propagation -----===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file implements constant propagation and merging: | |
| // | |
| // Specifically, this: | |
| // * Converts instructions like "add int 1, 2" into 3 | |
| // | |
| // Notice that: | |
| // * This pass has a habit of making definitions be dead. It is a good idea | |
| // to run a DIE pass sometime after running this pass. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/ADT/SmallPtrSet.h" | |
| #include "llvm/ADT/SmallVector.h" | |
| #include "llvm/ADT/Statistic.h" | |
| #include "llvm/Analysis/ConstantFolding.h" | |
| #include "llvm/Analysis/TargetLibraryInfo.h" | |
| #include "llvm/IR/Constant.h" | |
| #include "llvm/IR/InstIterator.h" | |
| #include "llvm/IR/Instruction.h" | |
| #include "llvm/InitializePasses.h" | |
| #include "llvm/Pass.h" | |
| #include "llvm/Support/DebugCounter.h" | |
| #include "llvm/Transforms/Scalar.h" | |
| #include "llvm/Transforms/Utils/Local.h" | |
| using namespace llvm; | |
| #define DEBUG_TYPE "constprop" | |
| STATISTIC(NumInstKilled, "Number of instructions killed"); | |
| DEBUG_COUNTER(CPCounter, "constprop-transform", | |
| "Controls which instructions are killed"); | |
| namespace { | |
| struct ConstantPropagation : public FunctionPass { | |
| static char ID; // Pass identification, replacement for typeid | |
| ConstantPropagation() : FunctionPass(ID) { | |
| initializeConstantPropagationPass(*PassRegistry::getPassRegistry()); | |
| } | |
| bool runOnFunction(Function &F) override; | |
| void getAnalysisUsage(AnalysisUsage &AU) const override { | |
| AU.setPreservesCFG(); | |
| AU.addRequired<TargetLibraryInfoWrapperPass>(); | |
| } | |
| }; | |
| } | |
| char ConstantPropagation::ID = 0; | |
| INITIALIZE_PASS_BEGIN(ConstantPropagation, "constprop", | |
| "Simple constant propagation", false, false) | |
| INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) | |
| INITIALIZE_PASS_END(ConstantPropagation, "constprop", | |
| "Simple constant propagation", false, false) | |
| FunctionPass *llvm::createConstantPropagationPass() { | |
| return new ConstantPropagation(); | |
| } | |
| bool ConstantPropagation::runOnFunction(Function &F) { | |
| if (skipFunction(F)) | |
| return false; | |
| // Initialize the worklist to all of the instructions ready to process... | |
| SmallPtrSet<Instruction *, 16> WorkList; | |
| // The SmallVector of WorkList ensures that we do iteration at stable order. | |
| // We use two containers rather than one SetVector, since remove is | |
| // linear-time, and we don't care enough to remove from Vec. | |
| SmallVector<Instruction *, 16> WorkListVec; | |
| for (Instruction &I : instructions(&F)) { | |
| WorkList.insert(&I); | |
| WorkListVec.push_back(&I); | |
| } | |
| bool Changed = false; | |
| const DataLayout &DL = F.getParent()->getDataLayout(); | |
| TargetLibraryInfo *TLI = | |
| &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F); | |
| while (!WorkList.empty()) { | |
| SmallVector<Instruction*, 16> NewWorkListVec; | |
| for (auto *I : WorkListVec) { | |
| WorkList.erase(I); // Remove element from the worklist... | |
| if (!I->use_empty()) // Don't muck with dead instructions... | |
| if (Constant *C = ConstantFoldInstruction(I, DL, TLI)) { | |
| if (!DebugCounter::shouldExecute(CPCounter)) | |
| continue; | |
| // Add all of the users of this instruction to the worklist, they might | |
| // be constant propagatable now... | |
| for (User *U : I->users()) { | |
| // If user not in the set, then add it to the vector. | |
| if (WorkList.insert(cast<Instruction>(U)).second) | |
| NewWorkListVec.push_back(cast<Instruction>(U)); | |
| } | |
| // Replace all of the uses of a variable with uses of the constant. | |
| I->replaceAllUsesWith(C); | |
| if (isInstructionTriviallyDead(I, TLI)) { | |
| I->eraseFromParent(); | |
| ++NumInstKilled; | |
| } | |
| // We made a change to the function... | |
| Changed = true; | |
| } | |
| } | |
| WorkListVec = std::move(NewWorkListVec); | |
| } | |
| return Changed; | |
| } |