parent
c4c9628de7
commit
e74aa2bdff
@ -24,12 +24,14 @@ impl BitVector {
|
||||
(self.data[word] & mask) != 0
|
||||
}
|
||||
|
||||
/// Returns true if the bit has changed.
|
||||
pub fn insert(&mut self, bit: usize) -> bool {
|
||||
let (word, mask) = word_mask(bit);
|
||||
let data = &mut self.data[word];
|
||||
let value = *data;
|
||||
*data = value | mask;
|
||||
(value | mask) != value
|
||||
let new_value = value | mask;
|
||||
*data = new_value;
|
||||
new_value != value
|
||||
}
|
||||
|
||||
pub fn insert_all(&mut self, all: &BitVector) -> bool {
|
||||
|
@ -11,7 +11,7 @@
|
||||
//! An analysis to determine which temporaries require allocas and
|
||||
//! which do not.
|
||||
|
||||
use rustc_data_structures::fnv::FnvHashSet;
|
||||
use rustc_data_structures::bitvec::BitVector;
|
||||
use rustc::mir::repr as mir;
|
||||
use rustc::mir::visit::{Visitor, LvalueContext};
|
||||
use trans::common::{self, Block};
|
||||
@ -19,8 +19,8 @@ use super::rvalue;
|
||||
|
||||
pub fn lvalue_temps<'bcx,'tcx>(bcx: Block<'bcx,'tcx>,
|
||||
mir: &mir::Mir<'tcx>)
|
||||
-> FnvHashSet<usize> {
|
||||
let mut analyzer = TempAnalyzer::new();
|
||||
-> BitVector {
|
||||
let mut analyzer = TempAnalyzer::new(mir.temp_decls.len());
|
||||
|
||||
analyzer.visit_mir(mir);
|
||||
|
||||
@ -51,18 +51,28 @@ pub fn lvalue_temps<'bcx,'tcx>(bcx: Block<'bcx,'tcx>,
|
||||
}
|
||||
|
||||
struct TempAnalyzer {
|
||||
lvalue_temps: FnvHashSet<usize>,
|
||||
lvalue_temps: BitVector,
|
||||
seen_assigned: BitVector
|
||||
}
|
||||
|
||||
impl TempAnalyzer {
|
||||
fn new() -> TempAnalyzer {
|
||||
TempAnalyzer { lvalue_temps: FnvHashSet() }
|
||||
fn new(temp_count: usize) -> TempAnalyzer {
|
||||
TempAnalyzer {
|
||||
lvalue_temps: BitVector::new(temp_count),
|
||||
seen_assigned: BitVector::new(temp_count)
|
||||
}
|
||||
}
|
||||
|
||||
fn mark_as_lvalue(&mut self, temp: usize) {
|
||||
debug!("marking temp {} as lvalue", temp);
|
||||
self.lvalue_temps.insert(temp);
|
||||
}
|
||||
|
||||
fn mark_assigned(&mut self, temp: usize) {
|
||||
if !self.seen_assigned.insert(temp) {
|
||||
self.mark_as_lvalue(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Visitor<'tcx> for TempAnalyzer {
|
||||
@ -74,6 +84,7 @@ impl<'tcx> Visitor<'tcx> for TempAnalyzer {
|
||||
|
||||
match *lvalue {
|
||||
mir::Lvalue::Temp(index) => {
|
||||
self.mark_assigned(index as usize);
|
||||
if !rvalue::rvalue_creates_operand(rvalue) {
|
||||
self.mark_as_lvalue(index as usize);
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ pub fn trans_mir<'bcx, 'tcx>(bcx: Block<'bcx, 'tcx>) {
|
||||
let temps = mir.temp_decls.iter()
|
||||
.map(|decl| bcx.monomorphize(&decl.ty))
|
||||
.enumerate()
|
||||
.map(|(i, mty)| if lvalue_temps.contains(&i) {
|
||||
.map(|(i, mty)| if lvalue_temps.contains(i) {
|
||||
TempRef::Lvalue(LvalueRef::alloca(bcx,
|
||||
mty,
|
||||
&format!("temp{:?}", i)))
|
||||
|
22
src/test/run-pass/mir_temp_promotions.rs
Normal file
22
src/test/run-pass/mir_temp_promotions.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#[rustc_mir]
|
||||
fn test1(f: f32) -> bool {
|
||||
// test that we properly promote temporaries to allocas when a temporary is assigned to
|
||||
// multiple times (assignment is still happening once ∀ possible dataflows).
|
||||
!(f.is_nan() || f.is_infinite())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(test1(0.0), true);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user