Skip to content

Missed optimization: The optimizer forgets that Some(function) is Some(_) #74425

Closed
@yvt

Description

@yvt
#![no_std]

extern "C" {
    fn ext_fn0();
}

pub fn test() {
    test_inner(Some(inner0));
}

#[inline(always)]
fn test_inner(f_maybe: Option<fn()>) {
    if let Some(f) = f_maybe {
        f();
    }
}

#[inline(always)]
fn inner0() {
    unsafe { ext_fn0() };
}

I expected to see this happen: The branch in test_inner is optimized out and the test function compiles down to a single call to ext_fn0.

; expected
example::test:
        b       ext_fn0

Instead, this happened: The compiled test function includes a branch that checks if Some(inner0) is Some(_) or not.

; -Copt-level=3 -Cpanic=abort --target=thumbv7em-none-eabihf -Clto=on
example::test:
        movw    r0, :lower16:example::inner0
        movt    r0, :upper16:example::inner0
        cmp     r0, #0
        it      ne
        bne     ext_fn0
        bx      lr

example::inner0:
        b       ext_fn0

Compiler Explorer (Nightly, 1.45.0)

Meta

rustc --version --verbose:

rustc 1.46.0-nightly (23744c84d 2020-07-14)
binary: rustc
commit-hash: 23744c84d9c0f8e4e870edb983f1ad6d33449c34
commit-date: 2020-07-14
host: x86_64-unknown-linux-gnu
release: 1.46.0-nightly
LLVM version: 10.0

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.I-slowIssue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions