{"id":298,"hash":"3eab201b215167c47144a12b31edaaacad18e53f39603ccf45b2154997132320","pattern":"Why does the Rust compiler not optimize code assuming that two mutable references cannot alias?","full_message":"As far as I know, reference/pointer aliasing can hinder the compiler's ability to generate optimized code, since they must ensure the generated binary behaves correctly in the case where the two references/pointers indeed alias. For instance, in the following C code,\n\nvoid adds(int *a, int *b) {\n    *a += *b;\n    *a += *b;\n}\n\nwhen compiled by clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) with the -O3 flag, it emits\n\n0000000000000000 <adds>:\n   0:    8b 07                    mov    (%rdi),%eax  # load a into EAX\n   2:    03 06                    add    (%rsi),%eax  # load-and-add b\n   4:    89 07                    mov    %eax,(%rdi)  # store into a\n   6:    03 06                    add    (%rsi),%eax  # load-and-add b again\n   8:    89 07                    mov    %eax,(%rdi)  # store into a again\n   a:    c3                       retq\n\nHere the code stores back to (%rdi) twice in case int *a and int *b alias.\n\nWhen we explicitly tell the compiler that these two pointers cannot alias with the restrict keyword:\n\nvoid adds(int *restrict a, int *restrict b) {\n    *a += *b;\n    *a += *b;\n}\n\nThen Clang will emit a more optimized version that effectively does *a += 2 * (*b), which is equivalent if (as promised by restrict) *b isn't modified by assigning to *a:\n\n0000000000000000 <adds>:\n   0:    8b 06                    mov    (%rsi),%eax   # load b once\n   2:    01 c0                    add    %eax,%eax     # double it\n   4:    01 07                    add    %eax,(%rdi)   # *a += 2 * (*b)\n   6:    c3                       retq\n\nSince Rust makes sure (except in unsafe code) that two mutable references cannot alias, I would think that the compiler should be able to emit the more optimized version of the code.\n\nWhen I test with the code below and compile it with rustc 1.35.0 with -C opt-level=3 --emit obj,\n\n#![crate_type = \"staticlib\"]\n#[no_mangle]\nfn adds(a: &mut i32, b: &mut i32) {\n    *a += *b;\n    *a += *b;\n}\n\nit generates:\n\n0000000000000000 <adds>:\n   0:    8b 07                    mov    (%rdi),%eax\n   2:    03 06                    add    (%rsi),%eax\n   4:    89 07                    mov    %eax,(%rdi)\n   6:    03 06                    add    (%rsi),%eax\n   8:    89 07                    mov    %eax,(%rdi)\n   a:    c3                       retq\n\nThis does not take advantage of the guarantee that a and b cannot alias.\n\nIs this because the current Rust compiler is still in development and has not yet incorporated alias analysis to do the optimization?\n\nIs this because there is still a chance that a and b could alias, even in safe Rust?","ecosystem":"cargo","package_name":"reference","package_version":null,"solution":"Rust originally did enable LLVM's noalias attribute, but this caused miscompiled code. When all supported LLVM versions no longer miscompile the code, it will be re-enabled.\n\nIf you add -Zmutable-noalias=yes to the compiler options, you get the expected assembly:\n\nadds:\n        mov     eax, dword ptr [rsi]\n        add     eax, eax\n        add     dword ptr [rdi], eax\n        ret\n\nSimply put, Rust put the equivalent of C's restrict keyword everywhere, far more prevalent than any usual C program. This exercised corner cases of LLVM more than it was able to handle correctly. It turns out that C and C++ programmers simply don't use restrict as frequently as &mut is used in Rust.\n\nThis has happened multiple times.\n\nRust 1.0 through 1.7 — noalias enabled\nRust 1.8 through 1.27 — noalias disabled\nRust 1.28 through 1.29 — noalias enabled\nRust 1.30 through 1.54 — noalias disabled\nRust 1.54 through ??? — noalias conditionally enabled depending on the version of LLVM the compiler uses\n\nRelated Rust issues\n\nCurrent case\n\nIncorrect code generation for nalgebra's Matrix::swap_rows() #54462\nRe-enable noalias annotations by default once LLVM no longer miscompiles them #54878\nEnable mutable noalias for LLVM >= 12 #82834\nRegression: Miscompilation due to bug in \"mutable noalias\" logic #84958\n\nPrevious case\n\nWorkaround LLVM optimizer bug by not marking &mut pointers as noalias #31545\nMark &mut pointers as noalias once LLVM no longer miscompiles them #31681\n\nOther\n\nmake use of LLVM's scoped noalias metadata #16515\nMissed optimization: references from pointers aren't treated as noalias #38941\nnoalias is not enough #53105\nmutable noalias: re-enable permanently, only for panic=abort, or stabilize flag? #45029","confidence":0.95,"source":"stackoverflow","source_url":"https://stackoverflow.com/questions/57259126/why-does-the-rust-compiler-not-optimize-code-assuming-that-two-mutable-reference","votes":424,"created_at":"2026-04-19T04:41:47.320917+00:00","updated_at":"2026-04-19T04:52:27.229199+00:00"}