Skip to content

Commit 6665696

Browse files
authored
Merge pull request #463 from wesleywiser/patch-1
[Inside Rust] Add const prop on by default blog post
2 parents b63dc40 + fc28af1 commit 6665696

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
---
2+
layout: post
3+
title: "Constant propagation is now on by default in nightly"
4+
author: "Wesley Wiser"
5+
description: "Constant propagation is now on by default in nightly"
6+
team: the MIR Optimizations WG <https://rust-lang.github.io/compiler-team/working-groups/mir-opt/>
7+
---
8+
9+
I'm pleased to announce that the [Mid-level IR][mir] (MIR) constant propagation pass has been [switched on][pr] by default on Rust nightly which will eventually become Rust 1.41!
10+
11+
## What is constant propagation?
12+
13+
Constant propagation is an optimization where the compiler recognizes code that can be run at compile time, evaluates it, and replaces the original code with the result.
14+
15+
For example:
16+
17+
```rust
18+
const X: u32 = 2;
19+
20+
let y = X + X;
21+
```
22+
23+
Rather than evaluating `X + X` at runtime, the compiler can recognize that the value of `X` is known at compile time and replace it with the correct value resulting in:
24+
25+
```rust
26+
const X: u32 = 2;
27+
28+
let y = 4;
29+
```
30+
31+
This optimization is opportunistic and automatically recognizes constants even when they are not declared as such:
32+
33+
```rust
34+
struct Point {
35+
x: u32,
36+
y: u32,
37+
}
38+
39+
let a = 2 + 2; // optimizes to 4
40+
let b = [0, 1, 2, 3, 4, 5][3]; // optimizes to 3
41+
let c = (Point { x: 21, y: 42 }).y; // optimizes to 42
42+
```
43+
44+
## Propagation into control flow
45+
46+
The constant propagation pass also handles propagating into control flow.
47+
For example:
48+
49+
```rust
50+
const Foo: Option<u8> = B(12);
51+
52+
let x = match Foo {
53+
Bar::A => panic!("no value"),
54+
Bar::B(v) => v,
55+
};
56+
```
57+
58+
becomes:
59+
60+
```rust
61+
const Foo: Option<u8> = B(12);
62+
63+
let x = 12;
64+
```
65+
66+
This is very helpful for checked math, the default in `debug` mode, which introduces additional control flow after every operation:
67+
68+
```rust
69+
let x = 2 + 4 * 6;
70+
```
71+
72+
actually operates like this with overflow checking enabled:
73+
74+
```rust
75+
let (_tmp0, overflowed) = CheckedMultiply(4, 6);
76+
assert!(!overflowed, "attempt to multiply with overflow");
77+
78+
let (_tmp1, overflowed) = CheckedAdd(_tmp0, 2);
79+
assert!(!overflowed, "attempt to add with overflow");
80+
81+
let x = _temp1;
82+
```
83+
84+
which adds quite a bit of control flow!
85+
Constant propagation evaluates the math at compile time and reduces this to:
86+
87+
```rust
88+
let _tmp0 = 24;
89+
assert!(!false, "attempt to multiply with overflow");
90+
91+
let _tmp1 = 26;
92+
assert!(!false, "attempt to add with overflow");
93+
94+
let x = 26;
95+
```
96+
97+
which is further reduced to just:
98+
99+
```rust
100+
let x = 26;
101+
```
102+
103+
## Compiler performance
104+
105+
As you might have guessed, reducing the amount of control flow processed by the Rust compiler has a positive effect on compile times.
106+
We're seeing 2-10% improvement on a variety of test cases in both debug and release mode.
107+
Even though LLVM has its own constant propagation pass, we see improvements because our pass operates on MIR while it is still generic.
108+
The more concrete instances of a generic function that are instantiated, the larger the payoff from this optimization.
109+
110+
We've suspected for a while that the verbose LLVM IR the Rust compiler generates contributes considerably to long compilation times.
111+
By implementing optimizations like this, we believe there is significant potential to lower compile times by generating better LLVM IR.
112+
If you'd like to get involved with the MIR Optimizations working group, stop by our [Zulip channel][zulip] and say hello!
113+
114+
[mir]: https://blog.rust-lang.org/2016/04/19/MIR.html
115+
[pr]: https://github.com/rust-lang/rust/pull/66074
116+
[zulip]: https://rust-lang.zulipchat.com/#narrow/stream/189540-t-compiler.2Fwg-mir-opt

0 commit comments

Comments
 (0)