Skip to content
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

The panic branch of Some(x).unwrap() is not removed for some types #93011

Closed
saethlin opened this issue Jan 17, 2022 · 3 comments
Closed

The panic branch of Some(x).unwrap() is not removed for some types #93011

saethlin opened this issue Jan 17, 2022 · 3 comments
Labels
A-codegen Area: Code generation A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. I-heavy Issue: Problems and improvements with respect to binary size of generated code. I-slow Issue: Problems and improvements with respect to performance of generated code.

Comments

@saethlin
Copy link
Member

Demos: https://godbolt.org/z/TMh3Krfc5

The motivating example is:

pub fn bad_vec(s: Vec<u8>) -> Vec<u8> {
    Some(s).expect("bad_vec")
}
example::bad_myvec:
        push    rax
        mov     rax, qword ptr [rsi]
        test    rax, rax
        je      .LBB5_1
        mov     qword ptr [rdi], rax
        movups  xmm0, xmmword ptr [rsi + 8]
        movups  xmmword ptr [rdi + 8], xmm0
        mov     rax, rdi
        pop     rcx
        ret
.LBB5_1:
        lea     rdi, [rip + .L__unnamed_5]
        lea     rdx, [rip + .L__unnamed_6]
        mov     esi, 9
        call    qword ptr [rip + core::option::expect_failed@GOTPCREL]
        ud2

It looks to me like the problem with Vec is that specifically the nonnull attribute does not survive being wrapped in two structs that each contain a second member. If either of RawVec or Vec is missing a usize member, the optimization works.

There is a missed NonZero* optimization in here that I found looking for types that fail to optimize. It's unclear to me if this was reported previously in #49572, or if whatever fixes the problem with Vec will also fix the NonZero* example.


I think this is similar but not the same problem as seen in #71257

@scottmcm
Copy link
Member

You might be interested in #85646 (which came from #85133), which tried to make some progress here and found some LLVM issues with matching on 2-variant enums (like the Option here).

nox was working on some codegen improvements that might help at some point: https://rust-lang.zulipchat.com/#narrow/stream/189540-t-compiler.2Fwg-mir-opt/topic/Discriminant.20computation.20yields.20bad.20output/near/264996641

@Dylan-DPC Dylan-DPC added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-bug Category: This is a bug. and removed T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 20, 2023
@workingjubilee workingjubilee changed the title The panic branch in the expression Some(x).unwrap() is not removed for some types The panic branch of Some(x).unwrap() is not removed for some types May 6, 2023
@workingjubilee workingjubilee added I-slow Issue: Problems and improvements with respect to performance of generated code. A-codegen Area: Code generation I-heavy Issue: Problems and improvements with respect to binary size of generated code. A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. labels May 6, 2023
@saethlin
Copy link
Member Author

saethlin commented May 19, 2023

🤔 this is fixed by DataflowConstProp: https://godbolt.org/z/zEKcobr6q

@cjgillot
Copy link
Contributor

The motivating example is handled by #109597
Test:

rust/tests/mir-opt/gvn.rs

Lines 148 to 157 in 5a345b3

fn wrap_unwrap<T: Copy>(x: T) -> T {
// CHECK-LABEL: fn wrap_unwrap(
// CHECK: [[some:_.*]] = Option::<T>::Some(_1);
// CHECK: switchInt(const 1_isize)
// CHECK: _0 = _1;
match Some(x) {
Some(y) => y,
None => panic!(),
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-codegen Area: Code generation A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. I-heavy Issue: Problems and improvements with respect to binary size of generated code. I-slow Issue: Problems and improvements with respect to performance of generated code.
Projects
None yet
Development

No branches or pull requests

5 participants