================
@@ -157,24 +193,46 @@ template <typename T> static bool isSubset(ArrayRef<T> 
C0, ArrayRef<T> C1) {
       ++It1;
       continue;
     }
-    ++It0;
+    ++It1;
   }
   return true;
 }
 
 static bool isStrictSubset(const VariantMatchInfo &VMI0,
                            const VariantMatchInfo &VMI1) {
-  // If all required traits are a strict subset and the ordered vectors storing
-  // the construct traits, we say it is a strict subset. Note that the latter
-  // relation is not required to be strict.
-  if (VMI0.RequiredTraits.count() >= VMI1.RequiredTraits.count())
+  // kind(any) is equivalent to omitting the kind selector.
+  BitVector Traits0 = VMI0.RequiredTraits, Traits1 = VMI1.RequiredTraits;
+  for (TraitProperty Property : {TraitProperty::device_kind_any,
+                                 TraitProperty::target_device_kind_any}) {
+    Traits0.reset(unsigned(Property));
+    Traits1.reset(unsigned(Property));
+  }
+  size_t TraitCount0 = Traits0.count() + VMI0.UnknownTraits.size();
+  size_t TraitCount1 = Traits1.count() + VMI1.UnknownTraits.size();
+  if (TraitCount0 > TraitCount1)
     return false;
-  for (unsigned Bit : VMI0.RequiredTraits.set_bits())
-    if (!VMI1.RequiredTraits.test(Bit))
+  for (unsigned Bit : Traits0.set_bits())
+    if (!Traits1.test(Bit))
+      return false;
+  for (const auto &Trait : VMI0.UnknownTraits)
+    if (!llvm::is_contained(VMI1.UnknownTraits, Trait))
+      return false;
+  for (const auto &Trait : VMI0.ISATraits)
+    if (!llvm::is_contained(VMI1.ISATraits, Trait))
       return false;
-  if (!isSubset<TraitProperty>(VMI0.ConstructTraits, VMI1.ConstructTraits))
+  bool HasAdditionalISATrait =
+      llvm::any_of(VMI1.ISATraits, [&](const auto &Trait) {
+        return !llvm::is_contained(VMI0.ISATraits, Trait);
+      });
+  if (!VMI0.UserCondition.empty() && VMI0.UserCondition != VMI1.UserCondition)
----------------
chichunchen wrote:

Thanks for the reproducers. I agree with the Flang case, but I don't think the 
C case is a bug.

For Flang, `condition(a)` and `condition(b)` are different conditions, so 
neither selector is a subset of the other, and lexical order should decide the 
tie. This is an existing bug: #233038 reproduces it on main without the scoring 
changes here. I'll put up a separate fix that compares non-constant conditions 
by their folded expressions. Two `condition(a)` clauses still form a strict 
subset, and since identity only matters for ties, a higher score on the first 
selector still wins. I'll add your reproducer as a regression test.

For C, I'd treat `condition(1)` and `condition(2)` as the same trait. The spec 
doesn't say when two `condition` selectors are equivalent. OMPContext already 
records constant conditions by truth value 
(`user_condition_true`/`user_condition_false`), and GCC does the same: 
`omp_context_selector_props_compare` treats constants with the same truth value 
as equal and all non-constant expressions as distinct. Under that rule the 
second selector is a strict superset of the first, so TASKWAIT is the expected 
result once the vendor score is counted only once. The parent picked TASKYIELD 
because it counted `score(4)` twice.

I know I tried identifying conditions by expression earlier in this review, but 
I don't think it's the right rule. It makes the selection depend on how a 
constant is written (`1` vs. `1+0`). It's also hard to do reliably in Clang, 
since the AST doesn't keep the written form of things like `typeof(1+1)` vs. 
`typeof(2)`, so `Stmt::Profile` would keep needing special cases. The same 
reasoning applies to the earlier `__builtin_LINE`/`__builtin_COLUMN`, compound 
literal and `va_arg` examples.

I'll add your C example as a test expecting TASKWAIT so the behavior is 
documented. Does that sound reasonable?

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