-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Missed optimization between range
parameter metadata and assume
s
#123278
Comments
Emit fewer `assume`s now that we have `range` metadata on parameters We still need the `assume` for the *target* type's range, but we no longer need it for the *source* type's range. Admittedly there's one test not properly handled by LLVM today, but it's synthetic, so I'd still be fine doing this and just updating the test once LLVM fixes the bug (llvm/llvm-project#123278). All the other optimization tests still pass. Hopefully this means less crud for LLVM to churn through in `opt` builds...
I cannot reproduce this issue: https://godbolt.org/z/aeh996njM It should be simplified by CVP/SCCP. BTW, if the range is known in the frontend, you can convert it into the canonical form |
On nightly there's a another Adding define noundef range(i8 1, 4) i8 @ordering_transmute_onetwothree(i8 noundef range(i8 -1, 2) %x) unnamed_addr {
start:
%x.dbg.spill = alloca [1 x i8], align 1
store i8 %x, ptr %x.dbg.spill, align 1
%0 = icmp uge i8 %x, -1
%1 = icmp ule i8 %x, 1
%2 = or i1 %0, %1
call void @llvm.assume(i1 %2)
%3 = icmp uge i8 %x, 1
call void @llvm.assume(i1 %3)
%4 = icmp ule i8 %x, 3
call void @llvm.assume(i1 %4)
ret i8 %x
} Where it's that first of the three And sorry for not providing a repro link earlier, but here's one with
Oh, if that's better I'll absolutely do that. Thanks! |
I am trying to avoid breaking llvm-project/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp Lines 3164 to 3183 in 7253c6f
|
Update: I locally changed how rustc emits those Now I get define noundef range(i8 1, 4) i8 @ordering_transmute_onetwothree(i8 noundef range(i8 -1, 2) %x) unnamed_addr #2 {
start:
%0 = add nsw i8 %x, -1
%1 = icmp ult i8 %0, 3
tail call void @llvm.assume(i1 %1)
ret i8 1
} And the compiler need to do less work to emit these in the first place, so beautiful. Thank you, @dtcxzyw! I appreciate your help ❤ Up to you if you want to keep this open or close it as "frontend doing it wrong". |
Confirmed that it doesn't help :( |
Emit fewer `assume`s now that we have `range` metadata on parameters We still need the `assume` for the *target* type's range, but we no longer need it for the *source* type's range. The first stab at this regressed a test, but thanks to good advice in llvm/llvm-project#123278 (comment) the second commit here changes how we emit these range assertions to the form that LLVM apparently likes better (and, conveniently, is easier to emit too) which got that test passing again 🎉 Hopefully this means less crud for LLVM to churn through in `opt` builds...
Update our range `assume`s to the format that LLVM prefers I found out in llvm/llvm-project#123278 (comment) that the way I started emitting the `assume`s in rust-lang#109993 was suboptimal, and as seen in that LLVM issue the way we're doing it -- with two `assume`s sometimes -- can at times lead to CVP/SCCP not realize what's happening because one of them turns into a `ne` instead of conveying a range. So this updates how it's emitted from ``` assume( x >= LOW ); assume( x <= HIGH ); ``` to ``` assume( (x - LOW) <= (HIGH - LOW) ); ``` so that we don't need multiple `icmp`s nor multiple `assume`s for a single value.
Update our range `assume`s to the format that LLVM prefers I found out in llvm/llvm-project#123278 (comment) that the way I started emitting the `assume`s in rust-lang#109993 was suboptimal, and as seen in that LLVM issue the way we're doing it -- with two `assume`s sometimes -- can at times lead to CVP/SCCP not realize what's happening because one of them turns into a `ne` instead of conveying a range. So this updates how it's emitted from ``` assume( x >= LOW ); assume( x <= HIGH ); ``` or ``` // (for ranges that wrap the range) assume( (x <= LOW) | (x >= HIGH) ); ``` to ``` assume( (x - LOW) <= (HIGH - LOW) ); ``` so that we don't need multiple `icmp`s nor multiple `assume`s for a single value, and both wrappping and non-wrapping ranges emit the same shape. (And we don't bother emitting the subtraction if `LOW` is zero, since that's trivial for us to check too.)
Update our range `assume`s to the format that LLVM prefers I found out in llvm/llvm-project#123278 (comment) that the way I started emitting the `assume`s in #109993 was suboptimal, and as seen in that LLVM issue the way we're doing it -- with two `assume`s sometimes -- can at times lead to CVP/SCCP not realize what's happening because one of them turns into a `ne` instead of conveying a range. So this updates how it's emitted from ``` assume( x >= LOW ); assume( x <= HIGH ); ``` or ``` // (for ranges that wrap the range) assume( (x <= LOW) | (x >= HIGH) ); ``` to ``` assume( (x - LOW) <= (HIGH - LOW) ); ``` so that we don't need multiple `icmp`s nor multiple `assume`s for a single value, and both wrappping and non-wrapping ranges emit the same shape. (And we don't bother emitting the subtraction if `LOW` is zero, since that's trivial for us to check too.)
Now that
range
parameter metadata exists (🎉) I'm trying to remove some of ourassume
s thatrustc
outputs which should no longer be necessary (rust-lang/rust#135610).That works for almost all of our tests in https://github.com/rust-lang/rust/blob/master/tests/codegen/transmute-optimized.rs , but one.
We end up, after optimizations, still getting
That input range is
[-1, 2)
and those assumes are a range[1, 4)
, so it ought to simplify to justret i8 1
, but it doesn't.Alive2 proof that it would be legal: https://alive2.llvm.org/ce/z/GucQsJ -- and legal even without the
range
on the return value.Maybe this is somehow related to the
x uge 1
being turned intox ne 0
, and thus it not noticing there's a range? Or maybe it's something about the wrap-around?SEO: rust transmute range bounds
As an aside, I'd love to emit these as
range
assume operand bundles instead oficmp
s, but AFAICT those don't exist yet, so I'm stuck with theicmp
s for now 🙁The text was updated successfully, but these errors were encountered: