Issue 141042
Summary [OpenMP] Mapping of 'middle' structures chained through '->' does not work
Labels new issue
Assignees
Reporter jtb20
    Consider this testcase:

```
#include <cstdlib>
#include <cstdio>
#include <cassert>

struct S {
  int a;
 int b;
  int c;
};

struct T {
  S *s0;
  S *s1;
  S *s2;
};

int main() {
  T *v = (T *) malloc (sizeof(T));
  v->s0 = (S *) malloc (sizeof(S));
  v->s1 = (S *) malloc (sizeof(S));
  v->s2 = (S *) malloc (sizeof(S));
  v->s0->a = 10;
  v->s0->b = 10;
  v->s0->c = 10;
 v->s1->a = 20;
  v->s1->b = 20;
  v->s1->c = 20;
  v->s2->a = 30;
 v->s2->b = 30;
  v->s2->c = 30;

  fprintf(stderr, "about to call target region:\n");
  fprintf(stderr, "&v=%p, &v->s0=%p, &v->s1=%p, &v->s2=%p, v->s0=%p, v->s1=%p, v->s2=%p\n",
          &v, &v->s0, &v->s1, &v->s2, (void*)v->s0, (void*)v->s1, (void*)v->s2);
  fprintf(stderr, "&v->s0->c=%p, &v->s0->b=%p, &v->s0->c=%p\n",
          &v->s0->a, &v->s0->b, &v->s0->c);
  fprintf(stderr, "&v->s1->c=%p, &v->s1->b=%p, &v->s1->c=%p\n",
          &v->s1->a, &v->s1->b, &v->s1->c);
 fprintf(stderr, "&v->s2->c=%p, &v->s2->b=%p, &v->s2->c=%p\n",
 &v->s2->a, &v->s2->b, &v->s2->c);
  fprintf(stderr, "sizeof(S)=%d\n", (int)sizeof(S));
  fprintf(stderr, "sizeof(T)=%d\n", (int)sizeof(T));

#pragma omp target map(tofrom: v->s1->b, v->s1->c, v->s2->b)
//#pragma omp target map(to: v[:1]) map(tofrom: v->s1->b, v->s1->c, v->s2->b)
  {
    v->s1->b += 3;
    v->s1->c += 5;
 v->s2->b += 7;
  }

  fprintf(stderr, "v->s0->a=%d, v->s0->b=%d, v->s0->c=%d\n",
          v->s0->a, v->s0->b, v->s0->c);
 fprintf(stderr, "v->s1->a=%d, v->s1->b=%d, v->s1->c=%d\n",
 v->s1->a, v->s1->b, v->s1->c);
  fprintf(stderr, "v->s2->a=%d, v->s2->b=%d, v->s2->c=%d\n",
          v->s2->a, v->s2->b, v->s2->c);

  assert (v->s0->a == 10);
  assert (v->s0->b == 10);
  assert (v->s0->c == 10);
 assert (v->s1->a == 20);
  assert (v->s1->b == 23);
  assert (v->s1->c == 25);
  assert (v->s2->a == 30);
  assert (v->s2->b == 37);
  assert (v->s2->c == 30);

  free(v->s0);
  free(v->s1);
  free(v->s2);
 free(v);

  return 0;
}

```
Compiled with offloading to AMDGCN, this gives the following result:
```
about to call target region:
&v=0x7ffeb71ab720, &v->s0=0x56eb0cb17630, &v->s1=0x56eb0cb17638, &v->s2=0x56eb0cb17640, v->s0=0x56eb0cb17650, v->s1=0x56eb0cb17670, v->s2=0x56eb0cb17690
&v->s0->c=0x56eb0cb17650, &v->s0->b=0x56eb0cb17654, &v->s0->c=0x56eb0cb17658
&v->s1->c=0x56eb0cb17670, &v->s1->b=0x56eb0cb17674, &v->s1->c=0x56eb0cb17678
&v->s2->c=0x56eb0cb17690, &v->s2->b=0x56eb0cb17694, &v->s2->c=0x56eb0cb17698
sizeof(S)=12
sizeof(T)=24
v->s0->a=10, v->s0->b=10, v->s0->c=10
v->s1->a=20, v->s1->b=20, v->s1->c=25
v->s2->a=30, v->s2->b=37, v->s2->c=30
map-struct-6: map-struct-6.cc:63: int main(): Assertion `v->s1->b == 23' failed.
Aborted (core dumped)
```
The modification of `v->s1->b` in the target region has been lost.

(I used options `-fopenmp --offload-arch=gfx90a -fopenmp-version=60`)

If I set LIBOMPTARGET_DEBUG=5, we get a clue what's happening here:
```
omptarget --> Entry  0: Base=0x0000641caa1f8360, Begin=0x0000641caa1f8368, Size=16, Type=0x20, Name=unknown
(base is &v->s0, begin is &v->s1)
omptarget --> Entry  1: Base=0x0000641caa1f8368, Begin=0x0000641caa1f83a4, Size=4, Type=0x1000000000013, Name=unknown
(base is &v->s1, begin is &v->s1->b)
omptarget --> Entry  2: Base=0x0000641caa1f8368, Begin=0x0000641caa1f83a8, Size=4, Type=0x1000000000013, Name=unknown
(base is &v->s1, begin is &v->s1->c)
omptarget --> Entry  3: Base=0x0000641caa1f8370, Begin=0x0000641caa1f83c4, Size=4, Type=0x1000000000013, Name=unknown
(base is &v->s2, begin is &v->s2->b)
```
For entries 1 & 2, the _containing structure_ of `v->s1` has not been aggregated properly, i.e. according to the spec (6.0, 7.9.6 map Clause):

> All map clause list items that share storage or have the same containing structure or containing array
> result in a single mappable storage block that contains the storage of the list items, unless otherwise
> specified.

There's no indication, AFAICT, that this does *not* apply if the containing structure is "in the middle" of map expressions -- so there should be just three mappings generated here, and the middle one should be a block of size 8 containing both the `b` and `c` elements of `s1`.

I haven't examined the generated code for the offload region in detail -- I assume the `v->s1->b` field is not modified because the data is accessed through the wrong (other) pointer.

I think both variants of the target directive in the above test should work, but definitely the commented-out version that maps the base `v[:1]` explicitly should. Neither works at present.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to