[llvm-branch-commits] [flang] [flang][OpenMP] Support lowering of metadirective (part 2) (PR #194424)

Abid Qadeer via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue May 26 02:25:57 PDT 2026


================
@@ -4629,35 +4638,83 @@ static void genMetadirective(lower::AbstractConverter &converter,
                    queue.begin());
   };
 
-  const parser::OmpDirectiveSpecification *selected = fallback;
-  if (candidates.size() == 1) {
-    selected = candidates.front().spec;
-  } else if (!candidates.empty()) {
+  auto selectBestCandidate =
+      [](llvm::ArrayRef<unsigned> candidateIndices,
+         llvm::ArrayRef<MetadirectiveCandidate> candidates,
+         const TargetOMPContext &ompCtx) -> std::optional<unsigned> {
+    if (candidateIndices.empty())
+      return std::nullopt;
+    if (candidateIndices.size() == 1)
+      return candidateIndices.front();
+
     // The OpenMP context scorer preserves input order for tied candidates.
     // Put explicit variants first so they take precedence over implicit
     // `nothing`, as required by metadirective selection.
     llvm::SmallVector<unsigned, 4> candidateOrder;
-    candidateOrder.reserve(candidates.size());
-    for (auto [idx, candidate] : llvm::enumerate(candidates))
-      if (candidate.isExplicit)
+    candidateOrder.reserve(candidateIndices.size());
+    for (unsigned idx : candidateIndices)
+      if (candidates[idx].isExplicit)
         candidateOrder.push_back(idx);
-    for (auto [idx, candidate] : llvm::enumerate(candidates))
-      if (!candidate.isExplicit)
+    for (unsigned idx : candidateIndices)
+      if (!candidates[idx].isExplicit)
         candidateOrder.push_back(idx);
 
     llvm::SmallVector<llvm::omp::VariantMatchInfo, 4> orderedVMIs;
-    orderedVMIs.reserve(candidates.size());
+    orderedVMIs.reserve(candidateOrder.size());
     for (unsigned idx : candidateOrder)
       orderedVMIs.push_back(candidates[idx].vmi);
 
     int bestIdx = llvm::omp::getBestVariantMatchForContext(orderedVMIs, ompCtx);
     if (bestIdx >= 0) {
       assert(static_cast<size_t>(bestIdx) < candidateOrder.size() &&
              "best variant index out of range");
-      selected = candidates[candidateOrder[bestIdx]].spec;
+      return candidateOrder[bestIdx];
+    }
+    return std::nullopt;
+  };
+
+  llvm::SmallVector<unsigned, 4> remainingCandidates;
+  remainingCandidates.reserve(candidates.size());
+  for (unsigned idx = 0, end = candidates.size(); idx < end; ++idx)
+    remainingCandidates.push_back(idx);
+
+  mlir::Location loc = converter.genLocation(clauseList.source);
+  lower::StatementContext stmtCtx;
+
+  while (!remainingCandidates.empty()) {
+    std::optional<unsigned> selected =
+        selectBestCandidate(remainingCandidates, candidates, ompCtx);
+    if (!selected) {
+      genVariant(fallback);
+      return;
+    }
+
+    const MetadirectiveCandidate &candidate = candidates[*selected];
+    if (!candidate.condExpr) {
+      genVariant(candidate.spec);
+      return;
     }
+
+    const auto *condExpr = semantics::GetExpr(semaCtx, *candidate.condExpr);
+    assert(condExpr && "missing expression for user condition");
+    mlir::Value condVal =
+        fir::getBase(converter.genExprValue(*condExpr, stmtCtx, &loc));
+
+    if (condVal.getType() != builder.getI1Type())
+      condVal = builder.createConvert(loc, builder.getI1Type(), condVal);
+
+    auto ifOp =
+        fir::IfOp::create(builder, loc, condVal, /*withElseRegion=*/true);
----------------
abidh wrote:

We can be more precise by using the location of `candidate.condExpr` here. The same applies to the `createConvert` and `converter.genExprValue` calls above.

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


More information about the llvm-branch-commits mailing list