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

    <tr>
        <th>Summary</th>
        <td>
            `llvm.lifetime.end` is emitted too early for variables captured in `linear` clause
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang,
            openmp
      </td>
    </tr>

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

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

<pre>
    Currently if an OpenMP program uses `linear` clause, and is compiled with optimization, `llvm.lifetime.end` for variables listed in `linear` clause are emitted too early such that there could still be uses after that. Let's take the following code as example:
```
// loop.c
int j;
int *u;

void loop(int n) {
  int i;
#pragma omp parallel master taskloop simd linear(j)
  for (i = 0; i < n; ++i) {
    ++j;
    u = &j;
  }
}
```
We compile using the command:
```
clang -cc1 -fopenmp-simd -O3 -x c -triple x86_64-apple-darwin10 -emit-llvm loop.c -o loop.ll
```
The following IR (simplified) will be generated:
```
@j = local_unnamed_addr global i32 0, align 4
@u = local_unnamed_addr global ptr null, align 8

define void @loop(i32 noundef %n) local_unnamed_addr {
entry:
  %j = alloca i32, align 4
  %cmp = icmp sgt i32 %n, 0
  br i1 %cmp, label %simd.if.then, label %simd.if.end

simd.if.then:                                     ; preds = %entry
  call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %j)
  store ptr %j, ptr @u, align 8
  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %j)
  %0 = load i32, ptr %j, align 4
  store i32 %0, ptr @j, align 4
  br label %simd.if.end

simd.if.end:                                      ; preds = %simd.if.then, %entry
  ret void
}
```
The most important part is:
```
  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %j)
  %0 = load i32, ptr %j, align 4
  store i32 %0, ptr @j, align 4
```
`%j` is still loaded after `@llvm.lifetime.end.p0(i64 4, ptr nonnull %j)`. This could cause the backend incorrectly optimizes the code and further generates incorrect code. It is not shown in this case, but I do have an internal reproducer that crashes exactly because of the same issue. The root cause is, when we emit a construct that could have `linear` clause, it usually has the following pattern:
```
EmitOMPLinearClauseInit(S)
{
  OMPPrivateScope LoopScope(*this);
  ...
  EmitOMPLinearClause(S, LoopScope);
  ...
  (void)LoopScope.Privatize();
  ...
}
EmitOMPLinearClauseFinal(S, [](CodeGenFunction &) { return nullptr; });
```
Variables that need to be privatized are added into `LoopScope`, which also serves as a RAII object. When `LoopScope` is destructed and if optimization is enabled, a `@llvm.lifetime.end` is also emitted for each privatized variable. However, the writing back to original variables in `linear` clause happens after the scope in `EmitOMPLinearClauseFinal`, causing the issue we see above.

A quick "fix" seems to be, moving `EmitOMPLinearClauseFinal` inside the scope. However, it doesn't work. That's because the local variable map has been updated by `LoopScope` such that a variable declaration is mapped to the privatized variable, instead of the actual one. In that way, the following code will be generated:
```
  %0 = load i32, ptr %j, align 4
  store i32 %0, ptr %j, align 4
  call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %j)
```
Well, now the life time is correct, but apparently the writing back is broken.

I assigned the issue to myself, but don't have a clear clue on how to fix that. Any suggestion would be appreciated!
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzVV1tv47YS_jXyy8CCLF9iP_ghm5ycE2CLXbRF-7igJMpmViJ1SMre9Nf3G1K-xLG3i6IvDQRHl-HMcL5vLixM9bp-6K2V2jevpGoSmj51Uv_0mTprNla01DvpKFlkjdJSWNxQ2Qi8TPIHSFekHJWm7VQjK9orvyXTedWqP4RXRrMQr212bdqoWuKLTKWuWE1tLO2EVaJoYKFRzkOD0tdskbCSZKs8i3hjCF_hr-vLLfmt8PiRkChN31TkvGoaKmT0XNRe2iCU0kfpk_zOkRdfJS-BC01j9kpvsLSCFUfym2i7RibT-yR7TLJ7-DBc8TF_wkWNMV1axldKe3pJph9OT0l-3x9fxN-dUVVYleRLFkFgVpTcDTJE_E6d1uTTzopNKwiBpU5Y0TSyoVa4sBfhvrIqcqqF0hiqfPkClQd1HFq2RMn0kTLoJb59gFncJvkHXOrCAxren7bC7_qgIckX56-Tu8fBz-PN2yj9Lg-UAAYcXY413rTgy63IAmgIjstyQuPagIJtNw4bHH-a0vgblTT2VgEa-rZcfFnMxqLDw7gSFvhNMhozPcZMtAEdGpt41zRXDf76Bv_nnzlgMNiBpkpWHJ39wKON1NIKUO8mK2bZSwhUY0rRfOm1Fq2svoiqsrRpTCEaUtMcQHDKNGqjaXZc2P_Fws5b0j32cFy7PCdWJWsQgAK_oO1AMVjTptf4im3NA9uumDjCj_S3r8fdMRXmcUMgHpax9-98D1Il-Mlyim_cxod9RosPlB0EC0tqMojzh0YUoDOeGeBU1Sn4oa9-4FJxtts38tPA0L_8Y8p3VlZuoPI8bnZwDTFpTtF7U6acF9anXcbxXMywbTgY0DCaAQlBOss55w1KEAvED1GYEX4H3XfNYss_bhSP2UAgUR1gOvfhArLo5ABSdubkNWHA9qOAyJDYP4THe0AuWXCJkZU-xOr7RYfzuTUOFGw7Y71ARUXlxKO7lbb_ChguSw1uWCdaIxpvbHVsFH0xdjoW-Ht7WWQp_boN7ZzbaBkaL1fuQpRfJXd6XRqMCiWPCkOTR4ONtZ27J0Tq3nIrPpZMd1oUhFJ6ZkRg25Pbmr3mhu-DURFHiqL39EyVoa3YsU5ujdJqVEIrMZJUfTm0cyqtcFsZWnZwqZDRZVMHnxzqHEy5XvK2JFkDm1EClIClPehG-zhXkIB72nnbl37QHoIQnLgx_GBV73ow6BVi7mKe6IRnt29R7z-w-emnzx-D2oeg8lkrTCfLX460OmvOEP1s1Q4B_aVEb6SPKPPhDgswbXAAedmpRadperi9YiqaeThXc2MxJEPm5aujbBo9AfbB-NWFxxy9YvxJAcyDB8n8QzJ_xNMDyPFfqZ96XfLcyCPHMKBw-vdWhyYI2oYJBurPDF_E9rfjTBmA1DLMjNzIu4PnVRgo0QPDxImPWHwKxiKL9FCYLkXjDDlpdzxK4qKf75-fyRQvYHRKvzOFLtYyvSsZqcSGOHHqN0MxS0jNLlYh3W_l7KAsuHAYfnmykwKOne3lMESn9D-zlztpWSvTcW-VZzJyAnMIjFUbjv7Z2H1j3t5iupL6ND0jnQLxovhNVGPkOMkOU19IQM4yJxHwwuxket4_7un_vYJzSZ7X6ht-Wa51ES_W1Zodq_q-UbjlVCVPfr6JBPK0MtKhtdx52hv7leuBiCeBQ83glWFAOoYG03YX8rqQwLjvKh4AqXh9B_fpECJOiyuJQNoj2i2HM7CQDV2BLviJ-iPRPob6haKG4kJGc9HU0cJevB6wvTi6_PCs-o81q-vC_0xHfXeeiPOvNvuIFFQS64yHz9BeDr0DkRbDcfZdCkC6sAa97A0Hn5HYDptggI6MBVTtq5NNfdBbmUig2JaQJ2AhfiEKiLfsmCFQeDhp3ms-nW42qANMgX1oJoAH3sFZFQDKJyO5nizmq_lqsrybj6r1tFpNV2LklW_k-taxmYvHu5Pw27N0KTqUzJun6VFvm_XW-y5MRuFEu8HBvS9SnNHwwGaHf2O03JcQ3acQF7SZp_liNZmOtmu5FJPV8m6a5fVqUkxXs1k9n1byTtzNJ_NyLkdheHRrrvF5Hs53-B8HvDye8Ph5_jhS6zzL82yZzbL5bDadpotyUU-r-bKcZHVd5iW4JFuhmjRExNjNyK6De0W_cUw05bw7fRzwlINpt1WNV0IP1kTvt8auD29HYWPrsKs_AaA3RA8">