================
@@ -313,91 +333,78 @@ bool llvm::omp::isVariantApplicableInContext(
 static APInt getVariantMatchScore(const VariantMatchInfo &VMI,
                                   const OMPContext &Ctx,
                                   SmallVectorImpl<unsigned> &ConstructMatches) 
{
-  APInt Score(64, 1);
-
-  unsigned NoConstructTraits = VMI.ConstructTraits.size();
-  for (unsigned Bit : VMI.RequiredTraits.set_bits()) {
-    TraitProperty Property = TraitProperty(Bit);
-    // If there is a user score attached, use it.
-    if (VMI.ScoreMap.count(Property)) {
-      const APInt &UserScore = VMI.ScoreMap.lookup(Property);
-      assert(UserScore.uge(0) && "Expect non-negative user scores!");
-      Score += UserScore.getZExtValue();
-      continue;
-    }
+  APInt Score(1, 1);
+
+  // A sum of valid scores can exceed the width of any individual score.
+  // Retain all active bits and allow one more bit for each addition's carry.
+  auto AddScore = [&](const APInt &Value) {
+    unsigned Width = std::max(Score.getActiveBits(), Value.getActiveBits()) + 
1;
+    Score = Score.zextOrTrunc(Width);
+    Score += Value.zextOrTrunc(Width);
+  };
+  auto AddPowerOfTwo = [&](unsigned Exponent) {
+    AddScore(APInt::getOneBitSet(Exponent + 1, Exponent));
+  };
 
-    switch (getOpenMPContextTraitSetForProperty(Property)) {
-    case TraitSet::construct:
-      // We handle the construct traits later via the VMI.ConstructTraits
-      // container.
-      continue;
-    case TraitSet::implementation:
-      // No effect on the score (implementation defined).
-      continue;
-    case TraitSet::user:
-      // No effect on the score.
-      continue;
-    case TraitSet::device:
-      // Handled separately below.
-      break;
-    case TraitSet::target_device:
-      // TODO: Handling separately.
-      break;
-    case TraitSet::invalid:
-      llvm_unreachable("Unknown trait set is not to be used!");
+  unsigned NoConstructTraits = Ctx.ConstructTraits.size();
----------------
MattPD wrote:

Both frontends include constructs outside the nearest TARGET in 
`Ctx.ConstructTraits`. Using `Ctx.ConstructTraits.size()` for device weights 
changes a previously correct selection.

Compiling the following reproducer with `flang -fopenmp -fopenmp-version=52 -S 
-emit-llvm repro.f90 -o -` emits TASKYIELD at b165f599 instead of the TASKWAIT 
selected by the [parent 
commit](https://github.com/llvm/llvm-project/commit/81b82b8012a2bf9a1f1822af10778922b4646fef):

```fortran
subroutine outer_parallel()
  !$omp parallel
  !$omp target
  !$omp metadirective &
  !$omp& when(device={kind(cpu)}: taskyield) &
  !$omp& when(implementation={vendor(score(3): llvm)}: taskwait)
  !$omp end target
  !$omp end parallel
end subroutine
```

OpenMP 5.2 section 7.1 ends the construct set at TARGET. In this example, the 
construct-set depth is 1, so the KIND candidate scores 3 and loses to the 
vendor candidate's 4. The recorded outer PARALLEL raises the KIND candidate's 
score to 5.

Clang DECLARE VARIANT has the same regression, including NVPTX device 
compilation.

Could the device-weight calculation respect the TARGET boundary, with tests 
showing that PARALLEL inside TARGET still contributes while PARALLEL outside 
TARGET does not?

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

Reply via email to