This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/71793] New: Volatile local variable passed by value is (wrongly?) optimised away, but the containing loop is not


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71793

            Bug ID: 71793
           Summary: Volatile local variable passed by value is (wrongly?)
                    optimised away, but the containing loop is not
           Product: gcc
           Version: 5.4.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: db0451 at gmail dot com
  Target Milestone: ---

Here's the original SO thread with more info and/or meandering pondering:
http://stackoverflow.com/questions/38235112/why-is-a-volatile-local-variable-optimised-differently-from-a-volatile-argument

g++ seems to break in a simple situation involving a function argument passed
by value and declared volatile, wherein it acts differently than if such
variable is declared in-body. In the former case, it elides volatile reads.

    #include <cstddef>

    void f(void *const p, std::size_t n)
    {
        unsigned char *y = static_cast<unsigned char *>(p);
        volatile unsigned char const x = 42;

        while (n--) {
            *y++ = x;
        }
    }

    void g(void *const p, std::size_t n, volatile unsigned char const x)
    {
        unsigned char *y = static_cast<unsigned char *>(p);

        while (n--) {
            *y++ = x;
        }
    }

    void h(void *const p, std::size_t n, volatile unsigned char const &x)
    {
        unsigned char *y = static_cast<unsigned char *>(p);

        while (n--) {
            *y++ = x;
        }
    }

    int main(int, char **)
    {
        int y[1000];
        f(&y, sizeof y);
        volatile unsigned char const x{99};
        g(&y, sizeof y, x);
        h(&y, sizeof y, x);
    }

=> ASM

    main:
    .LFB3:
        .cfi_startproc

    # f()
        movb    $42, -1(%rsp)
        movl    $4000, %eax
        .p2align 4,,10
        .p2align 3
    .L21:
        subq    $1, %rax
        movzbl  -1(%rsp), %edx
        jne .L21

    # x = 99
        movb    $99, -2(%rsp)
        movzbl  -2(%rsp), %eax

    # g()
        movl    $4000, %eax
        .p2align 4,,10
        .p2align 3
    .L22:
        subq    $1, %rax
        jne .L22

    # h()
        movl    $4000, %eax
        .p2align 4,,10
        .p2align 3
    .L23:
        subq    $1, %rax
        movzbl  -2(%rsp), %edx
        jne .L23

Is g() non-conforming here because it elides reads to a volatile variable? That
might represent a hardware register whose polling has side-effects, etc.

And either way, how is it that the loop body can be totally elided, rightly or
not - but the loop itself still executes? (It's like I'm back programming waits
on a CPC 464! ;-)

thanks

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]