OpenMP Updates and Fixes for C++ in Visual Studio 2019 version 16.10

Chris Pulido

In our previous blog post about improved OpenMP support in Visual Studio, we announced the addition of the -openmp:llvm switch in Visual Studio 2019 version 16.9 to enable compiled programs to target LLVM’s OpenMP runtime library for the x64 architecture. This switch supports all the OpenMP 2.0 directives that -openmp supports, as well as unsigned integer indices in parallel for loops, and a subset of the SIMD directives that are supported under -openmp:experimental. It also enabled a few correctness fixes. Starting in Visual Studio 2019 version 16.10 Preview 2, the -openmp:llvm switch now works for x86 and arm64. We have also fixed a couple of bugs in 16.10 Preview 3.

-openmp:llvm Now Available for x86 and arm64

Starting in Visual Studio 2019 version 16.10 Preview 2, in addition to X64 support, we have added support for targeting LLVM’s OpenMP runtime library with -openmp:llvm for the x86 and ARM64 architectures. Compiling with -openmp:llvm will automatically add a dynamic link to libomp140.i386.dll (or libomp140d.i386.dll under /DEBUG) when targeting x86, or libomp140.aarch64.dll (or libomp140d.aarch64.dll under /DEBUG) when targeting ARM64. You can find these libraries under the Visual Studio installation directory at VC\Redist\MSVC\<version>\debug_nonredist\<arch>\Microsoft.VC142.OpenMP.LLVM.

As a reminder, the -openmp:llvm switch is experimental, and features from OpenMP 3.0 that were added with the -openmp:llvm switch in Visual Studio version 16.9 are still only supported with the additional -openmp:experimental flag in Visual Studio version 16.10, and thus are provided with certain limitations in 16.10. In particular, #pragma omp task is not yet available on x86 or arm64, and there is only limited functionality on x64 in 16.10. Lastly, future versions of the LLVM OpenMP runtime DLLs may not be backwards compatible and the current version of these DLLs is not redistributable.

Bug Fixes in 16.10 Preview 3

  • return statements inside parallel regions now issue a helpful error message since they are non-conforming. The snippet below would previously crash the compiler with an internal compiler error.
#include <iostream>

int main()
    std::cout << "Hello World!\n";

#pragma omp parallel for schedule(dynamic)
    for (auto i = 0; i < 100; ++i)
        // should issue error C3010: 'return': jump out of OpenMP structured block not allowed
        return -1;  

    return 0;
  • The if clause now chooses the correct scope for a variable. In the snippet below, the inner if clause was referencing the outer shared variable i which has a value of 1, rather than the inner private variable i which has the value of 0, causing the program to print “nested” four times instead of one. A similar fix was also applied to the num_threads clause.
#include <stdio.h>
#include <omp.h>
int main(void)
  int i = 1;
  int retVal = 0;
  #pragma omp parallel if(retVal) default(none) private(i)
    i = 0;
    #pragma omp parallel if(i) default(none) num_threads(4)
  return 0;

Our OpenMP Plans

As of 16.10, the currently supported standard is still OpenMP 2.0, though we have made some improvements and fixed some long-standing bugs. We have started the long process to support newer versions of the OpenMP standard. Our goal is to support the most recent OpenMP standard, and this will be done step-by-step, with new features leveraging LLVM’s OpenMP runtime. Our next step for OpenMP will be to support the additional features added in the OpenMP 3.1 standard. Then we will add support for the pragmas and clauses added in the OpenMP 4.5 standard that do not involve offloading. Which features are added first after that will depend on your feedback. We would love to hear from you which specific OpenMP features you would like to see first.


We encourage you to try out this update in the latest Visual Studio 2019 version 16.10 Preview. If you encounter a correctness issue in code generated with the -openmp:llvm switch or bugs in the libomp140 DLLs shipped with Visual Studio, please let us know. We can be reached via the comments below, via twitter (@visualc), or via Developer Community.


Discussion is closed. Login to edit/delete existing comments.

  • zzm3145 0

    Good news on the progress. Tim Mattson has written a book (a PDF overview can be found on the internet) called “The OpenMP Common Core”, listing features that are most commonly used. Task is the most notably missing feature in that list.

    • Chris PulidoMicrosoft employee 0

      Thanks for the suggestion! I can attest that Tim Mattson is very good at explaining OpenMP. And yeah you’re correct, tasks are currently missing because they were introduced in 3.0. Our next goal is to support OpenMP standard 3.1, and among the 3.1 features, our first priority is all task-related features.

  • deadpin 0

    At some point in the past I think the OpenMP support had problems with “two-phase name lookup” when using permissive-.

    Is disabling two-phase lookup with /Zc:twoPhase- still required when using OpenMP at all? If so, do you know which VS release first supported this?

    • Natalia GlagolevaMicrosoft employee 0

      With these releases we didn’t do any major changes in the compiler front-end yet, so two-phase lookup is still not working with OpenMP. While working on OpenMP 3.1 we’ll be looking at how to enable this, but actual work will more likely happen after OpenMP 3.1 support.
      MSDN docs suggest that /Zc:twoPhase- flag was introduced in Visual Studio 2017 version 15.3, or was your question different?

      • deadpin 0

        Thanks for the clarification Natalia. That answers my question 🙂 I tried out a small OpenMP sample yesterday with permissive- and without /Zc:twoPhase- and didn’t notice any immediate problem so I thought it might have been fixed.

        I’m definitely looking forward to proper support in the future though. Thanks again.

        • Natalia GlagolevaMicrosoft employee 0

          I asked Front End developer, and got a better answer to your question. Apparently two-phase lookup for OpenMP code was fixed in version 16.5, for -openmp switch (and as a result now for -openmp:llvm switch too)

  • Ianier Munoz 0

    In a reply to a comment I left in a previous post about OpenMP, you mentioned that there are currently no plans for the llvm runtime to support Store (sandboxed) apps.
    I’d expect the old OpenMP runtime to be deprecated at some point; however, I’d be great if you do so only when there’s an alternative for Store apps.

    • Natalia GlagolevaMicrosoft employee 0

      Thank you for your suggestion! We are still weighting out what will be supported in the future releases. Currently the old OpenMP runtime (+ older compiler support) are available via /openmp switch, and the new support is available with experimental /openmp:llvm switch. At some point we’ll flip it, and /openmp switch will invoke the new compiler support and usage of llvm runtime. At that point current /openmp switch will become e.g. /openmp:legacy switch – to continue existing support for everything what we supported so far but won’t do further development for, most likely: store apps, managed C++, Arm32.

Feedback usabilla icon