xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Scalar/InstSimplifyPass.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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