| Age | Commit message (Collapse) | Author | Lines |
|
|
|
|
|
|
|
|
|
|
|
check target abi support
This PR checks for each extern function / block whether the ABI / calling convention used is supported by the current target.
This was achieved by adding an `abi_blacklist` field to the target specifications, listing the calling conventions unsupported for that target.
|
|
|
|
|
|
Implement .zip() specialization for Map and Cloned.
The crucial thing for transparent specialization is that we want to
preserve the potential side effects.
The simplest example is that in this code snippet:
`(0..6).map(f).zip((0..4).map(g)).count()`
`f` will be called five times, and `g` four times. The last time for `f`
is when the other iterator is at its end, so this element is unused.
This side effect can be preserved without disturbing code generation for
simple uses of `.map()`.
The `Zip::next_back()` case is even more complicated, unfortunately.
|
|
Fixes #36955.
|
|
There's no need for a long prefix, since there's nothing to distinguish
anymore.
|
|
|
|
refactor to remove trans::adt and make rustc::ty::layout authoritative
I asked on IRC about optimizing struct layout by reordering fields from most-aligned to least-aligned and somehow ended up getting talked into doing this. The goal here is to make `layout` authoritative and to remove `adt`. The former has been accomplished by reimplementing `represent_type_uncached` and the latter is in progress. @eddyb thought I should make the PR now.
My plan is to reserve the actual optimization for a second PR, as this work is useful by itself.
|
|
|
|
This optimization kicks in a lot when bootstrapping the compiler.
|
|
This only supports trivial cases in which there is exactly one def and
one use.
|
|
core: add likely and unlikely intrinsics
I'm no good at reading assembly, but I have tried a stage1 compiler with this patch, and it does cause different asm output. Additionally, testing this compiler on my httparse crate with some `likely` usage added in to the branches does affect benchmarks. However, I'm sure a codegen test should be included, if anyone knows what it should look like.
There isn't an entry in `librustc_trans/context.rs` in this diff, because it already exists (`llvm.expect.i1` is used for array indices).
----
Even though this does affect httparse benchmarks, it doesn't seem to affect it the same way GCC's `__builtin_expect` affects picohttpparser. I was confused that the deviation on the benchmarks grew hugely when testing this, especially since I'm absolutely certain that the branchs where I added `likely` were always `true`. I chalk that up to GCC and LLVM handle branch prediction differently.
cc #26179
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Add regression test for #32364
This PR adds a regression test for #32364.
r? @eddyb
|
|
|
|
add a test case for issue #32031
I propose a test case to finish the fix for issue #32031. Please review this commit thoroughly, as I have never written a codegen test before.
r? @eddyb
|
|
|
|
|
|
|
|
This commit is an implementation of [RFC 1513] which allows applications to
alter the behavior of panics at compile time. A new compiler flag, `-C panic`,
is added and accepts the values `unwind` or `panic`, with the default being
`unwind`. This model affects how code is generated for the local crate, skipping
generation of landing pads with `-C panic=abort`.
[RFC 1513]: https://github.com/rust-lang/rfcs/blob/master/text/1513-less-unwinding.md
Panic implementations are then provided by crates tagged with
`#![panic_runtime]` and lazily required by crates with
`#![needs_panic_runtime]`. The panic strategy (`-C panic` value) of the panic
runtime must match the final product, and if the panic strategy is not `abort`
then the entire DAG must have the same panic strategy.
With the `-C panic=abort` strategy, users can expect a stable method to disable
generation of landing pads, improving optimization in niche scenarios,
decreasing compile time, and decreasing output binary size. With the `-C
panic=unwind` strategy users can expect the existing ability to isolate failure
in Rust code from the outside world.
Organizationally, this commit dismantles the `sys_common::unwind` module in
favor of some bits moving part of it to `libpanic_unwind` and the rest into the
`panicking` module in libstd. The custom panic runtime support is pretty similar
to the custom allocator support with the only major difference being how the
panic runtime is injected (takes the `-C panic` flag into account).
|
|
|
|
`fast` a.k.a UnsafeAlgebra is the flag for enabling all "unsafe"
(according to llvm) float optimizations.
See LangRef for more information http://llvm.org/docs/LangRef.html#fast-math-flags
Providing these operations with less precise associativity rules (for
example) is useful to numerical applications.
For example, the summation loop:
let sum = 0.;
for element in data {
sum += *element;
}
Using the default floating point semantics, this loop expresses the
floats must be added in a sequence, one after another. This constraint
is usually completely unintended, and it means that no autovectorization
is possible.
|
|
|
|
|
|
|
|
LLVM's memory dependence analysis doesn't properly account for calls
that could unwind and thus effectively act as a branching point. This
can lead to stores that are only visible when the call unwinds being
removed, possibly leading to calls to drop() functions with b0rked
memory contents.
As there is no fix for this in LLVM yet and we want to keep
compatibility to current LLVM versions anyways, we have to workaround
this bug by omitting the noalias attribute on &mut function arguments.
Benchmarks suggest that the performance loss by this change is very
small.
Thanks to @RalfJung for pushing me towards not removing too many
noalias annotations and @alexcrichton for helping out with the test for
this bug.
Fixes #29485
|
|
If a new cleanup is added to a cleanup scope, the cached exits for that
scope are cleared, so all previous cleanups have to be translated
again. In the worst case this means that we get N distinct landing pads
where the last one has N cleanups, then N-1 and so on.
As new cleanups are to be executed before older ones, we can instead
cache the number of already translated cleanups in addition to the
block that contains them, and then only translate new ones, if any and
then jump to the cached ones, getting away with linear growth instead.
For the crate in #31381 this reduces the compile time for an optimized
build from >20 minutes (I cancelled the build at that point) to about 11
seconds. Testing a few crates that come with rustc show compile time
improvements somewhere between 1 and 8%. The "big" winner being
rustc_platform_intrinsics which features code similar to that in #31381.
Fixes #31381
|
|
Fixes #30831
|
|
Since fat pointers do not qualify as structural types, they got copied
using load_ty and store_ty, which means that we load an FCA and use
extractvalue to get the components of the fat pointer. This breaks
certain optimizations in LLVM.
Found via apasel422/ref_count#13
|
|
For enum variants, the default alignment for a specific variant might be
lower than the alignment of the enum type itself. In such cases we, for
example, generate memcpy calls with an alignment that's higher than the
alignment of the constant we copy from.
To avoid that, we need to explicitly set the required alignment on
constants.
Fixes #28912.
|
|
A DST value and a fat pointer to it have the same representation, all we
have to do is to adjust the type of the datum holding the pointer.
|
|
By putting an "unreachable" instruction into the default arm of a switch
instruction we can let LLVM know that the match is exhaustive, allowing
for better optimizations.
For example, this match:
```rust
pub enum Enum {
One,
Two,
Three,
}
impl Enum {
pub fn get_disc(self) -> u8 {
match self {
Enum::One => 0,
Enum::Two => 1,
Enum::Three => 2,
}
}
}
```
Currently compiles to this on x86_64:
```asm
.cfi_startproc
movzbl %dil, %ecx
cmpl $1, %ecx
setne %al
testb %cl, %cl
je .LBB0_2
incb %al
movb %al, %dil
.LBB0_2:
movb %dil, %al
retq
.Lfunc_end0:
```
But with this change we get:
```asm
.cfi_startproc
movb %dil, %al
retq
.Lfunc_end0:
```
|
|
This is so LLVM isn't forced to load every byte of it. Also sets the alignment of
the load. Adds a test for the debug script section.
|
|
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
```
|
|
Currently, we're generating adjustments, for example, to get from &[u8]
to &[u8], which is unneeded and kicks us out of trans_into() into
trans() which means an additional stack slot and copy in the unoptimized
code.
|
|
Unwinding across an FFI boundary is undefined behaviour, so we can mark
all external function as nounwind. The obvious exception are those
functions that actually perform the unwinding.
|
|
Intrinsics never have an address, so it doesn't make sense to say that their
address is unnamed.
|
|
|