blob: e097510592c9ab2e03a29fa6eef5a9f9c0c4576f [file] [log] [blame]
//===- OMP.cpp ------ Collection of helpers for OpenMP --------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/Frontend/OpenMP/OMP.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
#include <iterator>
#include <type_traits>
using namespace llvm;
using namespace llvm::omp;
#define GEN_DIRECTIVES_IMPL
#include "llvm/Frontend/OpenMP/OMP.inc"
namespace llvm::omp {
ArrayRef<Directive> getLeafConstructs(Directive D) {
auto Idx = static_cast<std::size_t>(D);
if (Idx >= Directive_enumSize)
return std::nullopt;
const auto *Row = LeafConstructTable[LeafConstructTableOrdering[Idx]];
return ArrayRef(&Row[2], static_cast<int>(Row[1]));
}
Directive getCompoundConstruct(ArrayRef<Directive> Parts) {
if (Parts.empty())
return OMPD_unknown;
// Parts don't have to be leafs, so expand them into leafs first.
// Store the expanded leafs in the same format as rows in the leaf
// table (generated by tablegen).
SmallVector<Directive> RawLeafs(2);
for (Directive P : Parts) {
ArrayRef<Directive> Ls = getLeafConstructs(P);
if (!Ls.empty())
RawLeafs.append(Ls.begin(), Ls.end());
else
RawLeafs.push_back(P);
}
// RawLeafs will be used as key in the binary search. The search doesn't
// guarantee that the exact same entry will be found (since RawLeafs may
// not correspond to any compound directive). Because of that, we will
// need to compare the search result with the given set of leafs.
// Also, if there is only one leaf in the list, it corresponds to itself,
// no search is necessary.
auto GivenLeafs{ArrayRef<Directive>(RawLeafs).drop_front(2)};
if (GivenLeafs.size() == 1)
return GivenLeafs.front();
RawLeafs[1] = static_cast<Directive>(GivenLeafs.size());
auto Iter = std::lower_bound(
LeafConstructTable, LeafConstructTableEndDirective,
static_cast<std::decay_t<decltype(*LeafConstructTable)>>(RawLeafs.data()),
[](const llvm::omp::Directive *RowA, const llvm::omp::Directive *RowB) {
const auto *BeginA = &RowA[2];
const auto *EndA = BeginA + static_cast<int>(RowA[1]);
const auto *BeginB = &RowB[2];
const auto *EndB = BeginB + static_cast<int>(RowB[1]);
if (BeginA == EndA && BeginB == EndB)
return static_cast<int>(RowA[0]) < static_cast<int>(RowB[0]);
return std::lexicographical_compare(BeginA, EndA, BeginB, EndB);
});
if (Iter == std::end(LeafConstructTable))
return OMPD_unknown;
// Verify that we got a match.
Directive Found = (*Iter)[0];
ArrayRef<Directive> FoundLeafs = getLeafConstructs(Found);
if (FoundLeafs == GivenLeafs)
return Found;
return OMPD_unknown;
}
} // namespace llvm::omp