GCC over-optimizing issue with Pair::init_style()

Hi,

I just noticed a problem when compiling my own pair style with nvcc 5.5 and gcc 4.7.2.

The code was
void MyPair::init_style()
{
NeighRequest* req = neighbor->requests[neighbor->request(this)];
req->cudable = 1;
}

and gdb reports:
Program received signal SIGSEGV, Segmentation fault.
LAMMPS_NS::MyPair::init_style (this=) at pair_my.cu:546
546 req->cudable = 1;
(gdb) p req
Cannot access memory at address 0x0
(gdb) p &req
$1 = (LAMMPS_NS::NeighRequest **) 0x0

Apparently the variable req was optimized out. So I rearranged my code into the form that I assume similar to that understood by the compiler:
void MyPair::init_style()
{
neighbor->requests[ neighbor->request(this) ]->cudable = 1;
}

Which generates exactly the same seg fault error.

Here we see that the issue is incurred because the pointer neighbor->requests is modified inside of neighbor->request(this) (initially NULL and some value after allocating the first request), while the compiler probably doesn’t see that. While I have figured out the cause of the issue and is able to fix it manually, I am afraid that some future(aggressive) optimization technique can break the fix easily. There is also no compile-time warning to prevent users from running into the problem unknowingly. Is there any method to help in this situation?

Best,

Yu-Hang Tang
Division of Applied Mathematics, Brown University
Providence, RI 02912

Hi,

I just noticed a problem when compiling my own pair style with nvcc 5.5 and
gcc 4.7.2.
The code was
void MyPair::init_style()
{
    NeighRequest* req = neighbor->requests[neighbor->request(this)];
    req->cudable = 1;
}
and gdb reports:
Program received signal SIGSEGV, Segmentation fault.
LAMMPS_NS::MyPair::init_style (this=<optimized out>) at pair_my.cu:546
546 req->cudable = 1;
(gdb) p req
Cannot access memory at address 0x0
(gdb) p &req
$1 = (LAMMPS_NS::NeighRequest **) 0x0
Apparently the variable req was optimized out. So I rearranged my code into
the form that I assume similar to that understood by the compiler:
void MyPair::init_style()
{
    neighbor->requests[ neighbor->request(this) ]->cudable = 1;
}
Which generates exactly the same seg fault error.
Here we see that the issue is incurred because the pointer
neighbor->requests is modified inside of neighbor->request(this) (initially
NULL and some value after allocating the first request), while the compiler
probably doesn't see that. While I have figured out the cause of the issue
and is able to fix it manually, I am afraid that some future(aggressive)
optimization technique can break the fix easily. There is also no
compile-time warning to prevent users from running into the problem
unknowingly. Is there any method to help in this situation?

i don't think your original code is not correct.
i don't see this construct anywhere in the current version of LAMMPS.
we always have something like this:

int irequest = neighbor->request(this);
neighbor->requests[irequest]->half = 0;
neighbor->requests[irequest]->full = 1;

and that seems to be working just fine with all kinds of compilers as
it enforces the ordering of operations (which your code doesn't).

axel.