cfallin labeled issue #1598:
Add Volatile flag to MemFlags.
Benefit
When some optimization pass knows about load/store type (is it volatile or not?) then it's possible to do a lot of optimizations. One of it is memory to register promotion. I tried to implement mem2reg pass there cranelift-mem2reg and this pass works but in some cases it fails e.g this simple C code:
// compiled with rcc typedef struct Foo { int x; int y; } Foo; int main() { Foo foo; foo.y = 42; }Message: definition error: Compilation error: Verifier errors note: while compiling function u0:0() -> i32 system_v { ss0 = explicit_slot 8 block0: v1 = iconst.i64 4 v2 = iadd.i64 v0, v1 v3 = iconst.i32 42 store v3, v2 v4 = iconst.i32 0 return v4 }All loads and stores might be marked as volatile and mem2reg will not optimize
struct Foointo registers.
Volatile flag also can help in SRoA when it's possible to replace allocation on stack with single 32 or 64 bit register.Implementation
Just add additional enum case in
codegen/ir/memflags.rsand add 3 simple functions to MemFlags:volatile() -> Self,is_volatile() -> bool, set_volatile(&mut self).Alternatives
I do not see any alternatives.
UPD: This might be useful for this issue: Support volatile store/loads
cfallin labeled issue #1598:
Add Volatile flag to MemFlags.
Benefit
When some optimization pass knows about load/store type (is it volatile or not?) then it's possible to do a lot of optimizations. One of it is memory to register promotion. I tried to implement mem2reg pass there cranelift-mem2reg and this pass works but in some cases it fails e.g this simple C code:
// compiled with rcc typedef struct Foo { int x; int y; } Foo; int main() { Foo foo; foo.y = 42; }Message: definition error: Compilation error: Verifier errors note: while compiling function u0:0() -> i32 system_v { ss0 = explicit_slot 8 block0: v1 = iconst.i64 4 v2 = iadd.i64 v0, v1 v3 = iconst.i32 42 store v3, v2 v4 = iconst.i32 0 return v4 }All loads and stores might be marked as volatile and mem2reg will not optimize
struct Foointo registers.
Volatile flag also can help in SRoA when it's possible to replace allocation on stack with single 32 or 64 bit register.Implementation
Just add additional enum case in
codegen/ir/memflags.rsand add 3 simple functions to MemFlags:volatile() -> Self,is_volatile() -> bool, set_volatile(&mut self).Alternatives
I do not see any alternatives.
UPD: This might be useful for this issue: Support volatile store/loads
wareya commented on issue #1598:
Has there been any movement on this? Something like it is a precondition to implementing any mem2reg-like thing safely, and the alternatives proposed so far seem to be research-project-worthy and hard to implement.
bjorn3 commented on issue #1598:
This has become a fair bit more important now that Cranelift has introduced memory optimizations.
sunfishcode edited a comment on issue #1598:
Giving frontends a way to provide explicit memory dependencies, and using that to implement volatile semantics would be cool. If anyone's interested in a designing a system to do this, it'd be good to start with a design document so we can look at how it'll impact compile times in fast-compilation use cases, and other tradeoffs involved.
We may want to do something simpler for now that just addresses volatile, and I have a possible alternative. Traditional volatile flags on regular memory accesses turn out to be very error prone. The recommended solution is to transform volatile into a call or separate opcode, and optionally inline the call after all optimizations. It's now how it systematically eliminates a common class of volatile bugs, however it does add complexity in the backend. So instead, how about the following design:
Add new two instructions to the IR:
-
y = volatile_unary(x)- observe the value ofx, do side effects, and return a new value
-volatile_rmw(p)- observe the value of*p, do side effects, and then clobber*p.At a very late stage,
volatile_unarywould be translated as if it were an identity operation, andvolatile_rmwwould be translated as if it were a no-op. With those, frontends could then translate a volatile load like this:volatile_rmw(p) x0 = load(p) x = volatile_unary(x0)and a volatile store like this:
x0 = volatile_unary(x) store(p, x0) volatile_rmw(p)That is, we'd use plain load and store instructions, but boxed in with volatile operations, both in control flow and data flow, to prevent any code motion or redundancy elimination. It'll get chatty, especially in the volatile-atomic case, but volatile is rare so it seems like an ok tradeoff. This should let most of the compiler automatically do the right thing, at low cost in overall complexity. And,
volatile_rmwandvolatile_unarywould be handy besides for crafting compiler unit tests :-).
Last updated: Aug 30 2026 at 09:07 UTC