<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.sarg.dev/index.php?action=history&amp;feed=atom&amp;title=Loop-invariant_code_motion</id>
	<title>Loop-invariant code motion - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.sarg.dev/index.php?action=history&amp;feed=atom&amp;title=Loop-invariant_code_motion"/>
	<link rel="alternate" type="text/html" href="https://wiki.sarg.dev/index.php?title=Loop-invariant_code_motion&amp;action=history"/>
	<updated>2026-04-18T16:44:59Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://wiki.sarg.dev/index.php?title=Loop-invariant_code_motion&amp;diff=479556&amp;oldid=prev</id>
		<title>imported&gt;Jochen Burghardt: /* Invariant code detection */ the authors are active, not their paper (and shorter); rm 2nd wikilink (kept 1st one since a draft seems to be forthcoming)</title>
		<link rel="alternate" type="text/html" href="https://wiki.sarg.dev/index.php?title=Loop-invariant_code_motion&amp;diff=479556&amp;oldid=prev"/>
		<updated>2025-09-04T14:41:18Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;Invariant code detection: &lt;/span&gt; the authors are active, not their paper (and shorter); rm 2nd wikilink (kept 1st one since a draft seems to be forthcoming)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{short description|Type of compiler optimization}}&lt;br /&gt;
{{More citations needed|date=January 2021}}&lt;br /&gt;
&lt;br /&gt;
In [[computer programming]], [[loop-invariant code]] consists of statements or expressions (in an [[imperative programming|imperative]] [[programming language]]) that can be moved outside the body of a loop without affecting the semantics of the program. &amp;#039;&amp;#039;&amp;#039;Loop-invariant code motion&amp;#039;&amp;#039;&amp;#039; (also called &amp;#039;&amp;#039;&amp;#039;hoisting&amp;#039;&amp;#039;&amp;#039; or &amp;#039;&amp;#039;&amp;#039;scalar promotion&amp;#039;&amp;#039;&amp;#039;) is a [[compiler optimization]] that performs this movement automatically.&lt;br /&gt;
&lt;br /&gt;
==Example==&lt;br /&gt;
In the following code sample, two optimizations can be applied.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
int i = 0;&lt;br /&gt;
while (i &amp;lt; n) {&lt;br /&gt;
    x = y + z;&lt;br /&gt;
    a[i] = 6 * i + x * x;&lt;br /&gt;
    ++i;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Although the calculation &amp;lt;code&amp;gt;x = y + z&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;x * x&amp;lt;/code&amp;gt; is loop-invariant, precautions must be taken before moving the code outside the loop. It is possible that the loop condition is &amp;lt;code&amp;gt;false&amp;lt;/code&amp;gt; (for example, if &amp;lt;code&amp;gt;n&amp;lt;/code&amp;gt; holds a negative value), and in such case, the loop body should not be executed at all. One way of guaranteeing correct behaviour is using a conditional branch outside of the loop. Evaluating the loop condition can have [[Side effect (computer science)|side effects]], so an additional evaluation by the &amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt; construct should be compensated by replacing the &amp;lt;code&amp;gt;while&amp;lt;/code&amp;gt; loop with a &amp;lt;code&amp;gt;[[Do while loop|do {} while]]&amp;lt;/code&amp;gt;. If the code used &amp;lt;code&amp;gt;do {} while&amp;lt;/code&amp;gt; in the first place, the whole guarding process is not needed, as the loop body is guaranteed to execute at least once.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
int i = 0;&lt;br /&gt;
if (i &amp;lt; n) {&lt;br /&gt;
    x = y + z;&lt;br /&gt;
    int const t1 = x * x;&lt;br /&gt;
    do {&lt;br /&gt;
        a[i] = 6 * i + t1;&lt;br /&gt;
        ++i;&lt;br /&gt;
    } while (i &amp;lt; n);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code can be optimized further. For example, [[strength reduction]] could remove the two multiplications inside the loop (&amp;lt;code&amp;gt;6*i&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;a[i]&amp;lt;/code&amp;gt;), and [[induction variable]] elimination could then elide &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; completely. Since &amp;lt;code&amp;gt;6 * i&amp;lt;/code&amp;gt; must be in lock step with &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; itself, there is no need to have both.&lt;br /&gt;
&lt;br /&gt;
==Invariant code detection==&lt;br /&gt;
Usually, a [[Reaching definition|reaching definitions analysis]] is used to detect whether a statement or expression is loop invariant.&lt;br /&gt;
&lt;br /&gt;
For example, if all reaching definitions for the operands of some simple expression are outside of the loop, the expression can be moved out of the loop.&lt;br /&gt;
&lt;br /&gt;
Moyen, Rubiano and [[Thomas Seiller|Seiller]] used data-flow dependence analysis&amp;lt;ref&amp;gt;{{cite book |last1=Moyen |first1=Jean-Yves |last2=Rubiano |first2=Thomas |last3=Seiller |first3=Thomas |chapter=Loop Quasi-Invariant Chunk Detection |title=Automated Technology for Verification and Analysis |series=Lecture Notes in Computer Science |date=2017 |volume=10482 |pages=91–108 |doi=10.1007/978-3-319-68167-2_7|isbn=978-3-319-68166-5 }}&amp;lt;/ref&amp;gt; to detect not only invariant commands but larger code fragments such as an inner loop. The analysis also detects quasi-invariants of arbitrary degrees, that is commands or code fragments that become invariant after a fixed number of iterations of the loop body. This technique was later used by Aubert, Rubiano, Rusch, and Seiller to automatically parallelise loops.&amp;lt;ref&amp;gt;{{cite book |last1=Aubert |first1=Clément |last2=Rubiano |first2=Thomas &lt;br /&gt;
|last3=Rusch |first3=Neea |last4=Seiller |first4=Thomas |chapter= Distributing and Parallelizing Non-canonical Loops |title= Verification, Model Checking, and Abstract Interpretation |series=Lecture Notes in Computer Science |date=2023 |volume=13881 |pages=91–108 |doi=10.1007/978-3-031-24950-1_1 }}&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Benefits==&lt;br /&gt;
Loop-invariant code which has been hoisted out of a loop is executed less often, providing a speedup.  Another effect of this transformation is allowing constants to be stored in registers and not having to calculate the address and access the memory (or cache line) at each iteration.&lt;br /&gt;
&lt;br /&gt;
However, if too many variables are created, there will be high [[register pressure]], especially on processors with few registers, like the 32-bit [[x86]]. If the compiler runs out of registers, some variables will be [[register spilling|spilled]]. To counteract this, the inverse optimization can be performed, [[rematerialization]].&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
* [[Code motion]]&lt;br /&gt;
* [[Loop invariant]]&lt;br /&gt;
&lt;br /&gt;
==Further reading==&lt;br /&gt;
* Aho, Alfred V.; Sethi, Ravi; &amp;amp; Ullman, Jeffrey D. (1986). Compilers: Principles, Techniques, and Tools. Addison Wesley. {{ISBN|0-201-10088-6}}.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
{{Reflist}}&lt;br /&gt;
&lt;br /&gt;
==External links==&lt;br /&gt;
* [https://web.archive.org/web/20170806083023/http://www.compileroptimizations.com/category/hoisting.htm Compiler Optimizations &amp;amp;mdash; Hoisting]&lt;br /&gt;
&lt;br /&gt;
{{Compiler optimizations}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Compiler optimizations]]&lt;/div&gt;</summary>
		<author><name>imported&gt;Jochen Burghardt</name></author>
	</entry>
</feed>