Skip to content

Commit a17fb64

Browse files
committed
Workaround LLVM optimizer bug by not marking &mut pointers as noalias
LLVM's memory dependence analysis doesn't properly account for calls that could unwind and thus effectively act as a branching point. This can lead to stores that are only visible when the call unwinds being removed, possibly leading to calls to drop() functions with b0rked memory contents. As there is no fix for this in LLVM yet and we want to keep compatibility to current LLVM versions anyways, we have to workaround this bug by omitting the noalias attribute on &mut function arguments. Benchmarks suggest that the performance loss by this change is very small. Thanks to @RalfJung for pushing me towards not removing too many noalias annotations and @alexcrichton for helping out with the test for this bug. Fixes #29485
1 parent 052b3fd commit a17fb64

File tree

4 files changed

+58
-4
lines changed

4 files changed

+58
-4
lines changed

src/librustc_trans/trans/attributes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
265265
// on memory dependencies rather than pointer equality
266266
let interior_unsafe = mt.ty.type_contents(ccx.tcx()).interior_unsafe();
267267

268-
if mt.mutbl == hir::MutMutable || !interior_unsafe {
268+
if mt.mutbl != hir::MutMutable && !interior_unsafe {
269269
attrs.arg(idx, llvm::Attribute::NoAlias);
270270
}
271271

src/test/auxiliary/issue-29485.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_name="a"]
12+
#![crate_type = "lib"]
13+
14+
pub struct X(pub u8);
15+
16+
impl Drop for X {
17+
fn drop(&mut self) {
18+
assert_eq!(self.0, 1)
19+
}
20+
}
21+
22+
pub fn f(x: &mut X, g: fn()) {
23+
x.0 = 1;
24+
g();
25+
x.0 = 0;
26+
}

src/test/codegen/function-arguments.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,16 @@ pub fn named_borrow<'r>(_: &'r i32) {
5151
pub fn unsafe_borrow(_: &UnsafeInner) {
5252
}
5353

54-
// CHECK: @mutable_unsafe_borrow(%UnsafeInner* noalias dereferenceable(2))
54+
// CHECK: @mutable_unsafe_borrow(%UnsafeInner* dereferenceable(2))
5555
// ... unless this is a mutable borrow, those never alias
56+
// ... except that there's this LLVM bug that forces us to not use noalias, see #29485
5657
#[no_mangle]
5758
pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) {
5859
}
5960

60-
// CHECK: @mutable_borrow(i32* noalias dereferenceable(4))
61+
// CHECK: @mutable_borrow(i32* dereferenceable(4))
6162
// FIXME #25759 This should also have `nocapture`
63+
// ... there's this LLVM bug that forces us to not use noalias, see #29485
6264
#[no_mangle]
6365
pub fn mutable_borrow(_: &mut i32) {
6466
}
@@ -100,8 +102,9 @@ fn helper(_: usize) {
100102
fn slice(_: &[u8]) {
101103
}
102104

103-
// CHECK: @mutable_slice(i8* noalias nonnull, [[USIZE]])
105+
// CHECK: @mutable_slice(i8* nonnull, [[USIZE]])
104106
// FIXME #25759 This should also have `nocapture`
107+
// ... there's this LLVM bug that forces us to not use noalias, see #29485
105108
#[no_mangle]
106109
fn mutable_slice(_: &mut [u8]) {
107110
}

src/test/run-pass/issue-29485.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:issue-29485.rs
12+
13+
#[feature(recover)]
14+
15+
extern crate a;
16+
17+
fn main() {
18+
let _ = std::thread::spawn(move || {
19+
a::f(&mut a::X(0), g);
20+
}).join();
21+
}
22+
23+
fn g() {
24+
panic!();
25+
}

0 commit comments

Comments
 (0)