[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));
+
----------------
abidh wrote:
I think you need to call `stmtCtx.finalizeAndReset()` here to make sure any cleanups run at the correct location. Consider the following testcase. Without this call, the hlfir.end_associate is emitted in the wrong place.
```
subroutine test_dynamic_condition_with_cleanup()
interface
function getbool(s) result(r)
character(*), intent(in) :: s
logical :: r
end function
end interface
!$omp metadirective &
!$omp & when(user={condition(getbool("hello"))}: barrier) &
#ifdef OMP_52
!$omp & otherwise(taskwait)
#else
!$omp & default(taskwait)
#endif
end subroutine
```
https://github.com/llvm/llvm-project/pull/194424
More information about the llvm-branch-commits
mailing list