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

    <tr>
        <th>Summary</th>
        <td>
            [OpenMP][SIMD] `ordered` has no effect in a loop SIMD region as of LLVM 18.1.0
        </td>
    </tr>

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

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

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

<pre>
    This may be a regression between LLVM version 17.0.1 and 18.1.0.
The issue is still present in the main branch as of version 19.0.0 (dbc3e26c25587e5460ae12caed84cb09197c4ed7).

Consider the following loop:
```cpp
#define ARRAY_SIZE 256

__attribute__((noinline)) void omp_simd_loop(float X[ARRAY_SIZE][ARRAY_SIZE]) {
    for (int r = 1; r < ARRAY_SIZE; ++r) {
        for (int c = 1; c < ARRAY_SIZE; ++c) {
#pragma omp simd
 for (int k = 2; k < ARRAY_SIZE; ++k) {
#pragma omp ordered simd
                X[r][k] = X[r][k - 2] + sinf((float)(r / c));
 }
        }
    }
}
```

We have that:

> "2.13.8 ordered Construct:
> The ordered construct either specifies a structured block in a loop, simd, or loop SIMD region that will be executed in the order of the loop iterations, or it is a stand-alone directive that specifies cross-iteration dependences in a doacross loop nest. The ordered construct sequentializes and orders the execution of ordered regions while allowing code outside the region to run in parallel."

- OpenMP Application Programming Interface, Version 4.5, https://www.openmp.org/wp-content/uploads/openmp-4.5.pdf

However, as of LLVM 18.1.0 when we:
- run the `omp_simd_loop` using `#pragma omp simd` and `#pragma omp ordered simd`
- run the sequential `comparison_loop` (which is otherwise the same loop without any `#pragma omp`)
- compare the results, counting the number of errors whenever the comparison fails (up to an including a rather large relative comparison tolerance of `1000000.0 * FLT_EPSILON`)

We have 12,090 errors for the code compiled with LLVM 18.1.0 but 0 errors for the code compiled with LLVM 17.0.1.

Compiler Explorer repro:
- LLVM 18.1.0: https://godbolt.org/z/qbcecozbv - execution result: `totalErrors_simd: 12090`, FAIL: error in ordered simd computation.`
- LLVM 17.0.1: https://godbolt.org/z/oMv863fss - execution result: `Success!`

The bug is only present when compiling with -fopenmp (compiling without -fopenmp makes LLVM 18.1.0 pass).
Removing all `#pragma omp` also makes this pass.
Using `#pragma omp simd safelen(2)` instead of `#pragma omp simd` is similarly sufficient: But this effectively makes `#pragma omp ordered simd` unnecessary.
The above would strongly indicate this is an OpenMP issue. However, when attempting to track this down--and in particular analyze the interactions with different loop vectorizer decisions between LLVM 17.0.1 and 18.1.0--I've run into some "interesting" challenges (notes on the findings in the next comment to keep this one short).

This may be related to an earlier bug (although note that this one is a bit simpler in that it doesn't use `printf` inside the loop which currently prevents vectorization and thus does not reproduce for me at the time of writing):

[OpenMP 4.5] ORDERED SIMD construct in loop SIMD doesn't work as required by the specification
https://github.com/llvm/llvm-project/issues/51043

---

Full repro source code (for completeness only: the aforementioned Compiler Explorer repros are identical):

```cpp
#include <float.h>
#include <math.h>
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int compare_float(float x1, float x2, float scalar) {
    const float diff = fabsf(x1 - x2);
    x1 = fabsf(x1);
    x2 = fabsf(x2);
    const float l = (x2 > x1) ? x2 : x1;
    if (diff <= l * scalar * FLT_EPSILON)
        return 1;
    else
        return 0;
}

#define ARRAY_SIZE 256

__attribute__((noinline)) void initialization_loop(
    float X[ARRAY_SIZE][ARRAY_SIZE], float Y[ARRAY_SIZE][ARRAY_SIZE]) {
    const float max = 1000.0;
 srand(time(NULL));
    for (int r = 0; r < ARRAY_SIZE; r++) {
 for (int c = 0; c < ARRAY_SIZE; c++) {
            X[r][c] = ((float)rand() / (float)(RAND_MAX)) * max;
            Y[r][c] = X[r][c];
        }
    }
}

__attribute__((noinline)) void omp_simd_loop(float X[ARRAY_SIZE][ARRAY_SIZE]) {
    for (int r = 1; r < ARRAY_SIZE; ++r) {
        for (int c = 1; c < ARRAY_SIZE; ++c) {
#pragma omp simd
            for (int k = 2; k < ARRAY_SIZE; ++k) {
#pragma omp ordered simd
                X[r][k] = X[r][k - 2] + sinf((float)(r / c));
            }
        }
 }
}

__attribute__((noinline)) int comparison_loop(float X[ARRAY_SIZE][ARRAY_SIZE],
 float Y[ARRAY_SIZE][ARRAY_SIZE]) {
    int totalErrors_simd = 0;
 const float scalar = 1.0;
    for (int r = 1; r < ARRAY_SIZE; ++r) {
 for (int c = 1; c < ARRAY_SIZE; ++c) {
            for (int k = 2; k < ARRAY_SIZE; ++k) {
                Y[r][k] = Y[r][k - 2] + sinf((float)(r / c));
            }
        }
        // check row for simd update
        for (int k = 0; k < ARRAY_SIZE; ++k) {
 if (!compare_float(X[r][k], Y[r][k], scalar)) {
 ++totalErrors_simd;
            }
        }
    }
    return totalErrors_simd;
}

int main(void) {
    float X[ARRAY_SIZE][ARRAY_SIZE];
    float Y[ARRAY_SIZE][ARRAY_SIZE];

 initialization_loop(X, Y);
    omp_simd_loop(X);
    const int totalErrors_simd = comparison_loop(X, Y);

    if (totalErrors_simd) {
        fprintf(stdout, "totalErrors_simd: %d \n", totalErrors_simd);
        fprintf(stdout, "%s : %d - FAIL: error in ordered simd computation.\n",
                __FILE__, __LINE__);
 } else {
        fprintf(stdout, "Success!\n");
    }

 return totalErrors_simd;
}
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWUtv4zgS_jXMpWBDoh-xDznkiQ2Q7ml0z8x278WgqZLNDUVqSCpO-tcvipRs-TWTnhnsYbFGI21RZFWx-NVXVbTwXq0M4hWb3LDJ3YVowtq6qw8ihE93F0tbvF39vFYeKvEGSwQBDlcOvVfWwBLDBtHA09OvH-AFXRzML4fZMAdhCshnw3yYDVl2x7Lrn9cIyvuG_oIPSmuoHXo0AZSBsEaohDKwdMLINQgPttzJnA-zYQaMz4qlHCGfSj6ZzC5xMp5mAnMuBRazsVxm83x-KcdYXDI-b_Wmv7fWeFWgi4pKq7XdKLMCbW3NRu0cNs3SP1nX7QgfFVgqg3D9-fP1t8WXx3_dA59M-5IXCxGCU8sm4GLB-IzxmbHKaGWQ8Tnjc3ixqgBb1QuvqmIRVfJZqa0I8JVNbnai2eTu6JnPgV3eJFUAAKV15AdlAjhgozvI2egmfr3tGUljjN8wfuOOJBxIkTsp8qwUuSeF8VHtxKoStCugXbXSe2Kfo1hOIp7Pin3-HbHWFeiw6Is_-JDzXPLZM5vcRYX9MRgAj-P8BrwyZTqc6Ph4MjMy9gFkOiY26nzELu_2Fe4NbB92Xzrc9GHxT4S1eEEIaxF2CEt_R_fAOOfDfDScbfdJCA2ukb3Zo3ugqOlmyG4GoAprdOBrlKpU6EFAetPQvKW28pmCSiR889vkRH4L1sUh-PL44Y4imYKLLIQNxeMSAV9RNgGLLiajbgpFeohLVUAngrLGtwJVoIgmC4QpBkJbg1AohzKodv89Q6Wz3g-2MqDAGk2BRqJPFhdWxDlJmUEfhmec4PG3Bk1QQqvv5AJTpEk-2po2QipsuV2cduxhs1YaQXQsIG2BYJtADBEXd56x4BpDdtXCCa1RDxnn_aMcwE81mg-f4LqutZJpT5-cXTlRVST60QR0pZBIzvq1pbPxcEKP6xBqT6fNHxh_2Gw2Q1ujqeqhdSsaqAfSmoAmMP7Q1NqKwjP-kOYMxsPJsC7KvjH_sBt8QUeiE31GXk4kDJs1GtjgFlyDuDXaLJtm--Q0zaDxZDxB-jjUp1n09dHLvYDtgmGnZndctFTaqhZOeWu2OhmfbdZKrglNlvC9UT4dhxdVC76NCmvbBBDm7ciA-Dzv1CYF3XH6RoeIV2kbE2hvNG6aapnQjc5Z56OTyIXx7c5EKIXSngxsagKFIExI3RQkSIATMRq1cCvSpUUEfm95sBoprSGpYtMsz-InZrRreHj6eXH_6cvj008f-1vYp5GcM36bzbPOUmLaZGSRVCmNRXTP3qkvmwDvXxMz90HajLMc3L_W2jp04LB2toeinjY2uj7A9MoWS6tDC-jvjD_8tpQo7fflCwx6IZoOiNazaRZsEPo-mhxBScM5z-aRYfktPFw_PtFY3BUFZx94cV9NiIE47KGwt8H3mGk_vMymo9L782Z-aaRE7xnPD5if2GrZrCKMjX7bVjkxApPbCTfR74MyhTNha_8VoXz7thLP6PcOthakuqtxPmNlXyIYtT4VFyC0t62UQNUcLW_X_nI-1MGLEjUaxmeccDnNQBkfUBQtkE-zA9V3qlJaOP0GvilLJRWx2OgabpqQDMCyTAlCv7V2_RGfQGMMkseFe-uVlGJpXxA2ttEF5UBrVvoNlCmIjDHpouxkOqKOJegQelwZz0WEgFWdmMFCcEI-p8WF3ZjBgAgvpYGgZKOFA2GEfvue-EURyQsZUm6hcy1UWaKjU4-09YIyWKe-o4MCpfJx4l71fFQ1DwaPjF--YJuBggVvK6S6IWpDT7YyzkGuKTOZFUaCMjYg4S7VueQHs_JdMjf4GgiBFRkWLDwj1mmXlLP92rpwWDf3a_9IbVi0DIjCaYUuQp3xmdCE2dUayIKU9beSY3mwVIGOsiY2UW3VoQIUFr1h_DJA42Muqp0yoWyx1iXkRP4xO8jGkWNTYL2gCX7r3pR-yYdh3fgomsxJnFU0EiMFVgjROISgqkjJG6eSN-eHldrkpoUNpezJHfz0-e7-8_1dqp92pYgyvbJqt6ONdc-Uih3-1qhYmb2lfJbKoVQuJE0HhKTCulkOpa0Yf9D6pftvUDv7b5RUEEQcUz0wybPxaK8mGQz6jw-N1skD4G3jZMv_VAlbF_lIY0CDPtEVRSnZKErrkICirInV6clE4IFyrCponhT6hAdP9VQpeSK1BbEaH67Z6P7U20qE9dmXtqrPvvOhUPb33mq1PPuaYNF_Gf_GVinVFIu2hWh7uNecWKT9znffvRRaHLdfETXtFKKJ2LaUYumpP3nNYRCF9NoRAHjND2YdTeD7E44k9LXqODdOA-oxojhgo4ck5poG-mtVGTvvZOstrdWxcEkbPKphugKm654chsYZ2JeJ2uPJadl22q6_-rt7cWVUahtiAHYdea_Hfm9v3h31tx9u4_vnUYnX1IPHmnDnJu-EKRifER4Zn3385enpsFU9dSGQnbsQcKnp3rfl6CYgO3cTIE8tP92Oy64d32-52_1ECfwB9pvxz9cf7xYfrr-2B0WoqsTr3la7z7cTmg60H637ox7-_3c5B3c5vc__xrVO7_M7Nzx_Hhq7DLFra38AG7ddQP5JRlGxpttvnbYB3U7rs07H3gSYPuv8dVz-NUD-fcA7BNa3E8D69l8DVjcQCzyQa5TP4Owm7jGeVVMXIuDZ2H7esfO7HZAyN-P5YeVyEGOUyb4dD20rmH2pSdVxm_7D_th7aPP_WbEH8UguqYSi3pQ4-Zhb3xl3o6M1fxx6W5NaL58sJ74mpx4A5TB1fD1dqJ0N5mOCOdZzWLkdufRkFmn7Lj7zobBNIKmM81OXMYxPCmCTW8N4LHdPyD8CwxnxjE88bGUOfuRuZ6v_dLAvFg-PT_dE1bewWDw9fozf92_5YxX6blf0Lnw63fv7PEDoDyC6a5IuiqtRMR_NxQVe5Zf5bJzl8yy7WF_xbFleFvNyMp1OMzG-nEzFdCrnl9PRdD7JprMLdcUzPs6m-Zjnk3ycDaeTXBZFXuYzPpbLcsnGGVZC6SH1kUPrVhexg7yaT6Z5fqHFErWPvwFybnCTrkloj5O7C3cVe89ls_JsnGnlg99JCSro-ONhapRTuFAfHJl0mrUHSP38WlA73l797H6f2Psx4uji-qJx-urPd8dpey9X_D8BAAD__y32eqg">