Skip to content

Commit 913383d

Browse files
committed
rustc: Preserve more type information for interior vectors at the LLVM level, allowing SROA to take place. log ~[ 2 ].(0) now optimizes to just log 2.
1 parent 770bf24 commit 913383d

File tree

2 files changed

+39
-21
lines changed

2 files changed

+39
-21
lines changed

src/comp/back/abi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ const int closure_elt_bindings = 2;
6767
const int closure_elt_ty_params = 3;
6868

6969
const uint ivec_default_size = 64u;
70+
const uint ivec_default_length = 8u;
7071

7172
const uint ivec_elt_len = 0u;
7273
const uint ivec_elt_alen = 1u;

src/comp/middle/trans.rs

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -572,10 +572,17 @@ fn T_opaque_vec_ptr() -> TypeRef {
572572
// Interior vector.
573573
//
574574
// TODO: Support user-defined vector sizes.
575-
fn T_ivec() -> TypeRef {
575+
fn T_ivec(TypeRef t) -> TypeRef {
576576
ret T_struct([T_int(), // Length ("fill"; if zero, heapified)
577577
T_int(), // Alloc
578-
T_array(T_i8(), abi::ivec_default_size)]); // Body elements
578+
T_array(t, abi::ivec_default_length)]); // Body elements
579+
}
580+
581+
// Note that the size of this one is in bytes.
582+
fn T_opaque_ivec() -> TypeRef {
583+
ret T_struct([T_int(), // Length ("fill"; if zero, heapified)
584+
T_int(), // Alloc
585+
T_array(T_i8(), abi::ivec_default_size)]); // Body elements
579586
}
580587

581588
// Interior vector on the heap. Cast to this when the allocated length (second
@@ -868,7 +875,7 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
868875
}
869876
case (ty::ty_char) { llty = T_char(); }
870877
case (ty::ty_str) { llty = T_ptr(T_str()); }
871-
case (ty::ty_istr) { llty = T_ivec(); }
878+
case (ty::ty_istr) { llty = T_ivec(T_i8()); }
872879
case (ty::ty_tag(_, _)) {
873880
if (ty::type_has_dynamic_size(cx.tcx, t)) {
874881
llty = T_opaque_tag(cx.tn);
@@ -884,7 +891,11 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
884891
llty = T_ptr(T_vec(type_of_inner(cx, sp, mt.ty)));
885892
}
886893
case (ty::ty_ivec(?mt)) {
887-
llty = T_ivec();
894+
if (ty::type_has_dynamic_size(cx.tcx, mt.ty)) {
895+
llty = T_opaque_ivec();
896+
} else {
897+
llty = T_ivec(type_of_inner(cx, sp, mt.ty));
898+
}
888899
}
889900
case (ty::ty_ptr(?mt)) {
890901
llty = T_ptr(type_of_inner(cx, sp, mt.ty));
@@ -2661,9 +2672,8 @@ fn get_ivec_len_and_data(&@block_ctxt bcx, ValueRef v, ty::t unit_ty) ->
26612672
auto stack_len = bcx.build.Load(bcx.build.InBoundsGEP(v,
26622673
[C_int(0), C_uint(abi::ivec_elt_len)]));
26632674
auto stack_elem = bcx.build.InBoundsGEP(v, [C_int(0),
2664-
C_uint(abi::ivec_elt_elems)]);
2665-
stack_elem = bcx.build.PointerCast(stack_elem,
2666-
T_ptr(T_array(llunitty, 0u)));
2675+
C_uint(abi::ivec_elt_elems),
2676+
C_int(0)]);
26672677

26682678
auto on_heap = bcx.build.ICmp(lib::llvm::LLVMIntEQ, stack_len, C_int(0));
26692679

@@ -2691,22 +2701,22 @@ fn get_ivec_len_and_data(&@block_ctxt bcx, ValueRef v, ty::t unit_ty) ->
26912701
// Technically this context is unnecessary, but it makes this function
26922702
// clearer.
26932703
auto zero_len = C_int(0);
2694-
auto zero_elem = C_null(T_ptr(T_array(llunitty, 0u)));
2704+
auto zero_elem = C_null(T_ptr(llunitty));
26952705
zero_len_cx.build.Br(next_cx.llbb);
26962706

26972707
// If we're here, then we actually have a heapified vector.
26982708
auto heap_len = nonzero_len_cx.build.Load(
26992709
nonzero_len_cx.build.InBoundsGEP(heap_ptr,
27002710
[C_int(0), C_uint(abi::ivec_heap_elt_len)]));
27012711
auto heap_elem = nonzero_len_cx.build.InBoundsGEP(heap_ptr,
2702-
[C_int(0), C_uint(abi::ivec_heap_elt_elems)]);
2712+
[C_int(0), C_uint(abi::ivec_heap_elt_elems), C_int(0)]);
27032713
nonzero_len_cx.build.Br(next_cx.llbb);
27042714

27052715
// Now we can figure out the length of `v` and get a pointer to its first
27062716
// element.
27072717
auto len = next_cx.build.Phi(T_int(), [stack_len, zero_len, heap_len],
27082718
[bcx.llbb, zero_len_cx.llbb, nonzero_len_cx.llbb]);
2709-
auto elem = next_cx.build.Phi(T_ptr(T_array(llunitty, 0u)),
2719+
auto elem = next_cx.build.Phi(T_ptr(llunitty),
27102720
[stack_elem, zero_elem, heap_elem],
27112721
[bcx.llbb, zero_len_cx.llbb, nonzero_len_cx.llbb]);
27122722
ret tup(len, elem, next_cx);
@@ -2791,6 +2801,8 @@ fn iter_structural_ty_full(&@block_ctxt cx,
27912801
bcx = b_len_and_data._2;
27922802

27932803
// Calculate the last pointer address we want to handle.
2804+
// TODO: Optimize this when the size of the unit type is statically
2805+
// known to not use pointer casts, which tend to confuse LLVM.
27942806
auto len = umin(bcx, a_len, b_len);
27952807
auto b_elem_i8 = bcx.build.PointerCast(b_elem, T_ptr(T_i8()));
27962808
auto b_end_i8 = bcx.build.GEP(b_elem_i8, [len]);
@@ -4817,16 +4829,17 @@ fn trans_index(&@block_ctxt cx, &span sp, &@ast::expr base,
48174829
alt (interior_len_and_data) {
48184830
case (some(?lad)) { body = lad._1; }
48194831
case (none) {
4820-
body = next_cx.build.GEP(v, [C_int(0), C_int(abi::vec_elt_data)]);
4832+
body = next_cx.build.GEP(v,
4833+
[C_int(0), C_int(abi::vec_elt_data), C_int(0)]);
48214834
}
48224835
}
48234836

48244837
auto elt;
48254838
if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, unit_ty)) {
4826-
body = next_cx.build.PointerCast(body, T_ptr(T_array(T_i8(), 0u)));
4827-
elt = next_cx.build.GEP(body, [C_int(0), scaled_ix]);
4839+
body = next_cx.build.PointerCast(body, T_ptr(T_i8()));
4840+
elt = next_cx.build.GEP(body, [scaled_ix]);
48284841
} else {
4829-
elt = next_cx.build.GEP(body, [C_int(0), ix_val]);
4842+
elt = next_cx.build.GEP(body, [ix_val]);
48304843

48314844
// We're crossing a box boundary here, so we may need to pointer cast.
48324845
auto llunitty = type_of(next_cx.fcx.lcx.ccx, sp, unit_ty);
@@ -5649,7 +5662,13 @@ fn trans_ivec(@block_ctxt bcx, &vec[@ast::expr] args, &ast::ann ann)
56495662
bcx = rslt.bcx;
56505663

56515664
auto llunitty = type_of_or_i8(bcx, unit_ty);
5652-
auto llvecptr = alloca(bcx, T_ivec());
5665+
auto llvecptr;
5666+
if (ty::type_has_dynamic_size(bcx.fcx.lcx.ccx.tcx, unit_ty)) {
5667+
llvecptr = alloca(bcx, T_opaque_ivec());
5668+
} else {
5669+
llvecptr = alloca(bcx, T_ivec(llunitty));
5670+
}
5671+
56535672
auto lllen = bcx.build.Mul(C_uint(vec::len(args)), unit_sz);
56545673

56555674
// Allocate the vector pieces and store length and allocated length.
@@ -5661,7 +5680,7 @@ fn trans_ivec(@block_ctxt bcx, &vec[@ast::expr] args, &ast::ann ann)
56615680
bcx.build.Store(C_uint(abi::ivec_elt_alen), bcx.build.GEP(llvecptr,
56625681
[C_int(0), C_uint(abi::ivec_elt_alen)]));
56635682
llfirsteltptr = bcx.build.GEP(llvecptr,
5664-
[C_int(0), C_uint(abi::ivec_elt_elems)]);
5683+
[C_int(0), C_uint(abi::ivec_elt_elems), C_int(0)]);
56655684
} else {
56665685
// Heap case.
56675686
auto llstubty = T_ivec_heap(llunitty);
@@ -5690,12 +5709,10 @@ fn trans_ivec(@block_ctxt bcx, &vec[@ast::expr] args, &ast::ann ann)
56905709
bcx.build.Store(lllen, bcx.build.GEP(llheapptr,
56915710
[C_int(0), C_uint(abi::ivec_heap_elt_len)]));
56925711
llfirsteltptr = bcx.build.GEP(llheapptr,
5693-
[C_int(0), C_uint(abi::ivec_heap_elt_elems)]);
5712+
[C_int(0), C_uint(abi::ivec_heap_elt_elems), C_int(0)]);
56945713
}
56955714
}
56965715

5697-
llfirsteltptr = bcx.build.PointerCast(llfirsteltptr, T_ptr(llunitty));
5698-
56995716
// Store the individual elements.
57005717
auto i = 0u;
57015718
for (@ast::expr e in args) {
@@ -5705,10 +5722,10 @@ fn trans_ivec(@block_ctxt bcx, &vec[@ast::expr] args, &ast::ann ann)
57055722

57065723
auto lleltptr;
57075724
if (ty::type_has_dynamic_size(bcx.fcx.lcx.ccx.tcx, unit_ty)) {
5708-
lleltptr = bcx.build.GEP(llfirsteltptr,
5725+
lleltptr = bcx.build.InBoundsGEP(llfirsteltptr,
57095726
[bcx.build.Mul(C_uint(i), unit_align)]);
57105727
} else {
5711-
lleltptr = bcx.build.GEP(llfirsteltptr, [C_uint(i)]);
5728+
lleltptr = bcx.build.InBoundsGEP(llfirsteltptr, [C_uint(i)]);
57125729
}
57135730

57145731
bcx = copy_val(bcx, INIT, lleltptr, llsrc, unit_ty).bcx;

0 commit comments

Comments
 (0)