Skip to content

Result<u32, u32> uses less efficient ABI than Result<i32, u32> #100698

Open
@Kobzol

Description

@Kobzol

I noticed this while writing a codegen test for #37939 (comment).
It seems that Result<u32, u32> and Result<i32, i32> are passed as two 32-bit numbers, while Result<i32, u32> and Result<u32, i32> are passed as a single 64-bit number.

Compiler: rustc 1.65.0-nightly (86c6ebee8 2022-08-16)

Code
pub fn result_nop_match_i32(x: Result<i32, i32>) -> Result<i32, i32> {
    match x {
        Ok(x) => Ok(x),
        Err(x) => Err(x),
    }
}
pub fn result_nop_match_u32(x: Result<u32, u32>) -> Result<u32, u32> {
    match x {
        Ok(x) => Ok(x),
        Err(x) => Err(x),
    }
}
pub fn result_nop_match_i32_u32(x: Result<i32, u32>) -> Result<i32, u32> {
    match x {
        Ok(x) => Ok(x),
        Err(x) => Err(x),
    }
}
pub fn result_nop_match_u32_i32(x: Result<u32, i32>) -> Result<u32, i32> {
    match x {
        Ok(x) => Ok(x),
        Err(x) => Err(x),
    }
}
LLVM IR
define { i32, i32 } @_ZN7example20result_nop_match_i3217h90973337e0ea1f0bE(i32 noundef %0, i32 %1) unnamed_addr #0 !dbg !6 {
  %2 = insertvalue { i32, i32 } undef, i32 %0, 0, !dbg !11
  %3 = insertvalue { i32, i32 } %2, i32 %1, 1, !dbg !11
  ret { i32, i32 } %3, !dbg !11
}

define { i32, i32 } @_ZN7example20result_nop_match_u3217ha367bf54ac4241a2E(i32 noundef %0, i32 %1) unnamed_addr #0 !dbg !12 {
  %2 = insertvalue { i32, i32 } undef, i32 %0, 0, !dbg !13
  %3 = insertvalue { i32, i32 } %2, i32 %1, 1, !dbg !13
  ret { i32, i32 } %3, !dbg !13
}

define i64 @_ZN7example24result_nop_match_i32_u3217h0912c9953cfa7e17E(i64 returned %0) unnamed_addr #0 !dbg !14 {
  ret i64 %0, !dbg !15
}

define i64 @_ZN7example24result_nop_match_u32_i3217h8fc452067b26b8ddE(i64 returned %0) unnamed_addr #0 !dbg !16 {
  ret i64 %0, !dbg !17
}

https://rust.godbolt.org/z/n91oWdjMh

I'm not sure if there's something stopping Result<u32, u32> from being coerced to a single 64-bit number (maybe some heuristic for auto-vectorization?), but this seemed a bit odd to me. It's also a bit surprising to me that Result<u32, u32> is represented as define { i32, i32 }, but I don't really know a lot about the Rust ABI.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-layoutArea: Memory layout of typesC-enhancementCategory: An issue proposing an enhancement or a PR with one.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