forked from OSchip/llvm-project
541 lines
15 KiB
C++
541 lines
15 KiB
C++
//===- unittests/AST/OMPStructuredBlockTest.cpp ---------------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Fine-grained tests for IsOMPStructuredBlock bit of Stmt.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "ASTPrint.h"
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/AST/StmtOpenMP.h"
|
|
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
|
#include "clang/ASTMatchers/ASTMatchers.h"
|
|
#include "clang/Tooling/Tooling.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "gmock/gmock.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace clang;
|
|
using namespace ast_matchers;
|
|
using namespace tooling;
|
|
|
|
namespace {
|
|
|
|
const ast_matchers::internal::VariadicDynCastAllOfMatcher<
|
|
OMPExecutableDirective, OMPTargetDirective>
|
|
ompTargetDirective;
|
|
|
|
StatementMatcher OMPInnermostStructuredBlockMatcher() {
|
|
return stmt(isOMPStructuredBlock(),
|
|
unless(hasDescendant(stmt(isOMPStructuredBlock()))))
|
|
.bind("id");
|
|
}
|
|
|
|
StatementMatcher OMPStandaloneDirectiveMatcher() {
|
|
return stmt(ompExecutableDirective(isStandaloneDirective())).bind("id");
|
|
}
|
|
|
|
template <typename T>
|
|
::testing::AssertionResult
|
|
PrintedOMPStmtMatches(StringRef Code, const T &NodeMatch,
|
|
StringRef ExpectedPrinted,
|
|
PolicyAdjusterType PolicyAdjuster = None) {
|
|
std::vector<std::string> Args = {
|
|
"-fopenmp=libomp",
|
|
};
|
|
return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted,
|
|
PolicyAdjuster);
|
|
}
|
|
|
|
static testing::AssertionResult NoMatches(StringRef Code,
|
|
const StatementMatcher &StmtMatch) {
|
|
PrintMatch Printer((PolicyAdjusterType()));
|
|
MatchFinder Finder;
|
|
Finder.addMatcher(StmtMatch, &Printer);
|
|
std::unique_ptr<FrontendActionFactory> Factory(
|
|
newFrontendActionFactory(&Finder));
|
|
if (!runToolOnCode(Factory->create(), Code))
|
|
return testing::AssertionFailure()
|
|
<< "Parsing error in \"" << Code.str() << "\"";
|
|
if (Printer.getNumFoundStmts() == 0)
|
|
return testing::AssertionSuccess();
|
|
return testing::AssertionFailure()
|
|
<< "Matcher should match only zero statements (found "
|
|
<< Printer.getNumFoundStmts() << ")";
|
|
}
|
|
|
|
} // unnamed namespace
|
|
|
|
TEST(OMPStructuredBlock, TestAtomic) {
|
|
const char *Source =
|
|
R"(
|
|
void test(int i) {
|
|
#pragma omp atomic
|
|
++i;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), "++i"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestBarrier) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp barrier
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
|
|
"#pragma omp barrier\n"));
|
|
ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestCancel) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp parallel
|
|
{
|
|
#pragma omp cancel parallel
|
|
}
|
|
})";
|
|
const char *Expected = R"({
|
|
#pragma omp cancel parallel
|
|
}
|
|
)";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), Expected));
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
|
|
"#pragma omp cancel parallel\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestCancellationPoint) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp parallel
|
|
{
|
|
#pragma omp cancellation point parallel
|
|
}
|
|
})";
|
|
const char *Expected = R"({
|
|
#pragma omp cancellation point parallel
|
|
}
|
|
)";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), Expected));
|
|
ASSERT_TRUE(
|
|
PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
|
|
"#pragma omp cancellation point parallel\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestCritical) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp critical
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// Loop tests
|
|
//----------------------------------------------------------------------------//
|
|
|
|
class OMPStructuredBlockLoop : public ::testing::TestWithParam<const char *> {};
|
|
|
|
TEST_P(OMPStructuredBlockLoop, TestDirective0) {
|
|
const std::string Source =
|
|
R"(
|
|
void test(int x) {
|
|
#pragma omp )" +
|
|
std::string(GetParam()) + R"(
|
|
for (int i = 0; i < x; i++)
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
TEST_P(OMPStructuredBlockLoop, TestDirective1) {
|
|
const std::string Source =
|
|
R"(
|
|
void test(int x, int y) {
|
|
#pragma omp )" +
|
|
std::string(GetParam()) + R"(
|
|
for (int i = 0; i < x; i++)
|
|
for (int i = 0; i < y; i++)
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(Source,
|
|
OMPInnermostStructuredBlockMatcher(),
|
|
"for (int i = 0; i < y; i++)\n ;\n"));
|
|
}
|
|
|
|
TEST_P(OMPStructuredBlockLoop, TestDirectiveCollapse1) {
|
|
const std::string Source =
|
|
R"(
|
|
void test(int x, int y) {
|
|
#pragma omp )" +
|
|
std::string(GetParam()) + R"( collapse(1)
|
|
for (int i = 0; i < x; i++)
|
|
for (int i = 0; i < y; i++)
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(Source,
|
|
OMPInnermostStructuredBlockMatcher(),
|
|
"for (int i = 0; i < y; i++)\n ;\n"));
|
|
}
|
|
|
|
TEST_P(OMPStructuredBlockLoop, TestDirectiveCollapse2) {
|
|
const std::string Source =
|
|
R"(
|
|
void test(int x, int y) {
|
|
#pragma omp )" +
|
|
std::string(GetParam()) + R"( collapse(2)
|
|
for (int i = 0; i < x; i++)
|
|
for (int i = 0; i < y; i++)
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
TEST_P(OMPStructuredBlockLoop, TestDirectiveCollapse22) {
|
|
const std::string Source =
|
|
R"(
|
|
void test(int x, int y, int z) {
|
|
#pragma omp )" +
|
|
std::string(GetParam()) + R"( collapse(2)
|
|
for (int i = 0; i < x; i++)
|
|
for (int i = 0; i < y; i++)
|
|
for (int i = 0; i < z; i++)
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(Source,
|
|
OMPInnermostStructuredBlockMatcher(),
|
|
"for (int i = 0; i < z; i++)\n ;\n"));
|
|
}
|
|
|
|
INSTANTIATE_TEST_CASE_P(
|
|
OMPStructuredBlockLoopDirectives, OMPStructuredBlockLoop,
|
|
::testing::Values("simd", "for", "for simd", "parallel for",
|
|
"parallel for simd", "target parallel for", "taskloop",
|
|
"taskloop simd", "distribute", "distribute parallel for",
|
|
"distribute parallel for simd", "distribute simd",
|
|
"target parallel for simd", "target simd",
|
|
"target\n#pragma omp teams distribute",
|
|
"target\n#pragma omp teams distribute simd",
|
|
"target\n#pragma omp teams distribute parallel for simd",
|
|
"target\n#pragma omp teams distribute parallel for",
|
|
"target teams distribute",
|
|
"target teams distribute parallel for",
|
|
"target teams distribute parallel for simd",
|
|
"target teams distribute simd"), );
|
|
|
|
//----------------------------------------------------------------------------//
|
|
// End Loop tests
|
|
//----------------------------------------------------------------------------//
|
|
|
|
TEST(OMPStructuredBlock, TestFlush) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp flush
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
|
|
"#pragma omp flush\n"));
|
|
ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestMaster) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp master
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestOrdered0) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp ordered
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestOrdered1) {
|
|
const char *Source =
|
|
R"(
|
|
void test(int x) {
|
|
#pragma omp for ordered
|
|
for (int i = 0; i < x; i++)
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestOrdered2) {
|
|
const char *Source =
|
|
R"(
|
|
void test(int x) {
|
|
#pragma omp for ordered(1)
|
|
for (int i = 0; i < x; i++) {
|
|
#pragma omp ordered depend(source)
|
|
}
|
|
})";
|
|
ASSERT_TRUE(
|
|
PrintedOMPStmtMatches(Source, OMPInnermostStructuredBlockMatcher(),
|
|
"{\n #pragma omp ordered depend(source)\n}\n"));
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
|
|
"#pragma omp ordered depend(source)\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, DISABLED_TestParallelMaster0XFAIL) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp parallel master
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, DISABLED_TestParallelMaster1XFAIL) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp parallel master
|
|
{ ; }
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), "{\n ;\n}\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestParallelSections) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp parallel sections
|
|
{ ; }
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), "{\n ;\n}\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestParallelDirective) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp parallel
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
const ast_matchers::internal::VariadicDynCastAllOfMatcher<
|
|
OMPExecutableDirective, OMPSectionsDirective>
|
|
ompSectionsDirective;
|
|
|
|
const ast_matchers::internal::VariadicDynCastAllOfMatcher<
|
|
OMPExecutableDirective, OMPSectionDirective>
|
|
ompSectionDirective;
|
|
|
|
StatementMatcher OMPSectionsDirectiveMatcher() {
|
|
return stmt(
|
|
isOMPStructuredBlock(),
|
|
hasAncestor(ompExecutableDirective(ompSectionsDirective())),
|
|
unless(hasAncestor(ompExecutableDirective(ompSectionDirective()))))
|
|
.bind("id");
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestSectionDirective) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp sections
|
|
{
|
|
#pragma omp section
|
|
;
|
|
}
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPSectionsDirectiveMatcher(),
|
|
"{\n"
|
|
" #pragma omp section\n"
|
|
" ;\n"
|
|
"}\n"));
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestSections) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp sections
|
|
{ ; }
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), "{\n ;\n}\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestSingleDirective) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp single
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TesTargetDataDirective) {
|
|
const char *Source =
|
|
R"(
|
|
void test(int x) {
|
|
#pragma omp target data map(x)
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TesTargetEnterDataDirective) {
|
|
const char *Source =
|
|
R"(
|
|
void test(int x) {
|
|
#pragma omp target enter data map(to : x)
|
|
})";
|
|
ASSERT_TRUE(
|
|
PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
|
|
"#pragma omp target enter data map(to: x)\n"));
|
|
ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TesTargetExitDataDirective) {
|
|
const char *Source =
|
|
R"(
|
|
void test(int x) {
|
|
#pragma omp target exit data map(from : x)
|
|
})";
|
|
ASSERT_TRUE(
|
|
PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
|
|
"#pragma omp target exit data map(from: x)\n"));
|
|
ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestTargetParallelDirective) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp target parallel
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestTargetTeams) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp target teams
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestTargetUpdateDirective) {
|
|
const char *Source =
|
|
R"(
|
|
void test(int x) {
|
|
#pragma omp target update to(x)
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
|
|
"#pragma omp target update to(x)\n"));
|
|
ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestTarget) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp target
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestTask) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp task
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestTaskgroup) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp taskgroup
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestTaskwaitDirective) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp taskwait
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
|
|
"#pragma omp taskwait\n"));
|
|
ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestTaskyieldDirective) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp taskyield
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(Source, OMPStandaloneDirectiveMatcher(),
|
|
"#pragma omp taskyield\n"));
|
|
ASSERT_TRUE(NoMatches(Source, OMPInnermostStructuredBlockMatcher()));
|
|
}
|
|
|
|
TEST(OMPStructuredBlock, TestTeams) {
|
|
const char *Source =
|
|
R"(
|
|
void test() {
|
|
#pragma omp target
|
|
#pragma omp teams
|
|
;
|
|
})";
|
|
ASSERT_TRUE(PrintedOMPStmtMatches(
|
|
Source, OMPInnermostStructuredBlockMatcher(), ";\n"));
|
|
}
|