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

    <tr>
        <th>Summary</th>
        <td>
            [openmp] Problem with OpenMP user-declared reduction
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

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

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

<pre>
    ## Brief description

Recently, I encounter some problem while using OpenMP user-declared reduction (`#pragma omp declare reduction`) for Eigen arrays or vectors. I found the reduction may fail (that cause incorrect result and may be different in each run) when I am using `clang` compiler with LLVM OpenMP library. The same problem is not found in GCC compiler. 

I wonder whether I did something wrong (for example, incorrect configuration of LLVM; incorrect declaration of OpenMP reduction, etc), or there may be some issues within LLVM OpenMP. I will appreciate it if anyone could give me some suggestion about this problem. Thanks in advance.

## Version and environment

LLVM version 18.1.8, built with GCC 14.1.0 compiler, using the CMake configuration command:

```shell
CC=gcc CXX=g++ cmake ../llvm -DLLVM_ENABLE_PROJECTS="clang;openmp;flang;compiler-rt" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/llvm/18.1.8
```

The GCC toolchain selected by the `clang` compiler (explicitly specified with `clang++ --gcc-toolchain=/xxx/gcc14.1.0`) is GCC 14.1.0.

The OS that runs the test is CentOS 7.

Latest Eigen (3.4.0) is used.

## Minimal example

Please see the attached ZIP file for this example, including source and CMake. The code is also listed here for convenience:

```C++
#include <iostream>
#include <Eigen/Core>
#include <omp.h>


#pragma omp declare reduction(redEigen: Eigen::Vector2i: omp_out += omp_in) initializer(omp_priv=omp_orig)

void test_reduction()
{
 Eigen::Vector2i res;
    res.setZero();

    constexpr int num = 200;

#pragma omp parallel for reduction(redEigen:res)
    for (int i=0; i<num; i++) {
        res += Eigen::Vector2i {i, i+1};
    }

    // The expected result
    Eigen::Vector2i expected_result;
    expected_result << num * (num-1) / 2, num * (num+1) / 2;

    if (res != expected_result) {
 std::cout << "TEST ERROR! got result " << res.transpose() << ", but expected " << expected_result.transpose() << std::endl;
    }
}


int main()
{
    for (int i=0; i<10000; i++) {
        test_reduction();
 }
}

```

In this example, I defined a reduction for the `Eigen::Vector2i` type using `#pragma omp declare reduction` (see OpenMP specification V 5.2, section 5.5.11), where the reduction variable is initialized with `initializer(omp_priv=omp_orig)`. The `test_reduction` function conducts a simple summation, and outputs error information if the reduction result is incorrect.

When I run this code with multiple threads, compiled with clang and LLVM OpenMP, I got some outputs like this,

```
TEST ERROR! got result 37350 37650, but expected 19900 20100
TEST ERROR! got result 46075 46425, but expected 19900 20100
TEST ERROR! got result 37350 20100, but expected 19900 20100
......
```

while the program compiled with GCC produces nothing (i.e., the reductions produce correct results).

## More information

The problem above appears for both `Release` and `Debug` buildings, though it is less frequently with `Debug` build.

In the example above, the initializer clause is changed from `initializer(omp_priv=omp_orig)` into `initializer(omp_priv=Eigen::Vector2i::Zero())`, the result seems to be correct with same version of LLVM. 

However, I still want to solve this problem, as the `omp_priv=omp_orig` initializer seems to be in line with OpenMP specification, and, more importantly, the initializer like `omp_priv=Eigen::Vector2i::Zero()` cannot be used for arrays/vectors with dynamic size (for example, `Eigen::VectorXd`), as I have no way to pass the size information.

Besides, I am not sure whether my declaration of OpenMP reduction is correct.

I will appreciate it if anyone could give me some suggestions about this problem, or other possible solutions for this kind of reduction. Thank you very much for your time.

## Attachment

[OmpReductionTest.zip](https://github.com/user-attachments/files/18135318/OmpReductionTest.zip)

</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJykWNty47jRfhr4psssEtTxwhc6WP_qX8_a5XEmk71xQWRTRIYEGACUrX36VAOkTtZ4N4lrqkYSmo2vvz5TWCu3CvGODedsuLwRrSu1uVssfx0lE7745flmo_P9HeMp4ynMjcQCcrSZkY2TWrF4xuLZM2aoXLVnfAFrQJXpVjk0YHWN0Bi9qbCGt1JWCK2VaguPDaovT9BaNLc5ZpUwmIPBvM1IKTA-YaOY8bQxYlsL0HUDndhRyktModAG7uUWFQhjxN6CNrDDzGljI1hDoVuVgytPHoRa7KEQsqJ7XCkcZKK1CFJl2hjMHBi0beVAqNzLbhByWRRoUDmQClBkJZhW0fVvJSpYg6g7y9goziqhtmwUQ6brRlZo4E26Eh4evn3pDa_kxgizj-ClRLDihCVpQWnXwZYK_m-xOOiJINC9hjetctJboivRwBpymXu2XUkg3owmKHxC5OC7qJsKyTdHCzOtCrltjfCE6MKjY-n8RCQQfhDokB_p5wtAlzE-pU_aEMcGe76856W1LVpvvVSn9pNj3mRVgWgag5kUDkE6kAUItdcKIdNtlcNW7hDqTpltt1u0Ho3Y6NaBK6XtaSMihfphiTGR74TKMApcdYH7DY31j6ocUO2k0apG5YKMR7brJJJJlEQTsmnTysoF35EXkkGUREenkkRwOQXX4ov4gResZrquhcpZOuugjOLwz5ZYVSyeLRYsXW6zDBbfv9MnxueMzyGrSVcUMb6qql0Nt0sC-Hr_22z-cP_69Pz4__eLl68sXTLOQ6ylc92gqhuWzovuhx7mrXGMc7hdLr7Mfr1_nf9t_bB8ffnH0z1Ll89YobB4OFz_9vVl9vDw-vR8v1p_9xesdOM6HIyvOm5OTAmWURQTRU7rKiuFVGCxwsxhDpu95-dqWjA-wfemkpl01R5sg5ksJOaB8sMTgZTb222W3R4uCODe398ZX22zLPimqwjSnvgrOiJ8_Ao-202rrAfl0DqSXqByj19h3Mk-CH8QigrjkzQaRL3i1mJ-HllfpJK1qA5p5s-eArEW0V8knBNZiTn8vn6Cgspg4RNG2ovsrNqcIsrq1mTog9UHVqgTmc4pp0BUVkMlLdHrc46UZVrtUElUGX4MuEUgMYAO1yCwdCG1dQZFzdL7D2fefMZXC23w2rmum6jsDno-Pi3XfGIwD1rTGfQfWDr75qs1l_SzrptXSm5Cmy79V-nrrFTSSVHJPyjzJvR7Y-SOpUv_hJFbKkQex07L3Lv29fTu7nhMJFy7nGo-S_0pAH2JLLrf0ejuWX_UnWZaWYfvjQGpHKi2BsLK4_ggdc5FI4yoKqy8o35CCF3vIdIFJMf4hLRLli5jX5hZulBtHT4Gd_IpdAZ1fwZtz9w1E9l4Ln2gMT5P2Hh5tJe-HMxjfMX4yoccvjchjUNH7ASu6e4lXzvJg-qLAwodli4Ca3xGZqq2vk28MXwFnACeH3q0h-NTR8gCPItkdUJWX6I4MmRdHhBnPrwCCMb5y_3XF7h_fn58ZjyBrT40f6qanRhFgzNC2UZbDPFwoiG0Cnfk6uTJCzw_03IAhyqvPnil9w2LZxQRNZW_i4D-JGaSOI7jT6Pmaq4EEJcIzsv-Wn2oYWvIsZAKcxAnA1eodr4LXMv7UQxu3-BxgvrzyY9MperaTSVd78hC4_0Gw8i7xWK4fxgNoyTpRpU3XzPPJ8KdMFJsKl9ej5Xm2In-UvUZxaFOs1F8QekohqJVWTcVKPrZggAriTawbV2LfqSimq9b17TOAhqjqcYU2gQBCvhz4F2wetjd4Na1p7-HwdS0nZN89_D21G3lJF3sSoMit3Rt15M7i33j9VBOhrbgXsoQP4_1ICv5A_0NjC8-RslP0ysdp8MY0vFoGH9IoGQ6jWPgcRJ_qmIwisdDGIwGfPjfqggogtjnKiL_9zEHwlZDTmmM3hpRX1BJk0hjdN5m6Cd7P59TnkYY0ZVn7rS9KJxvItQaLqYObfA0Mo5TTr9IiI3eIQ3YKIz1GbjRIZi7sY-iklzMRvESN60fzWjkpQnEBmi63ZZ-MLdQobVQGPxX6ze9Q2acPxqdFAbs60KA0ht7kkoUZ37xspCVQm0xh8Lo-j9IOGrA-lP563MGS2cnvd2rOjrDR4ZFrC04TctM7wxvs9_W-mWhW5z6xewX_Ya7sBqswTracN6EcqTG6mqHZzuLz3bb18VrJnr7jmydQpIKKqm6hL5WBLtaQv_VPlbqRhsn-i390hM-i89h_BXmaJoXihbWDfrZ2AdaWMQZX3V7eECZ75WoZQZW_oFXdtNrveF7Hkb6jqo1lGKHoDS8iT0R0QgbCPQ6T9Khi8M5WpmjDf4Qtd-sbWvwsDjX-z9bc31wnhXW_2V1tVd212591h5Qo62V1IisrtrwxGFV-CGpNxRHbN3WC3vdUkTuoW6z0svvdWvAyfpiC575PeS4-LLh_LFunnt9L2hd9Ids2HDJ-KR0rrHkDT8ObqUr202UadoD_XsbcVBGrqatxvoVMUmHaTJhfHVVtZ9abvK7NJ-mU3GDd8k4HSTjOBlPb8q7rNgM-SgWnPMiGYjxeJjnGzHNkmRaFGme38g7HvNBwpNBPB2Okkm0wTwejiYjxPFkMkhHbBBjLWQV0coaabO98W8h7pJkOh3FN5XYYGX7l13mjqRuN-3WskFMK5U9Puekq_xrsW63Hi7hqX-VdZJ1P3mHddOa6u4TCruN2t_fGP1PzGjPDm9MiMYAd3fH_x0AAP___L1GPQ">