/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Transforms/Scalar/ConstantProp.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- ConstantProp.cpp - Code to perform Simple Constant Propagation -----===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file implements constant propagation and merging: |
10 | | // |
11 | | // Specifically, this: |
12 | | // * Converts instructions like "add int 1, 2" into 3 |
13 | | // |
14 | | // Notice that: |
15 | | // * This pass has a habit of making definitions be dead. It is a good idea |
16 | | // to run a DIE pass sometime after running this pass. |
17 | | // |
18 | | //===----------------------------------------------------------------------===// |
19 | | |
20 | | #include "llvm/ADT/SmallPtrSet.h" |
21 | | #include "llvm/ADT/SmallVector.h" |
22 | | #include "llvm/ADT/Statistic.h" |
23 | | #include "llvm/Analysis/ConstantFolding.h" |
24 | | #include "llvm/Analysis/TargetLibraryInfo.h" |
25 | | #include "llvm/IR/Constant.h" |
26 | | #include "llvm/IR/InstIterator.h" |
27 | | #include "llvm/IR/Instruction.h" |
28 | | #include "llvm/Pass.h" |
29 | | #include "llvm/Support/DebugCounter.h" |
30 | | #include "llvm/Transforms/Scalar.h" |
31 | | #include "llvm/Transforms/Utils/Local.h" |
32 | | using namespace llvm; |
33 | | |
34 | | #define DEBUG_TYPE "constprop" |
35 | | |
36 | | STATISTIC(NumInstKilled, "Number of instructions killed"); |
37 | | DEBUG_COUNTER(CPCounter, "constprop-transform", |
38 | | "Controls which instructions are killed"); |
39 | | |
40 | | namespace { |
41 | | struct ConstantPropagation : public FunctionPass { |
42 | | static char ID; // Pass identification, replacement for typeid |
43 | 919 | ConstantPropagation() : FunctionPass(ID) { |
44 | 919 | initializeConstantPropagationPass(*PassRegistry::getPassRegistry()); |
45 | 919 | } |
46 | | |
47 | | bool runOnFunction(Function &F) override; |
48 | | |
49 | 912 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
50 | 912 | AU.setPreservesCFG(); |
51 | 912 | AU.addRequired<TargetLibraryInfoWrapperPass>(); |
52 | 912 | } |
53 | | }; |
54 | | } |
55 | | |
56 | | char ConstantPropagation::ID = 0; |
57 | 36.0k | INITIALIZE_PASS_BEGIN(ConstantPropagation, "constprop", |
58 | 36.0k | "Simple constant propagation", false, false) |
59 | 36.0k | INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) |
60 | 36.0k | INITIALIZE_PASS_END(ConstantPropagation, "constprop", |
61 | | "Simple constant propagation", false, false) |
62 | | |
63 | 869 | FunctionPass *llvm::createConstantPropagationPass() { |
64 | 869 | return new ConstantPropagation(); |
65 | 869 | } |
66 | | |
67 | 3.67k | bool ConstantPropagation::runOnFunction(Function &F) { |
68 | 3.67k | if (skipFunction(F)) |
69 | 10 | return false; |
70 | 3.66k | |
71 | 3.66k | // Initialize the worklist to all of the instructions ready to process... |
72 | 3.66k | SmallPtrSet<Instruction *, 16> WorkList; |
73 | 3.66k | // The SmallVector of WorkList ensures that we do iteration at stable order. |
74 | 3.66k | // We use two containers rather than one SetVector, since remove is |
75 | 3.66k | // linear-time, and we don't care enough to remove from Vec. |
76 | 3.66k | SmallVector<Instruction *, 16> WorkListVec; |
77 | 27.6k | for (Instruction &I : instructions(&F)) { |
78 | 27.6k | WorkList.insert(&I); |
79 | 27.6k | WorkListVec.push_back(&I); |
80 | 27.6k | } |
81 | 3.66k | |
82 | 3.66k | bool Changed = false; |
83 | 3.66k | const DataLayout &DL = F.getParent()->getDataLayout(); |
84 | 3.66k | TargetLibraryInfo *TLI = |
85 | 3.66k | &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); |
86 | 3.66k | |
87 | 7.33k | while (!WorkList.empty()) { |
88 | 3.66k | SmallVector<Instruction*, 16> NewWorkListVec; |
89 | 27.6k | for (auto *I : WorkListVec) { |
90 | 27.6k | WorkList.erase(I); // Remove element from the worklist... |
91 | 27.6k | |
92 | 27.6k | if (!I->use_empty()) // Don't muck with dead instructions... |
93 | 18.7k | if (Constant *C = ConstantFoldInstruction(I, DL, TLI)) { |
94 | 582 | if (!DebugCounter::shouldExecute(CPCounter)) |
95 | 0 | continue; |
96 | 582 | |
97 | 582 | // Add all of the users of this instruction to the worklist, they might |
98 | 582 | // be constant propagatable now... |
99 | 626 | for (User *U : I->users())582 { |
100 | 626 | // If user not in the set, then add it to the vector. |
101 | 626 | if (WorkList.insert(cast<Instruction>(U)).second) |
102 | 0 | NewWorkListVec.push_back(cast<Instruction>(U)); |
103 | 626 | } |
104 | 582 | |
105 | 582 | // Replace all of the uses of a variable with uses of the constant. |
106 | 582 | I->replaceAllUsesWith(C); |
107 | 582 | |
108 | 582 | if (isInstructionTriviallyDead(I, TLI)) { |
109 | 582 | I->eraseFromParent(); |
110 | 582 | ++NumInstKilled; |
111 | 582 | } |
112 | 582 | |
113 | 582 | // We made a change to the function... |
114 | 582 | Changed = true; |
115 | 582 | } |
116 | 27.6k | } |
117 | 3.66k | WorkListVec = std::move(NewWorkListVec); |
118 | 3.66k | } |
119 | 3.66k | return Changed; |
120 | 3.66k | } |