-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compile bools to i1, as per Clang #8106
Comments
@thestinger has been mentioning this for a long time. Nominating for Production Ready. |
I thought we used to do just this, and stopped because "it wasn't what clang did". |
@graydon: the issue before was that we were also storing them as |
The IRC convo is missing context. Why do we want to do this? |
It's mostly because our IR is resulting in poor optimization right now, because LLVM is designed to consume clang's output. The way clang handles this is to truncate down to i1 after a load, and zext to i8 before a store. Since there are range assertions output for the loads, LLVM will optimize the truncation to a no-op, resulting in it branching directly on the value in every case. We do actually output range assertions now, but they're not triggering the relevant knowledge in LLVM. There are also currently issues like this, because we aren't truncating to i1:
I could try to put together an isolated example where using |
Oh I see. Carry on then! |
Just a bug, de-nominating |
And I found an example where it really stops optimizations: // optimized to ret 0
fn foo(i: uint) -> uint {if i % 5 == 1 {if i % 4 == 0 {i % 4}else{0}}else{0}}
// not optimized to ret 0
fn foo(i: uint) -> uint {if i % 5 == 1 && i % 4 == 0 {i % 4}else{0}} // optimized in clang to ret 0, but I think it does short-circuiting differently,
// so it's equivalent to the optimized rustc one
unsigned long foo(unsigned long i) {return (i % 5 == 1 && i % 4 == 0) ? i % 4 : 0;} I realized the same thing as @thestinger by looking at the output of --emit-llvm. Update: the missing link in the optimization process is // this non-short-circuiting example behaves just like the unoptimized rust one,
// with my manual bool optimization applied
unsigned long foo(unsigned long i) {return (i % 5 == 1 & i % 4 == 0) ? i % 4 : 0;} |
I have a patch for this, but it's currently blocked on http://llvm.org/bugs/show_bug.cgi?id=19250 -- just to make sure that nobody wastes his time on this. |
We currently compiled bools to i8 values, because there was a bug in LLVM that sometimes caused miscompilations when using i1 in, for example, structs. Using i8 means a lot of unnecessary zero-extend and truncate operations though, since we have to convert the value from and to i1 when using for example icmp or br instructions. Besides the unnecessary overhead caused by this, it also sometimes made LLVM miss some optimizations. Fixes rust-lang#8106.
To fix rust-lang#8106, we need an LLVM version that contains r211082 aka 0dee6756 which fixes a bug that blocks that issue. There have been some tiny API changes in LLVM, and cmpxchg changed its return type. The i1 part of the new return type is only interesting when using the new weak cmpxchg, which we don't do.
We currently compiled bools to i8 values, because there was a bug in LLVM that sometimes caused miscompilations when using i1 in, for example, structs. Using i8 means a lot of unnecessary zero-extend and truncate operations though, since we have to convert the value from and to i1 when using for example icmp or br instructions. Besides the unnecessary overhead caused by this, it also sometimes made LLVM miss some optimizations. Fixes rust-lang#8106.
Remind users of separate `rustc` lint groups changelog: none fixes rust-lang#8104
The text was updated successfully, but these errors were encountered: