Skip to content

Commit 02d5f09

Browse files
committed
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.
2 parents 00605d5 + e7f42f1 commit 02d5f09

File tree

2 files changed

+51
-16
lines changed

2 files changed

+51
-16
lines changed

Diff for: src/librustc/middle/trans/tvec.rs

+44-16
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use middle::ty;
2727
use util::common::indenter;
2828
use util::ppaux::ty_to_str;
2929

30+
use core::option::None;
3031
use core::uint;
3132
use core::vec;
3233
use syntax::ast;
@@ -413,30 +414,57 @@ pub fn write_content(bcx: block,
413414
return bcx;
414415
}
415416

416-
let tmpdatum = unpack_datum!(bcx, {
417+
// Some cleanup would be required in the case in which failure happens
418+
// during a copy. But given that copy constructors are not overridable,
419+
// this can only happen as a result of OOM. So we just skip out on the
420+
// cleanup since things would *probably* be broken at that point anyways.
421+
422+
let elem = unpack_datum!(bcx, {
417423
expr::trans_to_datum(bcx, element)
418424
});
419425

420-
let mut temp_cleanups = ~[];
426+
let next_bcx = sub_block(bcx, ~"expr_repeat: while next");
427+
let loop_bcx = loop_scope_block(bcx, next_bcx, None, ~"expr_repeat", None);
428+
let cond_bcx = scope_block(loop_bcx, None, ~"expr_repeat: loop cond");
429+
let set_bcx = scope_block(loop_bcx, None, ~"expr_repeat: body: set");
430+
let inc_bcx = scope_block(loop_bcx, None, ~"expr_repeat: body: inc");
431+
Br(bcx, loop_bcx.llbb);
421432

422-
for uint::range(0, count) |i| {
423-
let lleltptr = GEPi(bcx, lldest, [i]);
424-
if i < count - 1 {
425-
// Copy all but the last one in.
426-
bcx = tmpdatum.copy_to(bcx, INIT, lleltptr);
427-
} else {
428-
// Move the last one in.
429-
bcx = tmpdatum.move_to(bcx, INIT, lleltptr);
430-
}
431-
add_clean_temp_mem(bcx, lleltptr, vt.unit_ty);
432-
temp_cleanups.push(lleltptr);
433+
let loop_counter = {
434+
// i = 0
435+
let i = alloca(loop_bcx, bcx.ccx().int_type);
436+
Store(loop_bcx, C_uint(bcx.ccx(), 0), i);
437+
438+
Br(loop_bcx, cond_bcx.llbb);
439+
i
440+
};
441+
442+
{ // i < count
443+
let lhs = Load(cond_bcx, loop_counter);
444+
let rhs = C_uint(bcx.ccx(), count);
445+
let cond_val = ICmp(cond_bcx, lib::llvm::IntULT, lhs, rhs);
446+
447+
CondBr(cond_bcx, cond_val, set_bcx.llbb, next_bcx.llbb);
433448
}
434449

435-
for vec::each(temp_cleanups) |cleanup| {
436-
revoke_clean(bcx, *cleanup);
450+
{ // v[i] = elem
451+
let i = Load(set_bcx, loop_counter);
452+
let lleltptr = InBoundsGEP(set_bcx, lldest, [i]);
453+
let set_bcx = elem.copy_to(set_bcx, INIT, lleltptr);
454+
455+
Br(set_bcx, inc_bcx.llbb);
437456
}
438457

439-
return bcx;
458+
{ // i += 1
459+
let i = Load(inc_bcx, loop_counter);
460+
let plusone = Add(inc_bcx, i, C_uint(bcx.ccx(), 1));
461+
Store(inc_bcx, plusone, loop_counter);
462+
463+
Br(inc_bcx, cond_bcx.llbb);
464+
}
465+
466+
return next_bcx;
467+
440468
}
441469
}
442470
}

Diff for: src/test/run-pass/repeated-vector-syntax.rs

+7
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,15 @@
99
// except according to those terms.
1010

1111
pub fn main() {
12+
struct Foo { a: ~str }
13+
14+
let v = [ ~Foo { a: ~"Hello!" }, ..129 ];
15+
let w = [ ~"Hello!", ..129 ];
1216
let x = [ @[true], ..512 ];
1317
let y = [ 0, ..1 ];
18+
19+
error!("%?", v);
20+
error!("%?", w);
1421
error!("%?", x);
1522
error!("%?", y);
1623
}

0 commit comments

Comments
 (0)