Skip to content

panic branch does not get removed in presence of other function (that also does not get it removed) #119923

@antonilol

Description

@antonilol

I tried this code (compiler explorer):

#[derive(Clone, Copy)]
pub enum Enum {
    None,
    Variant1,
    Variant2,
}

impl Enum {
    #[no_mangle]
    pub fn as_str_1(self) -> &'static str {
        // switch table for reference
        match self {
            Self::None => "",
            Self::Variant1 => "1",
            Self::Variant2 => "2",
        }
    }

    #[no_mangle]
    pub fn as_str_2(self) -> &'static str {
        let len = (self as usize + 1) / 2;
        let offs = self as usize / 2;
        &"12"[offs..len + offs]
    }

    #[no_mangle]
    pub fn as_str_3(self) -> &'static str {
        let len = (self as usize + 1) / 2;
        let offs = self as usize;
        &" 12"[offs..len + offs]
    }
}

and this code (compiler explorer):

#[derive(Clone, Copy)]
pub enum Enum {
    None,
    Variant1,
    Variant2,
}

impl Enum {
    #[no_mangle]
    pub fn as_str_1(self) -> &'static str {
        // switch table for reference
        match self {
            Self::None => "",
            Self::Variant1 => "1",
            Self::Variant2 => "2",
        }
    }

    #[no_mangle]
    pub fn as_str_2(self) -> &'static str {
        let len = (self as usize + 1) / 2;
        let offs = self as usize / 2;
        &"12"[offs..len + offs]
    }
}

(difference between the two is that as_str_3 only exists in the first example)

I expected to see this happen:
all as_str_ functions compile to roughly the same code (no memory accesses, just some pointer addition and getting the length right)

something like this (compiler explorer):

as_str_4:
        movzx   edx, dil
        lea     rax, [rip + .L__unnamed_3]
        add     rax, rdx
        inc     edx
        shr     edx
        ret

.L__unnamed_3:
        .ascii  " 12"

Instead, this happened:
as_str_1 became a switch table, so i pointed the compiler in the right direction with as_str_2, i tried a few other things, as_str_3 with an integer division less but a byte longer string and as_str_4 with unsafe code to get the desired output.
as_str_2's panic branch only got removed when i commented as_str_3 out, as_str_3 always had one

Meta

rustc --version --verbose:

rustc 1.77.0-nightly (62d7ed4a6 2024-01-11)
binary: rustc
commit-hash: 62d7ed4a6775c4490e493093ca98ef7c215b835b
commit-date: 2024-01-11
host: x86_64-unknown-linux-gnu
release: 1.77.0-nightly
LLVM version: 17.0.6

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.C-bugCategory: This is a bug.I-heavyIssue: Problems and improvements with respect to binary size of generated code.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