Skip to content

Instantly share code, notes, and snippets.

@shqld
Created September 4, 2023 03:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shqld/2b81fb4dd87ebf9c6c11f42451599913 to your computer and use it in GitHub Desktop.
Save shqld/2b81fb4dd87ebf9c6c11f42451599913 to your computer and use it in GitHub Desktop.
Rust generic function monomorphization optimization
#![allow(dead_code, unused_variables, clippy::from_over_into)]
struct Inner {
raw: *mut [u8; 0],
}
struct Object {
inner: Inner,
}
impl AsRef<Inner> for Object {
#[inline(never)]
fn as_ref(&self) -> &Inner {
&self.inner
}
}
struct SameObject {
inner: Inner,
}
impl AsRef<Inner> for SameObject {
#[inline(never)]
fn as_ref(&self) -> &Inner {
&self.inner
}
}
struct SameObjectWithPadding {
inner: Inner,
_padding: u8,
}
impl AsRef<Inner> for SameObjectWithPadding {
#[inline(never)]
fn as_ref(&self) -> &Inner {
&self.inner
}
}
struct SameObjectWithAnotherImpl {
c: Inner,
}
impl AsRef<Inner> for SameObjectWithAnotherImpl {
#[inline(never)]
fn as_ref(&self) -> &Inner {
println!("c");
&self.c
}
}
#[inline(never)]
fn take_any_struct(any_struct: impl AsRef<Inner>) {
let inner = any_struct.as_ref();
std::hint::black_box(inner);
}
fn main() {
let object = Object {
inner: Inner {
raw: std::ptr::null_mut(),
},
};
let same_object = SameObject {
inner: Inner {
raw: std::ptr::null_mut(),
},
};
let same_object_with_padding = SameObjectWithPadding {
inner: Inner {
raw: std::ptr::null_mut(),
},
_padding: 42,
};
let same_object_with_another_impl = SameObjectWithAnotherImpl {
c: Inner {
raw: std::ptr::null_mut(),
},
};
take_any_struct(&object);
take_any_struct(object);
take_any_struct(&same_object);
take_any_struct(same_object);
take_any_struct(&same_object_with_padding);
take_any_struct(same_object_with_padding);
take_any_struct(&same_object_with_another_impl);
take_any_struct(same_object_with_another_impl);
}
@shqld
Copy link
Author

shqld commented Sep 4, 2023

$ rustc --version
rustc 1.69.0-nightly (07c993eba 2023-02-23)

$ rustc main.ll --emit=llvm-ir -C opt-level=s
; call main::take_any_struct
  call fastcc void @_ZN4main15take_any_struct17h0855572da314e5b8(ptr noalias noundef nonnull readonly align 8 dereferenceable(8) %object)
  %1 = load ptr, ptr %object, align 8, !noundef !3
; call main::take_any_struct
  call fastcc void @_ZN4main15take_any_struct17heaa95f842be98e30E(ptr noundef %1)
; call main::take_any_struct
  call fastcc void @_ZN4main15take_any_struct17h0855572da314e5b8(ptr noalias noundef nonnull readonly align 8 dereferenceable(8) %same_object)
  %2 = load ptr, ptr %same_object, align 8, !noundef !3
; call main::take_any_struct
  call fastcc void @_ZN4main15take_any_struct17heaa95f842be98e30E(ptr noundef %2)
; call main::take_any_struct
  call fastcc void @_ZN4main15take_any_struct17h95134dd63a3f8201E(ptr noalias noundef nonnull readonly align 8 dereferenceable(16) %same_object_with_padding)
  %3 = load ptr, ptr %same_object_with_padding, align 8, !noundef !3
  %4 = load i8, ptr %0, align 8, !noundef !3
; call main::take_any_struct
  call fastcc void @_ZN4main15take_any_struct17h62ed7918170547caE(ptr noundef %3, i8 noundef %4)
; call main::take_any_struct
  call fastcc void @_ZN4main15take_any_struct17h15138211037d7e07E(ptr noalias noundef nonnull readonly align 8 dereferenceable(8) %same_object_with_another_impl)
  %5 = load ptr, ptr %same_object_with_another_impl, align 8, !noundef !3
; call main::take_any_struct
  call fastcc void @_ZN4main15take_any_struct17h4f18d7d3a390031dE(ptr noundef %5)

Unified

  • take_any_struct(&object) & take_any_struct(&same_object)
  • take_any_struct(object) & take_any_struct(same_object)

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