Skip to content

Array bounds check not elided when indexing with ZST enum #82871

Closed
@moxian

Description

@moxian
Contributor

I tried this code:

#[repr(C)]
pub enum E {
    A, 
}

pub fn index(x: &[u32; 3], ind: E) -> u32{
    x[ind as usize]
}

I expected to see this happen: no bounds check

Instead, this happened (with -C opt-level=3)

example::index:
        push    rax
        mov     rax, rdi
        mov     edi, esi
        cmp     esi, 2
        ja      .LBB0_2
        mov     eax, dword ptr [rax + 4*rdi]
        pop     rcx
        ret
.LBB0_2:
        lea     rdx, [rip + .L__unnamed_1]
        mov     esi, 3
        call    qword ptr [rip + core::panicking::panic_bounds_check@GOTPCREL]
        ud2

However adding more variants to the enum makes the bound check go away:

#[repr(C)]
pub enum E {
    A,
    B,
}

pub fn index(x: &[u32; 3], ind: E) -> u32{
    x[ind as usize]
}

generates:

example::index:
        mov     eax, esi
        mov     eax, dword ptr [rdi + 4*rax]
        ret

Here's a godbolt link to play around further: https://rust.godbolt.org/z/dK9e1z
The MIR of the two cases is identical, but the llvm IR in ZST case is lacking @llvm.assume, which I assume (heh!) leads to the bounds check being preserved. (However i don't actually understand LLVM, I'm just reading the diff...)

Meta

rustc 1.50.0

This sounds very closely related to #13926, but I'm not actually sure if it is. Please reroute as appropriate.

Activity

elomatreb

elomatreb commented on Mar 7, 2021

@elomatreb
Contributor

Removing any #[repr(...)] attributes from the enum also leads to the optimization occurring as expected (https://rust.godbolt.org/z/fPn613).

nikic

nikic commented on Mar 8, 2021

@nikic
Contributor

We don't emit the enum range assumption if the range only contains one element:

&& scalar.valid_range.end() > scalar.valid_range.start()

added
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.
on Mar 8, 2021
added
E-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.
on Mar 9, 2021
0xPoe

0xPoe commented on Mar 10, 2021

@0xPoe
Member

@rustbot claim

added a commit that references this issue on Mar 12, 2021

Rollup merge of rust-lang#83020 - hi-rustin:rustin-patch-enum, r=lcnr

c0033e5
added a commit that references this issue on Mar 13, 2021

Rollup merge of rust-lang#83020 - hi-rustin:rustin-patch-enum, r=lcnr

04e24ae
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

C-bugCategory: This is a bug.E-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.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

    Participants

    @nikic@estebank@elomatreb@moxian@0xPoe

    Issue actions

      Array bounds check not elided when indexing with ZST enum · Issue #82871 · rust-lang/rust