2001-06-07 04:29:01 +08:00
|
|
|
//===- DCE.cpp - Code to perform dead code elimination --------------------===//
|
2005-04-22 07:48:37 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2005-04-22 07:48:37 +08:00
|
|
|
//
|
2003-10-21 03:43:21 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2001-06-07 04:29:01 +08:00
|
|
|
//
|
2002-05-07 12:24:11 +08:00
|
|
|
// This file implements dead inst elimination and dead code elimination.
|
2001-06-07 04:29:01 +08:00
|
|
|
//
|
2002-05-07 12:24:11 +08:00
|
|
|
// Dead Inst Elimination performs a single pass over the function removing
|
|
|
|
// instructions that are obviously dead. Dead Code Elimination is similar, but
|
|
|
|
// it rechecks instructions that were used by removed instructions to see if
|
|
|
|
// they are newly dead.
|
2001-06-07 04:29:01 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-04-23 03:40:41 +08:00
|
|
|
#include "llvm/Transforms/Scalar/DCE.h"
|
2015-10-01 01:49:49 +08:00
|
|
|
#include "llvm/ADT/SetVector.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
2014-03-04 18:30:26 +08:00
|
|
|
#include "llvm/IR/InstIterator.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/Instruction.h"
|
Sink all InitializePasses.h includes
This file lists every pass in LLVM, and is included by Pass.h, which is
very popular. Every time we add, remove, or rename a pass in LLVM, it
caused lots of recompilation.
I found this fact by looking at this table, which is sorted by the
number of times a file was changed over the last 100,000 git commits
multiplied by the number of object files that depend on it in the
current checkout:
recompiles touches affected_files header
342380 95 3604 llvm/include/llvm/ADT/STLExtras.h
314730 234 1345 llvm/include/llvm/InitializePasses.h
307036 118 2602 llvm/include/llvm/ADT/APInt.h
213049 59 3611 llvm/include/llvm/Support/MathExtras.h
170422 47 3626 llvm/include/llvm/Support/Compiler.h
162225 45 3605 llvm/include/llvm/ADT/Optional.h
158319 63 2513 llvm/include/llvm/ADT/Triple.h
140322 39 3598 llvm/include/llvm/ADT/StringRef.h
137647 59 2333 llvm/include/llvm/Support/Error.h
131619 73 1803 llvm/include/llvm/Support/FileSystem.h
Before this change, touching InitializePasses.h would cause 1345 files
to recompile. After this change, touching it only causes 550 compiles in
an incremental rebuild.
Reviewers: bkramer, asbirlea, bollu, jdoerfert
Differential Revision: https://reviews.llvm.org/D70211
2019-11-14 05:15:01 +08:00
|
|
|
#include "llvm/InitializePasses.h"
|
2002-02-27 05:46:54 +08:00
|
|
|
#include "llvm/Pass.h"
|
2018-09-14 04:29:50 +08:00
|
|
|
#include "llvm/Support/DebugCounter.h"
|
2016-04-23 03:40:41 +08:00
|
|
|
#include "llvm/Transforms/Scalar.h"
|
2020-04-14 17:57:19 +08:00
|
|
|
#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
|
[BasicBlockUtils] Add utility to remove redundant dbg.value instrs
Summary:
Add a RemoveRedundantDbgInstrs to BasicBlockUtils with the
goal to remove redundant dbg intrinsics from a basic block.
This can be useful after various transforms, as it might
be simpler to do a filtering of dbg intrinsics after the
transform than during the transform.
One primary use case would be to replace a too aggressive
removal done by MergeBlockIntoPredecessor, seen at loop
rotate (not done in this patch).
The elimination algorithm currently focuses on dbg.value
intrinsics and is doing two iterations over the BB.
First we iterate backward starting at the last instruction
in the BB. Whenever a consecutive sequence of dbg.value
instructions are found we keep the last dbg.value for
each variable found (variable fragments are identified
using the {DILocalVariable, FragmentInfo, inlinedAt}
triple as given by the DebugVariable helper class).
Next we iterate forward starting at the first instruction
in the BB. Whenever we find a dbg.value describing a
DebugVariable (identified by {DILocalVariable, inlinedAt})
we save the {DIValue, DIExpression} that describes that
variables value. But if the variable already was mapped
to the same {DIValue, DIExpression} pair we instead drop
the second dbg.value.
To ease the process of making lit tests for this utility a
new pass is introduced called RedundantDbgInstElimination.
It can be executed by opt using -redundant-dbg-inst-elim.
Reviewers: aprantl, jmorse, vsk
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71478
2019-12-13 03:51:13 +08:00
|
|
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
Sink all InitializePasses.h includes
This file lists every pass in LLVM, and is included by Pass.h, which is
very popular. Every time we add, remove, or rename a pass in LLVM, it
caused lots of recompilation.
I found this fact by looking at this table, which is sorted by the
number of times a file was changed over the last 100,000 git commits
multiplied by the number of object files that depend on it in the
current checkout:
recompiles touches affected_files header
342380 95 3604 llvm/include/llvm/ADT/STLExtras.h
314730 234 1345 llvm/include/llvm/InitializePasses.h
307036 118 2602 llvm/include/llvm/ADT/APInt.h
213049 59 3611 llvm/include/llvm/Support/MathExtras.h
170422 47 3626 llvm/include/llvm/Support/Compiler.h
162225 45 3605 llvm/include/llvm/ADT/Optional.h
158319 63 2513 llvm/include/llvm/ADT/Triple.h
140322 39 3598 llvm/include/llvm/ADT/StringRef.h
137647 59 2333 llvm/include/llvm/Support/Error.h
131619 73 1803 llvm/include/llvm/Support/FileSystem.h
Before this change, touching InitializePasses.h would cause 1345 files
to recompile. After this change, touching it only causes 550 compiles in
an incremental rebuild.
Reviewers: bkramer, asbirlea, bollu, jdoerfert
Differential Revision: https://reviews.llvm.org/D70211
2019-11-14 05:15:01 +08:00
|
|
|
#include "llvm/Transforms/Utils/Local.h"
|
2004-01-09 14:02:20 +08:00
|
|
|
using namespace llvm;
|
2003-11-12 06:41:34 +08:00
|
|
|
|
2014-04-22 10:55:47 +08:00
|
|
|
#define DEBUG_TYPE "dce"
|
|
|
|
|
2006-12-20 05:40:18 +08:00
|
|
|
STATISTIC(DCEEliminated, "Number of insts removed");
|
2018-09-14 04:29:50 +08:00
|
|
|
DEBUG_COUNTER(DCECounter, "dce-transform",
|
|
|
|
"Controls which instructions are eliminated");
|
2002-05-10 23:38:35 +08:00
|
|
|
|
[BasicBlockUtils] Add utility to remove redundant dbg.value instrs
Summary:
Add a RemoveRedundantDbgInstrs to BasicBlockUtils with the
goal to remove redundant dbg intrinsics from a basic block.
This can be useful after various transforms, as it might
be simpler to do a filtering of dbg intrinsics after the
transform than during the transform.
One primary use case would be to replace a too aggressive
removal done by MergeBlockIntoPredecessor, seen at loop
rotate (not done in this patch).
The elimination algorithm currently focuses on dbg.value
intrinsics and is doing two iterations over the BB.
First we iterate backward starting at the last instruction
in the BB. Whenever a consecutive sequence of dbg.value
instructions are found we keep the last dbg.value for
each variable found (variable fragments are identified
using the {DILocalVariable, FragmentInfo, inlinedAt}
triple as given by the DebugVariable helper class).
Next we iterate forward starting at the first instruction
in the BB. Whenever we find a dbg.value describing a
DebugVariable (identified by {DILocalVariable, inlinedAt})
we save the {DIValue, DIExpression} that describes that
variables value. But if the variable already was mapped
to the same {DIValue, DIExpression} pair we instead drop
the second dbg.value.
To ease the process of making lit tests for this utility a
new pass is introduced called RedundantDbgInstElimination.
It can be executed by opt using -redundant-dbg-inst-elim.
Reviewers: aprantl, jmorse, vsk
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71478
2019-12-13 03:51:13 +08:00
|
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
// RedundantDbgInstElimination pass implementation
|
|
|
|
//
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
struct RedundantDbgInstElimination : public FunctionPass {
|
|
|
|
static char ID; // Pass identification, replacement for typeid
|
|
|
|
RedundantDbgInstElimination() : FunctionPass(ID) {
|
|
|
|
initializeRedundantDbgInstEliminationPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
|
|
|
bool runOnFunction(Function &F) override {
|
|
|
|
if (skipFunction(F))
|
|
|
|
return false;
|
|
|
|
bool Changed = false;
|
|
|
|
for (auto &BB : F)
|
|
|
|
Changed |= RemoveRedundantDbgInstrs(&BB);
|
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
|
|
|
AU.setPreservesCFG();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
char RedundantDbgInstElimination::ID = 0;
|
|
|
|
INITIALIZE_PASS(RedundantDbgInstElimination, "redundant-dbg-inst-elim",
|
|
|
|
"Redundant Dbg Instruction Elimination", false, false)
|
|
|
|
|
|
|
|
Pass *llvm::createRedundantDbgInstEliminationPass() {
|
|
|
|
return new RedundantDbgInstElimination();
|
|
|
|
}
|
|
|
|
|
2020-11-14 15:40:33 +08:00
|
|
|
PreservedAnalyses
|
|
|
|
RedundantDbgInstEliminationPass::run(Function &F, FunctionAnalysisManager &AM) {
|
|
|
|
bool Changed = false;
|
|
|
|
for (auto &BB : F)
|
|
|
|
Changed |= RemoveRedundantDbgInstrs(&BB);
|
|
|
|
if (!Changed)
|
|
|
|
return PreservedAnalyses::all();
|
|
|
|
PreservedAnalyses PA;
|
|
|
|
PA.preserveSet<CFGAnalyses>();
|
|
|
|
return PA;
|
|
|
|
}
|
|
|
|
|
[BasicBlockUtils] Add utility to remove redundant dbg.value instrs
Summary:
Add a RemoveRedundantDbgInstrs to BasicBlockUtils with the
goal to remove redundant dbg intrinsics from a basic block.
This can be useful after various transforms, as it might
be simpler to do a filtering of dbg intrinsics after the
transform than during the transform.
One primary use case would be to replace a too aggressive
removal done by MergeBlockIntoPredecessor, seen at loop
rotate (not done in this patch).
The elimination algorithm currently focuses on dbg.value
intrinsics and is doing two iterations over the BB.
First we iterate backward starting at the last instruction
in the BB. Whenever a consecutive sequence of dbg.value
instructions are found we keep the last dbg.value for
each variable found (variable fragments are identified
using the {DILocalVariable, FragmentInfo, inlinedAt}
triple as given by the DebugVariable helper class).
Next we iterate forward starting at the first instruction
in the BB. Whenever we find a dbg.value describing a
DebugVariable (identified by {DILocalVariable, inlinedAt})
we save the {DIValue, DIExpression} that describes that
variables value. But if the variable already was mapped
to the same {DIValue, DIExpression} pair we instead drop
the second dbg.value.
To ease the process of making lit tests for this utility a
new pass is introduced called RedundantDbgInstElimination.
It can be executed by opt using -redundant-dbg-inst-elim.
Reviewers: aprantl, jmorse, vsk
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D71478
2019-12-13 03:51:13 +08:00
|
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
// DeadCodeElimination pass implementation
|
|
|
|
//
|
|
|
|
|
2015-10-01 01:49:49 +08:00
|
|
|
static bool DCEInstruction(Instruction *I,
|
|
|
|
SmallSetVector<Instruction *, 16> &WorkList,
|
|
|
|
const TargetLibraryInfo *TLI) {
|
|
|
|
if (isInstructionTriviallyDead(I, TLI)) {
|
2018-09-14 04:29:50 +08:00
|
|
|
if (!DebugCounter::shouldExecute(DCECounter))
|
|
|
|
return false;
|
|
|
|
|
2018-02-16 06:26:18 +08:00
|
|
|
salvageDebugInfo(*I);
|
2020-04-14 17:57:19 +08:00
|
|
|
salvageKnowledge(I);
|
2018-02-16 06:26:18 +08:00
|
|
|
|
2015-10-01 01:49:49 +08:00
|
|
|
// Null out all of the instruction's operands to see if any operand becomes
|
|
|
|
// dead as we go.
|
|
|
|
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
|
|
|
|
Value *OpV = I->getOperand(i);
|
|
|
|
I->setOperand(i, nullptr);
|
|
|
|
|
|
|
|
if (!OpV->use_empty() || I == OpV)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// If the operand is an instruction that became dead as we nulled out the
|
|
|
|
// operand, and if it is 'trivially' dead, delete it in a future loop
|
|
|
|
// iteration.
|
|
|
|
if (Instruction *OpI = dyn_cast<Instruction>(OpV))
|
|
|
|
if (isInstructionTriviallyDead(OpI, TLI))
|
|
|
|
WorkList.insert(OpI);
|
|
|
|
}
|
|
|
|
|
|
|
|
I->eraseFromParent();
|
|
|
|
++DCEEliminated;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-05-15 23:18:11 +08:00
|
|
|
static bool eliminateDeadCode(Function &F, TargetLibraryInfo *TLI) {
|
2005-05-09 02:45:26 +08:00
|
|
|
bool MadeChange = false;
|
2015-10-01 01:49:49 +08:00
|
|
|
SmallSetVector<Instruction *, 16> WorkList;
|
|
|
|
// Iterate over the original function, only adding insts to the worklist
|
|
|
|
// if they actually need to be revisited. This avoids having to pre-init
|
|
|
|
// the worklist with the entire function's worth of instructions.
|
2021-02-26 11:54:38 +08:00
|
|
|
for (Instruction &I : llvm::make_early_inc_range(instructions(F))) {
|
2015-10-01 01:49:49 +08:00
|
|
|
// We're visiting this instruction now, so make sure it's not in the
|
|
|
|
// worklist from an earlier visit.
|
2021-02-26 11:54:38 +08:00
|
|
|
if (!WorkList.count(&I))
|
|
|
|
MadeChange |= DCEInstruction(&I, WorkList, TLI);
|
2015-10-01 01:49:49 +08:00
|
|
|
}
|
|
|
|
|
2002-05-07 12:24:11 +08:00
|
|
|
while (!WorkList.empty()) {
|
2015-10-01 01:49:49 +08:00
|
|
|
Instruction *I = WorkList.pop_back_val();
|
|
|
|
MadeChange |= DCEInstruction(I, WorkList, TLI);
|
2001-07-29 01:51:49 +08:00
|
|
|
}
|
2005-05-09 02:45:26 +08:00
|
|
|
return MadeChange;
|
2002-02-27 05:46:54 +08:00
|
|
|
}
|
|
|
|
|
2016-08-09 08:28:15 +08:00
|
|
|
PreservedAnalyses DCEPass::run(Function &F, FunctionAnalysisManager &AM) {
|
2020-11-14 15:34:11 +08:00
|
|
|
if (!eliminateDeadCode(F, &AM.getResult<TargetLibraryAnalysis>(F)))
|
2017-01-15 14:32:49 +08:00
|
|
|
return PreservedAnalyses::all();
|
|
|
|
|
|
|
|
PreservedAnalyses PA;
|
|
|
|
PA.preserveSet<CFGAnalyses>();
|
|
|
|
return PA;
|
2016-04-23 03:40:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
struct DCELegacyPass : public FunctionPass {
|
|
|
|
static char ID; // Pass identification, replacement for typeid
|
|
|
|
DCELegacyPass() : FunctionPass(ID) {
|
|
|
|
initializeDCELegacyPassPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool runOnFunction(Function &F) override {
|
2016-04-23 06:06:11 +08:00
|
|
|
if (skipFunction(F))
|
2016-04-23 03:40:41 +08:00
|
|
|
return false;
|
|
|
|
|
2020-11-14 15:34:11 +08:00
|
|
|
TargetLibraryInfo *TLI =
|
|
|
|
&getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
|
2016-04-23 03:40:41 +08:00
|
|
|
|
|
|
|
return eliminateDeadCode(F, TLI);
|
|
|
|
}
|
|
|
|
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
2020-11-14 15:34:11 +08:00
|
|
|
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
2016-04-23 03:40:41 +08:00
|
|
|
AU.setPreservesCFG();
|
|
|
|
}
|
|
|
|
};
|
2002-02-27 05:46:54 +08:00
|
|
|
}
|
2003-11-12 06:41:34 +08:00
|
|
|
|
2016-04-23 03:40:41 +08:00
|
|
|
char DCELegacyPass::ID = 0;
|
|
|
|
INITIALIZE_PASS(DCELegacyPass, "dce", "Dead Code Elimination", false, false)
|
|
|
|
|
|
|
|
FunctionPass *llvm::createDeadCodeEliminationPass() {
|
|
|
|
return new DCELegacyPass();
|
|
|
|
}
|