Change:
In MIR we want values to be SSA, however ensuring that constraint in trans (i.e. in TempRef) is wrong, I think. Namely, for code like this: we will generate following MIR (graphviz version, because easier to visualise): ! which will result in Note how we assign twice, but the two branches are fully disjoint, and thus, for the purposes of data-flow is still SSA, but for the purposes of translator is assigned multiple times. If we want s to stay across translation of the whole function, we will need something like a in the MIR. cc
Another option would be to convert these temporaries into lvalues (i.e. variables). Could it be that the unfinished is supposed to do just that?
I am confused. We do not require temps to be SSA, either in Mir or trans... But in trans we optimize in those cases where we can (I.e., where temps are SSA). Right?
suggests they are SSA with borrowing and mutation possible. Might be me misinterpreting what SSA means, but what I mean is that these are not supposed to be assigned more than once, for some definitions of once.
I see. Yes, ok, I agree that comment was in error. I think though that you probably ought to update it in :) I would still expect temps to be "DSA" -- which afaik I just made up -- that is, no two writes can reach one another without exiting the "live scope" of the temporary, but I don't know that it's an important property. FWIW I think SSA usually implies that values are "pure values", i.e., you can't take their address and mutate them. But I know what you mean in any case.
er, ought to have updated it
I’ll keep updating the comment in mind in whatever PR that comes next.

Discussion:
(self.data[word] & mask) != 0 } <ins> /// Returns true if the bit has changed. </ins> pub fn insert(&mut self, bit: usize) -> bool { let (word, mask) = word_mask(bit); let data = &mut self.data[word]; let value = *data; <del> *data = value | mask; (value | mask) != value </del> <ins> let new_value = value | mask; *data = new_value; new_value != value </ins> } pub fn insert_all(&mut self, all: &BitVector) -> bool {

//! An analysis to determine which temporaries require allocas and //! which do not. <del> use rustc_data_structures::fnv::FnvHashSet; </del> <ins> use rustc_data_structures::bitvec::BitVector; </ins> use rustc::mir::repr as mir; use rustc::mir::visit::{Visitor, LvalueContext}; use trans::common::{self, Block};

pub fn lvalue_temps<'bcx,'tcx>(bcx: Block<'bcx,'tcx>, mir: &mir::Mir<'tcx>) <del> -> FnvHashSet<usize> { let mut analyzer = TempAnalyzer::new(); </del> <ins> -> BitVector { let mut analyzer = TempAnalyzer::new(mir.temp_decls.len()); </ins> analyzer.visit_mir(mir);

} struct TempAnalyzer { <del> lvalue_temps: FnvHashSet<usize>, </del> <ins> lvalue_temps: BitVector, seen_assigned: BitVector </ins> } impl TempAnalyzer { <del> fn new() -> TempAnalyzer { TempAnalyzer { lvalue_temps: FnvHashSet() } </del> <ins> fn new(temp_count: usize) -> TempAnalyzer { TempAnalyzer { lvalue_temps: BitVector::new(temp_count), seen_assigned: BitVector::new(temp_count) } </ins> } fn mark_as_lvalue(&mut self, temp: usize) { debug!("marking temp {} as lvalue", temp); self.lvalue_temps.insert(temp); } <ins> fn mark_assigned(&mut self, temp: usize) { if !self.seen_assigned.insert(temp) { self.mark_as_lvalue(temp); } } </ins> } impl<'tcx> Visitor<'tcx> for TempAnalyzer {

match *lvalue { mir::Lvalue::Temp(index) => { <ins> self.mark_assigned(index as usize); </ins> if !rvalue::rvalue_creates_operand(rvalue) { self.mark_as_lvalue(index as usize); }

let temps = mir.temp_decls.iter() .map(|decl| bcx.monomorphize(&decl.ty)) .enumerate() <del> .map(|(i, mty)| if lvalue_temps.contains(&i) { </del> <ins> .map(|(i, mty)| if lvalue_temps.contains(i) { </ins> TempRef::Lvalue(LvalueRef::alloca(bcx, mty, &format!("temp{:?}", i)))

<ins> // 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); } </ins>