#include "llvm/Transforms/Scalar/InstSimplifyPass.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/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Transforms/Scalar.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) {
if (!SQ.DT->isReachableFromEntry(&BB))
continue;
SmallVector<WeakTrackingVH, 8> DeadInstsInBB;
for (Instruction &I : BB) {
if (!ToSimplify->empty() && !ToSimplify->count(&I))
continue;
if (isInstructionTriviallyDead(&I)) {
DeadInstsInBB.push_back(&I);
Changed = true;
} else if (!I.use_empty()) {
if (Value *V = simplifyInstruction(&I, SQ, ORE)) {
for (User *U : I.users())
Next->insert(cast<Instruction>(U));
I.replaceAllUsesWith(V);
++NumSimplified;
Changed = true;
if (isInstructionTriviallyDead(&I))
DeadInstsInBB.push_back(&I);
}
}
}
RecursivelyDeleteTriviallyDeadInstructions(DeadInstsInBB, SQ.TLI);
}
std::swap(ToSimplify, Next);
Next->clear();
} while (!ToSimplify->empty());
return Changed;
}
namespace {
struct InstSimplifyLegacyPass : public FunctionPass {
static char ID; 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>();
}
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);
}
};
}
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)
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;
}