In
compiler theory
In computing, a compiler is a computer program that Translator (computing), translates computer code written in one programming language (the ''source'' language) into another language (the ''target'' language). The name "compiler" is primaril ...
, dead-code elimination (DCE, dead-code removal, dead-code stripping, or dead-code strip) is a
compiler optimization
An optimizing compiler is a compiler designed to generate code that is optimized in aspects such as minimizing program execution time, memory usage, storage size, and power consumption. Optimization is generally implemented as a sequence of op ...
to remove
dead code
The term dead code has multiple definitions. Some use the term to refer to code (i.e. instructions in memory) which can never be executed at run-time.
In some areas of computer programming, dead code is a section in the source code of a program whi ...
(code that does not affect the program results). Removing such code has several benefits: it shrinks
program size, an important consideration in some contexts, it reduces resource usage such as the number of bytes to be transferred
[Malavolta, Ivano et al. “JavaScript Dead Code Identification, Elimination, and Empirical Assessment.” IEEE transactions on software engineering 49.7 (2023): 3692–3714. Web.] and it allows the running program to avoid executing irrelevant
operations, which reduces its
running time. It can also enable further optimizations by simplifying program structure. Dead code includes code that can never be executed (
unreachable code
In computer programming, unreachable code is part of the source code of a program which can never be executed because there exists no control flow path to the code from the rest of the program.
Unreachable code is sometimes also called ''dead code ...
), and code that only affects
dead variables (written to, but never read again), that is, irrelevant to the program.
Examples
Consider the following example written in
C.
int foo(void)
Simple analysis of the uses of values would show that the value of
b
after the first assignment is not used inside
foo
. Furthermore,
b
is declared as a local variable inside
foo
, so its value cannot be used outside
foo
. Thus, the variable
b
is ''dead'' and an optimizer can reclaim its storage space and eliminate its initialization.
Furthermore, because the first return statement is executed unconditionally and there is no label after it which a "goto" could reach, no feasible execution path reaches the second assignment to
b
. Thus, the assignment is ''unreachable'' and can be removed.
If the procedure had a more complex
control flow
In computer science, control flow (or flow of control) is the order in which individual statements, instructions or function calls of an imperative program are executed or evaluated. The emphasis on explicit control flow distinguishes an '' ...
, such as a label after the return statement and a
goto
elsewhere in the procedure, then a feasible execution path might exist to the assignment to
b
.
Also, even though some calculations are performed in the function, their values are not stored in locations accessible outside the
scope of this function. Furthermore, given the function returns a static value (96), it may be simplified to the value it returns (this simplification is called
constant folding
Constant folding and constant propagation are related compiler optimizations used by many modern compilers. An advanced form of constant propagation known as sparse conditional constant propagation can more accurately propagate constants and sim ...
).
Most advanced compilers have options to activate dead-code elimination, sometimes at varying levels. A lower level might only remove instructions that cannot be executed. A higher level might also not reserve space for unused variables. A yet higher level might determine instructions or functions that serve no purpose and eliminate them.
A common use of dead-code elimination is as an alternative to optional code inclusion via a
preprocessor
In computer science, a preprocessor (or precompiler) is a Computer program, program that processes its input data to produce output that is used as input in another program. The output is said to be a preprocessed form of the input data, which i ...
. Consider the following code.
int main(void)
Because the expression 0 will always evaluate to
false, the code inside the if statement can never be executed, and dead-code elimination would remove it entirely from the optimized program. This technique is common in
debugging
In engineering, debugging is the process of finding the Root cause analysis, root cause, workarounds, and possible fixes for bug (engineering), bugs.
For software, debugging tactics can involve interactive debugging, control flow analysis, Logf ...
to optionally activate blocks of code; using an optimizer with dead-code elimination eliminates the need for using a
preprocessor
In computer science, a preprocessor (or precompiler) is a Computer program, program that processes its input data to produce output that is used as input in another program. The output is said to be a preprocessed form of the input data, which i ...
to perform the same task.
In practice, much of the dead code that an optimizer finds is created by other transformations in the optimizer. For example, the classic techniques for operator
strength reduction
In compiler construction, strength reduction is a compiler optimization where expensive operations are replaced with equivalent but less expensive operations. The classic example of strength reduction converts ''strong'' multiplications inside a l ...
insert new computations into the code and render the older, more expensive computations dead.
Subsequent dead-code elimination removes those calculations and completes the effect (without complicating the strength-reduction algorithm).
Historically, dead-code elimination was performed using information derived from
data-flow analysis
Data-flow analysis is a technique for gathering information about the possible set of values calculated at various points in a computer program. It forms the foundation for a wide variety of compiler optimizations and program verification techn ...
.
An algorithm based on
static single-assignment form
In compiler design, static single assignment form (often abbreviated as SSA form or simply SSA) is a type of intermediate representation (IR) where each variable is assigned exactly once. SSA is used in most high-quality optimizing compilers for ...
(SSA) appears in the original journal article on ''SSA'' form by Ron Cytron et al.
Robert Shillingsburg (aka Shillner) improved on the algorithm and developed a companion algorithm for removing useless control-flow operations.
Dynamic dead-code elimination
Dead code is normally considered dead ''unconditionally''. Therefore, it is reasonable attempting to remove dead code through dead-code elimination at
compile time
In computer science, compile time (or compile-time) describes the time window during which a language's statements are converted into binary instructions for the processor to execute. The term is used as an adjective to describe concepts relat ...
.
However, in practice it is also common for code sections to represent dead or unreachable code only ''under certain conditions'', which may not be known at the time of compilation or assembly. Such conditions may be imposed by different
runtime environment
In computer programming, a runtime system or runtime environment is a sub-system that exists in the computer where a program is created, as well as in the computers where the program is intended to be run. The name comes from the compile time ...
s (for example different versions of an operating system, or different sets and combinations of drivers or services loaded in a particular target environment), which may require different sets of special cases in the code, but at the same time become conditionally dead code for the other cases.
Also, the software (for example, a driver or resident service) may be configurable to include or exclude certain features depending on user preferences, rendering unused code portions useless in a particular scenario.
While modular software may be developed to dynamically load libraries on demand only, in most cases, it is not possible to load only the relevant routines from a particular library, and even if this would be supported, a routine may still include code sections which can be considered dead code in a given scenario, but could not be ruled out at compile time, already.
The techniques used to dynamically detect demand, identify and resolve dependencies, remove such conditionally dead code, and to recombine the remaining code at
load or
runtime are called dynamic dead-code elimination
or dynamic dead-instruction elimination.
Most programming languages, compilers and operating systems offer no or little more support than
dynamic loading
Dynamic loading is a mechanism by which a computer program can, at run time, load a library (or other binary) into memory, retrieve the addresses of functions and variables contained in the library, execute those functions or access those var ...
of libraries and
late linking, therefore software utilizing dynamic dead-code elimination is very rare in conjunction with languages
compiled ahead-of-time or written in
assembly language
In computing, assembly language (alternatively assembler language or symbolic machine code), often referred to simply as assembly and commonly abbreviated as ASM or asm, is any low-level programming language with a very strong correspondence bet ...
.
However, language implementations doing
just-in-time compilation
In computing, just-in-time (JIT) compilation (also dynamic translation or run-time compilations) is compilation (of computer code) during execution of a program (at run time) rather than before execution. This may consist of source code transl ...
may dynamically optimize for dead-code elimination.
Although with a rather different focus, similar approaches are sometimes also utilized for
dynamic software updating
In computer science, dynamic software updating (DSU) is a field of research pertaining to upgrade, upgrading programs while they are running. DSU is not currently widely used in industry. However, researchers have developed a wide variety of system ...
and
hot patching.
See also
*
Redundant code In computer programming, redundant code is source code or compiled code in a computer program that is unnecessary, such as:
* recomputing a value that has previously been calculated and is still available,
* code that is never executed (known as unr ...
*
Simplification (symbolic computation)
In mathematics and computer science, computer algebra, also called symbolic computation or algebraic computation, is a scientific area that refers to the study and development of algorithms and software for manipulating mathematical expressions ...
*
Partial-redundancy elimination
*
Conjunction elimination
In propositional logic, conjunction elimination (also called ''and'' elimination, ∧ elimination, or simplification)Hurley is a valid immediate inference, argument form and rule of inference which makes the inference that, if the conjunction ...
*
Dynamic software updating
In computer science, dynamic software updating (DSU) is a field of research pertaining to upgrade, upgrading programs while they are running. DSU is not currently widely used in industry. However, researchers have developed a wide variety of system ...
*
Dynamic coupling (computing)
*
Self-relocation
*
Software cruft
*
Tree shaking
*
Post-pass optimization
*
Profile-guided optimization
In computer programming, profile-guided optimization (PGO, sometimes pronounced as ''pogo''), also known as profile-directed feedback (PDF) or feedback-directed optimization (FDO), is the compiler optimization technique of using prior analyses of ...
*
Superoptimizer
*
Function multi-versioning
References
Further reading
*
*
*
*
*
*
External links
How to trick C/C++ compilers into generating terrible code?
{{Compiler optimizations
Compiler optimizations