Skip to content

Commit 8f84e95

Browse files
committed
Allow projections to be promoted to constants in MIR.
1 parent 05f4a75 commit 8f84e95

File tree

3 files changed

+40
-13
lines changed

3 files changed

+40
-13
lines changed

src/librustc_mir/transform/promote_consts.rs

+12-13
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,8 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
9696
// Ignore drops, if the temp gets promoted,
9797
// then it's constant and thus drop is noop.
9898
// Storage live ranges are also irrelevant.
99-
match context {
100-
LvalueContext::Drop |
101-
LvalueContext::StorageLive |
102-
LvalueContext::StorageDead => return,
103-
_ => {}
99+
if context.is_drop() || context.is_storage_marker() {
100+
return;
104101
}
105102

106103
let temp = &mut self.temps[index];
@@ -117,15 +114,17 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
117114
_ => { /* mark as unpromotable below */ }
118115
}
119116
} else if let TempState::Defined { ref mut uses, .. } = *temp {
120-
match context {
121-
LvalueContext::Borrow {..} |
122-
LvalueContext::Consume |
123-
LvalueContext::Inspect => {
124-
*uses += 1;
125-
return;
126-
}
127-
_ => { /* mark as unpromotable below */ }
117+
// We always allow borrows, even mutable ones, as we need
118+
// to promote mutable borrows of some ZSTs e.g. `&mut []`.
119+
let allowed_use = match context {
120+
LvalueContext::Borrow {..} => true,
121+
_ => context.is_nonmutating_use()
122+
};
123+
if allowed_use {
124+
*uses += 1;
125+
return;
128126
}
127+
/* mark as unpromotable below */
129128
}
130129
*temp = TempState::Unpromotable;
131130
}

src/librustc_trans/collector.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,7 @@ fn collect_neighbours<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
12031203

12041204
visitor.visit_mir(&mir);
12051205
for promoted in &mir.promoted {
1206+
visitor.mir = promoted;
12061207
visitor.visit_mir(promoted);
12071208
}
12081209
}

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

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2017 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+
#![feature(platform_intrinsics, repr_simd)]
12+
13+
extern "platform-intrinsic" {
14+
fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
15+
}
16+
17+
#[repr(simd)]
18+
#[derive(Clone, Copy)]
19+
#[allow(non_camel_case_types)]
20+
struct u64x2(u64, u64);
21+
22+
fn main() {
23+
let a = u64x2(1, 2);
24+
let r: u64x2 = unsafe { simd_shuffle2(a, a, [0-0, 0-0]) };
25+
assert_eq!(r.0, 1);
26+
assert_eq!(r.1, 1);
27+
}

0 commit comments

Comments
 (0)