================
@@ -4448,16 +4448,43 @@ static void 
handleDeclareVariantConstructTrait(DSAStackTy *Stack,
                                                OpenMPDirectiveKind DKind,
                                                bool ScopeEntry) {
   SmallVector<llvm::omp::TraitProperty, 8> Traits;
-  if (isOpenMPTargetExecutionDirective(DKind))
-    Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
-  if (isOpenMPTeamsDirective(DKind))
-    Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
-  if (isOpenMPParallelDirective(DKind))
-    Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
-  if (isOpenMPWorksharingDirective(DKind))
-    Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
-  if (isOpenMPSimdDirective(DKind))
-    Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
+  // Update the enclosing construct stack for declare variant matching and
+  // scoring on region entry or exit. Record each directive's constructs in
+  // nesting order, using placeholders for constructs without selector
+  // properties so they still contribute to scoring positions and depth.
+  for (OpenMPDirectiveKind Leaf : getLeafConstructsOrSelf(DKind)) {
+    switch (Leaf) {
+    case OMPD_target:
+      Traits.push_back(llvm::omp::TraitProperty::construct_target_target);
+      break;
+    case OMPD_teams:
+      Traits.push_back(llvm::omp::TraitProperty::construct_teams_teams);
+      break;
+    case OMPD_parallel:
+      Traits.push_back(llvm::omp::TraitProperty::construct_parallel_parallel);
+      break;
+    case OMPD_for:
+      Traits.push_back(llvm::omp::TraitProperty::construct_for_for);
+      break;
+    case OMPD_simd:
+      Traits.push_back(llvm::omp::TraitProperty::construct_simd_simd);
+      break;
+    case OMPD_section:
+      // SECTION separates blocks within SECTIONS and adds no construct level.
+      // Do not add a placeholder: spelling the optional first SECTION must
+      // not change variant scores.
+      break;
+    case OMPD_dispatch:
+      // OpenMP allows omitting DISPATCH from the construct context. Keep it
+      // omitted here: adding it for the whole region would also affect calls
+      // in arguments, but the trait may apply only to the target call.
+      break;
+    default:
+      // Constructs without a selector property still affect scoring depth.
----------------
MattPD wrote:

`ActOnOpenMPRegionStart` also receives `OMPD_assume`, so this default arm gives 
the informational `assume` directive a construct position. The OpenMP 5.2 
glossary defines a construct as an executable directive with its associated 
block. Section 8.3.3 classifies `assume` as informational ("Category: 
informational"), so `assume` does not belong to the section 7.1 construct set.

You can reproduce this by saving the following to `assume.c` and running `clang 
-fopenmp -fopenmp-version=52 -S -emit-llvm -o - assume.c`:

```c
void cpu_variant(void);
void scored_variant(void);
#pragma omp declare variant(cpu_variant) match(device={kind(cpu)})
#pragma omp declare variant(scored_variant) 
match(implementation={vendor(score(3): llvm)})
void base(void);
void with_assume(void) {
#pragma omp parallel
  {
#pragma omp assume no_openmp_routines
    { base(); }
  }
}
void without_assume(void) {
#pragma omp parallel
  { base(); }
}
```

With this PR `with_assume` calls `cpu_variant`, since depth 2 makes `kind(cpu)` 
score 5 against 4. `without_assume` calls `scored_variant`, since depth 1 makes 
`kind(cpu)` score 3 against 4. The code already skips `section` and `dispatch`. 
Skipping every leaf whose `getDirectiveCategory` is `Informational` would keep 
the depth at 1 in both functions.

https://github.com/llvm/llvm-project/pull/224431
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to