[flang-commits] [flang] [llvm] [flang][OpenMP] Track reachable metadirective replacements (PR #219014)

via flang-commits flang-commits at lists.llvm.org
Fri Sep 11 22:52:01 PDT 2026


================
@@ -289,11 +290,29 @@ isVariantApplicableInContextHelper(const VariantMatchInfo &VMI,
       // TODO: Verify SIMD
     }
 
-    assert(isSubset<TraitProperty>(VMI.ConstructTraits, Ctx.ConstructTraits) &&
-           "Broken invariant!");
+    // A complete ordered match can have several embeddings in the context.
+    // Match backwards to choose the highest-valued one for scoring. Keep the
+    // forward scan's partial matches for the match_any extension.
+    if (ConstructMatches &&
+        ConstructMatches->size() == VMI.ConstructTraits.size()) {
+      ConstructIdx = NoConstructTraits;
+      for (unsigned I = VMI.ConstructTraits.size(); I > 0; --I) {
+        TraitProperty Property = VMI.ConstructTraits[I - 1];
+        while (ConstructIdx > 0 &&
+               Ctx.ConstructTraits[ConstructIdx - 1] != Property)
+          --ConstructIdx;
+        assert(ConstructIdx > 0 && "Previously matched construct not found!");
+        (*ConstructMatches)[I - 1] = --ConstructIdx;
----------------
MattPD wrote:

The highest-match change exposes a device-weight discrepancy in `getVariantMatchScore`. `NoConstructTraits` counts the candidate's construct selectors. [OpenMP 5.2 section 7.3](https://www.openmp.org/wp-content/uploads/OpenMP-API-Specification-5-2.pdf) uses the enclosing context's construct-trait count for the device exponent.

In this two-PARALLEL context, `kind(cpu)` should score 5, and the PARALLEL selector should score 3. Save the reproducer below as `repro.f90` and run `flang -fc1 -fopenmp -fopenmp-version=52 -emit-hlfir -o - repro.f90`. Revision `398137ee50c7` emits `omp.barrier`, while [the exact base](https://github.com/llvm/llvm-project/commit/6c68a1661af7dce1f121fd20dfce72f4ddc4afc9) emits the required `omp.taskyield`. With one PARALLEL, both revisions emit `omp.taskyield`. DECLARE VARIANT also selects the PARALLEL variant instead of the CPU variant in this context.

Could the device weights use the enclosing context's construct-trait count while retaining the correct highest-valued construct match?

```fortran
subroutine device_meta
  !$omp parallel
    !$omp parallel
      !$omp metadirective when(device={kind(cpu)}: taskyield) &
      !$omp& when(construct={parallel}: barrier)
    !$omp end parallel
  !$omp end parallel
end subroutine
```

https://github.com/llvm/llvm-project/pull/219014


More information about the flang-commits mailing list