Dead code

Last updated

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. [1] [2] [3] In some areas of computer programming, dead code is a section in the source code of a program which is executed but whose result is never used in any other computation. [4] [5] The execution of dead code wastes computation time and memory.

Contents

While the result of a dead computation may never be used, it may raise exceptions or affect some global state, thus removal of such code may change the output of the program and introduce unintended bugs. Compiler optimizations are typically conservative in their approach to dead-code removal if there is any ambiguity as to whether removal of the dead code will affect the program output. The programmer may aid the compiler in this matter by making additional use of static and/or inline functions and enabling the use of link-time optimization.

Example

intfoo(intiX,intiY){intiZ=iX/iY;returniX*iY;}

In the above example, although the division of iX by iY is computed and never used, it will throw an exception when a division by zero occurs. Therefore, the removal of the dead code may change the output of the program.

Analysis

Dead-code elimination is a form of compiler optimization in which dead code is removed from a program. Dead code analysis can be performed using live-variable analysis, a form of static-code analysis and data-flow analysis. This is in contrast to unreachable code analysis which is based on control-flow analysis.

The dead-code elimination technique is in the same class of optimizations as unreachable code elimination and redundant code elimination.

In large programming projects, it is sometimes difficult to recognize and eliminate dead code, particularly when entire modules become dead. Test scaffolding can make it appear that the code is still live, and at times, contract language can require delivery of the code even when the code is no longer relevant. [6]

Some IDEs (such as Xcode, Visual Studio 2010 [7] and Eclipse Galileo [8] ) have the ability to locate dead code during the compiling stage.

While most optimization techniques seek to remove dead code in an implementation, in extreme forms of optimization for size it may sometimes be desirable to deliberately introduce and carefully shape seemingly dead code, when it allows to fold otherwise unrelated code sections together (and thereby reduce their combined size) so that the extra code will effectively not harm the first path of execution through the code but is used to carry out the actions necessary for the alternative paths of execution, for which other sections of the code may become dead code. On a more functional level, this can be seen as both, artificially introduction of harmless/useful side-effects and reduction of the redundancy of the code, but it can also be used down to opcode level in order to allow the usage of shorter instructions, which would not be possible when folding code sequences without the concerted introduction of side-effects caused by the dead code.

See also

Related Research Articles

In computing, a compiler is a computer program that translates computer code written in one programming language into another language. The name "compiler" is primarily used for programs that translate source code from a high-level programming language to a low-level programming language to create an executable program.

In software engineering, code coverage is a percentage measure of the degree to which the source code of a program is executed when a particular test suite is run. A program with high test coverage has more of its source code executed during testing, which suggests it has a lower chance of containing undetected software bugs compared to a program with low test coverage. Many different metrics can be used to calculate test coverage. Some of the most basic are the percentage of program subroutines and the percentage of program statements called during execution of the test suite.

In programming language theory, lazy evaluation, or call-by-need, is an evaluation strategy which delays the evaluation of an expression until its value is needed and which also avoids repeated evaluations.

In computing, an optimizing compiler is a compiler that tries to minimize or maximize some attributes of an executable computer program. Common requirements are to minimize a program's execution time, memory footprint, storage size, and power consumption.

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 simultaneously remove dead code.

In computing, inline expansion, or inlining, is a manual or compiler optimization that replaces a function call site with the body of the called function. Inline expansion is similar to macro expansion, but occurs during compilation, without changing the source code, while macro expansion occurs prior to compilation, and results in different text that is then processed by the compiler.

In computing, just-in-time (JIT) compilation is compilation during execution of a program rather than before execution. This may consist of source code translation but is more commonly bytecode translation to machine code, which is then executed directly. A system implementing a JIT compiler typically continuously analyses the code being executed and identifies parts of the code where the speedup gained from compilation or recompilation would outweigh the overhead of compiling that code.

In computer science, program optimization, code optimization, or software optimization is the process of modifying a software system to make some aspect of it work more efficiently or use fewer resources. In general, a computer program may be optimized so that it executes more rapidly, or to make it capable of operating with less memory storage or other resources, or draw less power.

In compiler design, static single assignment form is a property of an intermediate representation (IR) that requires each variable to be assigned exactly once and defined before it is used. Existing variables in the original IR are split into versions, new variables typically indicated by the original name with a subscript in textbooks, so that every definition gets its own version. In SSA form, use-def chains are explicit and each contains a single element.

In compiler theory, dead-code elimination is a compiler optimization to remove dead code. 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 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, and code that only affects dead variables, that is, irrelevant to the program.

Loop splitting is a compiler optimization technique. It attempts to simplify a loop or eliminate dependencies by breaking it into multiple loops which have the same bodies but iterate over different contiguous portions of the index range.

Short-circuit evaluation, minimal evaluation, or McCarthy evaluation is the semantics of some Boolean operators in some programming languages in which the second argument is executed or evaluated only if the first argument does not suffice to determine the value of the expression: when the first argument of the AND function evaluates to false, the overall value must be false; and when the first argument of the OR function evaluates to true, the overall value must be true.

In computer programming, loop-invariant code consists of statements or expressions that can be moved outside the body of a loop without affecting the semantics of the program. Loop-invariant code motion is a compiler optimization that performs this movement automatically.

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.

In computer programming, redundant code is source code or compiled code in a computer program that is unnecessary, such as:

Interprocedural optimization (IPO) is a collection of compiler techniques used in computer programming to improve performance in programs containing many frequently used functions of small or medium length. IPO differs from other compiler optimizations by analyzing the entire program as opposed to a single function or block of code.

In computer programming, a pure function is a function that has the following properties:

  1. the function return values are identical for identical arguments, and
  2. the function has no side effects.

In computer programming, a dead store is a local variable that is assigned a value but is read by no following instruction. Dead stores waste processor time and memory, and may be detected through the use of static program analysis, and removed by an optimizing compiler.

OptimJ is an extension for Java with language support for writing optimization models and abstractions for bulk data processing. The extensions and the proprietary product implementing the extensions were developed by Ateji which went out of business in September 2011. OptimJ aims at providing a clear and concise algebraic notation for optimization modeling, removing compatibility barriers between optimization modeling and application programming tools, and bringing software engineering techniques such as object-orientation and modern IDE support to optimization experts.

Tracing just-in-time compilation is a technique used by virtual machines to optimize the execution of a program at runtime. This is done by recording a linear sequence of frequently executed operations, compiling them to native machine code and executing them. This is opposed to traditional just-in-time (JIT) compilers that work on a per-method basis.

References

  1. "Hongwei Xi, Dead Code Elimination through Dependent Types" (PDF). Archived from the original (PDF) on 2012-03-10. Retrieved 2020-05-06.
  2. Archived 2020-05-20 at the Wayback Machine DO-178B
  3. DO-178B Wikipedia/DO-178B.
  4. Debray, S. K., Evans, W., Muth, R., and De Sutter, B. 2000. Compiler techniques for code compaction. ACM Trans. Program. Lang. Syst. 22, 2 (Mar. 2000), 378–415.
  5. Appel, A. W. 1998 Modern Compiler Implementation in Java. Cambridge University Press.
  6. Douglas W. Jones Dead Code Maintenance, Risks 8.19 (Feb. 1, 1989) Archived 2011-07-08 at the Wayback Machine
  7. Habib Heydarian, Microsoft Corp
  8. Eclipse Developer Guide