17c557f80SChandler Carruth //===- InstSimplifyPass.cpp -----------------------------------------------===//
27c557f80SChandler Carruth //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67c557f80SChandler Carruth //
77c557f80SChandler Carruth //===----------------------------------------------------------------------===//
87c557f80SChandler Carruth
97c557f80SChandler Carruth #include "llvm/Transforms/Scalar/InstSimplifyPass.h"
107c557f80SChandler Carruth #include "llvm/ADT/SmallPtrSet.h"
117c557f80SChandler Carruth #include "llvm/ADT/Statistic.h"
127c557f80SChandler Carruth #include "llvm/Analysis/AssumptionCache.h"
137c557f80SChandler Carruth #include "llvm/Analysis/InstructionSimplify.h"
147c557f80SChandler Carruth #include "llvm/Analysis/OptimizationRemarkEmitter.h"
157c557f80SChandler Carruth #include "llvm/Analysis/TargetLibraryInfo.h"
167c557f80SChandler Carruth #include "llvm/IR/Dominators.h"
177c557f80SChandler Carruth #include "llvm/IR/Function.h"
1805da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
197c557f80SChandler Carruth #include "llvm/Pass.h"
20f50b3ff0SArthur Eubanks #include "llvm/Transforms/Scalar.h"
217c557f80SChandler Carruth #include "llvm/Transforms/Utils/Local.h"
2296f0b575SArthur Eubanks
237c557f80SChandler Carruth using namespace llvm;
247c557f80SChandler Carruth
257c557f80SChandler Carruth #define DEBUG_TYPE "instsimplify"
267c557f80SChandler Carruth
277c557f80SChandler Carruth STATISTIC(NumSimplified, "Number of redundant instructions removed");
287c557f80SChandler Carruth
runImpl(Function & F,const SimplifyQuery & SQ,OptimizationRemarkEmitter * ORE)297c557f80SChandler Carruth static bool runImpl(Function &F, const SimplifyQuery &SQ,
307c557f80SChandler Carruth OptimizationRemarkEmitter *ORE) {
317c557f80SChandler Carruth SmallPtrSet<const Instruction *, 8> S1, S2, *ToSimplify = &S1, *Next = &S2;
327c557f80SChandler Carruth bool Changed = false;
337c557f80SChandler Carruth
347c557f80SChandler Carruth do {
3502b9e45aSSanjay Patel for (BasicBlock &BB : F) {
364a2cd7beSSanjay Patel // Unreachable code can take on strange forms that we are not prepared to
374a2cd7beSSanjay Patel // handle. For example, an instruction may have itself as an operand.
384a2cd7beSSanjay Patel if (!SQ.DT->isReachableFromEntry(&BB))
394a2cd7beSSanjay Patel continue;
404a2cd7beSSanjay Patel
419e66c4ecSAlina Sbirlea SmallVector<WeakTrackingVH, 8> DeadInstsInBB;
4202b9e45aSSanjay Patel for (Instruction &I : BB) {
4302b9e45aSSanjay Patel // The first time through the loop, ToSimplify is empty and we try to
4402b9e45aSSanjay Patel // simplify all instructions. On later iterations, ToSimplify is not
457c557f80SChandler Carruth // empty and we only bother simplifying instructions that are in it.
4602b9e45aSSanjay Patel if (!ToSimplify->empty() && !ToSimplify->count(&I))
477c557f80SChandler Carruth continue;
487c557f80SChandler Carruth
4902b9e45aSSanjay Patel // Don't waste time simplifying dead/unused instructions.
5002b9e45aSSanjay Patel if (isInstructionTriviallyDead(&I)) {
5102b9e45aSSanjay Patel DeadInstsInBB.push_back(&I);
52d218a332SBjorn Pettersson Changed = true;
5302b9e45aSSanjay Patel } else if (!I.use_empty()) {
54*b8c2781fSSimon Moll if (Value *V = simplifyInstruction(&I, SQ, ORE)) {
557c557f80SChandler Carruth // Mark all uses for resimplification next time round the loop.
5602b9e45aSSanjay Patel for (User *U : I.users())
577c557f80SChandler Carruth Next->insert(cast<Instruction>(U));
5802b9e45aSSanjay Patel I.replaceAllUsesWith(V);
597c557f80SChandler Carruth ++NumSimplified;
607c557f80SChandler Carruth Changed = true;
6102b9e45aSSanjay Patel // A call can get simplified, but it may not be trivially dead.
6202b9e45aSSanjay Patel if (isInstructionTriviallyDead(&I))
6302b9e45aSSanjay Patel DeadInstsInBB.push_back(&I);
647c557f80SChandler Carruth }
657c557f80SChandler Carruth }
667c557f80SChandler Carruth }
6702b9e45aSSanjay Patel RecursivelyDeleteTriviallyDeadInstructions(DeadInstsInBB, SQ.TLI);
687c557f80SChandler Carruth }
697c557f80SChandler Carruth
707c557f80SChandler Carruth // Place the list of instructions to simplify on the next loop iteration
717c557f80SChandler Carruth // into ToSimplify.
727c557f80SChandler Carruth std::swap(ToSimplify, Next);
737c557f80SChandler Carruth Next->clear();
747c557f80SChandler Carruth } while (!ToSimplify->empty());
757c557f80SChandler Carruth
767c557f80SChandler Carruth return Changed;
777c557f80SChandler Carruth }
787c557f80SChandler Carruth
797c557f80SChandler Carruth namespace {
807c557f80SChandler Carruth struct InstSimplifyLegacyPass : public FunctionPass {
817c557f80SChandler Carruth static char ID; // Pass identification, replacement for typeid
InstSimplifyLegacyPass__anoncbdf17650111::InstSimplifyLegacyPass827c557f80SChandler Carruth InstSimplifyLegacyPass() : FunctionPass(ID) {
837c557f80SChandler Carruth initializeInstSimplifyLegacyPassPass(*PassRegistry::getPassRegistry());
847c557f80SChandler Carruth }
857c557f80SChandler Carruth
getAnalysisUsage__anoncbdf17650111::InstSimplifyLegacyPass867c557f80SChandler Carruth void getAnalysisUsage(AnalysisUsage &AU) const override {
877c557f80SChandler Carruth AU.setPreservesCFG();
887c557f80SChandler Carruth AU.addRequired<DominatorTreeWrapperPass>();
897c557f80SChandler Carruth AU.addRequired<AssumptionCacheTracker>();
907c557f80SChandler Carruth AU.addRequired<TargetLibraryInfoWrapperPass>();
917c557f80SChandler Carruth AU.addRequired<OptimizationRemarkEmitterWrapperPass>();
927c557f80SChandler Carruth }
937c557f80SChandler Carruth
944a2cd7beSSanjay Patel /// Remove instructions that simplify.
runOnFunction__anoncbdf17650111::InstSimplifyLegacyPass957c557f80SChandler Carruth bool runOnFunction(Function &F) override {
967c557f80SChandler Carruth if (skipFunction(F))
977c557f80SChandler Carruth return false;
987c557f80SChandler Carruth
997c557f80SChandler Carruth const DominatorTree *DT =
1007c557f80SChandler Carruth &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1017c557f80SChandler Carruth const TargetLibraryInfo *TLI =
1029c27b59cSTeresa Johnson &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
1037c557f80SChandler Carruth AssumptionCache *AC =
1047c557f80SChandler Carruth &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
1057c557f80SChandler Carruth OptimizationRemarkEmitter *ORE =
1067c557f80SChandler Carruth &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
1077c557f80SChandler Carruth const DataLayout &DL = F.getParent()->getDataLayout();
1087c557f80SChandler Carruth const SimplifyQuery SQ(DL, TLI, DT, AC);
1097c557f80SChandler Carruth return runImpl(F, SQ, ORE);
1107c557f80SChandler Carruth }
1117c557f80SChandler Carruth };
1127c557f80SChandler Carruth } // namespace
1137c557f80SChandler Carruth
1147c557f80SChandler Carruth char InstSimplifyLegacyPass::ID = 0;
1157c557f80SChandler Carruth INITIALIZE_PASS_BEGIN(InstSimplifyLegacyPass, "instsimplify",
1167c557f80SChandler Carruth "Remove redundant instructions", false, false)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)1177c557f80SChandler Carruth INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
1187c557f80SChandler Carruth INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
1197c557f80SChandler Carruth INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
1207c557f80SChandler Carruth INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass)
1217c557f80SChandler Carruth INITIALIZE_PASS_END(InstSimplifyLegacyPass, "instsimplify",
1227c557f80SChandler Carruth "Remove redundant instructions", false, false)
1237c557f80SChandler Carruth
1247c557f80SChandler Carruth // Public interface to the simplify instructions pass.
1257c557f80SChandler Carruth FunctionPass *llvm::createInstSimplifyLegacyPass() {
1267c557f80SChandler Carruth return new InstSimplifyLegacyPass();
1277c557f80SChandler Carruth }
1287c557f80SChandler Carruth
run(Function & F,FunctionAnalysisManager & AM)1297c557f80SChandler Carruth PreservedAnalyses InstSimplifyPass::run(Function &F,
1307c557f80SChandler Carruth FunctionAnalysisManager &AM) {
1317c557f80SChandler Carruth auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
1327c557f80SChandler Carruth auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
1337c557f80SChandler Carruth auto &AC = AM.getResult<AssumptionAnalysis>(F);
1347c557f80SChandler Carruth auto &ORE = AM.getResult<OptimizationRemarkEmitterAnalysis>(F);
1357c557f80SChandler Carruth const DataLayout &DL = F.getParent()->getDataLayout();
1367c557f80SChandler Carruth const SimplifyQuery SQ(DL, &TLI, &DT, &AC);
1377c557f80SChandler Carruth bool Changed = runImpl(F, SQ, &ORE);
1387c557f80SChandler Carruth if (!Changed)
1397c557f80SChandler Carruth return PreservedAnalyses::all();
1407c557f80SChandler Carruth
1417c557f80SChandler Carruth PreservedAnalyses PA;
1427c557f80SChandler Carruth PA.preserveSet<CFGAnalyses>();
1437c557f80SChandler Carruth return PA;
1447c557f80SChandler Carruth }
145