Skip to content

Commit 2c17bfc

Browse files
committed
Skip no-op adjustments in trans
That allows us to keep using trans_into() in case of adjustments that may actually be ignored in trans because they are a plain deref/ref pair with no overloaded deref or unsizing. Unoptimized(!) benchmarks from servo/servo#7638 Before ``` test goser::bench_clone ... bench: 17,701 ns/iter (+/- 58) = 30 MB/s test goser::bincode::bench_decoder ... bench: 33,715 ns/iter (+/- 300) = 11 MB/s test goser::bincode::bench_deserialize ... bench: 36,804 ns/iter (+/- 329) = 9 MB/s test goser::bincode::bench_encoder ... bench: 34,695 ns/iter (+/- 149) = 11 MB/s test goser::bincode::bench_populate ... bench: 18,879 ns/iter (+/- 88) test goser::bincode::bench_serialize ... bench: 31,668 ns/iter (+/- 156) = 11 MB/s test goser::capnp::bench_deserialize ... bench: 2,049 ns/iter (+/- 87) = 218 MB/s test goser::capnp::bench_deserialize_packed ... bench: 10,707 ns/iter (+/- 258) = 31 MB/s test goser::capnp::bench_populate ... bench: 635 ns/iter (+/- 5) test goser::capnp::bench_serialize ... bench: 35,657 ns/iter (+/- 155) = 12 MB/s test goser::capnp::bench_serialize_packed ... bench: 37,881 ns/iter (+/- 146) = 8 MB/s test goser::msgpack::bench_decoder ... bench: 50,634 ns/iter (+/- 307) = 5 MB/s test goser::msgpack::bench_encoder ... bench: 25,738 ns/iter (+/- 90) = 11 MB/s test goser::msgpack::bench_populate ... bench: 18,900 ns/iter (+/- 138) test goser::protobuf::bench_decoder ... bench: 2,791 ns/iter (+/- 29) = 102 MB/s test goser::protobuf::bench_encoder ... bench: 75,414 ns/iter (+/- 358) = 3 MB/s test goser::protobuf::bench_populate ... bench: 19,248 ns/iter (+/- 92) test goser::rustc_serialize_json::bench_decoder ... bench: 109,999 ns/iter (+/- 797) = 5 MB/s test goser::rustc_serialize_json::bench_encoder ... bench: 58,777 ns/iter (+/- 418) = 10 MB/s test goser::rustc_serialize_json::bench_populate ... bench: 18,887 ns/iter (+/- 76) test goser::serde_json::bench_deserializer ... bench: 104,803 ns/iter (+/- 770) = 5 MB/s test goser::serde_json::bench_populate ... bench: 18,890 ns/iter (+/- 69) test goser::serde_json::bench_serializer ... bench: 75,046 ns/iter (+/- 435) = 8 MB/s ``` After ``` test goser::bench_clone ... bench: 16,052 ns/iter (+/- 188) = 34 MB/s test goser::bincode::bench_decoder ... bench: 31,194 ns/iter (+/- 941) = 12 MB/s test goser::bincode::bench_deserialize ... bench: 33,934 ns/iter (+/- 352) = 10 MB/s test goser::bincode::bench_encoder ... bench: 30,737 ns/iter (+/- 1,969) = 13 MB/s test goser::bincode::bench_populate ... bench: 17,234 ns/iter (+/- 176) test goser::bincode::bench_serialize ... bench: 28,269 ns/iter (+/- 452) = 12 MB/s test goser::capnp::bench_deserialize ... bench: 2,019 ns/iter (+/- 85) = 221 MB/s test goser::capnp::bench_deserialize_packed ... bench: 10,662 ns/iter (+/- 527) = 31 MB/s test goser::capnp::bench_populate ... bench: 607 ns/iter (+/- 2) test goser::capnp::bench_serialize ... bench: 30,488 ns/iter (+/- 219) = 14 MB/s test goser::capnp::bench_serialize_packed ... bench: 33,731 ns/iter (+/- 201) = 9 MB/s test goser::msgpack::bench_decoder ... bench: 46,921 ns/iter (+/- 461) = 6 MB/s test goser::msgpack::bench_encoder ... bench: 22,315 ns/iter (+/- 96) = 12 MB/s test goser::msgpack::bench_populate ... bench: 17,268 ns/iter (+/- 73) test goser::protobuf::bench_decoder ... bench: 2,658 ns/iter (+/- 44) = 107 MB/s test goser::protobuf::bench_encoder ... bench: 71,024 ns/iter (+/- 359) = 4 MB/s test goser::protobuf::bench_populate ... bench: 17,704 ns/iter (+/- 104) test goser::rustc_serialize_json::bench_decoder ... bench: 107,867 ns/iter (+/- 759) = 5 MB/s test goser::rustc_serialize_json::bench_encoder ... bench: 52,327 ns/iter (+/- 479) = 11 MB/s test goser::rustc_serialize_json::bench_populate ... bench: 17,262 ns/iter (+/- 68) test goser::serde_json::bench_deserializer ... bench: 99,156 ns/iter (+/- 657) = 6 MB/s test goser::serde_json::bench_populate ... bench: 17,264 ns/iter (+/- 77) test goser::serde_json::bench_serializer ... bench: 66,135 ns/iter (+/- 392) = 9 MB/s ```
1 parent cff0411 commit 2c17bfc

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

src/librustc_trans/trans/expr.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
119119

120120
debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
121121

122-
if bcx.tcx().tables.borrow().adjustments.contains_key(&expr.id) {
122+
if adjustment_required(bcx, expr) {
123123
// use trans, which may be less efficient but
124124
// which will perform the adjustments:
125125
let datum = unpack_datum!(bcx, trans(bcx, expr));
@@ -334,6 +334,37 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
334334
}
335335
}
336336

337+
fn adjustment_required<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
338+
expr: &hir::Expr) -> bool {
339+
let adjustment = match bcx.tcx().tables.borrow().adjustments.get(&expr.id).cloned() {
340+
None => { return false; }
341+
Some(adj) => adj
342+
};
343+
344+
// Don't skip a conversion from Box<T> to &T, etc.
345+
if bcx.tcx().is_overloaded_autoderef(expr.id, 0) {
346+
return true;
347+
}
348+
349+
match adjustment {
350+
AdjustReifyFnPointer => {
351+
// FIXME(#19925) once fn item types are
352+
// zero-sized, we'll need to return true here
353+
false
354+
}
355+
AdjustUnsafeFnPointer => {
356+
// purely a type-level thing
357+
false
358+
}
359+
AdjustDerefRef(ref adj) => {
360+
// We are a bit paranoid about adjustments and thus might have a re-
361+
// borrow here which merely derefs and then refs again (it might have
362+
// a different region or mutability, but we don't care here).
363+
!(adj.autoderefs == 1 && adj.autoref.is_some() && adj.unsize.is_none())
364+
}
365+
}
366+
}
367+
337368
/// Helper for trans that apply adjustments from `expr` to `datum`, which should be the unadjusted
338369
/// translation of `expr`.
339370
fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,

src/test/codegen/adjustments.rs

+9
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,12 @@ pub fn no_op_slice_adjustment(x: &[u8]) -> &[u8] {
2626
// CHECK: call void @llvm.memcpy.{{.*}}(i8* [[DST]], i8* [[SRC]],
2727
{ x }
2828
}
29+
30+
// CHECK-LABEL: @no_op_slice_adjustment2
31+
#[no_mangle]
32+
pub fn no_op_slice_adjustment2(x: &[u8]) -> &[u8] {
33+
// We used to generate an extra alloca and memcpy for the function's return value, so check
34+
// that there's no memcpy (the slice is written to sret_slot element-wise)
35+
// CHECK-NOT: call void @llvm.memcpy.
36+
no_op_slice_adjustment(x)
37+
}

0 commit comments

Comments
 (0)