| //===- InstSimplifyPass.cpp -----------------------------------------------===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/Transforms/Scalar/InstSimplifyPass.h" |
| #include "llvm/ADT/DepthFirstIterator.h" |
| #include "llvm/ADT/SmallPtrSet.h" |
| #include "llvm/ADT/Statistic.h" |
| #include "llvm/Analysis/AssumptionCache.h" |
| #include "llvm/Analysis/InstructionSimplify.h" |
| #include "llvm/Analysis/OptimizationRemarkEmitter.h" |
| #include "llvm/Analysis/TargetLibraryInfo.h" |
| #include "llvm/IR/DataLayout.h" |
| #include "llvm/IR/Dominators.h" |
| #include "llvm/IR/Function.h" |
| #include "llvm/IR/Type.h" |
| #include "llvm/InitializePasses.h" |
| #include "llvm/Pass.h" |
| #include "llvm/Transforms/Utils.h" |
| #include "llvm/Transforms/Utils/Local.h" |
| using namespace llvm; |
| |
| #define DEBUG_TYPE "instsimplify" |
| |
| STATISTIC(NumSimplified, "Number of redundant instructions removed"); |
| |
| static bool runImpl(Function &F, const SimplifyQuery &SQ, |
| OptimizationRemarkEmitter *ORE) { |
| SmallPtrSet<const Instruction *, 8> S1, S2, *ToSimplify = &S1, *Next = &S2; |
| bool Changed = false; |
| |
| do { |
| for (BasicBlock &BB : F) { |
| // Unreachable code can take on strange forms that we are not prepared to |
| // handle. For example, an instruction may have itself as an operand. |
| if (!SQ.DT->isReachableFromEntry(&BB)) |
| continue; |
| |
| SmallVector<Instruction *, 8> DeadInstsInBB; |
| for (Instruction &I : BB) { |
| // The first time through the loop, ToSimplify is empty and we try to |
| // simplify all instructions. On later iterations, ToSimplify is not |
| // empty and we only bother simplifying instructions that are in it. |
| if (!ToSimplify->empty() && !ToSimplify->count(&I)) |
| continue; |
| |
| // Don't waste time simplifying dead/unused instructions. |
| if (isInstructionTriviallyDead(&I)) { |
| DeadInstsInBB.push_back(&I); |
| Changed = true; |
| } else if (!I.use_empty()) { |
| if (Value *V = SimplifyInstruction(&I, SQ, ORE)) { |
| // Mark all uses for resimplification next time round the loop. |
| for (User *U : I.users()) |
| Next->insert(cast<Instruction>(U)); |
| I.replaceAllUsesWith(V); |
| ++NumSimplified; |
| Changed = true; |
| // A call can get simplified, but it may not be trivially dead. |
| if (isInstructionTriviallyDead(&I)) |
| DeadInstsInBB.push_back(&I); |
| } |
| } |
| } |
| RecursivelyDeleteTriviallyDeadInstructions(DeadInstsInBB, SQ.TLI); |
| } |
| |
| // Place the list of instructions to simplify on the next loop iteration |
| // into ToSimplify. |
| std::swap(ToSimplify, Next); |
| Next->clear(); |
| } while (!ToSimplify->empty()); |
| |
| return Changed; |
| } |
| |
| namespace { |
| struct InstSimplifyLegacyPass : public FunctionPass { |
| static char ID; // Pass identification, replacement for typeid |
| InstSimplifyLegacyPass() : FunctionPass(ID) { |
| initializeInstSimplifyLegacyPassPass(*PassRegistry::getPassRegistry()); |
| } |
| |
| void getAnalysisUsage(AnalysisUsage &AU) const override { |
| AU.setPreservesCFG(); |
| AU.addRequired<DominatorTreeWrapperPass>(); |
| AU.addRequired<AssumptionCacheTracker>(); |
| AU.addRequired<TargetLibraryInfoWrapperPass>(); |
| AU.addRequired<OptimizationRemarkEmitterWrapperPass>(); |
| } |
| |
| /// Remove instructions that simplify. |
| bool runOnFunction(Function &F) override { |
| if (skipFunction(F)) |
| return false; |
| |
| const DominatorTree *DT = |
| &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); |
| const TargetLibraryInfo *TLI = |
| &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F); |
| AssumptionCache *AC = |
| &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); |
| OptimizationRemarkEmitter *ORE = |
| &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE(); |
| const DataLayout &DL = F.getParent()->getDataLayout(); |
| const SimplifyQuery SQ(DL, TLI, DT, AC); |
| return runImpl(F, SQ, ORE); |
| } |
| }; |
| } // namespace |
| |
| char InstSimplifyLegacyPass::ID = 0; |
| INITIALIZE_PASS_BEGIN(InstSimplifyLegacyPass, "instsimplify", |
| "Remove redundant instructions", false, false) |
| INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) |
| INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) |
| INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) |
| INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass) |
| INITIALIZE_PASS_END(InstSimplifyLegacyPass, "instsimplify", |
| "Remove redundant instructions", false, false) |
| |
| // Public interface to the simplify instructions pass. |
| FunctionPass *llvm::createInstSimplifyLegacyPass() { |
| return new InstSimplifyLegacyPass(); |
| } |
| |
| PreservedAnalyses InstSimplifyPass::run(Function &F, |
| FunctionAnalysisManager &AM) { |
| auto &DT = AM.getResult<DominatorTreeAnalysis>(F); |
| auto &TLI = AM.getResult<TargetLibraryAnalysis>(F); |
| auto &AC = AM.getResult<AssumptionAnalysis>(F); |
| auto &ORE = AM.getResult<OptimizationRemarkEmitterAnalysis>(F); |
| const DataLayout &DL = F.getParent()->getDataLayout(); |
| const SimplifyQuery SQ(DL, &TLI, &DT, &AC); |
| bool Changed = runImpl(F, SQ, &ORE); |
| if (!Changed) |
| return PreservedAnalyses::all(); |
| |
| PreservedAnalyses PA; |
| PA.preserveSet<CFGAnalyses>(); |
| return PA; |
| } |