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
runImpl(Function & F,const SimplifyQuery & SQ)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
InstSimplifyLegacyPass__anon358ab4350111::InstSimplifyLegacyPass800b57cec5SDimitry Andric InstSimplifyLegacyPass() : FunctionPass(ID) {
810b57cec5SDimitry Andric initializeInstSimplifyLegacyPassPass(*PassRegistry::getPassRegistry());
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric
getAnalysisUsage__anon358ab4350111::InstSimplifyLegacyPass840b57cec5SDimitry 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.
runOnFunction__anon358ab4350111::InstSimplifyLegacyPass920b57cec5SDimitry 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)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)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
run(Function & F,FunctionAnalysisManager & AM)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