<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/141042>141042</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [OpenMP] Mapping of 'middle' structures chained through '->' does not work
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          jtb20
      </td>
    </tr>
</table>

<pre>
    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.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJy8WV9z4jgS_zTKiwpKlgHDAw8Ekq1U3exu3eSet2S5DZqxJZckk2Q__VXLBmxjSG7u6qaoXaz-9-tW66c2Ec6pvQZYk_kjme8eRO0Pxq5_-JSzh9RkH-ut0U5lYKk_KEc9OC-FAxJvCAufBWs_bEN4rLQs6gwoibfS-axQKYmfRkXKjEqEc2B9K2Ib520tPf1OSfJI2IZSpT0VJA4P-D1tv4cH2TyQZNd-OTt4PTv4TgnfOHYyax6j_iO_9oPuS6E04UvCV2dvr6h_pCTeUcKX4QnFpSgKI3HJqb_B5CgjfIWfNtBxQuInx06W3-9Yfh-zjH7Zkv-yJcP_imAesRFRelsk-6I2h4s_PjCKLv5GRXJUxC8O434ofvEXjxnJnihI88oq7bEYzmdgLeFbSjgXqak99YZKURTUC7sHTy3sldF4KOZbTTjvlO6GG8IXRxLvCJ9XzcqirdbYYjS2yDuL17bXhgOrE9BtQHn6F2D18fSB9BGEp-XRqKxppZ7N1Xp0Y_2L5ep002jlwhbflMjPE-80-ZjnEZdfxx3dxB3dxB39J7ija9zRNe5ogPsz2PwmbH4TNr8Nu68jxhyOePq0yn3aCoGzS2BsOaU94atb9PaZ29cvuu1xfHO3VVbsS0FNWZ24ohQV4UtvcmtKEve4MO2c3Db1Le1XZxXcPofPHefBMd7p8SYi813D8v9tXHq-9oY0zR8DfZ7qOaTqRjwfZeRGlpxM8c69T8C9Y9puyoUCO105XJZXW9g7ScPjPzz74wf_LshoHGQ0DjK6DXJ4xO_v3Wd93TuCQxR8HBz_cgX5ACUfoBwc6uChmfrC3TCYNNqx4ZLTqGr6dVU5pjrUjHrx-T2nUS8-jz9TPcfn8zuqvAcgvgeA9wDEyWeqcsRr0y0W4FKrbht1BdEtQecWP633_VvwtdWUXYbrqzeIrSkrVUBG35Q_UJPnhRGZ0nuctzbfdr9tf8c-Cm8ie3UER_0BaG6KwryhlgVXF759N-m4_WRmQ0YN0xh7T_Ic0iQSacLZ1VzG3ucLSJlMo2QRDwejgXh5Nat1xTPWn9q6sjnrz29dWcL6k1xXtmJtIn3Gu3Z9PTH1dGbjs1NPZ9kNFY2pJGx8yOnpzMbHnZ5OLxQfU1mx8cGkpzMbH1F6OhhqOEpEvLvYDgJ8RthmcA9FbOQWulqUzeLJ-nxBcDZyPVwtojWfn63PDB6zEf5GJrhi7xhjl6KaNO_FkwVOAt3nqZQk3ixiXO-_8-LKJhCKMpqSBbvFfwnNBR7iKWGbTWqshwwpSBoLNKvLCrJ2jOmc0NcD0NJkKldSBP8mH4YgC0aVDie-d4LpQTiaAmhaGOenp8lr-UJrBxk1Ffpz6G2Smwp0WdHJpKWWibDyQOLdPn9fMUFPCpMjWBfIYdcAbPCyzUtOX6gDT__x8vjHtz9fN__87en1r93T479-I_FujgV_A4rYBJVFDfTtIDzhiaMHUVWgkaQOYOGaokxZtVlNMFv6pL39oEiWG_oYfnDZsXfGGFvMIilElC_jRdj1R9grPSYNDPRd_Y2m0QIfXj-qxk_TWL-LEh9r_VObN90ULRUOqHKD978UY_SWo6YkN1BH91Av76EWsw7qWQ90xM7_ovjL-KMb-Dtj7Y0k-K8nsfw_JiHvJhHfSSK52z_yf70TfDyJ3otN50A8G0tBe6vA0QjVKW_ufqB_SaO9UOE0NbxVW_irTxnIFkgM2viGHMR-b2EvkIwqayqwxQf6U1OYUiGlsac5AyO4CsLvYYtpqFEyXU0XSJN0W4jaQcOGLdPET3RTFEEqg5QWynmqPJQ4nwhP3UFYoM4bK_ZAjaUHcYQmjiiBjmWDWp11Ya34aIM1Qw5SoaBO6X0BGLsSaXGJkRZG_myCt16aUemMIQ-PF6CYZa0LcI4afwD7phy08bAWKlcNnzdUbSFwmjZU6axlbPSwed68bF-bbRK-mdMyA7jbG2084Rsqqqr4oKqJP5p5aA7eMn2psqwAwjlCxhLDe2XBuUDpkwl1Yb-wugdTFxlNgf6oHYa20NRF6b2je9Bgw9434LdU6KwTgBrddSHaApqc4tVPl12kqfGHYEoWLFxK6IosmMTvUEAJ2ru2GUMftnV7CduuCU88hXdRKg0NhAs4aTIcZ21Ybq-o0y2nNM3AC1Vg2i842tclnHAM78lcQZFhJbH9m3sVMDMZ-hONMuEFKggpwbmAxJp632T2Zo3eY_-HXiB8RSujtAd7TsUflP7ZlOIorBJtyp3LOVMWpFdHOF3aIjXY9eD8qdJvxv4MpFB7mkGutPJQfLSdUWIdIZvg5N5ex01XlaJqmjkwDCbf-Z0Dt-C9KpRUvvho40zp76AwkRDQUeEp9hBoP33I1nG2ilfiAdZRMktWEV-x-cNhzSBdpatkyeQsj5nI0sUM-GyVJDPORbaIH9SaMz5nc86jiEez-XSxlHyZzuMsXySrdL4gMwalUMW0KI7l1Nj9g3KuhnU0i9iMPxQihcKFP7twruGNBim-VM93D3aNRpO03jsyY3hK3cWNV74If6_5owL97U8y39FvTZ-HpuPJ6cwkl0PlqDyItuGabSY8wW5BrXBCsVGwPA-1LdYH7yuHDBd-aNorf6jTqTQl4c8Io_3fpLLmB0hP-HMA7wh_brM7rvm_AwAA__8DejiT">