auto merge of #5524 : luqmana/rust/repeat-loop, r=pcwalton
`let v = [24, ..1000];` now more or less emits the same IR as: ```Rust let mut i = 0; while i < 1000 { v[i] = 24; i += 1; } ``` LLVM will still turn it into a memset if possible with optimization on.
This commit is contained in:
commit
02d5f090dc
2 changed files with 51 additions and 16 deletions
|
@ -27,6 +27,7 @@ use middle::ty;
|
|||
use util::common::indenter;
|
||||
use util::ppaux::ty_to_str;
|
||||
|
||||
use core::option::None;
|
||||
use core::uint;
|
||||
use core::vec;
|
||||
use syntax::ast;
|
||||
|
@ -413,30 +414,57 @@ pub fn write_content(bcx: block,
|
|||
return bcx;
|
||||
}
|
||||
|
||||
let tmpdatum = unpack_datum!(bcx, {
|
||||
// Some cleanup would be required in the case in which failure happens
|
||||
// during a copy. But given that copy constructors are not overridable,
|
||||
// this can only happen as a result of OOM. So we just skip out on the
|
||||
// cleanup since things would *probably* be broken at that point anyways.
|
||||
|
||||
let elem = unpack_datum!(bcx, {
|
||||
expr::trans_to_datum(bcx, element)
|
||||
});
|
||||
|
||||
let mut temp_cleanups = ~[];
|
||||
let next_bcx = sub_block(bcx, ~"expr_repeat: while next");
|
||||
let loop_bcx = loop_scope_block(bcx, next_bcx, None, ~"expr_repeat", None);
|
||||
let cond_bcx = scope_block(loop_bcx, None, ~"expr_repeat: loop cond");
|
||||
let set_bcx = scope_block(loop_bcx, None, ~"expr_repeat: body: set");
|
||||
let inc_bcx = scope_block(loop_bcx, None, ~"expr_repeat: body: inc");
|
||||
Br(bcx, loop_bcx.llbb);
|
||||
|
||||
for uint::range(0, count) |i| {
|
||||
let lleltptr = GEPi(bcx, lldest, [i]);
|
||||
if i < count - 1 {
|
||||
// Copy all but the last one in.
|
||||
bcx = tmpdatum.copy_to(bcx, INIT, lleltptr);
|
||||
} else {
|
||||
// Move the last one in.
|
||||
bcx = tmpdatum.move_to(bcx, INIT, lleltptr);
|
||||
}
|
||||
add_clean_temp_mem(bcx, lleltptr, vt.unit_ty);
|
||||
temp_cleanups.push(lleltptr);
|
||||
let loop_counter = {
|
||||
// i = 0
|
||||
let i = alloca(loop_bcx, bcx.ccx().int_type);
|
||||
Store(loop_bcx, C_uint(bcx.ccx(), 0), i);
|
||||
|
||||
Br(loop_bcx, cond_bcx.llbb);
|
||||
i
|
||||
};
|
||||
|
||||
{ // i < count
|
||||
let lhs = Load(cond_bcx, loop_counter);
|
||||
let rhs = C_uint(bcx.ccx(), count);
|
||||
let cond_val = ICmp(cond_bcx, lib::llvm::IntULT, lhs, rhs);
|
||||
|
||||
CondBr(cond_bcx, cond_val, set_bcx.llbb, next_bcx.llbb);
|
||||
}
|
||||
|
||||
for vec::each(temp_cleanups) |cleanup| {
|
||||
revoke_clean(bcx, *cleanup);
|
||||
{ // v[i] = elem
|
||||
let i = Load(set_bcx, loop_counter);
|
||||
let lleltptr = InBoundsGEP(set_bcx, lldest, [i]);
|
||||
let set_bcx = elem.copy_to(set_bcx, INIT, lleltptr);
|
||||
|
||||
Br(set_bcx, inc_bcx.llbb);
|
||||
}
|
||||
|
||||
return bcx;
|
||||
{ // i += 1
|
||||
let i = Load(inc_bcx, loop_counter);
|
||||
let plusone = Add(inc_bcx, i, C_uint(bcx.ccx(), 1));
|
||||
Store(inc_bcx, plusone, loop_counter);
|
||||
|
||||
Br(inc_bcx, cond_bcx.llbb);
|
||||
}
|
||||
|
||||
return next_bcx;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,15 @@
|
|||
// except according to those terms.
|
||||
|
||||
pub fn main() {
|
||||
struct Foo { a: ~str }
|
||||
|
||||
let v = [ ~Foo { a: ~"Hello!" }, ..129 ];
|
||||
let w = [ ~"Hello!", ..129 ];
|
||||
let x = [ @[true], ..512 ];
|
||||
let y = [ 0, ..1 ];
|
||||
|
||||
error!("%?", v);
|
||||
error!("%?", w);
|
||||
error!("%?", x);
|
||||
error!("%?", y);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue