Skip to content
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

Check if compiler optimizes fields by value #555

Closed
bvssvni opened this issue Jul 1, 2014 · 3 comments
Closed

Check if compiler optimizes fields by value #555

bvssvni opened this issue Jul 1, 2014 · 3 comments

Comments

@bvssvni
Copy link
Member

bvssvni commented Jul 1, 2014

Investigate whether context types can set their fields by value and still get the same compiler optimization. This might solve the problems with current Rust.

Use http://play.rust-lang.org/

@bvssvni
Copy link
Member Author

bvssvni commented Jul 1, 2014

Here is the code based on the current assumption:

pub fn field(a: uint, b: uint) -> (uint, uint) {
    enum Field<'a, T> {
        Value(T),
        Borrowed(&'a T),
    }

    impl<'a, T> Field<'a, T> {
        /// Gets a read only value.
        #[inline(always)]
        fn get(&'a self) -> &'a T {
            match *self {
                Value(ref val) => val,
                Borrowed(rval) => rval,
            }
        }
    }

    struct Foo<'a> {
        foo: Field<'a, uint>,
    }

    impl<'a> Foo<'a> {
        #[inline(always)]
        fn bar(&'a self, val: uint) -> BarFoo<'a> {
            BarFoo {
                foo: Borrowed(self.foo.get()),
                bar: Value(val),
            }
        }
    }

    struct BarFoo<'a> {
        foo: Field<'a, uint>,
        bar: Field<'a, uint>,
    }

    let foo = Foo { foo: Value(a) };
    let bar = foo.bar(b);
    (*bar.foo.get(), *bar.bar.get())
}

fn main() {
    let (x, y) = field(2, 4);
    println!("{}, {}", x, y)
}

This emits the assembly with -O2:

.text
    .file   "-.rs"
    .section    .text._ZN4main20h5ac5e5cb32d0c663nca4v0.0E,"ax",@progbits
    .align  16, 0x90
    .type   _ZN4main20h5ac5e5cb32d0c663nca4v0.0E,@function
_ZN4main20h5ac5e5cb32d0c663nca4v0.0E:
    .cfi_startproc
    cmpq    %fs:112, %rsp
    ja  .LBB0_2
    movabsq $88, %r10
    movabsq $0, %r11
    callq   __morestack
    retq
.LBB0_2:
    subq    $88, %rsp
.Ltmp0:
    .cfi_def_cfa_offset 96
    movq    $2, 80(%rsp)
    movq    $4, 72(%rsp)
    leaq    _ZN3fmt11secret_show20h23973399929398009214v0.0E(%rip), %rax
    movq    %rax, 40(%rsp)
    leaq    80(%rsp), %rcx
    movq    %rcx, 48(%rsp)
    movq    %rax, 56(%rsp)
    leaq    72(%rsp), %rax
    movq    %rax, 64(%rsp)
    leaq    _ZN4main15__STATIC_FMTSTR20h0d54fec8ba6e9728Mca4v0.0E(%rip), %rax
    movq    %rax, 8(%rsp)
    movq    $3, 16(%rsp)
    leaq    40(%rsp), %rax
    movq    %rax, 24(%rsp)
    movq    $2, 32(%rsp)
    leaq    8(%rsp), %rdi
    callq   _ZN2io5stdio12println_args20h216979612568a473ggl11v0.11.0.preE@PLT
    addq    $88, %rsp
    retq
.Ltmp1:
    .size   _ZN4main20h5ac5e5cb32d0c663nca4v0.0E, .Ltmp1-_ZN4main20h5ac5e5cb32d0c663nca4v0.0E
    .cfi_endproc

    .section    .text.main,"ax",@progbits
    .globl  main
    .align  16, 0x90
    .type   main,@function
main:
    .cfi_startproc
    movq    %rsi, %rax
    movq    %rdi, %rcx
    leaq    _ZN4main20h5ac5e5cb32d0c663nca4v0.0E(%rip), %rdi
    movq    %rcx, %rsi
    movq    %rax, %rdx
    jmp _ZN10lang_start20h7779600900fd5515Rje11v0.11.0.preE@PLT
.Ltmp2:
    .size   main, .Ltmp2-main
    .cfi_endproc

    .section    .text._ZN3fmt11secret_show20h23973399929398009214v0.0E,"ax",@progbits
    .align  16, 0x90
    .type   _ZN3fmt11secret_show20h23973399929398009214v0.0E,@function
_ZN3fmt11secret_show20h23973399929398009214v0.0E:
    .cfi_startproc
    jmp _ZN3fmt3num14uint.fmt..Show3fmt20h0858b562b1543b44bOI11v0.11.0.preE@PLT
.Ltmp3:
    .size   _ZN3fmt11secret_show20h23973399929398009214v0.0E, .Ltmp3-_ZN3fmt11secret_show20h23973399929398009214v0.0E
    .cfi_endproc

    .type   str1337,@object
    .section    .rodata.str1337,"a",@progbits
str1337:
    .ascii  ", "
    .size   str1337, 2

    .type   _ZN4main15__STATIC_FMTSTR20h0d54fec8ba6e9728Mca4v0.0E,@object
    .section    .data.rel.ro.local._ZN4main15__STATIC_FMTSTR20h0d54fec8ba6e9728Mca4v0.0E,"aw",@progbits
    .align  16
_ZN4main15__STATIC_FMTSTR20h0d54fec8ba6e9728Mca4v0.0E:
    .byte   1
    .zero   7
    .byte   0
    .zero   15
    .long   32
    .byte   2
    .zero   3
    .quad   0
    .byte   3
    .zero   15
    .byte   3
    .zero   15
    .byte   0
    .zero   7
    .quad   str1337
    .quad   2
    .zero   48
    .byte   1
    .zero   7
    .byte   0
    .zero   15
    .long   32
    .byte   2
    .zero   3
    .quad   0
    .byte   3
    .zero   15
    .byte   3
    .zero   15
    .size   _ZN4main15__STATIC_FMTSTR20h0d54fec8ba6e9728Mca4v0.0E, 216


    .section    ".note.GNU-stack","",@progbits

@bvssvni
Copy link
Member Author

bvssvni commented Jul 1, 2014

Here is the code based on value:

pub fn field(a: uint, b: uint) -> (uint, uint) {
    enum Field<T> {
        Value(T),
    }

    impl<T: Copy> Field<T> {
        /// Gets a copy of the value.
        #[inline(always)]
        fn get(&self) -> T {
            match *self {
                Value(val) => val,
            }
        }
    }

    struct Foo {
        foo: Field<uint>,
    }

    impl Foo {
        #[inline(always)]
        fn bar(&self, val: uint) -> BarFoo {
            BarFoo {
                foo: Value(self.foo.get()),
                bar: Value(val),
            }
        }
    }

    struct BarFoo {
        foo: Field<uint>,
        bar: Field<uint>,
    }

    let foo = Foo { foo: Value(a) };
    let bar = foo.bar(b);
    (bar.foo.get(), bar.bar.get())
}

fn main() {
    let (x, y) = field(2, 4);
    println!("{}, {}", x, y)
}

This emits the assembly with -O2:

.text
    .file   "-.rs"
    .section    .text._ZN4main20h282b95531535ea8bYba4v0.0E,"ax",@progbits
    .align  16, 0x90
    .type   _ZN4main20h282b95531535ea8bYba4v0.0E,@function
_ZN4main20h282b95531535ea8bYba4v0.0E:
    .cfi_startproc
    cmpq    %fs:112, %rsp
    ja  .LBB0_2
    movabsq $88, %r10
    movabsq $0, %r11
    callq   __morestack
    retq
.LBB0_2:
    subq    $88, %rsp
.Ltmp0:
    .cfi_def_cfa_offset 96
    movq    $2, 80(%rsp)
    movq    $4, 72(%rsp)
    leaq    _ZN3fmt11secret_show21h114544777529901186294v0.0E(%rip), %rax
    movq    %rax, 40(%rsp)
    leaq    80(%rsp), %rcx
    movq    %rcx, 48(%rsp)
    movq    %rax, 56(%rsp)
    leaq    72(%rsp), %rax
    movq    %rax, 64(%rsp)
    leaq    _ZN4main15__STATIC_FMTSTR20h90e030ad4229642enca4v0.0E(%rip), %rax
    movq    %rax, 8(%rsp)
    movq    $3, 16(%rsp)
    leaq    40(%rsp), %rax
    movq    %rax, 24(%rsp)
    movq    $2, 32(%rsp)
    leaq    8(%rsp), %rdi
    callq   _ZN2io5stdio12println_args20h216979612568a473ggl11v0.11.0.preE@PLT
    addq    $88, %rsp
    retq
.Ltmp1:
    .size   _ZN4main20h282b95531535ea8bYba4v0.0E, .Ltmp1-_ZN4main20h282b95531535ea8bYba4v0.0E
    .cfi_endproc

    .section    .text.main,"ax",@progbits
    .globl  main
    .align  16, 0x90
    .type   main,@function
main:
    .cfi_startproc
    movq    %rsi, %rax
    movq    %rdi, %rcx
    leaq    _ZN4main20h282b95531535ea8bYba4v0.0E(%rip), %rdi
    movq    %rcx, %rsi
    movq    %rax, %rdx
    jmp _ZN10lang_start20h7779600900fd5515Rje11v0.11.0.preE@PLT
.Ltmp2:
    .size   main, .Ltmp2-main
    .cfi_endproc

    .section    .text._ZN3fmt11secret_show21h114544777529901186294v0.0E,"ax",@progbits
    .align  16, 0x90
    .type   _ZN3fmt11secret_show21h114544777529901186294v0.0E,@function
_ZN3fmt11secret_show21h114544777529901186294v0.0E:
    .cfi_startproc
    jmp _ZN3fmt3num14uint.fmt..Show3fmt20h0858b562b1543b44bOI11v0.11.0.preE@PLT
.Ltmp3:
    .size   _ZN3fmt11secret_show21h114544777529901186294v0.0E, .Ltmp3-_ZN3fmt11secret_show21h114544777529901186294v0.0E
    .cfi_endproc

    .type   str1334,@object
    .section    .rodata.str1334,"a",@progbits
str1334:
    .ascii  ", "
    .size   str1334, 2

    .type   _ZN4main15__STATIC_FMTSTR20h90e030ad4229642enca4v0.0E,@object
    .section    .data.rel.ro.local._ZN4main15__STATIC_FMTSTR20h90e030ad4229642enca4v0.0E,"aw",@progbits
    .align  16
_ZN4main15__STATIC_FMTSTR20h90e030ad4229642enca4v0.0E:
    .byte   1
    .zero   7
    .byte   0
    .zero   15
    .long   32
    .byte   2
    .zero   3
    .quad   0
    .byte   3
    .zero   15
    .byte   3
    .zero   15
    .byte   0
    .zero   7
    .quad   str1334
    .quad   2
    .zero   48
    .byte   1
    .zero   7
    .byte   0
    .zero   15
    .long   32
    .byte   2
    .zero   3
    .quad   0
    .byte   3
    .zero   15
    .byte   3
    .zero   15
    .size   _ZN4main15__STATIC_FMTSTR20h90e030ad4229642enca4v0.0E, 216


    .section    ".note.GNU-stack","",@progbits

@bvssvni
Copy link
Member Author

bvssvni commented Jul 1, 2014

The emitted assembly is almost identical.

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

No branches or pull requests

1 participant