| Chandler Carruth | 7c557f8 | 2018-06-29 23:36:03 +0000 | [diff] [blame] | 1 | //===- InstSimplifyPass.cpp -----------------------------------------------===// | 
| Duncan Sands | eaff500 | 2010-12-20 21:07:42 +0000 | [diff] [blame] | 2 | // | 
| Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 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 | 
| Duncan Sands | eaff500 | 2010-12-20 21:07:42 +0000 | [diff] [blame] | 6 | // | 
|  | 7 | //===----------------------------------------------------------------------===// | 
| Duncan Sands | eaff500 | 2010-12-20 21:07:42 +0000 | [diff] [blame] | 8 |  | 
| Chandler Carruth | 7c557f8 | 2018-06-29 23:36:03 +0000 | [diff] [blame] | 9 | #include "llvm/Transforms/Scalar/InstSimplifyPass.h" | 
| Duncan Sands | 2c440fa | 2010-12-31 17:49:05 +0000 | [diff] [blame] | 10 | #include "llvm/ADT/DepthFirstIterator.h" | 
| Duncan Sands | 697de77 | 2011-01-03 10:50:04 +0000 | [diff] [blame] | 11 | #include "llvm/ADT/SmallPtrSet.h" | 
| Duncan Sands | eaff500 | 2010-12-20 21:07:42 +0000 | [diff] [blame] | 12 | #include "llvm/ADT/Statistic.h" | 
| Daniel Jasper | aec2fa3 | 2016-12-19 08:22:17 +0000 | [diff] [blame] | 13 | #include "llvm/Analysis/AssumptionCache.h" | 
| Duncan Sands | eaff500 | 2010-12-20 21:07:42 +0000 | [diff] [blame] | 14 | #include "llvm/Analysis/InstructionSimplify.h" | 
| Adam Nemet | 0965da2 | 2017-10-09 23:19:02 +0000 | [diff] [blame] | 15 | #include "llvm/Analysis/OptimizationRemarkEmitter.h" | 
| Weiming Zhao | 45d4cb9 | 2015-11-24 18:57:06 +0000 | [diff] [blame] | 16 | #include "llvm/Analysis/TargetLibraryInfo.h" | 
| Chandler Carruth | 9fb823b | 2013-01-02 11:36:10 +0000 | [diff] [blame] | 17 | #include "llvm/IR/DataLayout.h" | 
| Chandler Carruth | 5ad5f15 | 2014-01-13 09:26:24 +0000 | [diff] [blame] | 18 | #include "llvm/IR/Dominators.h" | 
| Chandler Carruth | 9fb823b | 2013-01-02 11:36:10 +0000 | [diff] [blame] | 19 | #include "llvm/IR/Function.h" | 
|  | 20 | #include "llvm/IR/Type.h" | 
| Chandler Carruth | ed0881b | 2012-12-03 16:50:05 +0000 | [diff] [blame] | 21 | #include "llvm/Pass.h" | 
| David Blaikie | a373d18 | 2018-03-28 17:44:36 +0000 | [diff] [blame] | 22 | #include "llvm/Transforms/Utils.h" | 
| Chandler Carruth | 7c557f8 | 2018-06-29 23:36:03 +0000 | [diff] [blame] | 23 | #include "llvm/Transforms/Utils/Local.h" | 
| Duncan Sands | eaff500 | 2010-12-20 21:07:42 +0000 | [diff] [blame] | 24 | using namespace llvm; | 
|  | 25 |  | 
| Chandler Carruth | 964daaa | 2014-04-22 02:55:47 +0000 | [diff] [blame] | 26 | #define DEBUG_TYPE "instsimplify" | 
|  | 27 |  | 
| Duncan Sands | eaff500 | 2010-12-20 21:07:42 +0000 | [diff] [blame] | 28 | STATISTIC(NumSimplified, "Number of redundant instructions removed"); | 
|  | 29 |  | 
| Daniel Berlin | 954006f | 2017-04-26 13:52:16 +0000 | [diff] [blame] | 30 | static bool runImpl(Function &F, const SimplifyQuery &SQ, | 
| Sanjay Patel | 54656ca | 2017-02-06 18:26:06 +0000 | [diff] [blame] | 31 | OptimizationRemarkEmitter *ORE) { | 
| Sanjay Patel | da9f7bf | 2016-11-27 15:53:48 +0000 | [diff] [blame] | 32 | SmallPtrSet<const Instruction *, 8> S1, S2, *ToSimplify = &S1, *Next = &S2; | 
| Davide Italiano | 16284df | 2016-07-07 21:14:36 +0000 | [diff] [blame] | 33 | bool Changed = false; | 
|  | 34 |  | 
|  | 35 | do { | 
| Sanjay Patel | da9f7bf | 2016-11-27 15:53:48 +0000 | [diff] [blame] | 36 | for (BasicBlock *BB : depth_first(&F.getEntryBlock())) { | 
| Davide Italiano | 16284df | 2016-07-07 21:14:36 +0000 | [diff] [blame] | 37 | // Here be subtlety: the iterator must be incremented before the loop | 
|  | 38 | // body (not sure why), so a range-for loop won't work here. | 
|  | 39 | for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) { | 
|  | 40 | Instruction *I = &*BI++; | 
|  | 41 | // The first time through the loop ToSimplify is empty and we try to | 
|  | 42 | // simplify all instructions.  On later iterations ToSimplify is not | 
|  | 43 | // empty and we only bother simplifying instructions that are in it. | 
|  | 44 | if (!ToSimplify->empty() && !ToSimplify->count(I)) | 
|  | 45 | continue; | 
| Sanjay Patel | da9f7bf | 2016-11-27 15:53:48 +0000 | [diff] [blame] | 46 |  | 
| Davide Italiano | 16284df | 2016-07-07 21:14:36 +0000 | [diff] [blame] | 47 | // Don't waste time simplifying unused instructions. | 
| Sanjay Patel | da9f7bf | 2016-11-27 15:53:48 +0000 | [diff] [blame] | 48 | if (!I->use_empty()) { | 
| Daniel Berlin | 4d0fe64 | 2017-04-28 19:55:38 +0000 | [diff] [blame] | 49 | if (Value *V = SimplifyInstruction(I, SQ, ORE)) { | 
| Davide Italiano | 16284df | 2016-07-07 21:14:36 +0000 | [diff] [blame] | 50 | // Mark all uses for resimplification next time round the loop. | 
|  | 51 | for (User *U : I->users()) | 
|  | 52 | Next->insert(cast<Instruction>(U)); | 
|  | 53 | I->replaceAllUsesWith(V); | 
|  | 54 | ++NumSimplified; | 
|  | 55 | Changed = true; | 
|  | 56 | } | 
| Sanjay Patel | da9f7bf | 2016-11-27 15:53:48 +0000 | [diff] [blame] | 57 | } | 
| Daniel Berlin | 954006f | 2017-04-26 13:52:16 +0000 | [diff] [blame] | 58 | if (RecursivelyDeleteTriviallyDeadInstructions(I, SQ.TLI)) { | 
| Sanjay Patel | da9f7bf | 2016-11-27 15:53:48 +0000 | [diff] [blame] | 59 | // RecursivelyDeleteTriviallyDeadInstruction can remove more than one | 
|  | 60 | // instruction, so simply incrementing the iterator does not work. | 
|  | 61 | // When instructions get deleted re-iterate instead. | 
|  | 62 | BI = BB->begin(); | 
|  | 63 | BE = BB->end(); | 
|  | 64 | Changed = true; | 
| Davide Italiano | 16284df | 2016-07-07 21:14:36 +0000 | [diff] [blame] | 65 | } | 
|  | 66 | } | 
| Sanjay Patel | da9f7bf | 2016-11-27 15:53:48 +0000 | [diff] [blame] | 67 | } | 
| Davide Italiano | 16284df | 2016-07-07 21:14:36 +0000 | [diff] [blame] | 68 |  | 
|  | 69 | // Place the list of instructions to simplify on the next loop iteration | 
|  | 70 | // into ToSimplify. | 
|  | 71 | std::swap(ToSimplify, Next); | 
|  | 72 | Next->clear(); | 
|  | 73 | } while (!ToSimplify->empty()); | 
|  | 74 |  | 
|  | 75 | return Changed; | 
|  | 76 | } | 
|  | 77 |  | 
| Duncan Sands | eaff500 | 2010-12-20 21:07:42 +0000 | [diff] [blame] | 78 | namespace { | 
| Chandler Carruth | 7c557f8 | 2018-06-29 23:36:03 +0000 | [diff] [blame] | 79 | struct InstSimplifyLegacyPass : public FunctionPass { | 
|  | 80 | static char ID; // Pass identification, replacement for typeid | 
|  | 81 | InstSimplifyLegacyPass() : FunctionPass(ID) { | 
|  | 82 | initializeInstSimplifyLegacyPassPass(*PassRegistry::getPassRegistry()); | 
|  | 83 | } | 
| Duncan Sands | eaff500 | 2010-12-20 21:07:42 +0000 | [diff] [blame] | 84 |  | 
| Chandler Carruth | 7c557f8 | 2018-06-29 23:36:03 +0000 | [diff] [blame] | 85 | void getAnalysisUsage(AnalysisUsage &AU) const override { | 
|  | 86 | AU.setPreservesCFG(); | 
|  | 87 | AU.addRequired<DominatorTreeWrapperPass>(); | 
|  | 88 | AU.addRequired<AssumptionCacheTracker>(); | 
|  | 89 | AU.addRequired<TargetLibraryInfoWrapperPass>(); | 
|  | 90 | AU.addRequired<OptimizationRemarkEmitterWrapperPass>(); | 
|  | 91 | } | 
| Duncan Sands | eaff500 | 2010-12-20 21:07:42 +0000 | [diff] [blame] | 92 |  | 
| Chandler Carruth | 7c557f8 | 2018-06-29 23:36:03 +0000 | [diff] [blame] | 93 | /// runOnFunction - Remove instructions that simplify. | 
|  | 94 | bool runOnFunction(Function &F) override { | 
|  | 95 | if (skipFunction(F)) | 
|  | 96 | return false; | 
| Andrew Kaylor | 50271f7 | 2016-05-03 22:32:30 +0000 | [diff] [blame] | 97 |  | 
| Chandler Carruth | 7c557f8 | 2018-06-29 23:36:03 +0000 | [diff] [blame] | 98 | const DominatorTree *DT = | 
|  | 99 | &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); | 
|  | 100 | const TargetLibraryInfo *TLI = | 
|  | 101 | &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); | 
|  | 102 | AssumptionCache *AC = | 
|  | 103 | &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); | 
|  | 104 | OptimizationRemarkEmitter *ORE = | 
|  | 105 | &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE(); | 
|  | 106 | const DataLayout &DL = F.getParent()->getDataLayout(); | 
|  | 107 | const SimplifyQuery SQ(DL, TLI, DT, AC); | 
|  | 108 | return runImpl(F, SQ, ORE); | 
|  | 109 | } | 
|  | 110 | }; | 
|  | 111 | } // namespace | 
| Duncan Sands | eaff500 | 2010-12-20 21:07:42 +0000 | [diff] [blame] | 112 |  | 
| Chandler Carruth | 7c557f8 | 2018-06-29 23:36:03 +0000 | [diff] [blame] | 113 | char InstSimplifyLegacyPass::ID = 0; | 
|  | 114 | INITIALIZE_PASS_BEGIN(InstSimplifyLegacyPass, "instsimplify", | 
| Chad Rosier | c24b86f | 2011-12-01 03:08:23 +0000 | [diff] [blame] | 115 | "Remove redundant instructions", false, false) | 
| Daniel Jasper | aec2fa3 | 2016-12-19 08:22:17 +0000 | [diff] [blame] | 116 | INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) | 
| Dehao Chen | 3857f8f | 2016-09-06 22:17:16 +0000 | [diff] [blame] | 117 | INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) | 
| Chandler Carruth | b98f63d | 2015-01-15 10:41:28 +0000 | [diff] [blame] | 118 | INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) | 
| Sanjay Patel | 54656ca | 2017-02-06 18:26:06 +0000 | [diff] [blame] | 119 | INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass) | 
| Chandler Carruth | 7c557f8 | 2018-06-29 23:36:03 +0000 | [diff] [blame] | 120 | INITIALIZE_PASS_END(InstSimplifyLegacyPass, "instsimplify", | 
| Chad Rosier | c24b86f | 2011-12-01 03:08:23 +0000 | [diff] [blame] | 121 | "Remove redundant instructions", false, false) | 
| Duncan Sands | eaff500 | 2010-12-20 21:07:42 +0000 | [diff] [blame] | 122 |  | 
|  | 123 | // Public interface to the simplify instructions pass. | 
| Chandler Carruth | 7c557f8 | 2018-06-29 23:36:03 +0000 | [diff] [blame] | 124 | FunctionPass *llvm::createInstSimplifyLegacyPass() { | 
|  | 125 | return new InstSimplifyLegacyPass(); | 
| Duncan Sands | eaff500 | 2010-12-20 21:07:42 +0000 | [diff] [blame] | 126 | } | 
| Davide Italiano | 16284df | 2016-07-07 21:14:36 +0000 | [diff] [blame] | 127 |  | 
| Chandler Carruth | 7c557f8 | 2018-06-29 23:36:03 +0000 | [diff] [blame] | 128 | PreservedAnalyses InstSimplifyPass::run(Function &F, | 
|  | 129 | FunctionAnalysisManager &AM) { | 
| Dehao Chen | 3857f8f | 2016-09-06 22:17:16 +0000 | [diff] [blame] | 130 | auto &DT = AM.getResult<DominatorTreeAnalysis>(F); | 
| Davide Italiano | 16284df | 2016-07-07 21:14:36 +0000 | [diff] [blame] | 131 | auto &TLI = AM.getResult<TargetLibraryAnalysis>(F); | 
| Daniel Jasper | aec2fa3 | 2016-12-19 08:22:17 +0000 | [diff] [blame] | 132 | auto &AC = AM.getResult<AssumptionAnalysis>(F); | 
| Sanjay Patel | 54656ca | 2017-02-06 18:26:06 +0000 | [diff] [blame] | 133 | auto &ORE = AM.getResult<OptimizationRemarkEmitterAnalysis>(F); | 
| Daniel Berlin | 954006f | 2017-04-26 13:52:16 +0000 | [diff] [blame] | 134 | const DataLayout &DL = F.getParent()->getDataLayout(); | 
|  | 135 | const SimplifyQuery SQ(DL, &TLI, &DT, &AC); | 
|  | 136 | bool Changed = runImpl(F, SQ, &ORE); | 
| Davide Italiano | 16284df | 2016-07-07 21:14:36 +0000 | [diff] [blame] | 137 | if (!Changed) | 
|  | 138 | return PreservedAnalyses::all(); | 
| Chandler Carruth | ca68a3e | 2017-01-15 06:32:49 +0000 | [diff] [blame] | 139 |  | 
|  | 140 | PreservedAnalyses PA; | 
|  | 141 | PA.preserveSet<CFGAnalyses>(); | 
|  | 142 | return PA; | 
| Davide Italiano | 16284df | 2016-07-07 21:14:36 +0000 | [diff] [blame] | 143 | } |