10b57cec5SDimitry Andric //===- InstSimplifyPass.cpp -----------------------------------------------===// 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 #include "llvm/Transforms/Scalar/InstSimplifyPass.h" 100b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 110b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h" 120b57cec5SDimitry Andric #include "llvm/Analysis/AssumptionCache.h" 130b57cec5SDimitry Andric #include "llvm/Analysis/InstructionSimplify.h" 140b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h" 150b57cec5SDimitry Andric #include "llvm/IR/Dominators.h" 160b57cec5SDimitry Andric #include "llvm/IR/Function.h" 17480093f4SDimitry Andric #include "llvm/InitializePasses.h" 180b57cec5SDimitry Andric #include "llvm/Pass.h" 19e8d8bef9SDimitry Andric #include "llvm/Transforms/Scalar.h" 200b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Local.h" 21e8d8bef9SDimitry Andric 220b57cec5SDimitry Andric using namespace llvm; 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #define DEBUG_TYPE "instsimplify" 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric STATISTIC(NumSimplified, "Number of redundant instructions removed"); 270b57cec5SDimitry Andric 2806c3fb27SDimitry Andric static bool runImpl(Function &F, const SimplifyQuery &SQ) { 290b57cec5SDimitry Andric SmallPtrSet<const Instruction *, 8> S1, S2, *ToSimplify = &S1, *Next = &S2; 300b57cec5SDimitry Andric bool Changed = false; 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric do { 338bcb0991SDimitry Andric for (BasicBlock &BB : F) { 348bcb0991SDimitry Andric // Unreachable code can take on strange forms that we are not prepared to 358bcb0991SDimitry Andric // handle. For example, an instruction may have itself as an operand. 368bcb0991SDimitry Andric if (!SQ.DT->isReachableFromEntry(&BB)) 370b57cec5SDimitry Andric continue; 380b57cec5SDimitry Andric 395ffd83dbSDimitry Andric SmallVector<WeakTrackingVH, 8> DeadInstsInBB; 408bcb0991SDimitry Andric for (Instruction &I : BB) { 418bcb0991SDimitry Andric // The first time through the loop, ToSimplify is empty and we try to 428bcb0991SDimitry Andric // simplify all instructions. On later iterations, ToSimplify is not 438bcb0991SDimitry Andric // empty and we only bother simplifying instructions that are in it. 448bcb0991SDimitry Andric if (!ToSimplify->empty() && !ToSimplify->count(&I)) 458bcb0991SDimitry Andric continue; 468bcb0991SDimitry Andric 478bcb0991SDimitry Andric // Don't waste time simplifying dead/unused instructions. 488bcb0991SDimitry Andric if (isInstructionTriviallyDead(&I)) { 498bcb0991SDimitry Andric DeadInstsInBB.push_back(&I); 508bcb0991SDimitry Andric Changed = true; 518bcb0991SDimitry Andric } else if (!I.use_empty()) { 5206c3fb27SDimitry Andric if (Value *V = simplifyInstruction(&I, SQ)) { 530b57cec5SDimitry Andric // Mark all uses for resimplification next time round the loop. 548bcb0991SDimitry Andric for (User *U : I.users()) 550b57cec5SDimitry Andric Next->insert(cast<Instruction>(U)); 568bcb0991SDimitry Andric I.replaceAllUsesWith(V); 570b57cec5SDimitry Andric ++NumSimplified; 580b57cec5SDimitry Andric Changed = true; 598bcb0991SDimitry Andric // A call can get simplified, but it may not be trivially dead. 608bcb0991SDimitry Andric if (isInstructionTriviallyDead(&I)) 618bcb0991SDimitry Andric DeadInstsInBB.push_back(&I); 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric } 658bcb0991SDimitry Andric RecursivelyDeleteTriviallyDeadInstructions(DeadInstsInBB, SQ.TLI); 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric // Place the list of instructions to simplify on the next loop iteration 690b57cec5SDimitry Andric // into ToSimplify. 700b57cec5SDimitry Andric std::swap(ToSimplify, Next); 710b57cec5SDimitry Andric Next->clear(); 720b57cec5SDimitry Andric } while (!ToSimplify->empty()); 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric return Changed; 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric namespace { 780b57cec5SDimitry Andric struct InstSimplifyLegacyPass : public FunctionPass { 790b57cec5SDimitry Andric static char ID; // Pass identification, replacement for typeid 800b57cec5SDimitry Andric InstSimplifyLegacyPass() : FunctionPass(ID) { 810b57cec5SDimitry Andric initializeInstSimplifyLegacyPassPass(*PassRegistry::getPassRegistry()); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 850b57cec5SDimitry Andric AU.setPreservesCFG(); 860b57cec5SDimitry Andric AU.addRequired<DominatorTreeWrapperPass>(); 870b57cec5SDimitry Andric AU.addRequired<AssumptionCacheTracker>(); 880b57cec5SDimitry Andric AU.addRequired<TargetLibraryInfoWrapperPass>(); 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 918bcb0991SDimitry Andric /// Remove instructions that simplify. 920b57cec5SDimitry Andric bool runOnFunction(Function &F) override { 930b57cec5SDimitry Andric if (skipFunction(F)) 940b57cec5SDimitry Andric return false; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric const DominatorTree *DT = 970b57cec5SDimitry Andric &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 980b57cec5SDimitry Andric const TargetLibraryInfo *TLI = 998bcb0991SDimitry Andric &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F); 1000b57cec5SDimitry Andric AssumptionCache *AC = 1010b57cec5SDimitry Andric &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); 102*0fca6ea1SDimitry Andric const DataLayout &DL = F.getDataLayout(); 1030b57cec5SDimitry Andric const SimplifyQuery SQ(DL, TLI, DT, AC); 10406c3fb27SDimitry Andric return runImpl(F, SQ); 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric }; 1070b57cec5SDimitry Andric } // namespace 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric char InstSimplifyLegacyPass::ID = 0; 1100b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(InstSimplifyLegacyPass, "instsimplify", 1110b57cec5SDimitry Andric "Remove redundant instructions", false, false) 1120b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) 1130b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 1140b57cec5SDimitry Andric INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) 1150b57cec5SDimitry Andric INITIALIZE_PASS_END(InstSimplifyLegacyPass, "instsimplify", 1160b57cec5SDimitry Andric "Remove redundant instructions", false, false) 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric // Public interface to the simplify instructions pass. 1190b57cec5SDimitry Andric FunctionPass *llvm::createInstSimplifyLegacyPass() { 1200b57cec5SDimitry Andric return new InstSimplifyLegacyPass(); 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric PreservedAnalyses InstSimplifyPass::run(Function &F, 1240b57cec5SDimitry Andric FunctionAnalysisManager &AM) { 1250b57cec5SDimitry Andric auto &DT = AM.getResult<DominatorTreeAnalysis>(F); 1260b57cec5SDimitry Andric auto &TLI = AM.getResult<TargetLibraryAnalysis>(F); 1270b57cec5SDimitry Andric auto &AC = AM.getResult<AssumptionAnalysis>(F); 128*0fca6ea1SDimitry Andric const DataLayout &DL = F.getDataLayout(); 1290b57cec5SDimitry Andric const SimplifyQuery SQ(DL, &TLI, &DT, &AC); 13006c3fb27SDimitry Andric bool Changed = runImpl(F, SQ); 1310b57cec5SDimitry Andric if (!Changed) 1320b57cec5SDimitry Andric return PreservedAnalyses::all(); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric PreservedAnalyses PA; 1350b57cec5SDimitry Andric PA.preserveSet<CFGAnalyses>(); 1360b57cec5SDimitry Andric return PA; 1370b57cec5SDimitry Andric } 138