Skip to content

Support move-val-init intrinsic #1902

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
2 tasks done
Tracked by #1895
philberty opened this issue Feb 21, 2023 · 0 comments · Fixed by #1999
Closed
2 tasks done
Tracked by #1895

Support move-val-init intrinsic #1902

philberty opened this issue Feb 21, 2023 · 0 comments · Fixed by #1999

Comments

@philberty
Copy link
Member

philberty commented Feb 21, 2023

I tried this code:

mod intrinsics {
    extern "rust-intrinsic" {
        pub fn offset<T>(ptr: *const T, count: isize) -> *const T;
        pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
        pub fn move_val_init<T>(dst: *mut T, src: T);
        pub fn uninit<T>() -> T;
    }
}

mod ptr {
    #[lang = "const_ptr"]
    impl<T> *const T {
        pub unsafe fn offset(self, count: isize) -> *const T {
            intrinsics::offset(self, count)
        }
    }

    #[lang = "mut_ptr"]
    impl<T> *mut T {
        pub unsafe fn offset(self, count: isize) -> *mut T {
            intrinsics::offset(self, count) as *mut T
        }
    }

    pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
        let x = x as *mut T;
        let y = y as *mut T;
        let len = mem::size_of::<T>() * count;
        swap_nonoverlapping_bytes(x, y, len)
    }

    pub(crate) unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
        // For types smaller than the block optimization below,
        // just swap directly to avoid pessimizing codegen.
        if mem::size_of::<T>() < 32 {
            let z = read(x);
            intrinsics::copy_nonoverlapping(y, x, 1);
            write(y, z);
        } else {
            swap_nonoverlapping(x, y, 1);
        }
    }

    pub unsafe fn write<T>(dst: *mut T, src: T) {
        intrinsics::move_val_init(&mut *dst, src)
    }

    pub unsafe fn read<T>(src: *const T) -> T {
        let mut tmp: T = mem::uninitialized();
        intrinsics::copy_nonoverlapping(src, &mut tmp, 1);
        tmp
    }

    unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
        struct Block(u64, u64, u64, u64);
        struct UnalignedBlock(u64, u64, u64, u64);

        let block_size = mem::size_of::<Block>();

        // Loop through x & y, copying them `Block` at a time
        // The optimizer should unroll the loop fully for most types
        // N.B. We can't use a for loop as the `range` impl calls `mem::swap` recursively
        let mut i = 0;
        while i + block_size <= len {
            // Create some uninitialized memory as scratch space
            // Declaring `t` here avoids aligning the stack when this loop is unused
            let mut t: Block = mem::uninitialized();
            let t = &mut t as *mut _ as *mut u8;
            let x = x.offset(i as isize);
            let y = y.offset(i as isize);

            // Swap a block of bytes of x & y, using t as a temporary buffer
            // This should be optimized into efficient SIMD operations where available
            intrinsics::copy_nonoverlapping(x, t, block_size);
            intrinsics::copy_nonoverlapping(y, x, block_size);
            intrinsics::copy_nonoverlapping(t, y, block_size);
            i += block_size;
        }

        if i < len {
            // Swap any remaining bytes
            let mut t: UnalignedBlock = mem::uninitialized();
            let rem = len - i;

            let t = &mut t as *mut _ as *mut u8;
            let x = x.offset(i as isize);
            let y = y.offset(i as isize);

            intrinsics::copy_nonoverlapping(x, t, rem);
            intrinsics::copy_nonoverlapping(y, x, rem);
            intrinsics::copy_nonoverlapping(t, y, rem);
        }
    }
}

mod mem {
    extern "rust-intrinsic" {
        pub fn transmute<T, U>(_: T) -> U;
        pub fn size_of<T>() -> usize;
    }

    pub fn swap<T>(x: &mut T, y: &mut T) {
        unsafe {
            ptr::swap_nonoverlapping_one(x, y);
        }
    }

    pub fn replace<T>(dest: &mut T, mut src: T) -> T {
        swap(dest, &mut src);
        src
    }

    pub unsafe fn uninitialized<T>() -> T {
        intrinsics::uninit()
    }
}

trait Step {
    fn replace_zero(&mut self) -> Self;
}

impl Step for i32 {
    fn replace_zero(&mut self) -> Self {
        mem::replace(self, 0)
    }
}

fn main() -> i32 {
    let a = 123;
    a.replace_zero();
    a
}

I expected to see this happen: compile without error

Instead, this happened:

There are a few issues here to fix first before we can implement this intrinsic: see

Meta

  • What version of Rust GCC were you using, git sha if possible.
@philberty philberty added the bug label Feb 21, 2023
@philberty philberty added this to the Final upstream patches milestone Feb 21, 2023
@github-project-automation github-project-automation bot moved this to Additional sprint items in libcore 1.49 Feb 21, 2023
@philberty philberty mentioned this issue Feb 21, 2023
41 tasks
philberty added a commit that referenced this issue Mar 17, 2023
TODO

Fixes #1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler):
	(uninit_handler):

Signed-off-by: Philip Herron <[email protected]>
philberty added a commit that referenced this issue Mar 17, 2023
TODO

Fixes #1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler):
	(uninit_handler):

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
philberty added a commit that referenced this issue Mar 17, 2023
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes #1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
@philberty philberty linked a pull request Mar 17, 2023 that will close this issue
philberty added a commit that referenced this issue Mar 18, 2023
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes #1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
@github-project-automation github-project-automation bot moved this from Additional sprint items to Done in libcore 1.49 Mar 18, 2023
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Mar 27, 2023
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Apr 6, 2023
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Apr 7, 2023
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Nov 15, 2023
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Nov 21, 2023
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Nov 21, 2023
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Jan 5, 2024
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Jan 8, 2024
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Jan 9, 2024
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Jan 9, 2024
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Jan 9, 2024
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Jan 9, 2024
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Jan 9, 2024
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Jan 11, 2024
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Jan 12, 2024
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Jan 16, 2024
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Jan 16, 2024
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
CohenArthur pushed a commit to CohenArthur/gccrs that referenced this issue Jan 17, 2024
This implements it as a builtin memcpy using the generic param T for the
size hint.

Fixes Rust-GCC#1902

gcc/rust/ChangeLog:

	* backend/rust-compile-intrinsic.cc (move_val_init_handler): new intrinsice
	(uninit_handler): use a builtin memcpy

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1981.rs: New test.

Signed-off-by: Philip Herron <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

1 participant